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