linkablemapobj.cpp
author insilmaril
Tue, 05 Sep 2006 07:56:57 +0000
branchqt4-port
changeset 20 9ad3d0391be1
parent 2 608f976aa7bb
permissions -rw-r--r--
More undo/redo commands. Undo debug output still enabled
insilmaril@2
     1
#include <math.h>
insilmaril@0
     2
insilmaril@0
     3
#include "linkablemapobj.h"
insilmaril@0
     4
#include "branchobj.h"
insilmaril@0
     5
#include "mapeditor.h"
insilmaril@0
     6
insilmaril@0
     7
#include "version.h"
insilmaril@2
     8
//Added by qt3to4:
insilmaril@2
     9
#include <Q3PointArray>
insilmaril@0
    10
insilmaril@0
    11
insilmaril@0
    12
/////////////////////////////////////////////////////////////////
insilmaril@0
    13
// LinkableMapObj
insilmaril@0
    14
/////////////////////////////////////////////////////////////////
insilmaril@0
    15
insilmaril@0
    16
LinkableMapObj::LinkableMapObj():MapObj()
insilmaril@0
    17
{
insilmaril@0
    18
  //  cout << "Const LinkableMapObj ()\n";
insilmaril@0
    19
    init ();
insilmaril@0
    20
}
insilmaril@0
    21
insilmaril@2
    22
LinkableMapObj::LinkableMapObj(Q3Canvas* c) :MapObj(c)
insilmaril@0
    23
{
insilmaril@0
    24
//    cout << "Const LinkableMapObj\n";
insilmaril@0
    25
    init ();
insilmaril@0
    26
}
insilmaril@0
    27
insilmaril@0
    28
LinkableMapObj::LinkableMapObj (LinkableMapObj* lmo) : MapObj (lmo->canvas)
insilmaril@0
    29
{
insilmaril@0
    30
    copy (lmo);
insilmaril@0
    31
}
insilmaril@0
    32
insilmaril@0
    33
LinkableMapObj::~LinkableMapObj()
insilmaril@0
    34
{
insilmaril@0
    35
    delete (bottomline);
insilmaril@0
    36
    delete (selbox);
insilmaril@0
    37
	delete (frame);
insilmaril@0
    38
	delLink();
insilmaril@0
    39
}
insilmaril@0
    40
insilmaril@0
    41
void LinkableMapObj::delLink()
insilmaril@0
    42
{
insilmaril@0
    43
	switch (style)
insilmaril@0
    44
	{
insilmaril@0
    45
		case StyleLine:
insilmaril@0
    46
			delete (l);
insilmaril@0
    47
			break;
insilmaril@0
    48
		case StyleParabel:
insilmaril@0
    49
			segment.clear();
insilmaril@0
    50
			break;
insilmaril@0
    51
		case StylePolyLine:
insilmaril@0
    52
			delete (p);
insilmaril@0
    53
			delete (l);
insilmaril@0
    54
			break;
insilmaril@0
    55
		case StylePolyParabel:
insilmaril@0
    56
			delete (p);
insilmaril@0
    57
			segment.clear();
insilmaril@0
    58
			break;
insilmaril@0
    59
		default:
insilmaril@0
    60
			break;
insilmaril@0
    61
	}		
insilmaril@0
    62
}
insilmaril@0
    63
insilmaril@0
    64
void LinkableMapObj::init ()
insilmaril@0
    65
{
insilmaril@0
    66
    depth=-1;	
insilmaril@2
    67
	mapEditor=NULL;
insilmaril@0
    68
    childObj=NULL;
insilmaril@0
    69
    parObj=NULL;
insilmaril@0
    70
    parObjTmpBuf=NULL;
insilmaril@0
    71
    parPos=QPoint(0,0);
insilmaril@0
    72
    childPos=QPoint(0,0);
insilmaril@0
    73
	link2ParPos=false;
insilmaril@0
    74
    l=NULL;
insilmaril@0
    75
    orientation=OrientUndef;
insilmaril@0
    76
    linkwidth=20;		
insilmaril@0
    77
	thickness_start=8;
insilmaril@0
    78
    style=StyleUndef;
insilmaril@0
    79
	linkpos=LinkBottom;
insilmaril@0
    80
    segment.setAutoDelete (TRUE);
insilmaril@0
    81
    arcsegs=13;
insilmaril@2
    82
	Q3PointArray pa(arcsegs*2+2);
insilmaril@0
    83
    
insilmaril@2
    84
    bottomline=new Q3CanvasLine(canvas);
insilmaril@0
    85
    bottomline->setPen( QPen(linkcolor, 1) );
insilmaril@0
    86
    bottomline->setZ(Z_LINK);
insilmaril@0
    87
    bottomline->show();
insilmaril@0
    88
insilmaril@0
    89
    // Prepare showing the selection of a MapObj
insilmaril@2
    90
    selbox = new Q3CanvasRectangle (canvas);
insilmaril@0
    91
    selbox->setZ(Z_SELBOX);
insilmaril@0
    92
    selbox->setBrush( QColor(255,255,0) );
insilmaril@0
    93
    selbox->setPen( QPen(QColor(255,255,0) ));
insilmaril@0
    94
    selbox->hide();
insilmaril@0
    95
    selected=false;
insilmaril@0
    96
insilmaril@2
    97
	hideLinkUnselected=false;
insilmaril@2
    98
insilmaril@2
    99
	topPad=botPad=leftPad=rightPad=0;
insilmaril@2
   100
insilmaril@0
   101
	// initialize frame
insilmaril@0
   102
	frame = new FrameObj (canvas);
insilmaril@0
   103
	
insilmaril@0
   104
	repositionRequest=false;
insilmaril@2
   105
insilmaril@2
   106
	// Rel Positions
insilmaril@2
   107
	relPos=QPoint(0,0);
insilmaril@2
   108
	useRelPos=false;
insilmaril@2
   109
	useOrientation=true;
insilmaril@0
   110
}
insilmaril@0
   111
insilmaril@0
   112
void LinkableMapObj::copy (LinkableMapObj* other)
insilmaril@0
   113
{
insilmaril@0
   114
    MapObj::copy(other);
insilmaril@0
   115
	bboxTotal=other->bboxTotal;
insilmaril@0
   116
    setLinkStyle(other->style);
insilmaril@0
   117
    setLinkColor (other->linkcolor);
insilmaril@2
   118
	relPos=other->relPos;
insilmaril@2
   119
	useOrientation=other->useOrientation;
insilmaril@2
   120
insilmaril@0
   121
}
insilmaril@0
   122
insilmaril@0
   123
void LinkableMapObj::setChildObj(LinkableMapObj* o)
insilmaril@0
   124
{
insilmaril@0
   125
    childObj=o;
insilmaril@0
   126
}
insilmaril@0
   127
insilmaril@0
   128
void LinkableMapObj::setParObj(LinkableMapObj* o)
insilmaril@0
   129
{
insilmaril@0
   130
    parObj=o;
insilmaril@0
   131
	mapEditor=parObj->getMapEditor();
insilmaril@0
   132
}
insilmaril@0
   133
insilmaril@0
   134
void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPoint,int)
insilmaril@0
   135
{
insilmaril@0
   136
}
insilmaril@0
   137
insilmaril@0
   138
void LinkableMapObj::unsetParObjTmp()
insilmaril@0
   139
{
insilmaril@0
   140
}
insilmaril@0
   141
insilmaril@2
   142
bool LinkableMapObj::hasParObjTmp()
insilmaril@2
   143
{
insilmaril@2
   144
	if (parObjTmpBuf) return true;
insilmaril@2
   145
	return false;
insilmaril@2
   146
}
insilmaril@2
   147
insilmaril@2
   148
void LinkableMapObj::setUseRelPos (const bool &b)
insilmaril@2
   149
{
insilmaril@2
   150
	useRelPos=b;
insilmaril@2
   151
}
insilmaril@2
   152
insilmaril@2
   153
void LinkableMapObj::setRelPos()
insilmaril@2
   154
{
insilmaril@2
   155
	if (parObj)
insilmaril@2
   156
	{	
insilmaril@20
   157
		relPos=getRelPos();
insilmaril@2
   158
insilmaril@2
   159
		parObj->calcBBoxSize();
insilmaril@2
   160
		parObj->requestReposition();
insilmaril@2
   161
	}	
insilmaril@2
   162
}
insilmaril@2
   163
insilmaril@2
   164
void LinkableMapObj::setRelPos(const QPoint &p)
insilmaril@2
   165
{
insilmaril@2
   166
	relPos=p;
insilmaril@2
   167
	if (parObj)
insilmaril@2
   168
	{	parObj->calcBBoxSize();
insilmaril@2
   169
		parObj->requestReposition();
insilmaril@2
   170
	}	
insilmaril@2
   171
}
insilmaril@2
   172
insilmaril@20
   173
QPoint LinkableMapObj::getRelPos()
insilmaril@20
   174
{
insilmaril@20
   175
	if (!parObj) return QPoint();
insilmaril@20
   176
	relPos.setX (absPos.x() - parObj->getChildPos().x() );
insilmaril@20
   177
	relPos.setY (absPos.y() - parObj->getChildPos().y() );
insilmaril@20
   178
	return relPos;
insilmaril@20
   179
}
insilmaril@20
   180
insilmaril@2
   181
int LinkableMapObj::getTopPad()
insilmaril@2
   182
{
insilmaril@2
   183
	return topPad;
insilmaril@2
   184
}
insilmaril@2
   185
insilmaril@2
   186
int LinkableMapObj::getLeftPad()
insilmaril@2
   187
{
insilmaril@2
   188
	return leftPad;
insilmaril@2
   189
}
insilmaril@2
   190
insilmaril@2
   191
int LinkableMapObj::getRightPad()
insilmaril@2
   192
{
insilmaril@2
   193
	return rightPad;
insilmaril@2
   194
}
insilmaril@2
   195
insilmaril@0
   196
LinkStyle LinkableMapObj::getDefLinkStyle ()
insilmaril@0
   197
{
insilmaril@2
   198
	if (!mapEditor) return StyleUndef;
insilmaril@2
   199
insilmaril@0
   200
	LinkStyle ls=mapEditor->getLinkStyle();
insilmaril@0
   201
	switch (ls)
insilmaril@0
   202
	{
insilmaril@0
   203
		case StyleLine: 
insilmaril@0
   204
			return ls;
insilmaril@0
   205
			break;
insilmaril@0
   206
		case StyleParabel:
insilmaril@0
   207
			return ls;
insilmaril@0
   208
			break;
insilmaril@0
   209
		case StylePolyLine:	
insilmaril@0
   210
			if (depth>1)
insilmaril@0
   211
				return StyleLine;
insilmaril@0
   212
			else	
insilmaril@0
   213
				return ls;
insilmaril@0
   214
			break;
insilmaril@0
   215
		case StylePolyParabel:	
insilmaril@0
   216
			if (depth>1)
insilmaril@0
   217
				return StyleParabel;
insilmaril@0
   218
			else	
insilmaril@0
   219
				return ls;
insilmaril@0
   220
			break;
insilmaril@0
   221
		default: 
insilmaril@0
   222
			break;	
insilmaril@0
   223
	}	
insilmaril@0
   224
	return StyleUndef;
insilmaril@0
   225
}
insilmaril@0
   226
insilmaril@0
   227
void LinkableMapObj::setLinkStyle(LinkStyle newstyle)
insilmaril@0
   228
{
insilmaril@2
   229
	//if (newstyle=style) return;
insilmaril@0
   230
	delLink();
insilmaril@0
   231
		
insilmaril@0
   232
	style=newstyle;
insilmaril@0
   233
insilmaril@0
   234
    if (childObj!=NULL && parObj != NULL)
insilmaril@0
   235
    {
insilmaril@0
   236
		int i;
insilmaril@2
   237
		Q3CanvasLine* cl;
insilmaril@0
   238
		switch (style)
insilmaril@0
   239
		{
insilmaril@0
   240
			case StyleUndef:
insilmaril@0
   241
				bottomline->hide();
insilmaril@0
   242
				break;
insilmaril@0
   243
			case StyleLine: 
insilmaril@2
   244
				l = new Q3CanvasLine(canvas);
insilmaril@0
   245
				l->setPen( QPen(linkcolor, 1) );
insilmaril@0
   246
				l->setZ(Z_LINK);
insilmaril@0
   247
				if (visible)
insilmaril@0
   248
					l->show();
insilmaril@0
   249
				else
insilmaril@0
   250
					l->hide();
insilmaril@0
   251
				break;
insilmaril@0
   252
			case StyleParabel:
insilmaril@0
   253
				for (i=0;i<arcsegs;i++)
insilmaril@0
   254
				{
insilmaril@2
   255
					cl = new Q3CanvasLine(canvas);
insilmaril@0
   256
					cl->setPen( QPen(linkcolor, 1) );
insilmaril@0
   257
					cl->setPoints( 0,0,i*10,100);
insilmaril@0
   258
					cl->setZ(Z_LINK);
insilmaril@0
   259
					if (visible)
insilmaril@0
   260
						cl->show();
insilmaril@0
   261
					else
insilmaril@0
   262
						cl->hide();
insilmaril@0
   263
					segment.append(cl);
insilmaril@0
   264
				}
insilmaril@0
   265
				pa0.resize (arcsegs+1);
insilmaril@0
   266
				break;
insilmaril@0
   267
			case StylePolyLine:	
insilmaril@2
   268
				p = new Q3CanvasPolygon(canvas);
insilmaril@0
   269
				p->setBrush( linkcolor );
insilmaril@0
   270
				p->setZ(Z_LINK);
insilmaril@0
   271
				if (visible)
insilmaril@0
   272
					p->show();
insilmaril@0
   273
				else
insilmaril@0
   274
					p->hide();
insilmaril@0
   275
				pa0.resize (3);
insilmaril@2
   276
				// TODO a bit awkward: draw the lines additionally to polygon, to avoid
insilmaril@0
   277
				// missing pixels, when polygon is extremly flat
insilmaril@2
   278
				l = new Q3CanvasLine(canvas);
insilmaril@0
   279
				l->setPen( QPen(linkcolor, 1) );
insilmaril@0
   280
				l->setZ(Z_LINK);
insilmaril@0
   281
				if (visible)
insilmaril@0
   282
					l->show();
insilmaril@0
   283
				else
insilmaril@0
   284
					l->hide();
insilmaril@0
   285
				break;
insilmaril@0
   286
			case StylePolyParabel:	
insilmaril@2
   287
				p = new Q3CanvasPolygon(canvas);
insilmaril@0
   288
				p->setBrush( linkcolor );
insilmaril@0
   289
				p->setZ(Z_LINK);
insilmaril@0
   290
				if (visible)
insilmaril@0
   291
					p->show();
insilmaril@0
   292
				else
insilmaril@0
   293
					p->hide();
insilmaril@0
   294
				pa0.resize (arcsegs*2+2);
insilmaril@0
   295
				pa1.resize (arcsegs+1);
insilmaril@0
   296
				pa2.resize (arcsegs+1);
insilmaril@0
   297
insilmaril@2
   298
				// TODO a bit awkward: draw the lines additionally 
insilmaril@0
   299
				// to polygon, to avoid missing pixels, 
insilmaril@0
   300
				// if polygon is extremly flat
insilmaril@0
   301
				for (i=0;i<arcsegs;i++)
insilmaril@0
   302
				{
insilmaril@2
   303
					cl = new Q3CanvasLine(canvas);
insilmaril@0
   304
					cl->setPen( QPen(linkcolor, 1) );
insilmaril@0
   305
					cl->setPoints( 0,0,i*10,100);
insilmaril@0
   306
					cl->setZ(Z_LINK);
insilmaril@0
   307
					if (visible)
insilmaril@0
   308
						cl->show();
insilmaril@0
   309
					else
insilmaril@0
   310
						cl->hide();
insilmaril@0
   311
					segment.append(cl);
insilmaril@0
   312
				}
insilmaril@0
   313
				break;
insilmaril@0
   314
			default: 
insilmaril@0
   315
				break;	
insilmaril@0
   316
		}	
insilmaril@2
   317
	} 
insilmaril@0
   318
}
insilmaril@0
   319
insilmaril@0
   320
LinkStyle LinkableMapObj::getLinkStyle()
insilmaril@0
   321
{
insilmaril@0
   322
	return style;
insilmaril@0
   323
}
insilmaril@0
   324
insilmaril@2
   325
void LinkableMapObj::setHideLinkUnselected(bool b)
insilmaril@2
   326
{
insilmaril@2
   327
	hideLinkUnselected=b;
insilmaril@2
   328
	setVisibility (visible);
insilmaril@2
   329
	updateLink();
insilmaril@2
   330
}
insilmaril@2
   331
insilmaril@2
   332
bool LinkableMapObj::getHideLinkUnselected()
insilmaril@2
   333
{
insilmaril@2
   334
	return hideLinkUnselected;
insilmaril@2
   335
}
insilmaril@2
   336
insilmaril@0
   337
void LinkableMapObj::setLinkPos(LinkPos lp)
insilmaril@0
   338
{
insilmaril@0
   339
	linkpos=lp;
insilmaril@0
   340
}
insilmaril@0
   341
insilmaril@0
   342
LinkPos LinkableMapObj::getLinkPos()
insilmaril@0
   343
{
insilmaril@0
   344
	return linkpos;
insilmaril@0
   345
}
insilmaril@0
   346
insilmaril@0
   347
insilmaril@0
   348
void LinkableMapObj::setLinkColor()
insilmaril@0
   349
{
insilmaril@0
   350
	// Overloaded in BranchObj and childs
insilmaril@0
   351
	// here only set default color
insilmaril@2
   352
	if (mapEditor)
insilmaril@2
   353
		setLinkColor (mapEditor->getDefLinkColor());
insilmaril@0
   354
}
insilmaril@0
   355
insilmaril@0
   356
void LinkableMapObj::setLinkColor(QColor col)
insilmaril@0
   357
{
insilmaril@0
   358
	linkcolor=col;
insilmaril@0
   359
    bottomline->setPen( QPen(linkcolor, 1) );
insilmaril@2
   360
	Q3CanvasLine *cl;
insilmaril@0
   361
	switch (style)
insilmaril@0
   362
	{
insilmaril@0
   363
		case StyleLine:
insilmaril@0
   364
			l->setPen( QPen(col,1));
insilmaril@0
   365
			break;	
insilmaril@0
   366
		case StyleParabel:	
insilmaril@0
   367
			for (cl=segment.first(); cl; cl=segment.next() )
insilmaril@0
   368
				cl->setPen( QPen(col,1));
insilmaril@0
   369
			break;
insilmaril@0
   370
		case StylePolyLine:
insilmaril@0
   371
			p->setBrush( QBrush(col));
insilmaril@0
   372
			l->setPen( QPen(col,1));
insilmaril@0
   373
			break;
insilmaril@0
   374
		case StylePolyParabel:	
insilmaril@0
   375
			p->setBrush( QBrush(col));
insilmaril@0
   376
			for (cl=segment.first(); cl; cl=segment.next() )
insilmaril@0
   377
				cl->setPen( QPen(col,1));
insilmaril@0
   378
			break;
insilmaril@0
   379
		default:
insilmaril@0
   380
			break;
insilmaril@0
   381
	} // switch (style)	
insilmaril@0
   382
}
insilmaril@0
   383
insilmaril@0
   384
QColor LinkableMapObj::getLinkColor()
insilmaril@0
   385
{
insilmaril@0
   386
	return linkcolor;
insilmaril@0
   387
}
insilmaril@0
   388
insilmaril@0
   389
FrameType LinkableMapObj::getFrameType()
insilmaril@0
   390
{
insilmaril@0
   391
	return frame->getFrameType();
insilmaril@0
   392
}
insilmaril@0
   393
insilmaril@0
   394
void LinkableMapObj::setFrameType(const FrameType &t)
insilmaril@0
   395
{
insilmaril@0
   396
	frame->setFrameType(t);
insilmaril@0
   397
	calcBBoxSize();
insilmaril@0
   398
	positionBBox();
insilmaril@0
   399
	requestReposition();
insilmaril@0
   400
}
insilmaril@0
   401
insilmaril@0
   402
void LinkableMapObj::setFrameType(const QString &t)
insilmaril@0
   403
{
insilmaril@0
   404
	frame->setFrameType(t);
insilmaril@0
   405
	calcBBoxSize();
insilmaril@0
   406
	positionBBox();
insilmaril@0
   407
	requestReposition();
insilmaril@0
   408
}
insilmaril@0
   409
insilmaril@0
   410
void LinkableMapObj::setVisibility (bool v)
insilmaril@0
   411
{
insilmaril@2
   412
	Q3CanvasLine* cl;
insilmaril@0
   413
	MapObj::setVisibility (v);
insilmaril@2
   414
	bool visnow=visible;
insilmaril@2
   415
insilmaril@2
   416
	// We can hide the link, while object is not selected
insilmaril@2
   417
	if (hideLinkUnselected && !selected)
insilmaril@2
   418
		visnow=false;
insilmaril@2
   419
insilmaril@2
   420
	if (visnow) 
insilmaril@0
   421
	{
insilmaril@0
   422
		bottomline->show();
insilmaril@2
   423
		switch (style)
insilmaril@0
   424
		{
insilmaril@2
   425
			case StyleLine:
insilmaril@2
   426
				if (l) l->show();
insilmaril@2
   427
				break;
insilmaril@2
   428
			case StyleParabel:	
insilmaril@2
   429
				for (cl=segment.first(); cl; cl=segment.next() )
insilmaril@2
   430
					cl->show();
insilmaril@2
   431
				break;	
insilmaril@2
   432
			case StylePolyLine:
insilmaril@2
   433
				if (p) p->show();
insilmaril@2
   434
				if (l) l->show();
insilmaril@2
   435
				break;
insilmaril@2
   436
			case StylePolyParabel:	
insilmaril@2
   437
				for (cl=segment.first(); cl; cl=segment.next() )
insilmaril@2
   438
					cl->show();
insilmaril@2
   439
				if (p) p->show();
insilmaril@2
   440
				break;
insilmaril@2
   441
			default:
insilmaril@2
   442
				break;
insilmaril@2
   443
		}
insilmaril@0
   444
	} else 
insilmaril@0
   445
	{
insilmaril@0
   446
		bottomline->hide();
insilmaril@2
   447
		switch (style)
insilmaril@0
   448
		{
insilmaril@2
   449
			case StyleLine:
insilmaril@2
   450
				if (l) l->hide();
insilmaril@2
   451
				break;
insilmaril@2
   452
			case StyleParabel:	
insilmaril@2
   453
				for (cl=segment.first(); cl; cl=segment.next() )
insilmaril@2
   454
					cl->hide();
insilmaril@2
   455
				break;	
insilmaril@2
   456
			case StylePolyLine:
insilmaril@2
   457
				if (p) p->hide();
insilmaril@2
   458
				if (l) l->hide();
insilmaril@2
   459
				break;
insilmaril@2
   460
			case StylePolyParabel:	
insilmaril@2
   461
				for (cl=segment.first(); cl; cl=segment.next() )
insilmaril@2
   462
					cl->hide();
insilmaril@2
   463
				if (p) p->hide();
insilmaril@2
   464
				break;
insilmaril@2
   465
			default:
insilmaril@2
   466
				break;
insilmaril@2
   467
		}
insilmaril@0
   468
	}	
insilmaril@0
   469
}
insilmaril@0
   470
insilmaril@0
   471
void LinkableMapObj::updateLink()
insilmaril@0
   472
{
insilmaril@0
   473
    // needs:
insilmaril@0
   474
    //	childPos of parent
insilmaril@0
   475
    //	orient   of parent
insilmaril@0
   476
    //	style
insilmaril@0
   477
    // 
insilmaril@0
   478
    // sets:
insilmaril@0
   479
    //	orientation
insilmaril@2
   480
    //	childPos	(by calling setDockPos())
insilmaril@2
   481
    //	parPos		(by calling setDockPos())
insilmaril@2
   482
	//  bottomlineY
insilmaril@0
   483
    //	drawing of the link itself
insilmaril@0
   484
insilmaril@0
   485
	// updateLink is called from move, but called from constructor we don't
insilmaril@0
   486
	// have parents yet...
insilmaril@0
   487
	if (style==StyleUndef) return;	
insilmaril@0
   488
insilmaril@0
   489
	if (frame->getFrameType() == NoFrame)
insilmaril@0
   490
		linkpos=LinkBottom;
insilmaril@0
   491
	else	
insilmaril@0
   492
		linkpos=LinkMiddle;
insilmaril@0
   493
	switch (linkpos)
insilmaril@0
   494
	{
insilmaril@0
   495
		case LinkMiddle:
insilmaril@2
   496
			bottomlineY=bbox.top()+bbox.height() /2;	// draw link to middle (of frame)
insilmaril@0
   497
			break;
insilmaril@0
   498
		default :
insilmaril@2
   499
			bottomlineY=bbox.bottom()-1;	// draw link to bottom of box
insilmaril@0
   500
			break;
insilmaril@0
   501
	}
insilmaril@0
   502
	
insilmaril@0
   503
    double p2x,p2y;								// Set P2 Before setting
insilmaril@0
   504
	if (!link2ParPos)
insilmaril@0
   505
	{
insilmaril@0
   506
		p2x=QPoint( parObj->getChildPos() ).x();	// P1, we have to look at
insilmaril@0
   507
		p2y=QPoint( parObj->getChildPos() ).y();	// orientation
insilmaril@0
   508
	} else	
insilmaril@0
   509
	{
insilmaril@0
   510
		p2x=QPoint( parObj->getParPos() ).x();	
insilmaril@0
   511
		p2y=QPoint( parObj->getParPos() ).y();
insilmaril@0
   512
	} 
insilmaril@0
   513
insilmaril@0
   514
	LinkOrient orientOld=orientation;
insilmaril@0
   515
insilmaril@0
   516
    // Set orientation, first look for orientation of parent
insilmaril@0
   517
    if (parObj->getOrientation() != OrientUndef ) 
insilmaril@0
   518
		// use the orientation of the parent:
insilmaril@0
   519
		orientation=parObj->getOrientation();
insilmaril@0
   520
    else
insilmaril@0
   521
    {
insilmaril@0
   522
		// calc orientation depending on position rel to mapCenter
insilmaril@0
   523
		if (absPos.x() < QPoint(parObj->getChildPos() ).x() )
insilmaril@0
   524
			orientation=OrientLeftOfCenter; 
insilmaril@0
   525
		else
insilmaril@0
   526
			orientation=OrientRightOfCenter;
insilmaril@0
   527
    }
insilmaril@0
   528
insilmaril@0
   529
	if ((orientation!=orientOld) && (orientOld!= OrientUndef))
insilmaril@0
   530
	{
insilmaril@0
   531
		// Orientation just changed. Reorient this subbranch, because move is called
insilmaril@0
   532
		// before updateLink => Position is still the old one, which could lead to 
insilmaril@0
   533
		// linking of subranch to itself => segfault
insilmaril@0
   534
		//
insilmaril@0
   535
		// Also possible: called in BranchObj::init(), then orientOld==OrientUndef,
insilmaril@0
   536
		// no need to reposition now
insilmaril@0
   537
		reposition();
insilmaril@0
   538
	}
insilmaril@0
   539
	
insilmaril@2
   540
	setDockPos();
insilmaril@0
   541
insilmaril@0
   542
	double p1x=parPos.x();	// Link is drawn from P1 to P2
insilmaril@0
   543
	double p1y=parPos.y();
insilmaril@0
   544
insilmaril@0
   545
	double vx=p2x - p1x;	// V=P2-P1
insilmaril@0
   546
	double vy=p2y - p1y;
insilmaril@0
   547
insilmaril@0
   548
	// Draw the horizontal line below heading (from ChildPos to ParPos)
insilmaril@2
   549
	bottomline->setPoints (qRound(childPos.x()),
insilmaril@2
   550
		qRound(childPos.y()),
insilmaril@2
   551
		qRound(p1x),
insilmaril@2
   552
		qRound(p1y) );
insilmaril@0
   553
insilmaril@0
   554
	double a;	// angle
insilmaril@0
   555
	if (vx > -0.000001 && vx < 0.000001)
insilmaril@0
   556
		a=M_PI_2;
insilmaril@0
   557
	else
insilmaril@0
   558
		a=atan( vy / vx );
insilmaril@0
   559
	// "turning point" for drawing polygonal links
insilmaril@2
   560
	QPoint tp (-qRound(sin (a)*thickness_start), qRound(cos (a)*thickness_start));	
insilmaril@0
   561
	
insilmaril@2
   562
	Q3CanvasLine *cl;
insilmaril@0
   563
insilmaril@0
   564
	int i;
insilmaril@0
   565
insilmaril@0
   566
    // Draw the link
insilmaril@0
   567
	switch (style)
insilmaril@0
   568
	{
insilmaril@0
   569
		case StyleLine:
insilmaril@2
   570
			l->setPoints( qRound (parPos.x()),
insilmaril@2
   571
				qRound(parPos.y()),
insilmaril@2
   572
				qRound(p2x),
insilmaril@2
   573
				qRound(p2y) );
insilmaril@0
   574
			break;	
insilmaril@0
   575
		case StyleParabel:	
insilmaril@0
   576
			parabel (pa0, p1x,p1y,p2x,p2y);
insilmaril@0
   577
			i=0;
insilmaril@0
   578
			for (cl=segment.first(); cl; cl=segment.next() )
insilmaril@0
   579
			{	
insilmaril@0
   580
				cl->setPoints( pa0.point(i).x(), pa0.point(i).y(),pa0.point(i+1).x(),pa0.point(i+1).y());
insilmaril@0
   581
				i++;
insilmaril@0
   582
			}
insilmaril@0
   583
			break;
insilmaril@0
   584
		case StylePolyLine:
insilmaril@2
   585
			pa0[0]=QPoint (qRound(p2x+tp.x()), qRound(p2y+tp.y()));
insilmaril@2
   586
			pa0[1]=QPoint (qRound(p2x-tp.x()), qRound(p2y-tp.y()));
insilmaril@2
   587
			pa0[2]=QPoint (qRound (parPos.x()), qRound(parPos.y()) );
insilmaril@0
   588
			p->setPoints (pa0);
insilmaril@0
   589
			// here too, draw line to avoid missing pixels
insilmaril@2
   590
			l->setPoints( qRound (parPos.x()),
insilmaril@2
   591
				qRound(parPos.y()),
insilmaril@2
   592
				qRound(p2x),
insilmaril@2
   593
				qRound(p2y) );
insilmaril@0
   594
			break;
insilmaril@0
   595
		case StylePolyParabel:	
insilmaril@0
   596
			parabel (pa1, p1x,p1y,p2x+tp.x(),p2y+tp.y());
insilmaril@0
   597
			parabel (pa2, p1x,p1y,p2x-tp.x(),p2y-tp.y());
insilmaril@0
   598
			for (i=0;i<=arcsegs;i++)
insilmaril@0
   599
			{
insilmaril@0
   600
				// Combine the arrays to a single one
insilmaril@0
   601
				pa0[i]=pa1[i];
insilmaril@0
   602
				pa0[i+arcsegs+1]=pa2[arcsegs-i];
insilmaril@0
   603
			}	
insilmaril@0
   604
			p->setPoints (pa0);
insilmaril@0
   605
			i=0;
insilmaril@0
   606
			for (cl=segment.first(); cl; cl=segment.next() )
insilmaril@0
   607
			{	
insilmaril@0
   608
				cl->setPoints( pa1.point(i).x(), pa1.point(i).y(),pa1.point(i+1).x(),pa1.point(i+1).y());
insilmaril@0
   609
				i++;
insilmaril@0
   610
			}
insilmaril@0
   611
			break;
insilmaril@0
   612
		default:
insilmaril@0
   613
			break;
insilmaril@0
   614
	} // switch (style)	
insilmaril@0
   615
}
insilmaril@0
   616
	
insilmaril@0
   617
LinkableMapObj* LinkableMapObj::getChildObj()
insilmaril@0
   618
{
insilmaril@0
   619
    return childObj;
insilmaril@0
   620
}
insilmaril@0
   621
insilmaril@0
   622
LinkableMapObj* LinkableMapObj::getParObj()
insilmaril@0
   623
{
insilmaril@0
   624
    return parObj;
insilmaril@0
   625
}
insilmaril@0
   626
insilmaril@2
   627
LinkableMapObj* LinkableMapObj::findObjBySelect (QString s)
insilmaril@2
   628
{
insilmaril@2
   629
	LinkableMapObj *lmo=this;
insilmaril@2
   630
	QString part;
insilmaril@2
   631
	QString typ;
insilmaril@2
   632
	QString num;
insilmaril@2
   633
	while (!s.isEmpty() )
insilmaril@2
   634
	{
insilmaril@2
   635
		part=s.section(",",0,0);
insilmaril@2
   636
		typ=part.left (3);
insilmaril@2
   637
		num=part.right(part.length() - 3);
insilmaril@2
   638
		if (typ=="mc:")
insilmaril@2
   639
		{
insilmaril@2
   640
			if (depth>0)
insilmaril@2
   641
				return false;	// in a subtree there is no center
insilmaril@2
   642
			else
insilmaril@2
   643
				break;
insilmaril@2
   644
		} else
insilmaril@2
   645
			if (typ=="bo:")
insilmaril@2
   646
				lmo=((BranchObj*)(lmo))->getBranchNum (num.toUInt());
insilmaril@2
   647
			else
insilmaril@2
   648
				if (typ=="fi:")
insilmaril@2
   649
					lmo=((BranchObj*)(lmo))->getFloatImageNum (num.toUInt());
insilmaril@2
   650
		if (!lmo) break;
insilmaril@2
   651
		
insilmaril@2
   652
		if (s.contains(","))
insilmaril@2
   653
			s=s.right(s.length() - part.length() -1 );
insilmaril@2
   654
		else	
insilmaril@2
   655
			break;
insilmaril@2
   656
	}
insilmaril@2
   657
	return lmo;
insilmaril@2
   658
}
insilmaril@2
   659
insilmaril@2
   660
void LinkableMapObj::setDockPos()
insilmaril@2
   661
{
insilmaril@2
   662
	cout <<"LMO::setDockPos()\n";
insilmaril@2
   663
}
insilmaril@2
   664
insilmaril@0
   665
QPoint LinkableMapObj::getChildPos()
insilmaril@0
   666
{
insilmaril@0
   667
    return childPos;
insilmaril@0
   668
}
insilmaril@0
   669
insilmaril@0
   670
QPoint LinkableMapObj::getParPos()
insilmaril@0
   671
{
insilmaril@0
   672
    return parPos;
insilmaril@0
   673
}
insilmaril@0
   674
insilmaril@2
   675
void LinkableMapObj::setUseOrientation (const bool &b)
insilmaril@2
   676
{	
insilmaril@2
   677
	if (useOrientation!=b)
insilmaril@2
   678
	{
insilmaril@2
   679
		useOrientation=b;
insilmaril@2
   680
		requestReposition();
insilmaril@2
   681
	}	
insilmaril@0
   682
}
insilmaril@0
   683
insilmaril@0
   684
LinkOrient LinkableMapObj::getOrientation()
insilmaril@0
   685
{
insilmaril@0
   686
    return orientation;
insilmaril@0
   687
}
insilmaril@0
   688
insilmaril@0
   689
int LinkableMapObj::getDepth()
insilmaril@0
   690
{
insilmaril@0
   691
    return depth;
insilmaril@0
   692
}
insilmaril@0
   693
insilmaril@0
   694
void LinkableMapObj::setMapEditor (MapEditor *me)
insilmaril@0
   695
{
insilmaril@0
   696
	mapEditor=me;
insilmaril@0
   697
}
insilmaril@0
   698
insilmaril@0
   699
MapEditor* LinkableMapObj::getMapEditor ()
insilmaril@0
   700
{
insilmaril@0
   701
	return mapEditor;
insilmaril@0
   702
}
insilmaril@0
   703
insilmaril@0
   704
QPoint LinkableMapObj::getRandPos()
insilmaril@0
   705
{
insilmaril@0
   706
	// Choose a random position with given distance to parent:
insilmaril@0
   707
	double a=rand()%360 * 2 * M_PI / 360;
insilmaril@0
   708
    return QPoint ( (int)( + 150*cos (a)),
insilmaril@0
   709
                    (int)( + 150*sin (a)));
insilmaril@0
   710
}
insilmaril@0
   711
insilmaril@0
   712
void LinkableMapObj::alignRelativeTo (QPoint ref)
insilmaril@0
   713
{
insilmaril@2
   714
	// FIXME testing, seems not to be used right now...
insilmaril@2
   715
	cout << "LMO::alignRelTo   ref="<<ref<<endl;
insilmaril@0
   716
}
insilmaril@0
   717
insilmaril@0
   718
void LinkableMapObj::reposition()
insilmaril@0
   719
{
insilmaril@0
   720
	if (depth==0)
insilmaril@0
   721
	{
insilmaril@0
   722
		// only calculate the sizes once. If the deepest LMO changes its height,
insilmaril@0
   723
		// all upper LMOs have to change, too.
insilmaril@0
   724
		calcBBoxSizeWithChilds();
insilmaril@0
   725
insilmaril@0
   726
	    alignRelativeTo ( QPoint (absPos.x(),
insilmaril@0
   727
							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
insilmaril@0
   728
	} else
insilmaril@0
   729
	{
insilmaril@0
   730
		// This is only important for moving branches:
insilmaril@0
   731
		// For editing a branch it isn't called...
insilmaril@0
   732
	    alignRelativeTo ( QPoint (absPos.x(),
insilmaril@0
   733
							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
insilmaril@0
   734
	}
insilmaril@0
   735
}
insilmaril@0
   736
insilmaril@0
   737
void LinkableMapObj::requestReposition()
insilmaril@0
   738
{
insilmaril@0
   739
	if (!repositionRequest)
insilmaril@0
   740
	{
insilmaril@0
   741
		// Pass on the request to parental objects, if this hasn't
insilmaril@0
   742
		// been done yet
insilmaril@0
   743
		repositionRequest=true;
insilmaril@0
   744
		if (parObj) parObj->requestReposition();
insilmaril@0
   745
	}
insilmaril@0
   746
}
insilmaril@0
   747
insilmaril@0
   748
void LinkableMapObj::forceReposition()
insilmaril@0
   749
{
insilmaril@0
   750
	// Sometimes a reposition has to be done immediatly: For example
insilmaril@0
   751
	// if the note editor flag changes, there is no user event in mapeditor
insilmaril@0
   752
	// which could collect requests for a reposition.
insilmaril@0
   753
	// Then we have to call forceReposition()
insilmaril@0
   754
	// But no rule without exception: While loading a map or undoing it,
insilmaril@0
   755
	// we want to block expensive repositioning, but just do it once at
insilmaril@0
   756
	// the end, thus check first:
insilmaril@0
   757
insilmaril@2
   758
	if (mapEditor->isRepositionBlocked()) return;
insilmaril@0
   759
	
insilmaril@0
   760
	// Pass on the request to parental objects, if this hasn't been done yet
insilmaril@0
   761
	
insilmaril@0
   762
	if (parObj) 
insilmaril@0
   763
		parObj->forceReposition(); 
insilmaril@0
   764
	else 
insilmaril@2
   765
		reposition(); 
insilmaril@2
   766
}
insilmaril@0
   767
insilmaril@0
   768
bool LinkableMapObj::repositionRequested()
insilmaril@0
   769
{
insilmaril@0
   770
	return repositionRequest;
insilmaril@0
   771
}
insilmaril@0
   772
insilmaril@0
   773
insilmaril@0
   774
void LinkableMapObj::setSelBox()
insilmaril@0
   775
{
insilmaril@2
   776
    selbox->setX (clickBox.x() );
insilmaril@2
   777
    selbox->setY (clickBox.y() );
insilmaril@2
   778
    selbox->setSize (clickBox.width(), clickBox.height() );
insilmaril@0
   779
}
insilmaril@0
   780
insilmaril@0
   781
void LinkableMapObj::select()
insilmaril@0
   782
{
insilmaril@0
   783
	setSelBox();
insilmaril@0
   784
    selected=true;
insilmaril@0
   785
    selbox->show();
insilmaril@2
   786
// FIXME not needed?	
insilmaril@2
   787
	setVisibility (visible);
insilmaril@0
   788
}
insilmaril@0
   789
insilmaril@0
   790
insilmaril@0
   791
void LinkableMapObj::unselect()
insilmaril@0
   792
{
insilmaril@0
   793
    selected=false;
insilmaril@0
   794
    selbox->hide();
insilmaril@2
   795
	// Maybe we have to hide the link:
insilmaril@2
   796
	setVisibility (visible);
insilmaril@0
   797
}
insilmaril@0
   798
insilmaril@2
   799
void LinkableMapObj::parabel (Q3PointArray &ya, double p1x, double p1y, double p2x, double p2y)
insilmaril@0
   800
insilmaril@0
   801
{
insilmaril@0
   802
	double vx=p2x - p1x;	// V=P2-P1
insilmaril@0
   803
	double vy=p2y - p1y;
insilmaril@0
   804
insilmaril@0
   805
	double dx;				// delta x during calculation of parabel
insilmaril@0
   806
	
insilmaril@0
   807
	double pnx;				// next point
insilmaril@0
   808
	double pny;
insilmaril@0
   809
	double m;
insilmaril@0
   810
insilmaril@0
   811
	if (vx > -0.0001 && vx < 0.0001)
insilmaril@0
   812
		m=0;
insilmaril@0
   813
	else	
insilmaril@0
   814
		m=(vy / (vx*vx));
insilmaril@0
   815
	dx=vx/(arcsegs);
insilmaril@0
   816
	int i;
insilmaril@2
   817
	ya.setPoint (0,QPoint (qRound(p1x),qRound(p1y)));
insilmaril@0
   818
	for (i=1;i<=arcsegs;i++)
insilmaril@0
   819
	{	
insilmaril@0
   820
		pnx=p1x+dx;
insilmaril@0
   821
		pny=m*(pnx-parPos.x())*(pnx-parPos.x())+parPos.y();
insilmaril@2
   822
		ya.setPoint (i,QPoint (qRound(pnx),qRound(pny)));
insilmaril@0
   823
		p1x=pnx;
insilmaril@0
   824
		p1y=pny;
insilmaril@0
   825
	}	
insilmaril@0
   826
}
insilmaril@0
   827
insilmaril@2
   828
QString LinkableMapObj::getLinkAttr ()
insilmaril@2
   829
{
insilmaril@2
   830
	if (hideLinkUnselected)
insilmaril@2
   831
		return attribut ("hideLink","true");
insilmaril@2
   832
	else
insilmaril@2
   833
		return attribut ("hideLink","false");
insilmaril@2
   834
	
insilmaril@2
   835
}