Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <svx/svdoedge.hxx>
31 : : #include <svx/xpool.hxx>
32 : : #include <svx/xpoly.hxx>
33 : : #include <svx/svdattrx.hxx>
34 : : #include <svx/svdpool.hxx>
35 : : #include <svx/svdmodel.hxx>
36 : : #include <svx/svdpage.hxx>
37 : : #include <svx/svdpagv.hxx>
38 : : #include <svx/svdview.hxx>
39 : : #include <svx/svddrag.hxx>
40 : : #include <svx/svddrgv.hxx>
41 : : #include "svddrgm1.hxx"
42 : : #include <svx/svdhdl.hxx>
43 : : #include <svx/svdtrans.hxx>
44 : : #include <svx/svdetc.hxx>
45 : : #include "svx/svdglob.hxx" // StringCache
46 : : #include "svx/svdstr.hrc" // the object's name
47 : : #include <svl/style.hxx>
48 : : #include <svl/smplhint.hxx>
49 : : #include <editeng/eeitem.hxx>
50 : : #include <svx/sdr/properties/connectorproperties.hxx>
51 : : #include <svx/sdr/contact/viewcontactofsdredgeobj.hxx>
52 : : #include <basegfx/polygon/b2dpolygon.hxx>
53 : : #include <basegfx/polygon/b2dpolygontools.hxx>
54 : : #include <basegfx/matrix/b2dhommatrix.hxx>
55 : : #include <svx/sdrhittesthelper.hxx>
56 : :
57 : : ////////////////////////////////////////////////////////////////////////////////////////////////////
58 : :
59 : 0 : SdrObjConnection::~SdrObjConnection()
60 : : {
61 : 0 : }
62 : :
63 : 0 : void SdrObjConnection::ResetVars()
64 : : {
65 : 0 : pObj=NULL;
66 : 0 : nConId=0;
67 : 0 : nXDist=0;
68 : 0 : nYDist=0;
69 : 0 : bBestConn=sal_True;
70 : 0 : bBestVertex=sal_True;
71 : 0 : bXDistOvr=sal_False;
72 : 0 : bYDistOvr=sal_False;
73 : 0 : bAutoVertex=sal_False;
74 : 0 : bAutoCorner=sal_False;
75 : 0 : }
76 : :
77 : 0 : bool SdrObjConnection::TakeGluePoint(SdrGluePoint& rGP, bool bSetAbsPos) const
78 : : {
79 : 0 : bool bRet = false;
80 [ # # ]: 0 : if (pObj!=NULL) { // one object has to be docked already!
81 [ # # ]: 0 : if (bAutoVertex) {
82 : 0 : rGP=pObj->GetVertexGluePoint(nConId);
83 : 0 : bRet = true;
84 [ # # ]: 0 : } else if (bAutoCorner) {
85 : 0 : rGP=pObj->GetCornerGluePoint(nConId);
86 : 0 : bRet = true;
87 : : } else {
88 : 0 : const SdrGluePointList* pGPL=pObj->GetGluePointList();
89 [ # # ]: 0 : if (pGPL!=NULL) {
90 : 0 : sal_uInt16 nNum=pGPL->FindGluePoint(nConId);
91 [ # # ]: 0 : if (nNum!=SDRGLUEPOINT_NOTFOUND) {
92 : 0 : rGP=(*pGPL)[nNum];
93 : 0 : bRet = true;
94 : : }
95 : : }
96 : : }
97 : : }
98 [ # # ][ # # ]: 0 : if (bRet && bSetAbsPos) {
99 [ # # ]: 0 : Point aPt(rGP.GetAbsolutePos(*pObj));
100 : 0 : aPt+=aObjOfs;
101 : 0 : rGP.SetPos(aPt);
102 : : }
103 : 0 : return bRet;
104 : : }
105 : :
106 : 0 : Point& SdrEdgeInfoRec::ImpGetLineVersatzPoint(SdrEdgeLineCode eLineCode)
107 : : {
108 [ # # # # : 0 : switch (eLineCode) {
# # ]
109 : 0 : case OBJ1LINE2 : return aObj1Line2;
110 : 0 : case OBJ1LINE3 : return aObj1Line3;
111 : 0 : case OBJ2LINE2 : return aObj2Line2;
112 : 0 : case OBJ2LINE3 : return aObj2Line3;
113 : 0 : case MIDDLELINE: return aMiddleLine;
114 : : } // switch
115 : 0 : return aMiddleLine;
116 : : }
117 : :
118 : 0 : sal_uInt16 SdrEdgeInfoRec::ImpGetPolyIdx(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const
119 : : {
120 [ # # # # : 0 : switch (eLineCode) {
# # ]
121 : 0 : case OBJ1LINE2 : return 1;
122 : 0 : case OBJ1LINE3 : return 2;
123 : 0 : case OBJ2LINE2 : return rXP.GetPointCount()-3;
124 : 0 : case OBJ2LINE3 : return rXP.GetPointCount()-4;
125 : 0 : case MIDDLELINE: return nMiddleLine;
126 : : } // switch
127 : 0 : return 0;
128 : : }
129 : :
130 : 0 : bool SdrEdgeInfoRec::ImpIsHorzLine(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const
131 : : {
132 : 0 : sal_uInt16 nIdx=ImpGetPolyIdx(eLineCode,rXP);
133 [ # # ][ # # ]: 0 : bool bHorz=nAngle1==0 || nAngle1==18000;
134 [ # # ][ # # ]: 0 : if (eLineCode==OBJ2LINE2 || eLineCode==OBJ2LINE3) {
135 : 0 : nIdx=rXP.GetPointCount()-nIdx;
136 [ # # ][ # # ]: 0 : bHorz=nAngle2==0 || nAngle2==18000;
137 : : }
138 [ # # ]: 0 : if ((nIdx & 1)==1) bHorz=!bHorz;
139 : 0 : return bHorz;
140 : : }
141 : :
142 : 0 : void SdrEdgeInfoRec::ImpSetLineVersatz(SdrEdgeLineCode eLineCode, const XPolygon& rXP, long nVal)
143 : : {
144 : 0 : Point& rPt=ImpGetLineVersatzPoint(eLineCode);
145 [ # # ]: 0 : if (ImpIsHorzLine(eLineCode,rXP)) rPt.Y()=nVal;
146 : 0 : else rPt.X()=nVal;
147 : 0 : }
148 : :
149 : 0 : long SdrEdgeInfoRec::ImpGetLineVersatz(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const
150 : : {
151 : 0 : const Point& rPt=ImpGetLineVersatzPoint(eLineCode);
152 [ # # ]: 0 : if (ImpIsHorzLine(eLineCode,rXP)) return rPt.Y();
153 : 0 : else return rPt.X();
154 : : }
155 : :
156 : : //////////////////////////////////////////////////////////////////////////////
157 : : // BaseProperties section
158 : :
159 : 0 : sdr::properties::BaseProperties* SdrEdgeObj::CreateObjectSpecificProperties()
160 : : {
161 [ # # ]: 0 : return new sdr::properties::ConnectorProperties(*this);
162 : : }
163 : :
164 : : //////////////////////////////////////////////////////////////////////////////
165 : : // DrawContact section
166 : :
167 : 0 : sdr::contact::ViewContact* SdrEdgeObj::CreateObjectSpecificViewContact()
168 : : {
169 [ # # ]: 0 : return new sdr::contact::ViewContactOfSdrEdgeObj(*this);
170 : : }
171 : :
172 : : //////////////////////////////////////////////////////////////////////////////
173 : :
174 [ # # ][ # # ]: 1577 : TYPEINIT1(SdrEdgeObj,SdrTextObj);
175 : :
176 : 0 : SdrEdgeObj::SdrEdgeObj()
177 : : : SdrTextObj(),
178 : : nNotifyingCount(0),
179 : : bEdgeTrackDirty(sal_False),
180 : : bEdgeTrackUserDefined(sal_False),
181 : : // Default is to allow default connects
182 : : mbSuppressDefaultConnect(sal_False),
183 [ # # ][ # # ]: 0 : mbBoundRectCalculationRunning(sal_False)
184 : : {
185 : 0 : bClosedObj=sal_False;
186 : 0 : bIsEdge=sal_True;
187 [ # # ][ # # ]: 0 : pEdgeTrack=new XPolygon;
188 : :
189 : 0 : }
190 : :
191 [ # # ][ # # ]: 0 : SdrEdgeObj::~SdrEdgeObj()
192 : : {
193 [ # # ]: 0 : DisconnectFromNode(sal_True);
194 [ # # ]: 0 : DisconnectFromNode(sal_False);
195 [ # # ][ # # ]: 0 : delete pEdgeTrack;
196 [ # # ]: 0 : }
197 : :
198 : 0 : void SdrEdgeObj::ImpSetAttrToEdgeInfo()
199 : : {
200 : 0 : const SfxItemSet& rSet = GetObjectItemSet();
201 : 0 : SdrEdgeKind eKind = ((SdrEdgeKindItem&)(rSet.Get(SDRATTR_EDGEKIND))).GetValue();
202 : 0 : sal_Int32 nVal1 = ((SdrEdgeLine1DeltaItem&)rSet.Get(SDRATTR_EDGELINE1DELTA)).GetValue();
203 : 0 : sal_Int32 nVal2 = ((SdrEdgeLine2DeltaItem&)rSet.Get(SDRATTR_EDGELINE2DELTA)).GetValue();
204 : 0 : sal_Int32 nVal3 = ((SdrEdgeLine3DeltaItem&)rSet.Get(SDRATTR_EDGELINE3DELTA)).GetValue();
205 : :
206 [ # # ][ # # ]: 0 : if(eKind == SDREDGE_ORTHOLINES || eKind == SDREDGE_BEZIER)
207 : : {
208 : 0 : sal_Int32 nVals[3] = { nVal1, nVal2, nVal3 };
209 : 0 : sal_uInt16 n = 0;
210 : :
211 [ # # ][ # # ]: 0 : if(aEdgeInfo.nObj1Lines >= 2 && n < 3)
212 : : {
213 [ # # ]: 0 : aEdgeInfo.ImpSetLineVersatz(OBJ1LINE2, *pEdgeTrack, nVals[n]);
214 : 0 : n++;
215 : : }
216 : :
217 [ # # ][ # # ]: 0 : if(aEdgeInfo.nObj1Lines >= 3 && n < 3)
218 : : {
219 [ # # ]: 0 : aEdgeInfo.ImpSetLineVersatz(OBJ1LINE3, *pEdgeTrack, nVals[n]);
220 : 0 : n++;
221 : : }
222 : :
223 [ # # ][ # # ]: 0 : if(aEdgeInfo.nMiddleLine != 0xFFFF && n < 3)
224 : : {
225 [ # # ]: 0 : aEdgeInfo.ImpSetLineVersatz(MIDDLELINE, *pEdgeTrack, nVals[n]);
226 : 0 : n++;
227 : : }
228 : :
229 [ # # ][ # # ]: 0 : if(aEdgeInfo.nObj2Lines >= 3 && n < 3)
230 : : {
231 [ # # ]: 0 : aEdgeInfo.ImpSetLineVersatz(OBJ2LINE3, *pEdgeTrack, nVals[n]);
232 : 0 : n++;
233 : : }
234 : :
235 [ # # ][ # # ]: 0 : if(aEdgeInfo.nObj2Lines >= 2 && n < 3)
236 : : {
237 [ # # ]: 0 : aEdgeInfo.ImpSetLineVersatz(OBJ2LINE2, *pEdgeTrack, nVals[n]);
238 : 0 : n++;
239 : 0 : }
240 : : }
241 [ # # ]: 0 : else if(eKind == SDREDGE_THREELINES)
242 : : {
243 [ # # ][ # # ]: 0 : sal_Bool bHor1 = aEdgeInfo.nAngle1 == 0 || aEdgeInfo.nAngle1 == 18000;
244 [ # # ][ # # ]: 0 : sal_Bool bHor2 = aEdgeInfo.nAngle2 == 0 || aEdgeInfo.nAngle2 == 18000;
245 : :
246 [ # # ]: 0 : if(bHor1)
247 : : {
248 : 0 : aEdgeInfo.aObj1Line2.X() = nVal1;
249 : : }
250 : : else
251 : : {
252 : 0 : aEdgeInfo.aObj1Line2.Y() = nVal1;
253 : : }
254 : :
255 [ # # ]: 0 : if(bHor2)
256 : : {
257 : 0 : aEdgeInfo.aObj2Line2.X() = nVal2;
258 : : }
259 : : else
260 : : {
261 : 0 : aEdgeInfo.aObj2Line2.Y() = nVal2;
262 : : }
263 : : }
264 : :
265 : 0 : ImpDirtyEdgeTrack();
266 : 0 : }
267 : :
268 : 0 : void SdrEdgeObj::ImpSetEdgeInfoToAttr()
269 : : {
270 [ # # ]: 0 : const SfxItemSet& rSet = GetObjectItemSet();
271 [ # # ]: 0 : SdrEdgeKind eKind = ((SdrEdgeKindItem&)(rSet.Get(SDRATTR_EDGEKIND))).GetValue();
272 [ # # ]: 0 : sal_Int32 nValAnz = ((SdrEdgeLineDeltaAnzItem&)rSet.Get(SDRATTR_EDGELINEDELTAANZ)).GetValue();
273 [ # # ]: 0 : sal_Int32 nVal1 = ((SdrEdgeLine1DeltaItem&)rSet.Get(SDRATTR_EDGELINE1DELTA)).GetValue();
274 [ # # ]: 0 : sal_Int32 nVal2 = ((SdrEdgeLine2DeltaItem&)rSet.Get(SDRATTR_EDGELINE2DELTA)).GetValue();
275 [ # # ]: 0 : sal_Int32 nVal3 = ((SdrEdgeLine3DeltaItem&)rSet.Get(SDRATTR_EDGELINE3DELTA)).GetValue();
276 : 0 : sal_Int32 nVals[3] = { nVal1, nVal2, nVal3 };
277 : 0 : sal_uInt16 n = 0;
278 : :
279 [ # # ][ # # ]: 0 : if(eKind == SDREDGE_ORTHOLINES || eKind == SDREDGE_BEZIER)
280 : : {
281 [ # # ][ # # ]: 0 : if(aEdgeInfo.nObj1Lines >= 2 && n < 3)
282 : : {
283 [ # # ]: 0 : nVals[n] = aEdgeInfo.ImpGetLineVersatz(OBJ1LINE2, *pEdgeTrack);
284 : 0 : n++;
285 : : }
286 : :
287 [ # # ][ # # ]: 0 : if(aEdgeInfo.nObj1Lines >= 3 && n < 3)
288 : : {
289 [ # # ]: 0 : nVals[n] = aEdgeInfo.ImpGetLineVersatz(OBJ1LINE3, *pEdgeTrack);
290 : 0 : n++;
291 : : }
292 : :
293 [ # # ][ # # ]: 0 : if(aEdgeInfo.nMiddleLine != 0xFFFF && n < 3)
294 : : {
295 [ # # ]: 0 : nVals[n] = aEdgeInfo.ImpGetLineVersatz(MIDDLELINE, *pEdgeTrack);
296 : 0 : n++;
297 : : }
298 : :
299 [ # # ][ # # ]: 0 : if(aEdgeInfo.nObj2Lines >= 3 && n < 3)
300 : : {
301 [ # # ]: 0 : nVals[n] = aEdgeInfo.ImpGetLineVersatz(OBJ2LINE3, *pEdgeTrack);
302 : 0 : n++;
303 : : }
304 : :
305 [ # # ][ # # ]: 0 : if(aEdgeInfo.nObj2Lines >= 2 && n < 3)
306 : : {
307 [ # # ]: 0 : nVals[n] = aEdgeInfo.ImpGetLineVersatz(OBJ2LINE2, *pEdgeTrack);
308 : 0 : n++;
309 : : }
310 : : }
311 [ # # ]: 0 : else if(eKind == SDREDGE_THREELINES)
312 : : {
313 [ # # ][ # # ]: 0 : sal_Bool bHor1 = aEdgeInfo.nAngle1 == 0 || aEdgeInfo.nAngle1 == 18000;
314 [ # # ][ # # ]: 0 : sal_Bool bHor2 = aEdgeInfo.nAngle2 == 0 || aEdgeInfo.nAngle2 == 18000;
315 : :
316 : 0 : n = 2;
317 [ # # ]: 0 : nVals[0] = bHor1 ? aEdgeInfo.aObj1Line2.X() : aEdgeInfo.aObj1Line2.Y();
318 [ # # ]: 0 : nVals[1] = bHor2 ? aEdgeInfo.aObj2Line2.X() : aEdgeInfo.aObj2Line2.Y();
319 : : }
320 : :
321 [ # # ][ # # ]: 0 : if(n != nValAnz || nVals[0] != nVal1 || nVals[1] != nVal2 || nVals[2] != nVal3)
[ # # ][ # # ]
322 : : {
323 : : // Here no more notifying is necessary, just local changes are OK.
324 [ # # ]: 0 : if(n != nValAnz)
325 : : {
326 [ # # ][ # # ]: 0 : GetProperties().SetObjectItemDirect(SdrEdgeLineDeltaAnzItem(n));
[ # # ][ # # ]
327 : : }
328 : :
329 [ # # ]: 0 : if(nVals[0] != nVal1)
330 : : {
331 [ # # ][ # # ]: 0 : GetProperties().SetObjectItemDirect(SdrEdgeLine1DeltaItem(nVals[0]));
[ # # ][ # # ]
332 : : }
333 : :
334 [ # # ]: 0 : if(nVals[1] != nVal2)
335 : : {
336 [ # # ][ # # ]: 0 : GetProperties().SetObjectItemDirect(SdrEdgeLine2DeltaItem(nVals[1]));
[ # # ][ # # ]
337 : : }
338 : :
339 [ # # ]: 0 : if(nVals[2] != nVal3)
340 : : {
341 [ # # ][ # # ]: 0 : GetProperties().SetObjectItemDirect(SdrEdgeLine3DeltaItem(nVals[2]));
[ # # ][ # # ]
342 : : }
343 : :
344 [ # # ]: 0 : if(n < 3)
345 : : {
346 [ # # ][ # # ]: 0 : GetProperties().ClearObjectItemDirect(SDRATTR_EDGELINE3DELTA);
347 : : }
348 : :
349 [ # # ]: 0 : if(n < 2)
350 : : {
351 [ # # ][ # # ]: 0 : GetProperties().ClearObjectItemDirect(SDRATTR_EDGELINE2DELTA);
352 : : }
353 : :
354 [ # # ]: 0 : if(n < 1)
355 : : {
356 [ # # ][ # # ]: 0 : GetProperties().ClearObjectItemDirect(SDRATTR_EDGELINE1DELTA);
357 : : }
358 : : }
359 : 0 : }
360 : :
361 : 0 : void SdrEdgeObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
362 : : {
363 : 0 : rInfo.bRotateFreeAllowed=sal_False;
364 : 0 : rInfo.bRotate90Allowed =sal_False;
365 : 0 : rInfo.bMirrorFreeAllowed=sal_False;
366 : 0 : rInfo.bMirror45Allowed =sal_False;
367 : 0 : rInfo.bMirror90Allowed =sal_False;
368 : 0 : rInfo.bTransparenceAllowed = sal_False;
369 : 0 : rInfo.bGradientAllowed = sal_False;
370 : 0 : rInfo.bShearAllowed =sal_False;
371 : 0 : rInfo.bEdgeRadiusAllowed=sal_False;
372 [ # # ][ # # ]: 0 : bool bCanConv=!HasText() || ImpCanConvTextToCurve();
373 : 0 : rInfo.bCanConvToPath=bCanConv;
374 : 0 : rInfo.bCanConvToPoly=bCanConv;
375 [ # # ][ # # ]: 0 : rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
376 : 0 : }
377 : :
378 : 0 : sal_uInt16 SdrEdgeObj::GetObjIdentifier() const
379 : : {
380 : 0 : return sal_uInt16(OBJ_EDGE);
381 : : }
382 : :
383 : 0 : const Rectangle& SdrEdgeObj::GetCurrentBoundRect() const
384 : : {
385 [ # # ]: 0 : if(bEdgeTrackDirty)
386 : : {
387 : 0 : ((SdrEdgeObj*)this)->ImpRecalcEdgeTrack();
388 : : }
389 : :
390 : 0 : return SdrTextObj::GetCurrentBoundRect();
391 : : }
392 : :
393 : 0 : const Rectangle& SdrEdgeObj::GetSnapRect() const
394 : : {
395 [ # # ]: 0 : if(bEdgeTrackDirty)
396 : : {
397 : 0 : ((SdrEdgeObj*)this)->ImpRecalcEdgeTrack();
398 : : }
399 : :
400 : 0 : return SdrTextObj::GetSnapRect();
401 : : }
402 : :
403 : 0 : void SdrEdgeObj::RecalcSnapRect()
404 : : {
405 : 0 : maSnapRect=pEdgeTrack->GetBoundRect();
406 : 0 : }
407 : :
408 : 0 : void SdrEdgeObj::TakeUnrotatedSnapRect(Rectangle& rRect) const
409 : : {
410 : 0 : rRect=GetSnapRect();
411 : 0 : }
412 : :
413 : 0 : bool SdrEdgeObj::IsNode() const
414 : : {
415 : 0 : return true;
416 : : }
417 : :
418 : 0 : SdrGluePoint SdrEdgeObj::GetVertexGluePoint(sal_uInt16 nNum) const
419 : : {
420 : 0 : Point aPt;
421 [ # # ]: 0 : sal_uInt16 nPntAnz=pEdgeTrack->GetPointCount();
422 [ # # ]: 0 : if (nPntAnz>0)
423 : : {
424 [ # # ][ # # ]: 0 : Point aOfs = GetSnapRect().Center();
425 [ # # ][ # # ]: 0 : if (nNum==2 && GetConnectedNode(sal_True)==NULL) aPt=(*pEdgeTrack)[0];
[ # # ][ # # ]
[ # # ]
426 [ # # ][ # # ]: 0 : else if (nNum==3 && GetConnectedNode(sal_False)==NULL) aPt=(*pEdgeTrack)[nPntAnz-1];
[ # # ][ # # ]
[ # # ]
427 : : else {
428 [ # # ]: 0 : if ((nPntAnz & 1) ==1) {
429 [ # # ]: 0 : aPt=(*pEdgeTrack)[nPntAnz/2];
430 : : } else {
431 [ # # ]: 0 : Point aPt1((*pEdgeTrack)[nPntAnz/2-1]);
432 [ # # ]: 0 : Point aPt2((*pEdgeTrack)[nPntAnz/2]);
433 : 0 : aPt1+=aPt2;
434 : 0 : aPt1.X()/=2;
435 : 0 : aPt1.Y()/=2;
436 : 0 : aPt=aPt1;
437 : : }
438 : : }
439 : 0 : aPt-=aOfs;
440 : : }
441 : 0 : SdrGluePoint aGP(aPt);
442 : 0 : aGP.SetPercent(sal_False);
443 : 0 : return aGP;
444 : : }
445 : :
446 : 0 : SdrGluePoint SdrEdgeObj::GetCornerGluePoint(sal_uInt16 nNum) const
447 : : {
448 : 0 : return GetVertexGluePoint(nNum);
449 : : }
450 : :
451 : 0 : const SdrGluePointList* SdrEdgeObj::GetGluePointList() const
452 : : {
453 : 0 : return NULL; // no user defined glue points for connectors
454 : : }
455 : :
456 : 0 : SdrGluePointList* SdrEdgeObj::ForceGluePointList()
457 : : {
458 : 0 : return NULL; // no user defined glue points for connectors
459 : : }
460 : :
461 : 0 : bool SdrEdgeObj::IsEdge() const
462 : : {
463 : 0 : return true;
464 : : }
465 : :
466 : 0 : void SdrEdgeObj::ConnectToNode(bool bTail1, SdrObject* pObj)
467 : : {
468 : 0 : SdrObjConnection& rCon=GetConnection(bTail1);
469 : 0 : DisconnectFromNode(bTail1);
470 [ # # ]: 0 : if (pObj!=NULL) {
471 : 0 : pObj->AddListener(*this);
472 : 0 : rCon.pObj=pObj;
473 : 0 : ImpDirtyEdgeTrack();
474 : : }
475 : 0 : }
476 : :
477 : 0 : void SdrEdgeObj::DisconnectFromNode(bool bTail1)
478 : : {
479 : 0 : SdrObjConnection& rCon=GetConnection(bTail1);
480 [ # # ]: 0 : if (rCon.pObj!=NULL) {
481 : 0 : rCon.pObj->RemoveListener(*this);
482 : 0 : rCon.pObj=NULL;
483 : : }
484 : 0 : }
485 : :
486 : 0 : SdrObject* SdrEdgeObj::GetConnectedNode(bool bTail1) const
487 : : {
488 : 0 : SdrObject* pObj=GetConnection(bTail1).pObj;
489 [ # # ][ # # ]: 0 : if (pObj!=NULL && (pObj->GetPage()!=pPage || !pObj->IsInserted())) pObj=NULL;
[ # # ][ # # ]
490 : 0 : return pObj;
491 : : }
492 : :
493 : 0 : bool SdrEdgeObj::CheckNodeConnection(bool bTail1) const
494 : : {
495 : 0 : bool bRet = false;
496 : 0 : const SdrObjConnection& rCon=GetConnection(bTail1);
497 : 0 : sal_uInt16 nPtAnz=pEdgeTrack->GetPointCount();
498 [ # # ][ # # ]: 0 : if (rCon.pObj!=NULL && rCon.pObj->GetPage()==pPage && nPtAnz!=0) {
[ # # ][ # # ]
499 [ # # ]: 0 : const SdrGluePointList* pGPL=rCon.pObj->GetGluePointList();
500 [ # # ]: 0 : sal_uInt16 nConAnz=pGPL==NULL ? 0 : pGPL->GetCount();
501 : 0 : sal_uInt16 nGesAnz=nConAnz+8;
502 [ # # ][ # # ]: 0 : Point aTail(bTail1 ? (*pEdgeTrack)[0] : (*pEdgeTrack)[sal_uInt16(nPtAnz-1)]);
[ # # ]
503 [ # # ][ # # ]: 0 : for (sal_uInt16 i=0; i<nGesAnz && !bRet; i++) {
[ # # ]
504 [ # # ]: 0 : if (i<nConAnz) { // UserDefined
505 [ # # ][ # # ]: 0 : bRet=aTail==(*pGPL)[i].GetAbsolutePos(*rCon.pObj);
506 [ # # ]: 0 : } else if (i<nConAnz+4) { // Vertex
507 [ # # ]: 0 : SdrGluePoint aPt(rCon.pObj->GetVertexGluePoint(i-nConAnz));
508 [ # # ]: 0 : bRet=aTail==aPt.GetAbsolutePos(*rCon.pObj);
509 : : } else { // Corner
510 [ # # ]: 0 : SdrGluePoint aPt(rCon.pObj->GetCornerGluePoint(i-nConAnz-4));
511 [ # # ]: 0 : bRet=aTail==aPt.GetAbsolutePos(*rCon.pObj);
512 : : }
513 : : }
514 : : }
515 : 0 : return bRet;
516 : : }
517 : :
518 : 0 : void SdrEdgeObj::ImpSetTailPoint(bool bTail1, const Point& rPt)
519 : : {
520 : 0 : sal_uInt16 nPtAnz=pEdgeTrack->GetPointCount();
521 [ # # ]: 0 : if (nPtAnz==0) {
522 : 0 : (*pEdgeTrack)[0]=rPt;
523 : 0 : (*pEdgeTrack)[1]=rPt;
524 [ # # ]: 0 : } else if (nPtAnz==1) {
525 [ # # ]: 0 : if (!bTail1) (*pEdgeTrack)[1]=rPt;
526 : 0 : else { (*pEdgeTrack)[1]=(*pEdgeTrack)[0]; (*pEdgeTrack)[0]=rPt; }
527 : : } else {
528 [ # # ]: 0 : if (!bTail1) (*pEdgeTrack)[sal_uInt16(nPtAnz-1)]=rPt;
529 : 0 : else (*pEdgeTrack)[0]=rPt;
530 : : }
531 : 0 : ImpRecalcEdgeTrack();
532 : 0 : SetRectsDirty();
533 : 0 : }
534 : :
535 : 0 : void SdrEdgeObj::ImpDirtyEdgeTrack()
536 : : {
537 [ # # ][ # # ]: 0 : if ( !bEdgeTrackUserDefined || !(GetModel() && GetModel()->isLocked()) )
[ # # ][ # # ]
538 : 0 : bEdgeTrackDirty = sal_True;
539 : 0 : }
540 : :
541 : 0 : void SdrEdgeObj::ImpUndirtyEdgeTrack()
542 : : {
543 [ # # ][ # # ]: 0 : if (bEdgeTrackDirty && (GetModel() && GetModel()->isLocked()) ) {
[ # # ][ # # ]
544 : 0 : ImpRecalcEdgeTrack();
545 : : }
546 : 0 : }
547 : :
548 : 0 : void SdrEdgeObj::ImpRecalcEdgeTrack()
549 : : {
550 [ # # ][ # # ]: 0 : if ( bEdgeTrackUserDefined && (GetModel() && GetModel()->isLocked()) )
[ # # ][ # # ]
551 : 0 : return;
552 : :
553 [ # # ]: 0 : if(IsBoundRectCalculationRunning())
554 : : {
555 : : // This object is involved into another ImpRecalcEdgeTrack() call
556 : : // from another SdrEdgeObj. Do not calculate again to avoid loop.
557 : : // Also, do not change bEdgeTrackDirty so that it gets recalculated
558 : : // later at the first non-looping call.
559 : : }
560 : : // #i43068#
561 [ # # ][ # # ]: 0 : else if(GetModel() && GetModel()->isLocked())
[ # # ]
562 : : {
563 : : // avoid re-layout during imports/API call sequences
564 : : // #i45294# but calculate EdgeTrack and secure properties there
565 : 0 : ((SdrEdgeObj*)this)->mbBoundRectCalculationRunning = sal_True;
566 [ # # ]: 0 : *pEdgeTrack=ImpCalcEdgeTrack(*pEdgeTrack,aCon1,aCon2,&aEdgeInfo);
567 : 0 : ImpSetAttrToEdgeInfo();
568 : 0 : bEdgeTrackDirty=sal_False;
569 : 0 : ((SdrEdgeObj*)this)->mbBoundRectCalculationRunning = sal_False;
570 : : }
571 : : else
572 : : {
573 : : // To not run in a depth loop, use a coloring algorithm on
574 : : // SdrEdgeObj BoundRect calculations
575 : 0 : ((SdrEdgeObj*)this)->mbBoundRectCalculationRunning = sal_True;
576 : :
577 [ # # ][ # # ]: 0 : Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
[ # # ]
578 [ # # ]: 0 : SetRectsDirty();
579 [ # # ][ # # ]: 0 : *pEdgeTrack=ImpCalcEdgeTrack(*pEdgeTrack,aCon1,aCon2,&aEdgeInfo);
[ # # ]
580 [ # # ]: 0 : ImpSetEdgeInfoToAttr(); // copy values from aEdgeInfo into the pool
581 : 0 : bEdgeTrackDirty=sal_False;
582 : :
583 : : // Only redraw here, no object change
584 [ # # ]: 0 : ActionChanged();
585 : :
586 [ # # ]: 0 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
587 : :
588 : 0 : ((SdrEdgeObj*)this)->mbBoundRectCalculationRunning = sal_False;
589 : : }
590 : : }
591 : :
592 : 0 : sal_uInt16 SdrEdgeObj::ImpCalcEscAngle(SdrObject* pObj, const Point& rPt) const
593 : : {
594 [ # # ]: 0 : if (pObj==NULL) return SDRESC_ALL;
595 [ # # ]: 0 : Rectangle aR(pObj->GetSnapRect());
596 : 0 : long dxl=rPt.X()-aR.Left();
597 : 0 : long dyo=rPt.Y()-aR.Top();
598 : 0 : long dxr=aR.Right()-rPt.X();
599 : 0 : long dyu=aR.Bottom()-rPt.Y();
600 : 0 : bool bxMitt=Abs(dxl-dxr)<2;
601 : 0 : bool byMitt=Abs(dyo-dyu)<2;
602 : 0 : long dx=Min(dxl,dxr);
603 : 0 : long dy=Min(dyo,dyu);
604 : 0 : bool bDiag=Abs(dx-dy)<2;
605 [ # # ][ # # ]: 0 : if (bxMitt && byMitt) return SDRESC_ALL; // in the center
606 [ # # ]: 0 : if (bDiag) { // diagonally
607 : 0 : sal_uInt16 nRet=0;
608 [ # # ]: 0 : if (byMitt) nRet|=SDRESC_VERT;
609 [ # # ]: 0 : if (bxMitt) nRet|=SDRESC_HORZ;
610 [ # # ]: 0 : if (dxl<dxr) { // left
611 [ # # ]: 0 : if (dyo<dyu) nRet|=SDRESC_LEFT | SDRESC_TOP;
612 : 0 : else nRet|=SDRESC_LEFT | SDRESC_BOTTOM;
613 : : } else { // right
614 [ # # ]: 0 : if (dyo<dyu) nRet|=SDRESC_RIGHT | SDRESC_TOP;
615 : 0 : else nRet|=SDRESC_RIGHT | SDRESC_BOTTOM;
616 : : }
617 : 0 : return nRet;
618 : : }
619 [ # # ]: 0 : if (dx<dy) { // horizontal
620 [ # # ]: 0 : if (bxMitt) return SDRESC_HORZ;
621 [ # # ]: 0 : if (dxl<dxr) return SDRESC_LEFT;
622 : 0 : else return SDRESC_RIGHT;
623 : : } else { // vertical
624 [ # # ]: 0 : if (byMitt) return SDRESC_VERT;
625 [ # # ]: 0 : if (dyo<dyu) return SDRESC_TOP;
626 : 0 : else return SDRESC_BOTTOM;
627 : : }
628 : : }
629 : :
630 : 0 : XPolygon SdrEdgeObj::ImpCalcObjToCenter(const Point& rStPt, long nEscAngle, const Rectangle& rRect, const Point& rMeeting) const
631 : : {
632 [ # # ]: 0 : XPolygon aXP;
633 [ # # ]: 0 : aXP.Insert(XPOLY_APPEND,rStPt,XPOLY_NORMAL);
634 : 0 : bool bRts=nEscAngle==0;
635 : 0 : bool bObn=nEscAngle==9000;
636 : 0 : bool bLks=nEscAngle==18000;
637 : 0 : bool bUnt=nEscAngle==27000;
638 : :
639 : 0 : Point aP1(rStPt); // mandatory difference first,...
640 [ # # ]: 0 : if (bLks) aP1.X()=rRect.Left();
641 [ # # ]: 0 : if (bRts) aP1.X()=rRect.Right();
642 [ # # ]: 0 : if (bObn) aP1.Y()=rRect.Top();
643 [ # # ]: 0 : if (bUnt) aP1.Y()=rRect.Bottom();
644 : :
645 : 0 : Point aP2(aP1); // ...now increase to Meeting height, if necessary
646 [ # # ][ # # ]: 0 : if (bLks && rMeeting.X()<=aP2.X()) aP2.X()=rMeeting.X();
[ # # ]
647 [ # # ][ # # ]: 0 : if (bRts && rMeeting.X()>=aP2.X()) aP2.X()=rMeeting.X();
[ # # ]
648 [ # # ][ # # ]: 0 : if (bObn && rMeeting.Y()<=aP2.Y()) aP2.Y()=rMeeting.Y();
[ # # ]
649 [ # # ][ # # ]: 0 : if (bUnt && rMeeting.Y()>=aP2.Y()) aP2.Y()=rMeeting.Y();
[ # # ]
650 [ # # ]: 0 : aXP.Insert(XPOLY_APPEND,aP2,XPOLY_NORMAL);
651 : :
652 : 0 : Point aP3(aP2);
653 [ # # ][ # # ]: 0 : if ((bLks && rMeeting.X()>aP2.X()) || (bRts && rMeeting.X()<aP2.X())) { // around
[ # # ][ # # ]
[ # # ]
654 [ # # ]: 0 : if (rMeeting.Y()<aP2.Y()) {
655 : 0 : aP3.Y()=rRect.Top();
656 [ # # ]: 0 : if (rMeeting.Y()<aP3.Y()) aP3.Y()=rMeeting.Y();
657 : : } else {
658 : 0 : aP3.Y()=rRect.Bottom();
659 [ # # ]: 0 : if (rMeeting.Y()>aP3.Y()) aP3.Y()=rMeeting.Y();
660 : : }
661 [ # # ]: 0 : aXP.Insert(XPOLY_APPEND,aP3,XPOLY_NORMAL);
662 [ # # ]: 0 : if (aP3.Y()!=rMeeting.Y()) {
663 : 0 : aP3.X()=rMeeting.X();
664 [ # # ]: 0 : aXP.Insert(XPOLY_APPEND,aP3,XPOLY_NORMAL);
665 : : }
666 : : }
667 [ # # ][ # # ]: 0 : if ((bObn && rMeeting.Y()>aP2.Y()) || (bUnt && rMeeting.Y()<aP2.Y())) { // around
[ # # ][ # # ]
[ # # ]
668 [ # # ]: 0 : if (rMeeting.X()<aP2.X()) {
669 : 0 : aP3.X()=rRect.Left();
670 [ # # ]: 0 : if (rMeeting.X()<aP3.X()) aP3.X()=rMeeting.X();
671 : : } else {
672 : 0 : aP3.X()=rRect.Right();
673 [ # # ]: 0 : if (rMeeting.X()>aP3.X()) aP3.X()=rMeeting.X();
674 : : }
675 [ # # ]: 0 : aXP.Insert(XPOLY_APPEND,aP3,XPOLY_NORMAL);
676 [ # # ]: 0 : if (aP3.X()!=rMeeting.X()) {
677 : 0 : aP3.Y()=rMeeting.Y();
678 [ # # ]: 0 : aXP.Insert(XPOLY_APPEND,aP3,XPOLY_NORMAL);
679 : : }
680 : : }
681 : : #ifdef DBG_UTIL
682 : : if (aXP.GetPointCount()>4) {
683 : : OSL_FAIL("SdrEdgeObj::ImpCalcObjToCenter(): Polygon has more than 4 points!");
684 : : }
685 : : #endif
686 : 0 : return aXP;
687 : : }
688 : :
689 : 0 : XPolygon SdrEdgeObj::ImpCalcEdgeTrack(const XPolygon& rTrack0, SdrObjConnection& rCon1, SdrObjConnection& rCon2, SdrEdgeInfoRec* pInfo) const
690 : : {
691 : 0 : Point aPt1,aPt2;
692 : 0 : SdrGluePoint aGP1,aGP2;
693 : 0 : sal_uInt16 nEsc1=SDRESC_ALL,nEsc2=SDRESC_ALL;
694 [ # # ]: 0 : Rectangle aBoundRect1;
695 [ # # ]: 0 : Rectangle aBoundRect2;
696 [ # # ]: 0 : Rectangle aBewareRect1;
697 [ # # ]: 0 : Rectangle aBewareRect2;
698 : : // first, get the old corner points
699 [ # # ][ # # ]: 0 : if (rTrack0.GetPointCount()!=0) {
700 [ # # ]: 0 : aPt1=rTrack0[0];
701 [ # # ]: 0 : sal_uInt16 nSiz=rTrack0.GetPointCount();
702 : 0 : nSiz--;
703 [ # # ]: 0 : aPt2=rTrack0[nSiz];
704 : : } else {
705 [ # # ][ # # ]: 0 : if (!aOutRect.IsEmpty()) {
706 : 0 : aPt1=aOutRect.TopLeft();
707 [ # # ]: 0 : aPt2=aOutRect.BottomRight();
708 : : }
709 : : }
710 [ # # ][ # # ]: 0 : bool bCon1=rCon1.pObj!=NULL && rCon1.pObj->GetPage()==pPage && rCon1.pObj->IsInserted();
[ # # ][ # # ]
[ # # ]
711 [ # # ][ # # ]: 0 : bool bCon2=rCon2.pObj!=NULL && rCon2.pObj->GetPage()==pPage && rCon2.pObj->IsInserted();
[ # # ][ # # ]
[ # # ]
712 [ # # ]: 0 : const SfxItemSet& rSet = GetObjectItemSet();
713 : :
714 [ # # ]: 0 : if (bCon1) {
715 [ # # ]: 0 : if (rCon1.pObj==(SdrObject*)this)
716 : : {
717 : : // check, just in case
718 : 0 : aBoundRect1=aOutRect;
719 : : }
720 : : else
721 : : {
722 [ # # ]: 0 : aBoundRect1 = rCon1.pObj->GetCurrentBoundRect();
723 : : }
724 [ # # ]: 0 : aBoundRect1.Move(rCon1.aObjOfs.X(),rCon1.aObjOfs.Y());
725 : 0 : aBewareRect1=aBoundRect1;
726 : :
727 [ # # ]: 0 : sal_Int32 nH = ((SdrEdgeNode1HorzDistItem&)rSet.Get(SDRATTR_EDGENODE1HORZDIST)).GetValue();
728 [ # # ]: 0 : sal_Int32 nV = ((SdrEdgeNode1VertDistItem&)rSet.Get(SDRATTR_EDGENODE1VERTDIST)).GetValue();
729 : :
730 : 0 : aBewareRect1.Left()-=nH;
731 : 0 : aBewareRect1.Right()+=nH;
732 : 0 : aBewareRect1.Top()-=nV;
733 : 0 : aBewareRect1.Bottom()+=nV;
734 : : } else {
735 [ # # ]: 0 : aBoundRect1=Rectangle(aPt1,aPt1);
736 [ # # ]: 0 : aBoundRect1.Move(rCon1.aObjOfs.X(),rCon1.aObjOfs.Y());
737 : 0 : aBewareRect1=aBoundRect1;
738 : : }
739 [ # # ]: 0 : if (bCon2) {
740 [ # # ]: 0 : if (rCon2.pObj==(SdrObject*)this) { // check, just in case
741 : 0 : aBoundRect2=aOutRect;
742 : : }
743 : : else
744 : : {
745 [ # # ]: 0 : aBoundRect2 = rCon2.pObj->GetCurrentBoundRect();
746 : : }
747 [ # # ]: 0 : aBoundRect2.Move(rCon2.aObjOfs.X(),rCon2.aObjOfs.Y());
748 : 0 : aBewareRect2=aBoundRect2;
749 : :
750 [ # # ]: 0 : sal_Int32 nH = ((SdrEdgeNode2HorzDistItem&)rSet.Get(SDRATTR_EDGENODE2HORZDIST)).GetValue();
751 [ # # ]: 0 : sal_Int32 nV = ((SdrEdgeNode2VertDistItem&)rSet.Get(SDRATTR_EDGENODE2VERTDIST)).GetValue();
752 : :
753 : 0 : aBewareRect2.Left()-=nH;
754 : 0 : aBewareRect2.Right()+=nH;
755 : 0 : aBewareRect2.Top()-=nV;
756 : 0 : aBewareRect2.Bottom()+=nV;
757 : : } else {
758 [ # # ]: 0 : aBoundRect2=Rectangle(aPt2,aPt2);
759 [ # # ]: 0 : aBoundRect2.Move(rCon2.aObjOfs.X(),rCon2.aObjOfs.Y());
760 : 0 : aBewareRect2=aBoundRect2;
761 : : }
762 [ # # ]: 0 : XPolygon aBestXP;
763 : 0 : sal_uIntPtr nBestQual=0xFFFFFFFF;
764 : 0 : SdrEdgeInfoRec aBestInfo;
765 [ # # ][ # # ]: 0 : bool bAuto1=bCon1 && rCon1.bBestVertex;
766 [ # # ][ # # ]: 0 : bool bAuto2=bCon2 && rCon2.bBestVertex;
767 [ # # ]: 0 : if (bAuto1) rCon1.bAutoVertex=sal_True;
768 [ # # ]: 0 : if (bAuto2) rCon2.bAutoVertex=sal_True;
769 : 0 : sal_uInt16 nBestAuto1=0;
770 : 0 : sal_uInt16 nBestAuto2=0;
771 [ # # ]: 0 : sal_uInt16 nAnz1=bAuto1 ? 4 : 1;
772 [ # # ]: 0 : sal_uInt16 nAnz2=bAuto2 ? 4 : 1;
773 [ # # ]: 0 : for (sal_uInt16 nNum1=0; nNum1<nAnz1; nNum1++) {
774 [ # # ]: 0 : if (bAuto1) rCon1.nConId=nNum1;
775 [ # # ][ # # ]: 0 : if (bCon1 && rCon1.TakeGluePoint(aGP1,sal_True)) {
[ # # ][ # # ]
776 : 0 : aPt1=aGP1.GetPos();
777 : 0 : nEsc1=aGP1.GetEscDir();
778 [ # # ][ # # ]: 0 : if (nEsc1==SDRESC_SMART) nEsc1=ImpCalcEscAngle(rCon1.pObj,aPt1-rCon1.aObjOfs);
779 : : }
780 [ # # ]: 0 : for (sal_uInt16 nNum2=0; nNum2<nAnz2; nNum2++) {
781 [ # # ]: 0 : if (bAuto2) rCon2.nConId=nNum2;
782 [ # # ][ # # ]: 0 : if (bCon2 && rCon2.TakeGluePoint(aGP2,sal_True)) {
[ # # ][ # # ]
783 : 0 : aPt2=aGP2.GetPos();
784 : 0 : nEsc2=aGP2.GetEscDir();
785 [ # # ][ # # ]: 0 : if (nEsc2==SDRESC_SMART) nEsc2=ImpCalcEscAngle(rCon2.pObj,aPt2-rCon2.aObjOfs);
786 : : }
787 [ # # ]: 0 : for (long nA1=0; nA1<36000; nA1+=9000) {
788 [ # # ][ # # ]: 0 : sal_uInt16 nE1=nA1==0 ? SDRESC_RIGHT : nA1==9000 ? SDRESC_TOP : nA1==18000 ? SDRESC_LEFT : nA1==27000 ? SDRESC_BOTTOM : 0;
[ # # ][ # # ]
789 [ # # ]: 0 : for (long nA2=0; nA2<36000; nA2+=9000) {
790 [ # # ][ # # ]: 0 : sal_uInt16 nE2=nA2==0 ? SDRESC_RIGHT : nA2==9000 ? SDRESC_TOP : nA2==18000 ? SDRESC_LEFT : nA2==27000 ? SDRESC_BOTTOM : 0;
[ # # ][ # # ]
791 [ # # ][ # # ]: 0 : if ((nEsc1&nE1)!=0 && (nEsc2&nE2)!=0) {
792 : 0 : sal_uIntPtr nQual=0;
793 : 0 : SdrEdgeInfoRec aInfo;
794 [ # # ]: 0 : if (pInfo!=NULL) aInfo=*pInfo;
795 [ # # ]: 0 : XPolygon aXP(ImpCalcEdgeTrack(aPt1,nA1,aBoundRect1,aBewareRect1,aPt2,nA2,aBoundRect2,aBewareRect2,&nQual,&aInfo));
796 [ # # ]: 0 : if (nQual<nBestQual) {
797 [ # # ]: 0 : aBestXP=aXP;
798 : 0 : nBestQual=nQual;
799 : 0 : aBestInfo=aInfo;
800 : 0 : nBestAuto1=nNum1;
801 : 0 : nBestAuto2=nNum2;
802 [ # # ]: 0 : }
803 : : }
804 : : }
805 : : }
806 : : }
807 : : }
808 [ # # ]: 0 : if (bAuto1) rCon1.nConId=nBestAuto1;
809 [ # # ]: 0 : if (bAuto2) rCon2.nConId=nBestAuto2;
810 [ # # ]: 0 : if (pInfo!=NULL) *pInfo=aBestInfo;
811 : 0 : return aBestXP;
812 : : }
813 : :
814 : 0 : XPolygon SdrEdgeObj::ImpCalcEdgeTrack(const Point& rPt1, long nAngle1, const Rectangle& rBoundRect1, const Rectangle& rBewareRect1,
815 : : const Point& rPt2, long nAngle2, const Rectangle& rBoundRect2, const Rectangle& rBewareRect2,
816 : : sal_uIntPtr* pnQuality, SdrEdgeInfoRec* pInfo) const
817 : : {
818 [ # # ]: 0 : SdrEdgeKind eKind=((SdrEdgeKindItem&)(GetObjectItem(SDRATTR_EDGEKIND))).GetValue();
819 : 0 : bool bRts1=nAngle1==0;
820 : 0 : bool bObn1=nAngle1==9000;
821 : 0 : bool bLks1=nAngle1==18000;
822 : 0 : bool bUnt1=nAngle1==27000;
823 [ # # ][ # # ]: 0 : bool bHor1=bLks1 || bRts1;
824 [ # # ][ # # ]: 0 : bool bVer1=bObn1 || bUnt1;
825 : 0 : bool bRts2=nAngle2==0;
826 : 0 : bool bObn2=nAngle2==9000;
827 : 0 : bool bLks2=nAngle2==18000;
828 : 0 : bool bUnt2=nAngle2==27000;
829 [ # # ][ # # ]: 0 : bool bHor2=bLks2 || bRts2;
830 [ # # ][ # # ]: 0 : bool bVer2=bObn2 || bUnt2;
831 : 0 : bool bInfo=pInfo!=NULL;
832 [ # # ]: 0 : if (bInfo) {
833 : 0 : pInfo->cOrthoForm=0;
834 : 0 : pInfo->nAngle1=nAngle1;
835 : 0 : pInfo->nAngle2=nAngle2;
836 : 0 : pInfo->nObj1Lines=1;
837 : 0 : pInfo->nObj2Lines=1;
838 : 0 : pInfo->nMiddleLine=0xFFFF;
839 : : }
840 : 0 : Point aPt1(rPt1);
841 : 0 : Point aPt2(rPt2);
842 : 0 : Rectangle aBoundRect1 (rBoundRect1 );
843 : 0 : Rectangle aBoundRect2 (rBoundRect2 );
844 : 0 : Rectangle aBewareRect1(rBewareRect1);
845 : 0 : Rectangle aBewareRect2(rBewareRect2);
846 : 0 : Point aMeeting((aPt1.X()+aPt2.X()+1)/2,(aPt1.Y()+aPt2.Y()+1)/2);
847 [ # # ]: 0 : if (eKind==SDREDGE_ONELINE) {
848 [ # # ]: 0 : XPolygon aXP(2);
849 [ # # ]: 0 : aXP[0]=rPt1;
850 [ # # ]: 0 : aXP[1]=rPt2;
851 [ # # ]: 0 : if (pnQuality!=NULL) {
852 : 0 : *pnQuality=Abs(rPt1.X()-rPt2.X())+Abs(rPt1.Y()-rPt2.Y());
853 : : }
854 [ # # ][ # # ]: 0 : return aXP;
855 [ # # ]: 0 : } else if (eKind==SDREDGE_THREELINES) {
856 [ # # ]: 0 : XPolygon aXP(4);
857 [ # # ]: 0 : aXP[0]=rPt1;
858 [ # # ]: 0 : aXP[1]=rPt1;
859 [ # # ]: 0 : aXP[2]=rPt2;
860 [ # # ]: 0 : aXP[3]=rPt2;
861 [ # # ][ # # ]: 0 : if (bRts1) aXP[1].X()=aBewareRect1.Right(); //+=500;
862 [ # # ][ # # ]: 0 : if (bObn1) aXP[1].Y()=aBewareRect1.Top(); //-=500;
863 [ # # ][ # # ]: 0 : if (bLks1) aXP[1].X()=aBewareRect1.Left(); //-=500;
864 [ # # ][ # # ]: 0 : if (bUnt1) aXP[1].Y()=aBewareRect1.Bottom(); //+=500;
865 [ # # ][ # # ]: 0 : if (bRts2) aXP[2].X()=aBewareRect2.Right(); //+=500;
866 [ # # ][ # # ]: 0 : if (bObn2) aXP[2].Y()=aBewareRect2.Top(); //-=500;
867 [ # # ][ # # ]: 0 : if (bLks2) aXP[2].X()=aBewareRect2.Left(); //-=500;
868 [ # # ][ # # ]: 0 : if (bUnt2) aXP[2].Y()=aBewareRect2.Bottom(); //+=500;
869 [ # # ]: 0 : if (pnQuality!=NULL) {
870 [ # # ][ # # ]: 0 : long nQ=Abs(aXP[1].X()-aXP[0].X())+Abs(aXP[1].Y()-aXP[0].Y());
[ # # ][ # # ]
871 [ # # ][ # # ]: 0 : nQ+=Abs(aXP[2].X()-aXP[1].X())+Abs(aXP[2].Y()-aXP[1].Y());
[ # # ][ # # ]
872 [ # # ][ # # ]: 0 : nQ+=Abs(aXP[3].X()-aXP[2].X())+Abs(aXP[3].Y()-aXP[2].Y());
[ # # ][ # # ]
873 : 0 : *pnQuality=nQ;
874 : : }
875 [ # # ]: 0 : if (bInfo) {
876 : 0 : pInfo->nObj1Lines=2;
877 : 0 : pInfo->nObj2Lines=2;
878 [ # # ]: 0 : if (bHor1) {
879 [ # # ]: 0 : aXP[1].X()+=pInfo->aObj1Line2.X();
880 : : } else {
881 [ # # ]: 0 : aXP[1].Y()+=pInfo->aObj1Line2.Y();
882 : : }
883 [ # # ]: 0 : if (bHor2) {
884 [ # # ]: 0 : aXP[2].X()+=pInfo->aObj2Line2.X();
885 : : } else {
886 [ # # ]: 0 : aXP[2].Y()+=pInfo->aObj2Line2.Y();
887 : : }
888 : : }
889 [ # # ][ # # ]: 0 : return aXP;
890 : : }
891 : 0 : sal_uInt16 nIntersections=0;
892 : : {
893 [ # # ]: 0 : Point aC1(aBewareRect1.Center());
894 [ # # ]: 0 : Point aC2(aBewareRect2.Center());
895 [ # # ][ # # ]: 0 : if (aBewareRect1.Left()<=aBewareRect2.Right() && aBewareRect1.Right()>=aBewareRect2.Left()) {
[ # # ]
896 : : // overlapping on the x axis
897 : 0 : long n1=Max(aBewareRect1.Left(),aBewareRect2.Left());
898 : 0 : long n2=Min(aBewareRect1.Right(),aBewareRect2.Right());
899 : 0 : aMeeting.X()=(n1+n2+1)/2;
900 : : } else {
901 : : // otherwise the center point of the empty space
902 [ # # ]: 0 : if (aC1.X()<aC2.X()) {
903 : 0 : aMeeting.X()=(aBewareRect1.Right()+aBewareRect2.Left()+1)/2;
904 : : } else {
905 : 0 : aMeeting.X()=(aBewareRect1.Left()+aBewareRect2.Right()+1)/2;
906 : : }
907 : : }
908 [ # # ][ # # ]: 0 : if (aBewareRect1.Top()<=aBewareRect2.Bottom() && aBewareRect1.Bottom()>=aBewareRect2.Top()) {
[ # # ]
909 : : // overlapping on the x axis
910 : 0 : long n1=Max(aBewareRect1.Top(),aBewareRect2.Top());
911 : 0 : long n2=Min(aBewareRect1.Bottom(),aBewareRect2.Bottom());
912 : 0 : aMeeting.Y()=(n1+n2+1)/2;
913 : : } else {
914 : : // otherwise the center point of the empty space
915 [ # # ]: 0 : if (aC1.Y()<aC2.Y()) {
916 : 0 : aMeeting.Y()=(aBewareRect1.Bottom()+aBewareRect2.Top()+1)/2;
917 : : } else {
918 : 0 : aMeeting.Y()=(aBewareRect1.Top()+aBewareRect2.Bottom()+1)/2;
919 : : }
920 : : }
921 : : // Here, there are three cases:
922 : : // 1. both go into the same direction
923 : : // 2. both go into opposite directions
924 : : // 3. one is vertical, the other is horizontal
925 : 0 : long nXMin=Min(aBewareRect1.Left(),aBewareRect2.Left());
926 : 0 : long nXMax=Max(aBewareRect1.Right(),aBewareRect2.Right());
927 : 0 : long nYMin=Min(aBewareRect1.Top(),aBewareRect2.Top());
928 : 0 : long nYMax=Max(aBewareRect1.Bottom(),aBewareRect2.Bottom());
929 : 0 : bool bBewareOverlap=aBewareRect1.Right()>aBewareRect2.Left() && aBewareRect1.Left()<aBewareRect2.Right() &&
930 [ # # ][ # # ]: 0 : aBewareRect1.Bottom()>aBewareRect2.Top() && aBewareRect1.Top()<aBewareRect2.Bottom();
[ # # # # ]
931 : 0 : unsigned nMainCase=3;
932 [ # # ]: 0 : if (nAngle1==nAngle2) nMainCase=1;
933 [ # # ][ # # ]: 0 : else if ((bHor1 && bHor2) || (bVer1 && bVer2)) nMainCase=2;
[ # # ][ # # ]
934 [ # # ]: 0 : if (nMainCase==1) { // case 1 (both go in one direction) is possible
935 [ # # ]: 0 : if (bVer1) aMeeting.X()=(aPt1.X()+aPt2.X()+1)/2; // Here, this is better than
936 [ # # ]: 0 : if (bHor1) aMeeting.Y()=(aPt1.Y()+aPt2.Y()+1)/2; // using center point of empty space
937 : : // bX1Ok means that the vertical exiting Obj1 doesn't conflict with Obj2, ...
938 [ # # ][ # # ]: 0 : bool bX1Ok=aPt1.X()<=aBewareRect2.Left() || aPt1.X()>=aBewareRect2.Right();
939 [ # # ][ # # ]: 0 : bool bX2Ok=aPt2.X()<=aBewareRect1.Left() || aPt2.X()>=aBewareRect1.Right();
940 [ # # ][ # # ]: 0 : bool bY1Ok=aPt1.Y()<=aBewareRect2.Top() || aPt1.Y()>=aBewareRect2.Bottom();
941 [ # # ][ # # ]: 0 : bool bY2Ok=aPt2.Y()<=aBewareRect1.Top() || aPt2.Y()>=aBewareRect1.Bottom();
942 [ # # ][ # # ]: 0 : if (bLks1 && (bY1Ok || aBewareRect1.Left()<aBewareRect2.Right()) && (bY2Ok || aBewareRect2.Left()<aBewareRect1.Right())) {
[ # # ][ # # ]
[ # # ][ # # ]
943 : 0 : aMeeting.X()=nXMin;
944 : : }
945 [ # # ][ # # ]: 0 : if (bRts1 && (bY1Ok || aBewareRect1.Right()>aBewareRect2.Left()) && (bY2Ok || aBewareRect2.Right()>aBewareRect1.Left())) {
[ # # ][ # # ]
[ # # ][ # # ]
946 : 0 : aMeeting.X()=nXMax;
947 : : }
948 [ # # ][ # # ]: 0 : if (bObn1 && (bX1Ok || aBewareRect1.Top()<aBewareRect2.Bottom()) && (bX2Ok || aBewareRect2.Top()<aBewareRect1.Bottom())) {
[ # # ][ # # ]
[ # # ][ # # ]
949 : 0 : aMeeting.Y()=nYMin;
950 : : }
951 [ # # ][ # # ]: 0 : if (bUnt1 && (bX1Ok || aBewareRect1.Bottom()>aBewareRect2.Top()) && (bX2Ok || aBewareRect2.Bottom()>aBewareRect1.Top())) {
[ # # ][ # # ]
[ # # ][ # # ]
952 : 0 : aMeeting.Y()=nYMax;
953 : : }
954 [ # # ]: 0 : } else if (nMainCase==2) {
955 : : // case 2:
956 [ # # ]: 0 : if (bHor1) { // both horizontal
957 : : /* 9 sub-cases:
958 : : (legend: line exits to the left (-|), right (|-))
959 : :
960 : : 2.1: Facing; overlap only on y axis
961 : : * * *
962 : : |--| *
963 : : * * *
964 : :
965 : : 2.2, 2.3: Facing, offset vertically; no overlap on either
966 : : axis
967 : : |- * * * * *
968 : : * -| * * -| *
969 : : * * * , * * *
970 : :
971 : : 2.4, 2.5: One below the other; overlap only on y axis
972 : : * |- * * * *
973 : : * -| * * -| *
974 : : * * * , * |- *
975 : :
976 : : 2.6, 2.7: Not facing, offset vertically; no overlap on either
977 : : axis
978 : : * * |- * * *
979 : : * -| * * -| *
980 : : * * * , * * |-
981 : :
982 : : 2.8: Not facing; overlap only on y axis
983 : : * * *
984 : : * -| |-
985 : : * * *
986 : :
987 : : 2.9: The objects's BewareRects overlap on x and y axis
988 : :
989 : : These cases, with some modifications are also valid for
990 : : horizontal line exits.
991 : : Cases 2.1 through 2.7 are covered well enough with the
992 : : default meetings. Only for cases 2.8 and 2.9 do we determine
993 : : special meeting points here.
994 : : */
995 : :
996 : : // normalization; be aR1 the one exiting to the right,
997 : : // be aR2 the one exiting to the left
998 [ # # ]: 0 : Rectangle aBewR1(bRts1 ? aBewareRect1 : aBewareRect2);
999 [ # # ]: 0 : Rectangle aBewR2(bRts1 ? aBewareRect2 : aBewareRect1);
1000 [ # # ]: 0 : Rectangle aBndR1(bRts1 ? aBoundRect1 : aBoundRect2);
1001 [ # # ]: 0 : Rectangle aBndR2(bRts1 ? aBoundRect2 : aBoundRect1);
1002 [ # # ][ # # ]: 0 : if (aBewR1.Bottom()>aBewR2.Top() && aBewR1.Top()<aBewR2.Bottom()) {
[ # # ]
1003 : : // overlap on y axis; cases 2.1, 2.8, 2.9
1004 [ # # ]: 0 : if (aBewR1.Right()>aBewR2.Left()) {
1005 : : /* Cases 2.8, 2.9:
1006 : : Case 2.8: always going around on the outside
1007 : : (bDirect=sal_False).
1008 : :
1009 : : Case 2.9 could also be a direct connection (in the
1010 : : case that the BewareRects overlap only slightly and
1011 : : the BoundRects don't overlap at all and if the
1012 : : line exits would otherwise violate the respective
1013 : : other object's BewareRect).
1014 : : */
1015 : 0 : bool bCase29Direct = false;
1016 : 0 : bool bCase29=aBewR1.Right()>aBewR2.Left();
1017 [ # # ]: 0 : if (aBndR1.Right()<=aBndR2.Left()) { // case 2.9 without BoundRect overlap
1018 [ # # ][ # # : 0 : if ((aPt1.Y()>aBewareRect2.Top() && aPt1.Y()<aBewareRect2.Bottom()) ||
# # # # ]
[ # # ]
1019 : 0 : (aPt2.Y()>aBewareRect1.Top() && aPt2.Y()<aBewareRect1.Bottom())) {
1020 : 0 : bCase29Direct = true;
1021 : : }
1022 : : }
1023 [ # # ]: 0 : if (!bCase29Direct) {
1024 : 0 : bool bObenLang=Abs(nYMin-aMeeting.Y())<=Abs(nYMax-aMeeting.Y());
1025 [ # # ]: 0 : if (bObenLang) {
1026 : 0 : aMeeting.Y()=nYMin;
1027 : : } else {
1028 : 0 : aMeeting.Y()=nYMax;
1029 : : }
1030 [ # # ]: 0 : if (bCase29) {
1031 : : // now make sure that the surrounded object
1032 : : // isn't traversed
1033 [ # # ][ # # ]: 0 : if ((aBewR1.Center().Y()<aBewR2.Center().Y()) != bObenLang) {
[ # # ]
1034 : 0 : aMeeting.X()=aBewR2.Right();
1035 : : } else {
1036 : 0 : aMeeting.X()=aBewR1.Left();
1037 : : }
1038 : : }
1039 : : } else {
1040 : : // We need a direct connection (3-line Z connection),
1041 : : // because we have to violate the BewareRects.
1042 : : // Use rule of three to scale down the BewareRects.
1043 : 0 : long nWant1=aBewR1.Right()-aBndR1.Right(); // distance at Obj1
1044 : 0 : long nWant2=aBndR2.Left()-aBewR2.Left(); // distance at Obj2
1045 : 0 : long nSpace=aBndR2.Left()-aBndR1.Right(); // available space
1046 [ # # ]: 0 : long nGet1=BigMulDiv(nWant1,nSpace,nWant1+nWant2);
1047 : 0 : long nGet2=nSpace-nGet1;
1048 [ # # ]: 0 : if (bRts1) { // revert normalization
1049 : 0 : aBewareRect1.Right()+=nGet1-nWant1;
1050 : 0 : aBewareRect2.Left()-=nGet2-nWant2;
1051 : : } else {
1052 : 0 : aBewareRect2.Right()+=nGet1-nWant1;
1053 : 0 : aBewareRect1.Left()-=nGet2-nWant2;
1054 : : }
1055 : 0 : nIntersections++; // lower quality
1056 : : }
1057 : : }
1058 : : }
1059 [ # # ]: 0 : } else if (bVer1) { // both horizontal
1060 [ # # ]: 0 : Rectangle aBewR1(bUnt1 ? aBewareRect1 : aBewareRect2);
1061 [ # # ]: 0 : Rectangle aBewR2(bUnt1 ? aBewareRect2 : aBewareRect1);
1062 [ # # ]: 0 : Rectangle aBndR1(bUnt1 ? aBoundRect1 : aBoundRect2);
1063 [ # # ]: 0 : Rectangle aBndR2(bUnt1 ? aBoundRect2 : aBoundRect1);
1064 [ # # ][ # # ]: 0 : if (aBewR1.Right()>aBewR2.Left() && aBewR1.Left()<aBewR2.Right()) {
[ # # ]
1065 : : // overlap on y axis; cases 2.1, 2.8, 2.9
1066 [ # # ]: 0 : if (aBewR1.Bottom()>aBewR2.Top()) {
1067 : : /* Cases 2.8, 2.9
1068 : : Case 2.8 always going around on the outside (bDirect=sal_False).
1069 : :
1070 : : Case 2.9 could also be a direct connection (in the
1071 : : case that the BewareRects overlap only slightly and
1072 : : the BoundRects don't overlap at all and if the
1073 : : line exits would otherwise violate the respective
1074 : : other object's BewareRect).
1075 : : */
1076 : 0 : bool bCase29Direct = false;
1077 : 0 : bool bCase29=aBewR1.Bottom()>aBewR2.Top();
1078 [ # # ]: 0 : if (aBndR1.Bottom()<=aBndR2.Top()) { // case 2.9 without BoundRect overlap
1079 [ # # ][ # # : 0 : if ((aPt1.X()>aBewareRect2.Left() && aPt1.X()<aBewareRect2.Right()) ||
# # # # ]
[ # # ]
1080 : 0 : (aPt2.X()>aBewareRect1.Left() && aPt2.X()<aBewareRect1.Right())) {
1081 : 0 : bCase29Direct = true;
1082 : : }
1083 : : }
1084 [ # # ]: 0 : if (!bCase29Direct) {
1085 : 0 : bool bLinksLang=Abs(nXMin-aMeeting.X())<=Abs(nXMax-aMeeting.X());
1086 [ # # ]: 0 : if (bLinksLang) {
1087 : 0 : aMeeting.X()=nXMin;
1088 : : } else {
1089 : 0 : aMeeting.X()=nXMax;
1090 : : }
1091 [ # # ]: 0 : if (bCase29) {
1092 : : // now make sure that the surrounded object
1093 : : // isn't traversed
1094 [ # # ][ # # ]: 0 : if ((aBewR1.Center().X()<aBewR2.Center().X()) != bLinksLang) {
[ # # ]
1095 : 0 : aMeeting.Y()=aBewR2.Bottom();
1096 : : } else {
1097 : 0 : aMeeting.Y()=aBewR1.Top();
1098 : : }
1099 : : }
1100 : : } else {
1101 : : // We need a direct connection (3-line Z connection),
1102 : : // because we have to violate the BewareRects.
1103 : : // Use rule of three to scale down the BewareRects.
1104 : 0 : long nWant1=aBewR1.Bottom()-aBndR1.Bottom(); // difference at Obj1
1105 : 0 : long nWant2=aBndR2.Top()-aBewR2.Top(); // difference at Obj2
1106 : 0 : long nSpace=aBndR2.Top()-aBndR1.Bottom(); // available space
1107 [ # # ]: 0 : long nGet1=BigMulDiv(nWant1,nSpace,nWant1+nWant2);
1108 : 0 : long nGet2=nSpace-nGet1;
1109 [ # # ]: 0 : if (bUnt1) { // revert normalization
1110 : 0 : aBewareRect1.Bottom()+=nGet1-nWant1;
1111 : 0 : aBewareRect2.Top()-=nGet2-nWant2;
1112 : : } else {
1113 : 0 : aBewareRect2.Bottom()+=nGet1-nWant1;
1114 : 0 : aBewareRect1.Top()-=nGet2-nWant2;
1115 : : }
1116 : 0 : nIntersections++; // lower quality
1117 : : }
1118 : : }
1119 : : }
1120 : : }
1121 [ # # ]: 0 : } else if (nMainCase==3) { // case 3: one horizontal, the other vertical
1122 : : /* legend:
1123 : : The line exits to the:
1124 : : -| left
1125 : :
1126 : : |- right
1127 : :
1128 : : _|_ top
1129 : :
1130 : : T bottom
1131 : :
1132 : : * . * . * -- no overlap, at most might touch
1133 : : . . . . . -- overlap
1134 : : * . |- . * -- same height
1135 : : . . . . . -- overlap
1136 : : * . * . * -- no overlap, at most might touch
1137 : :
1138 : : Overall, there are 96 possible constellations, some of these can't even
1139 : : be unambiguously assigned to a certain case/method of handling.
1140 : :
1141 : :
1142 : : 3.1: All those constellations that are covered reasonably well
1143 : : by the default MeetingPoint (20+12).
1144 : :
1145 : : T T T . _|_ _|_ . T T T these 12 * . * T * * . * . * * T * . * * . * . *
1146 : : . . . . _|_ _|_ . . . . constellations . . . . . . . . . T . . . . . T . . . .
1147 : : * . |- . * * . -| . * are covered * . |- . _|_ * . |- . T _|_ . -| . * T . -| . *
1148 : : . . . . T T . . . . only in . . . . _|_ . . . . . _|_ . . . . . . . . .
1149 : : _|__|__|_ . T T . _|__|__|_ part: * . * _|_ * * . * . * * _|_ * . * * . * . *
1150 : :
1151 : : The last 16 of these cases can be excluded, if the objects face each other openly.
1152 : :
1153 : :
1154 : : 3.2: The objects face each other openly, thus a connection using only two lines is possible (4+20);
1155 : : This case is priority #1.
1156 : : * . * . T T . * . * these 20 * . * T * * T * . * * . * . * * . * . *
1157 : : . . . . . . . . . . constellations . . . T T T T . . . . . . . . . . . . .
1158 : : * . |- . * * . -| . * are covered * . |-_|__|_ _|__|_-| . * * . |- T T T T -| . *
1159 : : . . . . . . . . . . only in . . . _|__|_ _|__|_ . . . . . . . . . . . . .
1160 : : * . * . _|_ _|_ . * . * part: * . * _|_ * * _|_ * . * * . * . * * . * . *
1161 : :
1162 : : 3.3: The line exits point away from the other object or or miss its back (52+4).
1163 : : _|__|__|__|_ * * _|__|__|__|_ * . . . * * . * . * these 4 * . * . * * . * . *
1164 : : _|__|__|__|_ . . _|__|__|__|_ T T T . . . . T T T constellations . . . T . . T . . .
1165 : : _|__|_ |- . * * . -| _|__|_ T T |- . * * . -| T T are covered * . |- . * * . -| . *
1166 : : _|__|__|_ . . . . _|__|__|_ T T T T . . T T T T only in . . . _|_ . . _|_ . . .
1167 : : * . * . * * . * . * T T T T * * T T T T part: * . * . * * . * . *
1168 : : */
1169 : :
1170 : : // case 3.2
1171 : 0 : Rectangle aTmpR1(aBewareRect1);
1172 : 0 : Rectangle aTmpR2(aBewareRect2);
1173 [ # # ]: 0 : if (bBewareOverlap) {
1174 : : // overlapping BewareRects: use BoundRects for checking for case 3.2
1175 : 0 : aTmpR1=aBoundRect1;
1176 : 0 : aTmpR2=aBoundRect2;
1177 : : }
1178 [ # # ][ # # ]: 0 : if ((((bRts1 && aTmpR1.Right ()<=aPt2.X()) || (bLks1 && aTmpR1.Left()>=aPt2.X())) &&
[ # # ][ # # ]
[ # # # # ]
[ # # # # ]
[ # # # # ]
[ # # # # ]
[ # # # # ]
[ # # # # ]
[ # # ]
1179 : 0 : ((bUnt2 && aTmpR2.Bottom()<=aPt1.Y()) || (bObn2 && aTmpR2.Top ()>=aPt1.Y()))) ||
1180 : 0 : (((bRts2 && aTmpR2.Right ()<=aPt1.X()) || (bLks2 && aTmpR2.Left()>=aPt1.X())) &&
1181 : 0 : ((bUnt1 && aTmpR1.Bottom()<=aPt2.Y()) || (bObn1 && aTmpR1.Top ()>=aPt2.Y())))) {
1182 : : // case 3.2 applies: connector with only 2 lines
1183 [ # # ]: 0 : if (bHor1) {
1184 : 0 : aMeeting.X()=aPt2.X();
1185 : 0 : aMeeting.Y()=aPt1.Y();
1186 : : } else {
1187 : 0 : aMeeting.X()=aPt1.X();
1188 : 0 : aMeeting.Y()=aPt2.Y();
1189 : : }
1190 : : // in the case of overlapping BewareRects:
1191 : 0 : aBewareRect1=aTmpR1;
1192 : 0 : aBewareRect2=aTmpR2;
1193 [ # # ][ # # ]: 0 : } else if ((((bRts1 && aBewareRect1.Right ()>aBewareRect2.Left ()) ||
[ # # # # ]
[ # # # # ]
[ # # # # ]
[ # # # # ]
[ # # # # ]
[ # # # # ]
[ # # # # ]
[ # # ]
1194 : 0 : (bLks1 && aBewareRect1.Left ()<aBewareRect2.Right ())) &&
1195 : 0 : ((bUnt2 && aBewareRect2.Bottom()>aBewareRect1.Top ()) ||
1196 : 0 : (bObn2 && aBewareRect2.Top ()<aBewareRect1.Bottom()))) ||
1197 : 0 : (((bRts2 && aBewareRect2.Right ()>aBewareRect1.Left ()) ||
1198 : 0 : (bLks2 && aBewareRect2.Left ()<aBewareRect1.Right ())) &&
1199 : 0 : ((bUnt1 && aBewareRect1.Bottom()>aBewareRect2.Top ()) ||
1200 : 0 : (bObn1 && aBewareRect1.Top ()<aBewareRect2.Bottom())))) {
1201 : : // case 3.3
1202 [ # # ][ # # ]: 0 : if (bRts1 || bRts2) { aMeeting.X()=nXMax; }
1203 [ # # ][ # # ]: 0 : if (bLks1 || bLks2) { aMeeting.X()=nXMin; }
1204 [ # # ][ # # ]: 0 : if (bUnt1 || bUnt2) { aMeeting.Y()=nYMax; }
1205 [ # # ][ # # ]: 0 : if (bObn1 || bObn2) { aMeeting.Y()=nYMin; }
1206 : : }
1207 : : }
1208 : : }
1209 : :
1210 [ # # ]: 0 : XPolygon aXP1(ImpCalcObjToCenter(aPt1,nAngle1,aBewareRect1,aMeeting));
1211 [ # # ]: 0 : XPolygon aXP2(ImpCalcObjToCenter(aPt2,nAngle2,aBewareRect2,aMeeting));
1212 [ # # ]: 0 : sal_uInt16 nXP1Anz=aXP1.GetPointCount();
1213 [ # # ]: 0 : sal_uInt16 nXP2Anz=aXP2.GetPointCount();
1214 [ # # ]: 0 : if (bInfo) {
1215 [ # # ]: 0 : pInfo->nObj1Lines=nXP1Anz; if (nXP1Anz>1) pInfo->nObj1Lines--;
1216 [ # # ]: 0 : pInfo->nObj2Lines=nXP2Anz; if (nXP2Anz>1) pInfo->nObj2Lines--;
1217 : : }
1218 [ # # ]: 0 : Point aEP1(aXP1[nXP1Anz-1]);
1219 [ # # ]: 0 : Point aEP2(aXP2[nXP2Anz-1]);
1220 [ # # ][ # # ]: 0 : bool bInsMeetingPoint=aEP1.X()!=aEP2.X() && aEP1.Y()!=aEP2.Y();
1221 [ # # ]: 0 : bool bHorzE1=aEP1.Y()==aXP1[nXP1Anz-2].Y(); // is last line of XP1 horizontal?
1222 [ # # ]: 0 : bool bHorzE2=aEP2.Y()==aXP2[nXP2Anz-2].Y(); // is last line of XP2 horizontal?
1223 [ # # ][ # # ]: 0 : if (aEP1==aEP2 && ((bHorzE1 && bHorzE2 && aEP1.Y()==aEP2.Y()) || (!bHorzE1 && !bHorzE2 && aEP1.X()==aEP2.X()))) {
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1224 : : // special casing 'I' connectors
1225 [ # # ]: 0 : nXP1Anz--; aXP1.Remove(nXP1Anz,1);
1226 [ # # ]: 0 : nXP2Anz--; aXP2.Remove(nXP2Anz,1);
1227 : : }
1228 [ # # ]: 0 : if (bInsMeetingPoint) {
1229 [ # # ]: 0 : aXP1.Insert(XPOLY_APPEND,aMeeting,XPOLY_NORMAL);
1230 [ # # ]: 0 : if (bInfo) {
1231 : : // Inserting a MeetingPoint adds 2 new lines,
1232 : : // either might become the center line.
1233 [ # # ]: 0 : if (pInfo->nObj1Lines==pInfo->nObj2Lines) {
1234 : 0 : pInfo->nObj1Lines++;
1235 : 0 : pInfo->nObj2Lines++;
1236 : : } else {
1237 [ # # ]: 0 : if (pInfo->nObj1Lines>pInfo->nObj2Lines) {
1238 : 0 : pInfo->nObj2Lines++;
1239 : 0 : pInfo->nMiddleLine=nXP1Anz-1;
1240 : : } else {
1241 : 0 : pInfo->nObj1Lines++;
1242 : 0 : pInfo->nMiddleLine=nXP1Anz;
1243 : : }
1244 : : }
1245 : : }
1246 [ # # ][ # # ]: 0 : } else if (bInfo && aEP1!=aEP2 && nXP1Anz+nXP2Anz>=4) {
[ # # ][ # # ]
1247 : : // By connecting both ends, another line is added, this becomes the center line.
1248 : 0 : pInfo->nMiddleLine=nXP1Anz-1;
1249 : : }
1250 [ # # ]: 0 : sal_uInt16 nNum=aXP2.GetPointCount();
1251 [ # # ][ # # ]: 0 : if (aXP1[nXP1Anz-1]==aXP2[nXP2Anz-1] && nXP1Anz>1 && nXP2Anz>1) nNum--;
[ # # ][ # # ]
[ # # ][ # # ]
1252 [ # # ]: 0 : while (nNum>0) {
1253 : 0 : nNum--;
1254 [ # # ][ # # ]: 0 : aXP1.Insert(XPOLY_APPEND,aXP2[nNum],XPOLY_NORMAL);
1255 : : }
1256 [ # # ]: 0 : sal_uInt16 nPntAnz=aXP1.GetPointCount();
1257 : 0 : char cForm=0;
1258 [ # # ][ # # ]: 0 : if (bInfo || pnQuality!=NULL) {
1259 : 0 : cForm='?';
1260 [ # # ]: 0 : if (nPntAnz==2) cForm='I';
1261 [ # # ]: 0 : else if (nPntAnz==3) cForm='L';
1262 [ # # ]: 0 : else if (nPntAnz==4) { // Z or U
1263 [ # # ]: 0 : if (nAngle1==nAngle2) cForm='U';
1264 : 0 : else cForm='Z';
1265 [ # # ]: 0 : } else if (nPntAnz==6) { // S or C or ...
1266 [ # # ]: 0 : if (nAngle1!=nAngle2) {
1267 : : // For type S, line 2 has the same direction as line 4.
1268 : : // For type C, the opposite is true.
1269 [ # # ]: 0 : Point aP1(aXP1[1]);
1270 [ # # ]: 0 : Point aP2(aXP1[2]);
1271 [ # # ]: 0 : Point aP3(aXP1[3]);
1272 [ # # ]: 0 : Point aP4(aXP1[4]);
1273 [ # # ]: 0 : if (aP1.Y()==aP2.Y()) { // else both lines are horizontal
1274 [ # # ]: 0 : if ((aP1.X()<aP2.X())==(aP3.X()<aP4.X())) cForm='S';
1275 : 0 : else cForm='C';
1276 : : } else { // else both lines are vertical
1277 [ # # ]: 0 : if ((aP1.Y()<aP2.Y())==(aP3.Y()<aP4.Y())) cForm='S';
1278 : 0 : else cForm='C';
1279 : : }
1280 : 0 : } else cForm='4'; // else is case 3 with 5 lines
1281 : 0 : } else cForm='?'; //
1282 : : // more shapes:
1283 [ # # ]: 0 : if (bInfo) {
1284 : 0 : pInfo->cOrthoForm=cForm;
1285 [ # # ][ # # ]: 0 : if (cForm=='I' || cForm=='L' || cForm=='Z' || cForm=='U') {
[ # # ][ # # ]
1286 : 0 : pInfo->nObj1Lines=1;
1287 : 0 : pInfo->nObj2Lines=1;
1288 [ # # ][ # # ]: 0 : if (cForm=='Z' || cForm=='U') {
1289 : 0 : pInfo->nMiddleLine=1;
1290 : : } else {
1291 : 0 : pInfo->nMiddleLine=0xFFFF;
1292 : : }
1293 [ # # ][ # # ]: 0 : } else if (cForm=='S' || cForm=='C') {
1294 : 0 : pInfo->nObj1Lines=2;
1295 : 0 : pInfo->nObj2Lines=2;
1296 : 0 : pInfo->nMiddleLine=2;
1297 : : }
1298 : : }
1299 : : }
1300 [ # # ]: 0 : if (pnQuality!=NULL) {
1301 : 0 : sal_uIntPtr nQual=0;
1302 : 0 : sal_uIntPtr nQual0=nQual; // prevent overruns
1303 : 0 : bool bOverflow = false;
1304 [ # # ]: 0 : Point aPt0(aXP1[0]);
1305 [ # # ]: 0 : for (sal_uInt16 nPntNum=1; nPntNum<nPntAnz; nPntNum++) {
1306 [ # # ]: 0 : Point aPt1b(aXP1[nPntNum]);
1307 : 0 : nQual+=Abs(aPt1b.X()-aPt0.X())+Abs(aPt1b.Y()-aPt0.Y());
1308 [ # # ]: 0 : if (nQual<nQual0) bOverflow = true;
1309 : 0 : nQual0=nQual;
1310 : 0 : aPt0=aPt1b;
1311 : : }
1312 : :
1313 : 0 : sal_uInt16 nTmp=nPntAnz;
1314 [ # # ]: 0 : if (cForm=='Z') {
1315 : 0 : nTmp=2; // Z shape with good quality (nTmp=2 instead of 4)
1316 [ # # ][ # # ]: 0 : sal_uIntPtr n1=Abs(aXP1[1].X()-aXP1[0].X())+Abs(aXP1[1].Y()-aXP1[0].Y());
[ # # ][ # # ]
1317 [ # # ][ # # ]: 0 : sal_uIntPtr n2=Abs(aXP1[2].X()-aXP1[1].X())+Abs(aXP1[2].Y()-aXP1[1].Y());
[ # # ][ # # ]
1318 [ # # ][ # # ]: 0 : sal_uIntPtr n3=Abs(aXP1[3].X()-aXP1[2].X())+Abs(aXP1[3].Y()-aXP1[2].Y());
[ # # ][ # # ]
1319 : : // try to make lines lengths similar
1320 : 0 : sal_uIntPtr nBesser=0;
1321 : 0 : n1+=n3;
1322 : 0 : n3=n2/4;
1323 [ # # ]: 0 : if (n1>=n2) nBesser=6;
1324 [ # # ]: 0 : else if (n1>=3*n3) nBesser=4;
1325 [ # # ]: 0 : else if (n1>=2*n3) nBesser=2;
1326 [ # # ][ # # ]: 0 : if (aXP1[0].Y()!=aXP1[1].Y()) nBesser++; // vertical starting line gets a plus (for H/V-Prio)
[ # # ]
1327 [ # # ]: 0 : if (nQual>nBesser) nQual-=nBesser; else nQual=0;
1328 : : }
1329 [ # # ]: 0 : if (nTmp>=3) {
1330 : 0 : nQual0=nQual;
1331 : 0 : nQual+=(sal_uIntPtr)nTmp*0x01000000;
1332 [ # # ][ # # ]: 0 : if (nQual<nQual0 || nTmp>15) bOverflow = true;
1333 : : }
1334 [ # # ]: 0 : if (nPntAnz>=2) { // check exit angle again
1335 [ # # ][ # # ]: 0 : Point aP1(aXP1[1]); aP1-=aXP1[0];
1336 [ # # ][ # # ]: 0 : Point aP2(aXP1[nPntAnz-2]); aP2-=aXP1[nPntAnz-1];
1337 [ # # ][ # # ]: 0 : long nAng1=0; if (aP1.X()<0) nAng1=18000; if (aP1.Y()>0) nAng1=27000;
1338 [ # # ][ # # ]: 0 : if (aP1.Y()<0) nAng1=9000; if (aP1.X()!=0 && aP1.Y()!=0) nAng1=1; // slant?!
[ # # ][ # # ]
1339 [ # # ][ # # ]: 0 : long nAng2=0; if (aP2.X()<0) nAng2=18000; if (aP2.Y()>0) nAng2=27000;
1340 [ # # ][ # # ]: 0 : if (aP2.Y()<0) nAng2=9000; if (aP2.X()!=0 && aP2.Y()!=0) nAng2=1; // slant?!
[ # # ][ # # ]
1341 [ # # ]: 0 : if (nAng1!=nAngle1) nIntersections++;
1342 [ # # ]: 0 : if (nAng2!=nAngle2) nIntersections++;
1343 : : }
1344 : :
1345 : : // For the quality check, use the original Rects and at the same time
1346 : : // check whether one them was scaled down for the calculation of the
1347 : : // Edges (e. g. case 2.9)
1348 : 0 : aBewareRect1=rBewareRect1;
1349 : 0 : aBewareRect2=rBewareRect2;
1350 : :
1351 [ # # ]: 0 : for (sal_uInt16 i=0; i<nPntAnz; i++) {
1352 [ # # ]: 0 : Point aPt1b(aXP1[i]);
1353 : 0 : bool b1=aPt1b.X()>aBewareRect1.Left() && aPt1b.X()<aBewareRect1.Right() &&
1354 [ # # ][ # # ]: 0 : aPt1b.Y()>aBewareRect1.Top() && aPt1b.Y()<aBewareRect1.Bottom();
[ # # # # ]
1355 : 0 : bool b2=aPt1b.X()>aBewareRect2.Left() && aPt1b.X()<aBewareRect2.Right() &&
1356 [ # # ][ # # ]: 0 : aPt1b.Y()>aBewareRect2.Top() && aPt1b.Y()<aBewareRect2.Bottom();
[ # # # # ]
1357 : 0 : sal_uInt16 nInt0=nIntersections;
1358 [ # # ][ # # ]: 0 : if (i==0 || i==nPntAnz-1) {
1359 [ # # ][ # # ]: 0 : if (b1 && b2) nIntersections++;
1360 : : } else {
1361 [ # # ]: 0 : if (b1) nIntersections++;
1362 [ # # ]: 0 : if (b2) nIntersections++;
1363 : : }
1364 : : // check for overlaps
1365 [ # # ][ # # ]: 0 : if (i>0 && nInt0==nIntersections) {
1366 [ # # ]: 0 : if (aPt0.Y()==aPt1b.Y()) { // horizontal line
1367 [ # # ][ # # : 0 : if (aPt0.Y()>aBewareRect1.Top() && aPt0.Y()<aBewareRect1.Bottom() &&
# # # # #
# # # ]
[ # # ]
1368 : 0 : ((aPt0.X()<=aBewareRect1.Left() && aPt1b.X()>=aBewareRect1.Right()) ||
1369 : 0 : (aPt1b.X()<=aBewareRect1.Left() && aPt0.X()>=aBewareRect1.Right()))) nIntersections++;
1370 [ # # ][ # # : 0 : if (aPt0.Y()>aBewareRect2.Top() && aPt0.Y()<aBewareRect2.Bottom() &&
# # # # #
# # # ]
[ # # ]
1371 : 0 : ((aPt0.X()<=aBewareRect2.Left() && aPt1b.X()>=aBewareRect2.Right()) ||
1372 : 0 : (aPt1b.X()<=aBewareRect2.Left() && aPt0.X()>=aBewareRect2.Right()))) nIntersections++;
1373 : : } else { // vertical line
1374 [ # # ][ # # : 0 : if (aPt0.X()>aBewareRect1.Left() && aPt0.X()<aBewareRect1.Right() &&
# # # # #
# # # ]
[ # # ]
1375 : 0 : ((aPt0.Y()<=aBewareRect1.Top() && aPt1b.Y()>=aBewareRect1.Bottom()) ||
1376 : 0 : (aPt1b.Y()<=aBewareRect1.Top() && aPt0.Y()>=aBewareRect1.Bottom()))) nIntersections++;
1377 [ # # ][ # # : 0 : if (aPt0.X()>aBewareRect2.Left() && aPt0.X()<aBewareRect2.Right() &&
# # # # #
# # # ]
[ # # ]
1378 : 0 : ((aPt0.Y()<=aBewareRect2.Top() && aPt1b.Y()>=aBewareRect2.Bottom()) ||
1379 : 0 : (aPt1b.Y()<=aBewareRect2.Top() && aPt0.Y()>=aBewareRect2.Bottom()))) nIntersections++;
1380 : : }
1381 : : }
1382 : 0 : aPt0=aPt1b;
1383 : : }
1384 [ # # ]: 0 : if (nPntAnz<=1) nIntersections++;
1385 : 0 : nQual0=nQual;
1386 : 0 : nQual+=(sal_uIntPtr)nIntersections*0x10000000;
1387 [ # # ][ # # ]: 0 : if (nQual<nQual0 || nIntersections>15) bOverflow = true;
1388 : :
1389 [ # # ][ # # ]: 0 : if (bOverflow || nQual==0xFFFFFFFF) nQual=0xFFFFFFFE;
1390 : 0 : *pnQuality=nQual;
1391 : : }
1392 [ # # ]: 0 : if (bInfo) { // now apply line offsets to aXP1
1393 [ # # ]: 0 : if (pInfo->nMiddleLine!=0xFFFF) {
1394 [ # # ]: 0 : sal_uInt16 nIdx=pInfo->ImpGetPolyIdx(MIDDLELINE,aXP1);
1395 [ # # ][ # # ]: 0 : if (pInfo->ImpIsHorzLine(MIDDLELINE,aXP1)) {
1396 [ # # ]: 0 : aXP1[nIdx].Y()+=pInfo->aMiddleLine.Y();
1397 [ # # ]: 0 : aXP1[nIdx+1].Y()+=pInfo->aMiddleLine.Y();
1398 : : } else {
1399 [ # # ]: 0 : aXP1[nIdx].X()+=pInfo->aMiddleLine.X();
1400 [ # # ]: 0 : aXP1[nIdx+1].X()+=pInfo->aMiddleLine.X();
1401 : : }
1402 : : }
1403 [ # # ]: 0 : if (pInfo->nObj1Lines>=2) {
1404 [ # # ]: 0 : sal_uInt16 nIdx=pInfo->ImpGetPolyIdx(OBJ1LINE2,aXP1);
1405 [ # # ][ # # ]: 0 : if (pInfo->ImpIsHorzLine(OBJ1LINE2,aXP1)) {
1406 [ # # ]: 0 : aXP1[nIdx].Y()+=pInfo->aObj1Line2.Y();
1407 [ # # ]: 0 : aXP1[nIdx+1].Y()+=pInfo->aObj1Line2.Y();
1408 : : } else {
1409 [ # # ]: 0 : aXP1[nIdx].X()+=pInfo->aObj1Line2.X();
1410 [ # # ]: 0 : aXP1[nIdx+1].X()+=pInfo->aObj1Line2.X();
1411 : : }
1412 : : }
1413 [ # # ]: 0 : if (pInfo->nObj1Lines>=3) {
1414 [ # # ]: 0 : sal_uInt16 nIdx=pInfo->ImpGetPolyIdx(OBJ1LINE3,aXP1);
1415 [ # # ][ # # ]: 0 : if (pInfo->ImpIsHorzLine(OBJ1LINE3,aXP1)) {
1416 [ # # ]: 0 : aXP1[nIdx].Y()+=pInfo->aObj1Line3.Y();
1417 [ # # ]: 0 : aXP1[nIdx+1].Y()+=pInfo->aObj1Line3.Y();
1418 : : } else {
1419 [ # # ]: 0 : aXP1[nIdx].X()+=pInfo->aObj1Line3.X();
1420 [ # # ]: 0 : aXP1[nIdx+1].X()+=pInfo->aObj1Line3.X();
1421 : : }
1422 : : }
1423 [ # # ]: 0 : if (pInfo->nObj2Lines>=2) {
1424 [ # # ]: 0 : sal_uInt16 nIdx=pInfo->ImpGetPolyIdx(OBJ2LINE2,aXP1);
1425 [ # # ][ # # ]: 0 : if (pInfo->ImpIsHorzLine(OBJ2LINE2,aXP1)) {
1426 [ # # ]: 0 : aXP1[nIdx].Y()+=pInfo->aObj2Line2.Y();
1427 [ # # ]: 0 : aXP1[nIdx+1].Y()+=pInfo->aObj2Line2.Y();
1428 : : } else {
1429 [ # # ]: 0 : aXP1[nIdx].X()+=pInfo->aObj2Line2.X();
1430 [ # # ]: 0 : aXP1[nIdx+1].X()+=pInfo->aObj2Line2.X();
1431 : : }
1432 : : }
1433 [ # # ]: 0 : if (pInfo->nObj2Lines>=3) {
1434 [ # # ]: 0 : sal_uInt16 nIdx=pInfo->ImpGetPolyIdx(OBJ2LINE3,aXP1);
1435 [ # # ][ # # ]: 0 : if (pInfo->ImpIsHorzLine(OBJ2LINE3,aXP1)) {
1436 [ # # ]: 0 : aXP1[nIdx].Y()+=pInfo->aObj2Line3.Y();
1437 [ # # ]: 0 : aXP1[nIdx+1].Y()+=pInfo->aObj2Line3.Y();
1438 : : } else {
1439 [ # # ]: 0 : aXP1[nIdx].X()+=pInfo->aObj2Line3.X();
1440 [ # # ]: 0 : aXP1[nIdx+1].X()+=pInfo->aObj2Line3.X();
1441 : : }
1442 : : }
1443 : : }
1444 : : // make the connector a bezier curve, if appropriate
1445 [ # # ][ # # ]: 0 : if (eKind==SDREDGE_BEZIER && nPntAnz>2) {
1446 [ # # ]: 0 : Point* pPt1=&aXP1[0];
1447 [ # # ]: 0 : Point* pPt2=&aXP1[1];
1448 [ # # ]: 0 : Point* pPt3=&aXP1[nPntAnz-2];
1449 [ # # ]: 0 : Point* pPt4=&aXP1[nPntAnz-1];
1450 : 0 : long dx1=pPt2->X()-pPt1->X();
1451 : 0 : long dy1=pPt2->Y()-pPt1->Y();
1452 : 0 : long dx2=pPt3->X()-pPt4->X();
1453 : 0 : long dy2=pPt3->Y()-pPt4->Y();
1454 [ # # ]: 0 : if (cForm=='L') { // nPntAnz==3
1455 [ # # ]: 0 : aXP1.SetFlags(1,XPOLY_CONTROL);
1456 : 0 : Point aPt3(*pPt2);
1457 [ # # ]: 0 : aXP1.Insert(2,aPt3,XPOLY_CONTROL);
1458 [ # # ]: 0 : nPntAnz=aXP1.GetPointCount();
1459 [ # # ]: 0 : pPt1=&aXP1[0];
1460 [ # # ]: 0 : pPt2=&aXP1[1];
1461 [ # # ]: 0 : pPt3=&aXP1[nPntAnz-2];
1462 [ # # ]: 0 : pPt4=&aXP1[nPntAnz-1];
1463 : 0 : pPt2->X()-=dx1/3;
1464 : 0 : pPt2->Y()-=dy1/3;
1465 : 0 : pPt3->X()-=dx2/3;
1466 : 0 : pPt3->Y()-=dy2/3;
1467 [ # # ][ # # ]: 0 : } else if (nPntAnz>=4 && nPntAnz<=6) { // Z or U or ...
1468 : : // To all others, the end points of the original lines become control
1469 : : // points for now. Thus, we need to do some more work for nPntAnz>4!
1470 [ # # ]: 0 : aXP1.SetFlags(1,XPOLY_CONTROL);
1471 [ # # ]: 0 : aXP1.SetFlags(nPntAnz-2,XPOLY_CONTROL);
1472 : : // distance x1.5
1473 : 0 : pPt2->X()+=dx1/2;
1474 : 0 : pPt2->Y()+=dy1/2;
1475 : 0 : pPt3->X()+=dx2/2;
1476 : 0 : pPt3->Y()+=dy2/2;
1477 [ # # ]: 0 : if (nPntAnz==5) {
1478 : : // add a control point before and after center
1479 [ # # ]: 0 : Point aCenter(aXP1[2]);
1480 [ # # ]: 0 : long dx1b=aCenter.X()-aXP1[1].X();
1481 [ # # ]: 0 : long dy1b=aCenter.Y()-aXP1[1].Y();
1482 [ # # ]: 0 : long dx2b=aCenter.X()-aXP1[3].X();
1483 [ # # ]: 0 : long dy2b=aCenter.Y()-aXP1[3].Y();
1484 [ # # ]: 0 : aXP1.Insert(2,aCenter,XPOLY_CONTROL);
1485 [ # # ]: 0 : aXP1.SetFlags(3,XPOLY_SYMMTR);
1486 [ # # ]: 0 : aXP1.Insert(4,aCenter,XPOLY_CONTROL);
1487 [ # # ]: 0 : aXP1[2].X()-=dx1b/2;
1488 [ # # ]: 0 : aXP1[2].Y()-=dy1b/2;
1489 [ # # ]: 0 : aXP1[3].X()-=(dx1b+dx2b)/4;
1490 [ # # ]: 0 : aXP1[3].Y()-=(dy1b+dy2b)/4;
1491 [ # # ]: 0 : aXP1[4].X()-=dx2b/2;
1492 [ # # ]: 0 : aXP1[4].Y()-=dy2b/2;
1493 : : }
1494 [ # # ]: 0 : if (nPntAnz==6) {
1495 [ # # ]: 0 : Point aPt1b(aXP1[2]);
1496 [ # # ]: 0 : Point aPt2b(aXP1[3]);
1497 [ # # ]: 0 : aXP1.Insert(2,aPt1b,XPOLY_CONTROL);
1498 [ # # ]: 0 : aXP1.Insert(5,aPt2b,XPOLY_CONTROL);
1499 : 0 : long dx=aPt1b.X()-aPt2b.X();
1500 : 0 : long dy=aPt1b.Y()-aPt2b.Y();
1501 [ # # ]: 0 : aXP1[3].X()-=dx/2;
1502 [ # # ]: 0 : aXP1[3].Y()-=dy/2;
1503 [ # # ]: 0 : aXP1.SetFlags(3,XPOLY_SYMMTR);
1504 [ # # ]: 0 : aXP1.Remove(4,1); // because it's identical with aXP1[3]
1505 : : }
1506 : : }
1507 : : }
1508 [ # # ][ # # ]: 0 : return aXP1;
[ # # ]
1509 : : }
1510 : :
1511 : : /*
1512 : : There could be a maximum of 64 different developments with with 5 lines, a
1513 : : maximum of 32 developments with 4 lines, a maximum of 16 developments with
1514 : : 3 lines, a maximum of 8 developments with 2 lines.
1515 : : This gives us a total of 124 possibilities.
1516 : : Normalized for the 1st exit angle to the right, there remain 31 possibilities.
1517 : : Now, normalizing away the vertical mirroring, we get to a total of 16
1518 : : characteristic developments with 1 through 5 lines:
1519 : :
1520 : : 1 line (type "I") --
1521 : :
1522 : : 2 lines (type "L") __|
1523 : :
1524 : : 3 lines (type "U") __ (type "Z") _
1525 : : __| _|
1526 : : _ _
1527 : : 4 lines #1 _| #2 | | #3 |_ #4 | |
1528 : : _| _| _| _|
1529 : : Of these, #1 is implausible, #2 is a rotated version of #3. This leaves
1530 : : #2 (from now on referred to as 4.1) and #4 (from now on referred to as 4.2).
1531 : : _ _
1532 : : 5 lines #1 _| #2 _| #3 ___ #4 _
1533 : : _| _| _| _| _| |_
1534 : : _ _ _
1535 : : #5 |_ #6 |_ #7 _| | #8 ____
1536 : : _| _| _| |_ _|
1537 : : Of these, 5.1, 5.2, 5.4 and 5.5 are implausible, 5.7 is a reversed version
1538 : : of 5.3. This leaves 5.3 (type "4"), 5.6 (type "S") and 5.8 (type "C").
1539 : :
1540 : : We now have discerned the 9 basic types to cover all 400 possible constellations
1541 : : of object positions and exit angles. 4 of the 9 types have got a center
1542 : : line (CL). The number of object margins per object varies between 0 and 3:
1543 : :
1544 : : CL O1 O2 Note
1545 : : "I": n 0 0
1546 : : "L": n 0 0
1547 : : "U": n 0-1 0-1
1548 : : "Z": y 0 0
1549 : : 4.2: y 0 1 = U+1, respectively 1+U
1550 : : 4.4: n 0-2 0-2 = Z+1
1551 : : "4": y 0 2 = Z+2
1552 : : "S": y 1 1 = 1+Z+1
1553 : : "C": n 0-3 0-3 = 1+U+1
1554 : : */
1555 : :
1556 : 0 : void SdrEdgeObj::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
1557 : : {
1558 [ # # ][ # # ]: 0 : SfxSimpleHint* pSimple=PTR_CAST(SfxSimpleHint,&rHint);
1559 [ # # ]: 0 : sal_uIntPtr nId=pSimple==0 ? 0 : pSimple->GetId();
1560 : 0 : bool bDataChg=nId==SFX_HINT_DATACHANGED;
1561 : 0 : bool bDying=nId==SFX_HINT_DYING;
1562 [ # # ][ # # ]: 0 : bool bObj1=aCon1.pObj!=NULL && aCon1.pObj->GetBroadcaster()==&rBC;
1563 [ # # ][ # # ]: 0 : bool bObj2=aCon2.pObj!=NULL && aCon2.pObj->GetBroadcaster()==&rBC;
1564 [ # # ][ # # ]: 0 : if (bDying && (bObj1 || bObj2)) {
[ # # ]
1565 : : // catch Dying, so AttrObj doesn't start broadcasting
1566 : : // about an alleged change of template
1567 [ # # ]: 0 : if (bObj1) aCon1.pObj=NULL;
1568 [ # # ]: 0 : if (bObj2) aCon2.pObj=NULL;
1569 : 0 : return;
1570 : : }
1571 [ # # ][ # # ]: 0 : if ( bObj1 || bObj2 )
1572 : : {
1573 : 0 : bEdgeTrackUserDefined = sal_False;
1574 : : }
1575 : 0 : SdrTextObj::Notify(rBC,rHint);
1576 [ # # ]: 0 : if (nNotifyingCount==0) { // a locking flag
1577 : 0 : ((SdrEdgeObj*)this)->nNotifyingCount++;
1578 [ # # ][ # # ]: 0 : SdrHint* pSdrHint=PTR_CAST(SdrHint,&rHint);
1579 [ # # ]: 0 : if (bDataChg) { // StyleSheet changed
1580 : 0 : ImpSetAttrToEdgeInfo(); // when changing templates, copy values from Pool to aEdgeInfo
1581 : : }
1582 [ # # ]: 0 : if (bDataChg ||
[ # # # # ]
[ # # # # ]
[ # # # # ]
[ # # ]
1583 : 0 : (bObj1 && aCon1.pObj->GetPage()==pPage) ||
1584 : 0 : (bObj2 && aCon2.pObj->GetPage()==pPage) ||
1585 : 0 : (pSdrHint && pSdrHint->GetKind()==HINT_OBJREMOVED))
1586 : : {
1587 : : // broadcasting only, if on the same page
1588 [ # # ][ # # ]: 0 : Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
[ # # ]
1589 [ # # ]: 0 : ImpDirtyEdgeTrack();
1590 : :
1591 : : // only redraw here, object hasn't actually changed
1592 [ # # ]: 0 : ActionChanged();
1593 : :
1594 [ # # ]: 0 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
1595 : : }
1596 : 0 : ((SdrEdgeObj*)this)->nNotifyingCount--;
1597 : : }
1598 : : }
1599 : :
1600 : : /** updates edges that are connected to the edges of this object
1601 : : as if the connected objects sent a repaint broadcast
1602 : : */
1603 : 0 : void SdrEdgeObj::Reformat()
1604 : : {
1605 [ # # ]: 0 : if( NULL != aCon1.pObj )
1606 : : {
1607 [ # # ]: 0 : SfxSimpleHint aHint( SFX_HINT_DATACHANGED );
1608 [ # # ][ # # ]: 0 : Notify( *const_cast<SfxBroadcaster*>(aCon1.pObj->GetBroadcaster()), aHint );
[ # # ]
1609 : : }
1610 : :
1611 [ # # ]: 0 : if( NULL != aCon2.pObj )
1612 : : {
1613 [ # # ]: 0 : SfxSimpleHint aHint( SFX_HINT_DATACHANGED );
1614 [ # # ][ # # ]: 0 : Notify( *const_cast<SfxBroadcaster*>(aCon2.pObj->GetBroadcaster()), aHint );
[ # # ]
1615 : : }
1616 : 0 : }
1617 : :
1618 : 0 : SdrEdgeObj* SdrEdgeObj::Clone() const
1619 : : {
1620 : 0 : return CloneHelper< SdrEdgeObj >();
1621 : : }
1622 : :
1623 : 0 : SdrEdgeObj& SdrEdgeObj::operator=(const SdrEdgeObj& rObj)
1624 : : {
1625 [ # # ]: 0 : if( this == &rObj )
1626 : 0 : return *this;
1627 : 0 : SdrTextObj::operator=(rObj);
1628 : 0 : *pEdgeTrack =*rObj.pEdgeTrack;
1629 : 0 : bEdgeTrackDirty=rObj.bEdgeTrackDirty;
1630 : 0 : aCon1 =rObj.aCon1;
1631 : 0 : aCon2 =rObj.aCon2;
1632 : 0 : aCon1.pObj=NULL;
1633 : 0 : aCon2.pObj=NULL;
1634 : 0 : aEdgeInfo=rObj.aEdgeInfo;
1635 : 0 : return *this;
1636 : : }
1637 : :
1638 : 0 : void SdrEdgeObj::TakeObjNameSingul(XubString& rName) const
1639 : : {
1640 [ # # ][ # # ]: 0 : rName=ImpGetResStr(STR_ObjNameSingulEDGE);
[ # # ]
1641 : :
1642 [ # # ][ # # ]: 0 : String aName( GetName() );
1643 [ # # ]: 0 : if(aName.Len())
1644 : : {
1645 [ # # ]: 0 : rName += sal_Unicode(' ');
1646 [ # # ]: 0 : rName += sal_Unicode('\'');
1647 [ # # ]: 0 : rName += aName;
1648 [ # # ]: 0 : rName += sal_Unicode('\'');
1649 [ # # ]: 0 : }
1650 : 0 : }
1651 : :
1652 : 0 : void SdrEdgeObj::TakeObjNamePlural(XubString& rName) const
1653 : : {
1654 [ # # ]: 0 : rName=ImpGetResStr(STR_ObjNamePluralEDGE);
1655 : 0 : }
1656 : :
1657 : 0 : basegfx::B2DPolyPolygon SdrEdgeObj::TakeXorPoly() const
1658 : : {
1659 : 0 : basegfx::B2DPolyPolygon aPolyPolygon;
1660 : :
1661 [ # # ]: 0 : if (bEdgeTrackDirty)
1662 : : {
1663 [ # # ]: 0 : ((SdrEdgeObj*)this)->ImpRecalcEdgeTrack();
1664 : : }
1665 : :
1666 [ # # ]: 0 : if(pEdgeTrack)
1667 : : {
1668 [ # # ][ # # ]: 0 : aPolyPolygon.append(pEdgeTrack->getB2DPolygon());
[ # # ]
1669 : : }
1670 : :
1671 : 0 : return aPolyPolygon;
1672 : : }
1673 : :
1674 : 0 : void SdrEdgeObj::SetEdgeTrackPath( const basegfx::B2DPolyPolygon& rPoly )
1675 : : {
1676 [ # # ]: 0 : if ( !rPoly.count() )
1677 : : {
1678 : 0 : bEdgeTrackDirty = sal_True;
1679 : 0 : bEdgeTrackUserDefined = sal_False;
1680 : : }
1681 : : else
1682 : : {
1683 [ # # ][ # # ]: 0 : *pEdgeTrack = XPolygon( rPoly.getB2DPolygon( 0 ) );
[ # # ][ # # ]
[ # # ]
1684 : 0 : bEdgeTrackDirty = sal_False;
1685 : 0 : bEdgeTrackUserDefined = sal_True;
1686 : :
1687 : : // #i110629# also set aRect and maSnapeRect depending on pEdgeTrack
1688 [ # # ]: 0 : const Rectangle aPolygonBounds(pEdgeTrack->GetBoundRect());
1689 : 0 : aRect = aPolygonBounds;
1690 : 0 : maSnapRect = aPolygonBounds;
1691 : : }
1692 : 0 : }
1693 : :
1694 : 0 : basegfx::B2DPolyPolygon SdrEdgeObj::GetEdgeTrackPath() const
1695 : : {
1696 : 0 : basegfx::B2DPolyPolygon aPolyPolygon;
1697 : :
1698 [ # # ]: 0 : if (bEdgeTrackDirty)
1699 [ # # ]: 0 : ((SdrEdgeObj*)this)->ImpRecalcEdgeTrack();
1700 : :
1701 [ # # ][ # # ]: 0 : aPolyPolygon.append( pEdgeTrack->getB2DPolygon() );
[ # # ]
1702 : :
1703 : 0 : return aPolyPolygon;
1704 : : }
1705 : :
1706 : 0 : sal_uInt32 SdrEdgeObj::GetHdlCount() const
1707 : : {
1708 : 0 : SdrEdgeKind eKind=((SdrEdgeKindItem&)(GetObjectItem(SDRATTR_EDGEKIND))).GetValue();
1709 : 0 : sal_uInt32 nHdlAnz(0L);
1710 : 0 : sal_uInt32 nPntAnz(pEdgeTrack->GetPointCount());
1711 : :
1712 [ # # ]: 0 : if(nPntAnz)
1713 : : {
1714 : 0 : nHdlAnz = 2L;
1715 : :
1716 [ # # ][ # # ]: 0 : if ((eKind==SDREDGE_ORTHOLINES || eKind==SDREDGE_BEZIER) && nPntAnz >= 4L)
[ # # ]
1717 : : {
1718 [ # # ]: 0 : sal_uInt32 nO1(aEdgeInfo.nObj1Lines > 0L ? aEdgeInfo.nObj1Lines - 1L : 0L);
1719 [ # # ]: 0 : sal_uInt32 nO2(aEdgeInfo.nObj2Lines > 0L ? aEdgeInfo.nObj2Lines - 1L : 0L);
1720 [ # # ]: 0 : sal_uInt32 nM(aEdgeInfo.nMiddleLine != 0xFFFF ? 1L : 0L);
1721 : 0 : nHdlAnz += nO1 + nO2 + nM;
1722 : : }
1723 [ # # ][ # # ]: 0 : else if (eKind==SDREDGE_THREELINES && nPntAnz == 4L)
1724 : : {
1725 [ # # ]: 0 : if(GetConnectedNode(sal_True))
1726 : 0 : nHdlAnz++;
1727 : :
1728 [ # # ]: 0 : if(GetConnectedNode(sal_False))
1729 : 0 : nHdlAnz++;
1730 : : }
1731 : : }
1732 : :
1733 : 0 : return nHdlAnz;
1734 : : }
1735 : :
1736 : 0 : SdrHdl* SdrEdgeObj::GetHdl(sal_uInt32 nHdlNum) const
1737 : : {
1738 : 0 : SdrHdl* pHdl=NULL;
1739 : 0 : sal_uInt32 nPntAnz(pEdgeTrack->GetPointCount());
1740 [ # # ]: 0 : if (nPntAnz!=0) {
1741 [ # # ]: 0 : if (nHdlNum==0) {
1742 [ # # ]: 0 : pHdl=new ImpEdgeHdl((*pEdgeTrack)[0],HDL_POLY);
1743 [ # # ][ # # ]: 0 : if (aCon1.pObj!=NULL && aCon1.bBestVertex) pHdl->Set1PixMore(sal_True);
1744 [ # # ]: 0 : } else if (nHdlNum==1) {
1745 [ # # ]: 0 : pHdl=new ImpEdgeHdl((*pEdgeTrack)[sal_uInt16(nPntAnz-1)],HDL_POLY);
1746 [ # # ][ # # ]: 0 : if (aCon2.pObj!=NULL && aCon2.bBestVertex) pHdl->Set1PixMore(sal_True);
1747 : : } else {
1748 : 0 : SdrEdgeKind eKind=((SdrEdgeKindItem&)(GetObjectItem(SDRATTR_EDGEKIND))).GetValue();
1749 [ # # ][ # # ]: 0 : if (eKind==SDREDGE_ORTHOLINES || eKind==SDREDGE_BEZIER) {
1750 [ # # ]: 0 : sal_uInt32 nO1(aEdgeInfo.nObj1Lines > 0L ? aEdgeInfo.nObj1Lines - 1L : 0L);
1751 [ # # ]: 0 : sal_uInt32 nO2(aEdgeInfo.nObj2Lines > 0L ? aEdgeInfo.nObj2Lines - 1L : 0L);
1752 [ # # ]: 0 : sal_uInt32 nM(aEdgeInfo.nMiddleLine != 0xFFFF ? 1L : 0L);
1753 : 0 : sal_uInt32 nNum(nHdlNum - 2L);
1754 : 0 : sal_Int32 nPt(0L);
1755 [ # # ][ # # ]: 0 : pHdl=new ImpEdgeHdl(Point(),HDL_POLY);
1756 [ # # ]: 0 : if (nNum<nO1) {
1757 : 0 : nPt=nNum+1L;
1758 [ # # ]: 0 : if (nNum==0) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ1LINE2);
1759 [ # # ]: 0 : if (nNum==1) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ1LINE3);
1760 : : } else {
1761 : 0 : nNum=nNum-nO1;
1762 [ # # ]: 0 : if (nNum<nO2) {
1763 : 0 : nPt=nPntAnz-3-nNum;
1764 [ # # ]: 0 : if (nNum==0) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ2LINE2);
1765 [ # # ]: 0 : if (nNum==1) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ2LINE3);
1766 : : } else {
1767 : 0 : nNum=nNum-nO2;
1768 [ # # ]: 0 : if (nNum<nM) {
1769 : 0 : nPt=aEdgeInfo.nMiddleLine;
1770 : 0 : ((ImpEdgeHdl*)pHdl)->SetLineCode(MIDDLELINE);
1771 : : }
1772 : : }
1773 : : }
1774 [ # # ]: 0 : if (nPt>0) {
1775 [ # # ]: 0 : Point aPos((*pEdgeTrack)[(sal_uInt16)nPt]);
1776 [ # # ]: 0 : aPos+=(*pEdgeTrack)[(sal_uInt16)nPt+1];
1777 : 0 : aPos.X()/=2;
1778 : 0 : aPos.Y()/=2;
1779 [ # # ]: 0 : pHdl->SetPos(aPos);
1780 : : } else {
1781 [ # # ]: 0 : delete pHdl;
1782 : 0 : pHdl=NULL;
1783 : 0 : }
1784 [ # # ]: 0 : } else if (eKind==SDREDGE_THREELINES) {
1785 : 0 : sal_uInt32 nNum(nHdlNum);
1786 [ # # ][ # # ]: 0 : if (GetConnectedNode(sal_True)==NULL) nNum++;
1787 [ # # ]: 0 : Point aPos((*pEdgeTrack)[(sal_uInt16)nNum-1]);
1788 [ # # ][ # # ]: 0 : pHdl=new ImpEdgeHdl(aPos,HDL_POLY);
1789 [ # # ][ # # ]: 0 : if (nNum==2) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ1LINE2);
1790 [ # # ][ # # ]: 0 : if (nNum==3) ((ImpEdgeHdl*)pHdl)->SetLineCode(OBJ2LINE2);
1791 : : }
1792 : : }
1793 [ # # ]: 0 : if (pHdl!=NULL) {
1794 : 0 : pHdl->SetPointNum(nHdlNum);
1795 : : }
1796 : : }
1797 : 0 : return pHdl;
1798 : : }
1799 : :
1800 : : ////////////////////////////////////////////////////////////////////////////////////////////////////
1801 : :
1802 : 0 : bool SdrEdgeObj::hasSpecialDrag() const
1803 : : {
1804 : 0 : return true;
1805 : : }
1806 : :
1807 : 0 : SdrObject* SdrEdgeObj::getFullDragClone() const
1808 : : {
1809 : : // use Clone operator
1810 : 0 : SdrEdgeObj* pRetval = (SdrEdgeObj*)Clone();
1811 : :
1812 : : // copy connections for clone, SdrEdgeObj::operator= does not do this
1813 : 0 : pRetval->ConnectToNode(true, GetConnectedNode(true));
1814 : 0 : pRetval->ConnectToNode(false, GetConnectedNode(false));
1815 : :
1816 : 0 : return pRetval;
1817 : : }
1818 : :
1819 : 0 : bool SdrEdgeObj::beginSpecialDrag(SdrDragStat& rDrag) const
1820 : : {
1821 [ # # ]: 0 : if(!rDrag.GetHdl())
1822 : 0 : return false;
1823 : :
1824 : 0 : rDrag.SetEndDragChangesAttributes(true);
1825 : :
1826 [ # # ]: 0 : if(rDrag.GetHdl()->GetPointNum() < 2)
1827 : : {
1828 : 0 : rDrag.SetNoSnap(true);
1829 : : }
1830 : :
1831 : 0 : return true;
1832 : : }
1833 : :
1834 : 0 : bool SdrEdgeObj::applySpecialDrag(SdrDragStat& rDragStat)
1835 : : {
1836 [ # # ]: 0 : SdrEdgeObj* pOriginalEdge = dynamic_cast< SdrEdgeObj* >(rDragStat.GetHdl()->GetObj());
1837 : 0 : const bool bOriginalEdgeModified(pOriginalEdge == this);
1838 : :
1839 [ # # ][ # # ]: 0 : if(!bOriginalEdgeModified && pOriginalEdge)
1840 : : {
1841 : : // copy connections when clone is modified. This is needed because
1842 : : // as preparation to this modification the data from the original object
1843 : : // was copied to the clone using the operator=. As can be seen there,
1844 : : // that operator does not copy the connections (for good reason)
1845 : 0 : ConnectToNode(true, pOriginalEdge->GetConnection(true).GetObject());
1846 : 0 : ConnectToNode(false, pOriginalEdge->GetConnection(false).GetObject());
1847 : : }
1848 : :
1849 [ # # ]: 0 : if(rDragStat.GetHdl()->GetPointNum() < 2)
1850 : : {
1851 : : // start or end point connector drag
1852 : 0 : const bool bDragA(0 == rDragStat.GetHdl()->GetPointNum());
1853 [ # # ]: 0 : const Point aPointNow(rDragStat.GetNow());
1854 : :
1855 [ # # ]: 0 : if(rDragStat.GetPageView())
1856 : : {
1857 [ # # ]: 0 : SdrObjConnection* pDraggedOne(bDragA ? &aCon1 : &aCon2);
1858 : :
1859 : : // clear connection
1860 [ # # ]: 0 : DisconnectFromNode(bDragA);
1861 : :
1862 : : // look for new connection
1863 [ # # ]: 0 : ImpFindConnector(aPointNow, *rDragStat.GetPageView(), *pDraggedOne, pOriginalEdge);
1864 : :
1865 [ # # ]: 0 : if(pDraggedOne->pObj)
1866 : : {
1867 : : // if found, officially connect to it; ImpFindConnector only
1868 : : // sets pObj hard
1869 : 0 : SdrObject* pNewConnection = pDraggedOne->pObj;
1870 : 0 : pDraggedOne->pObj = 0;
1871 [ # # ]: 0 : ConnectToNode(bDragA, pNewConnection);
1872 : : }
1873 : :
1874 [ # # ][ # # ]: 0 : if(rDragStat.GetView() && !bOriginalEdgeModified)
[ # # ]
1875 : : {
1876 : : // show IA helper, but only do this during IA, so not when the original
1877 : : // Edge gets modified in the last call
1878 [ # # ]: 0 : rDragStat.GetView()->SetConnectMarker(*pDraggedOne, *rDragStat.GetPageView());
1879 : : }
1880 : : }
1881 : :
1882 [ # # ]: 0 : if(pEdgeTrack)
1883 : : {
1884 : : // change pEdgeTrack to modified position
1885 [ # # ]: 0 : if(bDragA)
1886 : : {
1887 [ # # ]: 0 : (*pEdgeTrack)[0] = aPointNow;
1888 : : }
1889 : : else
1890 : : {
1891 [ # # ][ # # ]: 0 : (*pEdgeTrack)[sal_uInt16(pEdgeTrack->GetPointCount()-1)] = aPointNow;
1892 : : }
1893 : : }
1894 : :
1895 : : // reset edge info's offsets, this is a end point drag
1896 : 0 : aEdgeInfo.aObj1Line2 = Point();
1897 : 0 : aEdgeInfo.aObj1Line3 = Point();
1898 : 0 : aEdgeInfo.aObj2Line2 = Point();
1899 : 0 : aEdgeInfo.aObj2Line3 = Point();
1900 : 0 : aEdgeInfo.aMiddleLine = Point();
1901 : : }
1902 : : else
1903 : : {
1904 : : // control point connector drag
1905 : 0 : const ImpEdgeHdl* pEdgeHdl = (ImpEdgeHdl*)rDragStat.GetHdl();
1906 : 0 : const SdrEdgeLineCode eLineCode = pEdgeHdl->GetLineCode();
1907 [ # # ][ # # ]: 0 : const Point aDist(rDragStat.GetNow() - rDragStat.GetStart());
1908 [ # # ][ # # ]: 0 : sal_Int32 nDist(pEdgeHdl->IsHorzDrag() ? aDist.X() : aDist.Y());
1909 : :
1910 [ # # ]: 0 : nDist += aEdgeInfo.ImpGetLineVersatz(eLineCode, *pEdgeTrack);
1911 [ # # ]: 0 : aEdgeInfo.ImpSetLineVersatz(eLineCode, *pEdgeTrack, nDist);
1912 : : }
1913 : :
1914 : : // force recalculation of EdgeTrack
1915 [ # # ]: 0 : *pEdgeTrack = ImpCalcEdgeTrack(*pEdgeTrack, aCon1, aCon2, &aEdgeInfo);
1916 : 0 : bEdgeTrackDirty=sal_False;
1917 : :
1918 : : // save EdgeInfos and mark object as user modified
1919 : 0 : ImpSetEdgeInfoToAttr();
1920 : 0 : bEdgeTrackUserDefined = false;
1921 : :
1922 : 0 : SetRectsDirty();
1923 : :
1924 [ # # ][ # # ]: 0 : if(bOriginalEdgeModified && rDragStat.GetView())
[ # # ]
1925 : : {
1926 : : // hide connect marker helper again when original gets changed.
1927 : : // This happens at the end of the interaction
1928 : 0 : rDragStat.GetView()->HideConnectMarker();
1929 : : }
1930 : :
1931 : 0 : return true;
1932 : : }
1933 : :
1934 : 0 : String SdrEdgeObj::getSpecialDragComment(const SdrDragStat& rDrag) const
1935 : : {
1936 [ # # ][ # # ]: 0 : const bool bCreateComment(rDrag.GetView() && this == rDrag.GetView()->GetCreateObj());
1937 : :
1938 [ # # ]: 0 : if(bCreateComment)
1939 : : {
1940 : 0 : return String();
1941 : : }
1942 : : else
1943 : : {
1944 : 0 : rtl::OUString aStr;
1945 [ # # ]: 0 : ImpTakeDescriptionStr(STR_DragEdgeTail, aStr);
1946 : :
1947 [ # # ]: 0 : return aStr;
1948 : : }
1949 : : }
1950 : :
1951 : : ////////////////////////////////////////////////////////////////////////////////////////////////////
1952 : :
1953 : 0 : basegfx::B2DPolygon SdrEdgeObj::ImplAddConnectorOverlay(SdrDragMethod& rDragMethod, bool bTail1, bool bTail2, bool bDetail) const
1954 : : {
1955 : 0 : basegfx::B2DPolygon aResult;
1956 : :
1957 [ # # ]: 0 : if(bDetail)
1958 : : {
1959 : 0 : SdrObjConnection aMyCon1(aCon1);
1960 : 0 : SdrObjConnection aMyCon2(aCon2);
1961 : :
1962 [ # # ]: 0 : if (bTail1)
1963 : : {
1964 [ # # ][ # # ]: 0 : const basegfx::B2DPoint aTemp(rDragMethod.getCurrentTransformation() * basegfx::B2DPoint(aMyCon1.aObjOfs.X(), aMyCon1.aObjOfs.Y()));
[ # # ]
1965 : 0 : aMyCon1.aObjOfs.X() = basegfx::fround(aTemp.getX());
1966 : 0 : aMyCon1.aObjOfs.Y() = basegfx::fround(aTemp.getY());
1967 : : }
1968 : :
1969 [ # # ]: 0 : if (bTail2)
1970 : : {
1971 [ # # ][ # # ]: 0 : const basegfx::B2DPoint aTemp(rDragMethod.getCurrentTransformation() * basegfx::B2DPoint(aMyCon2.aObjOfs.X(), aMyCon2.aObjOfs.Y()));
[ # # ]
1972 : 0 : aMyCon2.aObjOfs.X() = basegfx::fround(aTemp.getX());
1973 : 0 : aMyCon2.aObjOfs.Y() = basegfx::fround(aTemp.getY());
1974 : : }
1975 : :
1976 : 0 : SdrEdgeInfoRec aInfo(aEdgeInfo);
1977 [ # # ]: 0 : XPolygon aXP(ImpCalcEdgeTrack(*pEdgeTrack, aMyCon1, aMyCon2, &aInfo));
1978 : :
1979 [ # # ][ # # ]: 0 : if(aXP.GetPointCount())
1980 : : {
1981 [ # # ][ # # ]: 0 : aResult = aXP.getB2DPolygon();
[ # # ]
1982 [ # # ][ # # ]: 0 : }
[ # # ]
1983 : : }
1984 : : else
1985 : : {
1986 [ # # ]: 0 : Point aPt1((*pEdgeTrack)[0]);
1987 [ # # ][ # # ]: 0 : Point aPt2((*pEdgeTrack)[sal_uInt16(pEdgeTrack->GetPointCount() - 1)]);
1988 : :
1989 [ # # ][ # # ]: 0 : if (aCon1.pObj && (aCon1.bBestConn || aCon1.bBestVertex))
[ # # ]
1990 [ # # ][ # # ]: 0 : aPt1 = aCon1.pObj->GetSnapRect().Center();
1991 : :
1992 [ # # ][ # # ]: 0 : if (aCon2.pObj && (aCon2.bBestConn || aCon2.bBestVertex))
[ # # ]
1993 [ # # ][ # # ]: 0 : aPt2 = aCon2.pObj->GetSnapRect().Center();
1994 : :
1995 [ # # ]: 0 : if (bTail1)
1996 : : {
1997 [ # # ][ # # ]: 0 : const basegfx::B2DPoint aTemp(rDragMethod.getCurrentTransformation() * basegfx::B2DPoint(aPt1.X(), aPt1.Y()));
[ # # ]
1998 : 0 : aPt1.X() = basegfx::fround(aTemp.getX());
1999 : 0 : aPt1.Y() = basegfx::fround(aTemp.getY());
2000 : : }
2001 : :
2002 [ # # ]: 0 : if (bTail2)
2003 : : {
2004 [ # # ][ # # ]: 0 : const basegfx::B2DPoint aTemp(rDragMethod.getCurrentTransformation() * basegfx::B2DPoint(aPt2.X(), aPt2.Y()));
[ # # ]
2005 : 0 : aPt2.X() = basegfx::fround(aTemp.getX());
2006 : 0 : aPt2.Y() = basegfx::fround(aTemp.getY());
2007 : : }
2008 : :
2009 [ # # ]: 0 : aResult.append(basegfx::B2DPoint(aPt1.X(), aPt1.Y()));
2010 [ # # ]: 0 : aResult.append(basegfx::B2DPoint(aPt2.X(), aPt2.Y()));
2011 : : }
2012 : :
2013 : 0 : return aResult;
2014 : : }
2015 : :
2016 : 0 : bool SdrEdgeObj::BegCreate(SdrDragStat& rDragStat)
2017 : : {
2018 : 0 : rDragStat.SetNoSnap(sal_True);
2019 : 0 : pEdgeTrack->SetPointCount(2);
2020 : 0 : (*pEdgeTrack)[0]=rDragStat.GetStart();
2021 : 0 : (*pEdgeTrack)[1]=rDragStat.GetNow();
2022 [ # # ]: 0 : if (rDragStat.GetPageView()!=NULL) {
2023 : 0 : ImpFindConnector(rDragStat.GetStart(),*rDragStat.GetPageView(),aCon1,this);
2024 : 0 : ConnectToNode(sal_True,aCon1.pObj);
2025 : : }
2026 [ # # ]: 0 : *pEdgeTrack=ImpCalcEdgeTrack(*pEdgeTrack,aCon1,aCon2,&aEdgeInfo);
2027 : 0 : return sal_True;
2028 : : }
2029 : :
2030 : 0 : bool SdrEdgeObj::MovCreate(SdrDragStat& rDragStat)
2031 : : {
2032 : 0 : sal_uInt16 nMax=pEdgeTrack->GetPointCount();
2033 : 0 : (*pEdgeTrack)[nMax-1]=rDragStat.GetNow();
2034 [ # # ]: 0 : if (rDragStat.GetPageView()!=NULL) {
2035 : 0 : ImpFindConnector(rDragStat.GetNow(),*rDragStat.GetPageView(),aCon2,this);
2036 : 0 : rDragStat.GetView()->SetConnectMarker(aCon2,*rDragStat.GetPageView());
2037 : : }
2038 : 0 : SetBoundRectDirty();
2039 : 0 : bSnapRectDirty=sal_True;
2040 : 0 : ConnectToNode(sal_False,aCon2.pObj);
2041 [ # # ]: 0 : *pEdgeTrack=ImpCalcEdgeTrack(*pEdgeTrack,aCon1,aCon2,&aEdgeInfo);
2042 : 0 : bEdgeTrackDirty=sal_False;
2043 : 0 : return sal_True;
2044 : : }
2045 : :
2046 : 0 : bool SdrEdgeObj::EndCreate(SdrDragStat& rDragStat, SdrCreateCmd eCmd)
2047 : : {
2048 [ # # ][ # # ]: 0 : bool bOk=(eCmd==SDRCREATE_FORCEEND || rDragStat.GetPointAnz()>=2);
2049 [ # # ]: 0 : if (bOk) {
2050 : 0 : ConnectToNode(sal_True,aCon1.pObj);
2051 : 0 : ConnectToNode(sal_False,aCon2.pObj);
2052 [ # # ]: 0 : if (rDragStat.GetView()!=NULL) {
2053 : 0 : rDragStat.GetView()->HideConnectMarker();
2054 : : }
2055 : 0 : ImpSetEdgeInfoToAttr(); // copy values from aEdgeInfo into the pool
2056 : : }
2057 : 0 : SetRectsDirty();
2058 : 0 : return bOk;
2059 : : }
2060 : :
2061 : 0 : bool SdrEdgeObj::BckCreate(SdrDragStat& rDragStat)
2062 : : {
2063 [ # # ]: 0 : if (rDragStat.GetView()!=NULL) {
2064 : 0 : rDragStat.GetView()->HideConnectMarker();
2065 : : }
2066 : 0 : return sal_False;
2067 : : }
2068 : :
2069 : 0 : void SdrEdgeObj::BrkCreate(SdrDragStat& rDragStat)
2070 : : {
2071 [ # # ]: 0 : if (rDragStat.GetView()!=NULL) {
2072 : 0 : rDragStat.GetView()->HideConnectMarker();
2073 : : }
2074 : 0 : }
2075 : :
2076 : 0 : basegfx::B2DPolyPolygon SdrEdgeObj::TakeCreatePoly(const SdrDragStat& /*rStatDrag*/) const
2077 : : {
2078 : 0 : basegfx::B2DPolyPolygon aRetval;
2079 [ # # ][ # # ]: 0 : aRetval.append(pEdgeTrack->getB2DPolygon());
[ # # ]
2080 : 0 : return aRetval;
2081 : : }
2082 : :
2083 : 0 : Pointer SdrEdgeObj::GetCreatePointer() const
2084 : : {
2085 : 0 : return Pointer(POINTER_DRAW_CONNECT);
2086 : : }
2087 : :
2088 : 0 : bool SdrEdgeObj::ImpFindConnector(const Point& rPt, const SdrPageView& rPV, SdrObjConnection& rCon, const SdrEdgeObj* pThis, OutputDevice* pOut)
2089 : : {
2090 : 0 : rCon.ResetVars();
2091 [ # # ][ # # ]: 0 : if (pOut==NULL) pOut=rPV.GetView().GetFirstOutputDevice();
2092 [ # # ]: 0 : if (pOut==NULL) return sal_False;
2093 : 0 : SdrObjList* pOL=rPV.GetObjList();
2094 : 0 : const SetOfByte& rVisLayer=rPV.GetVisibleLayers();
2095 : : // sensitive area of connectors is twice as large as the one of the handles
2096 [ # # ]: 0 : sal_uInt16 nMarkHdSiz=rPV.GetView().GetMarkHdlSizePixel();
2097 : 0 : Size aHalfConSiz(nMarkHdSiz,nMarkHdSiz);
2098 [ # # ]: 0 : aHalfConSiz=pOut->PixelToLogic(aHalfConSiz);
2099 : 0 : Size aHalfCenterSiz(2*aHalfConSiz.Width(),2*aHalfConSiz.Height());
2100 [ # # ]: 0 : Rectangle aMouseRect(rPt,rPt);
2101 : 0 : aMouseRect.Left() -=aHalfConSiz.Width();
2102 : 0 : aMouseRect.Top() -=aHalfConSiz.Height();
2103 : 0 : aMouseRect.Right() +=aHalfConSiz.Width();
2104 : 0 : aMouseRect.Bottom()+=aHalfConSiz.Height();
2105 [ # # ]: 0 : sal_uInt16 nBoundHitTol=(sal_uInt16)aHalfConSiz.Width()/2; if (nBoundHitTol==0) nBoundHitTol=1;
2106 [ # # ]: 0 : sal_uIntPtr no=pOL->GetObjCount();
2107 : 0 : bool bFnd = false;
2108 [ # # ]: 0 : SdrObjConnection aTestCon;
2109 [ # # ]: 0 : SdrObjConnection aBestCon;
2110 : :
2111 [ # # ][ # # ]: 0 : while (no>0 && !bFnd) {
[ # # ]
2112 : : // issue: group objects on different layers return LayerID=0!
2113 : 0 : no--;
2114 [ # # ]: 0 : SdrObject* pObj=pOL->GetObj(no);
2115 [ # # ][ # # ]: 0 : if (rVisLayer.IsSet(pObj->GetLayer()) && pObj->IsVisible() && // only visible objects
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2116 : : (pThis==NULL || pObj!=(SdrObject*)pThis) && // don't connect it to itself
2117 [ # # ]: 0 : pObj->IsNode())
2118 : : {
2119 [ # # ]: 0 : Rectangle aObjBound(pObj->GetCurrentBoundRect());
2120 [ # # ][ # # ]: 0 : if (aObjBound.IsOver(aMouseRect)) {
2121 : 0 : aTestCon.ResetVars();
2122 [ # # ][ # # ]: 0 : bool bEdge=HAS_BASE(SdrEdgeObj,pObj); // no BestCon for Edge
[ # # ][ # # ]
2123 : : // User-defined connectors have absolute priority.
2124 : : // After those come Vertex, Corner and center (Best), all prioritized equally.
2125 : : // Finally, a HitTest for the object.
2126 [ # # ]: 0 : const SdrGluePointList* pGPL=pObj->GetGluePointList();
2127 [ # # ]: 0 : sal_uInt16 nConAnz=pGPL==NULL ? 0 : pGPL->GetCount();
2128 : 0 : sal_uInt16 nGesAnz=nConAnz+9;
2129 : 0 : bool bUserFnd = false;
2130 : 0 : sal_uIntPtr nBestDist=0xFFFFFFFF;
2131 [ # # ]: 0 : for (sal_uInt16 i=0; i<nGesAnz; i++)
2132 : : {
2133 : 0 : bool bUser=i<nConAnz;
2134 [ # # ][ # # ]: 0 : bool bVertex=i>=nConAnz+0 && i<nConAnz+4;
2135 [ # # ][ # # ]: 0 : bool bCorner=i>=nConAnz+4 && i<nConAnz+8;
2136 : 0 : bool bCenter=i==nConAnz+8;
2137 : 0 : bool bOk = false;
2138 : 0 : Point aConPos;
2139 : 0 : sal_uInt16 nConNum=i;
2140 [ # # ]: 0 : if (bUser) {
2141 [ # # ]: 0 : const SdrGluePoint& rGP=(*pGPL)[nConNum];
2142 [ # # ]: 0 : aConPos=rGP.GetAbsolutePos(*pObj);
2143 : 0 : nConNum=rGP.GetId();
2144 : 0 : bOk = true;
2145 [ # # ][ # # ]: 0 : } else if (bVertex && !bUserFnd) {
2146 : 0 : nConNum=nConNum-nConAnz;
2147 [ # # ]: 0 : if (rPV.GetView().IsAutoVertexConnectors()) {
2148 [ # # ]: 0 : SdrGluePoint aPt(pObj->GetVertexGluePoint(nConNum));
2149 [ # # ]: 0 : aConPos=aPt.GetAbsolutePos(*pObj);
2150 : 0 : bOk = true;
2151 : 0 : } else i+=3;
2152 [ # # ][ # # ]: 0 : } else if (bCorner && !bUserFnd) {
2153 : 0 : nConNum-=nConAnz+4;
2154 [ # # ]: 0 : if (rPV.GetView().IsAutoCornerConnectors()) {
2155 [ # # ]: 0 : SdrGluePoint aPt(pObj->GetCornerGluePoint(nConNum));
2156 [ # # ]: 0 : aConPos=aPt.GetAbsolutePos(*pObj);
2157 : 0 : bOk = true;
2158 : 0 : } else i+=3;
2159 : : }
2160 [ # # ][ # # ]: 0 : else if (bCenter && !bUserFnd && !bEdge)
[ # # ]
2161 : : {
2162 : : // Suppress default connect at object center
2163 [ # # ][ # # ]: 0 : if(!pThis || !pThis->GetSuppressDefaultConnect())
[ # # ]
2164 : : {
2165 : : // not the edges!
2166 : 0 : nConNum=0;
2167 [ # # ]: 0 : aConPos=aObjBound.Center();
2168 : 0 : bOk = true;
2169 : : }
2170 : : }
2171 [ # # ][ # # ]: 0 : if (bOk && aMouseRect.IsInside(aConPos)) {
[ # # ][ # # ]
2172 [ # # ]: 0 : if (bUser) bUserFnd = true;
2173 : 0 : bFnd = true;
2174 : 0 : sal_uIntPtr nDist=(sal_uIntPtr)Abs(aConPos.X()-rPt.X())+(sal_uIntPtr)Abs(aConPos.Y()-rPt.Y());
2175 [ # # ]: 0 : if (nDist<nBestDist) {
2176 : 0 : nBestDist=nDist;
2177 : 0 : aTestCon.pObj=pObj;
2178 : 0 : aTestCon.nConId=nConNum;
2179 : 0 : aTestCon.bAutoCorner=bCorner;
2180 : 0 : aTestCon.bAutoVertex=bVertex;
2181 : 0 : aTestCon.bBestConn=sal_False; // bCenter;
2182 : 0 : aTestCon.bBestVertex=bCenter;
2183 : : }
2184 : : }
2185 : : }
2186 : : // if no connector is hit, try HitTest again, for BestConnector (=bCenter)
2187 [ # # ][ # # ]: 0 : if(!bFnd &&
[ # # ][ # # ]
2188 : 0 : !bEdge &&
2189 [ # # ]: 0 : SdrObjectPrimitiveHit(*pObj, rPt, nBoundHitTol, rPV, &rVisLayer, false))
2190 : : {
2191 : : // Suppress default connect at object inside bound
2192 [ # # ][ # # ]: 0 : if(!pThis || !pThis->GetSuppressDefaultConnect())
[ # # ]
2193 : : {
2194 : 0 : bFnd = true;
2195 : 0 : aTestCon.pObj=pObj;
2196 : 0 : aTestCon.bBestConn=sal_True;
2197 : : }
2198 : : }
2199 [ # # ]: 0 : if (bFnd) {
2200 [ # # ]: 0 : Rectangle aMouseRect2(rPt,rPt);
2201 : 0 : aMouseRect.Left() -=nBoundHitTol;
2202 : 0 : aMouseRect.Top() -=nBoundHitTol;
2203 : 0 : aMouseRect.Right() +=nBoundHitTol;
2204 : 0 : aMouseRect.Bottom()+=nBoundHitTol;
2205 [ # # ]: 0 : aObjBound.IsOver(aMouseRect2);
2206 : : }
2207 : :
2208 : : }
2209 : : }
2210 : : }
2211 : 0 : rCon=aTestCon;
2212 [ # # ][ # # ]: 0 : return bFnd;
2213 : : }
2214 : :
2215 : 0 : void SdrEdgeObj::NbcSetSnapRect(const Rectangle& rRect)
2216 : : {
2217 [ # # ]: 0 : const Rectangle aOld(GetSnapRect());
2218 : :
2219 [ # # ][ # # ]: 0 : if(aOld != rRect)
2220 : : {
2221 [ # # ][ # # ]: 0 : if(aRect.IsEmpty() && 0 == pEdgeTrack->GetPointCount())
[ # # ][ # # ]
[ # # ]
2222 : : {
2223 : : // #i110629# When initializing, do not scale on empty Rectangle; this
2224 : : // will mirror the underlying text object (!)
2225 : 0 : aRect = rRect;
2226 : 0 : maSnapRect = rRect;
2227 : : }
2228 : : else
2229 : : {
2230 : 0 : long nMulX = rRect.Right() - rRect.Left();
2231 : 0 : long nDivX = aOld.Right() - aOld.Left();
2232 : 0 : long nMulY = rRect.Bottom() - rRect.Top();
2233 : 0 : long nDivY = aOld.Bottom() - aOld.Top();
2234 [ # # ]: 0 : if ( nDivX == 0 ) { nMulX = 1; nDivX = 1; }
2235 [ # # ]: 0 : if ( nDivY == 0 ) { nMulY = 1; nDivY = 1; }
2236 [ # # ]: 0 : Fraction aX(nMulX, nDivX);
2237 [ # # ]: 0 : Fraction aY(nMulY, nDivY);
2238 [ # # ]: 0 : NbcResize(aOld.TopLeft(), aX, aY);
2239 [ # # ]: 0 : NbcMove(Size(rRect.Left() - aOld.Left(), rRect.Top() - aOld.Top()));
2240 : : }
2241 : : }
2242 : 0 : }
2243 : :
2244 : 0 : void SdrEdgeObj::NbcMove(const Size& rSiz)
2245 : : {
2246 : 0 : SdrTextObj::NbcMove(rSiz);
2247 : 0 : MoveXPoly(*pEdgeTrack,rSiz);
2248 : 0 : }
2249 : :
2250 : 0 : void SdrEdgeObj::NbcResize(const Point& rRefPnt, const Fraction& aXFact, const Fraction& aYFact)
2251 : : {
2252 : 0 : SdrTextObj::NbcResize(rRefPnt,aXFact,aXFact);
2253 : 0 : ResizeXPoly(*pEdgeTrack,rRefPnt,aXFact,aYFact);
2254 : :
2255 : : // if resize is not from paste, forget user distances
2256 [ # # ]: 0 : if(!GetModel()->IsPasteResize())
2257 : : {
2258 : 0 : aEdgeInfo.aObj1Line2 = Point();
2259 : 0 : aEdgeInfo.aObj1Line3 = Point();
2260 : 0 : aEdgeInfo.aObj2Line2 = Point();
2261 : 0 : aEdgeInfo.aObj2Line3 = Point();
2262 : 0 : aEdgeInfo.aMiddleLine = Point();
2263 : : }
2264 : 0 : }
2265 : :
2266 : 0 : SdrObject* SdrEdgeObj::DoConvertToPolyObj(sal_Bool bBezier) const
2267 : : {
2268 [ # # ]: 0 : basegfx::B2DPolyPolygon aPolyPolygon;
2269 [ # # ][ # # ]: 0 : aPolyPolygon.append(pEdgeTrack->getB2DPolygon());
[ # # ]
2270 [ # # ]: 0 : SdrObject* pRet = ImpConvertMakeObj(aPolyPolygon, sal_False, bBezier);
2271 [ # # ]: 0 : pRet = ImpConvertAddText(pRet, bBezier);
2272 : :
2273 [ # # ]: 0 : return pRet;
2274 : : }
2275 : :
2276 : 0 : sal_uInt32 SdrEdgeObj::GetSnapPointCount() const
2277 : : {
2278 : 0 : return 2L;
2279 : : }
2280 : :
2281 : 0 : Point SdrEdgeObj::GetSnapPoint(sal_uInt32 i) const
2282 : : {
2283 : 0 : ((SdrEdgeObj*)this)->ImpUndirtyEdgeTrack();
2284 : 0 : sal_uInt16 nAnz=pEdgeTrack->GetPointCount();
2285 [ # # ]: 0 : if (i==0) return (*pEdgeTrack)[0];
2286 : 0 : else return (*pEdgeTrack)[nAnz-1];
2287 : : }
2288 : :
2289 : 0 : sal_Bool SdrEdgeObj::IsPolyObj() const
2290 : : {
2291 : 0 : return sal_False;
2292 : : }
2293 : :
2294 : 0 : sal_uInt32 SdrEdgeObj::GetPointCount() const
2295 : : {
2296 : 0 : return 0L;
2297 : : }
2298 : :
2299 : 0 : Point SdrEdgeObj::GetPoint(sal_uInt32 i) const
2300 : : {
2301 : 0 : ((SdrEdgeObj*)this)->ImpUndirtyEdgeTrack();
2302 : 0 : sal_uInt16 nAnz=pEdgeTrack->GetPointCount();
2303 [ # # ]: 0 : if (0L == i)
2304 : 0 : return (*pEdgeTrack)[0];
2305 : : else
2306 : 0 : return (*pEdgeTrack)[nAnz-1];
2307 : : }
2308 : :
2309 : 0 : void SdrEdgeObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i)
2310 : : {
2311 : : // TODO: Need an implementation to connect differently.
2312 : 0 : ImpUndirtyEdgeTrack();
2313 : 0 : sal_uInt16 nAnz=pEdgeTrack->GetPointCount();
2314 [ # # ]: 0 : if (0L == i)
2315 : 0 : (*pEdgeTrack)[0]=rPnt;
2316 [ # # ]: 0 : if (1L == i)
2317 : 0 : (*pEdgeTrack)[nAnz-1]=rPnt;
2318 : 0 : SetEdgeTrackDirty();
2319 : 0 : SetRectsDirty();
2320 : 0 : }
2321 : :
2322 [ # # ][ # # ]: 0 : SdrEdgeObjGeoData::SdrEdgeObjGeoData()
2323 : : {
2324 [ # # ][ # # ]: 0 : pEdgeTrack=new XPolygon;
2325 : 0 : }
2326 : :
2327 [ # # ][ # # ]: 0 : SdrEdgeObjGeoData::~SdrEdgeObjGeoData()
2328 : : {
2329 [ # # ][ # # ]: 0 : delete pEdgeTrack;
2330 [ # # ]: 0 : }
2331 : :
2332 : 0 : SdrObjGeoData* SdrEdgeObj::NewGeoData() const
2333 : : {
2334 [ # # ]: 0 : return new SdrEdgeObjGeoData;
2335 : : }
2336 : :
2337 : 0 : void SdrEdgeObj::SaveGeoData(SdrObjGeoData& rGeo) const
2338 : : {
2339 : 0 : SdrTextObj::SaveGeoData(rGeo);
2340 : 0 : SdrEdgeObjGeoData& rEGeo=(SdrEdgeObjGeoData&)rGeo;
2341 : 0 : rEGeo.aCon1 =aCon1;
2342 : 0 : rEGeo.aCon2 =aCon2;
2343 : 0 : *rEGeo.pEdgeTrack =*pEdgeTrack;
2344 : 0 : rEGeo.bEdgeTrackDirty=bEdgeTrackDirty;
2345 : 0 : rEGeo.bEdgeTrackUserDefined=bEdgeTrackUserDefined;
2346 : 0 : rEGeo.aEdgeInfo =aEdgeInfo;
2347 : 0 : }
2348 : :
2349 : 0 : void SdrEdgeObj::RestGeoData(const SdrObjGeoData& rGeo)
2350 : : {
2351 : 0 : SdrTextObj::RestGeoData(rGeo);
2352 : 0 : SdrEdgeObjGeoData& rEGeo=(SdrEdgeObjGeoData&)rGeo;
2353 [ # # ]: 0 : if (aCon1.pObj!=rEGeo.aCon1.pObj) {
2354 [ # # ]: 0 : if (aCon1.pObj!=NULL) aCon1.pObj->RemoveListener(*this);
2355 : 0 : aCon1=rEGeo.aCon1;
2356 [ # # ]: 0 : if (aCon1.pObj!=NULL) aCon1.pObj->AddListener(*this);
2357 : : }
2358 [ # # ]: 0 : if (aCon2.pObj!=rEGeo.aCon2.pObj) {
2359 [ # # ]: 0 : if (aCon2.pObj!=NULL) aCon2.pObj->RemoveListener(*this);
2360 : 0 : aCon2=rEGeo.aCon2;
2361 [ # # ]: 0 : if (aCon2.pObj!=NULL) aCon2.pObj->AddListener(*this);
2362 : : }
2363 : 0 : *pEdgeTrack =*rEGeo.pEdgeTrack;
2364 : 0 : bEdgeTrackDirty=rEGeo.bEdgeTrackDirty;
2365 : 0 : bEdgeTrackUserDefined=rEGeo.bEdgeTrackUserDefined;
2366 : 0 : aEdgeInfo =rEGeo.aEdgeInfo;
2367 : 0 : }
2368 : :
2369 : 0 : Point SdrEdgeObj::GetTailPoint( sal_Bool bTail ) const
2370 : : {
2371 [ # # ][ # # ]: 0 : if( pEdgeTrack && pEdgeTrack->GetPointCount()!=0)
[ # # ]
2372 : : {
2373 : 0 : const XPolygon& rTrack0 = *pEdgeTrack;
2374 [ # # ]: 0 : if(bTail)
2375 : : {
2376 : 0 : return rTrack0[0];
2377 : : }
2378 : : else
2379 : : {
2380 : 0 : const sal_uInt16 nSiz = rTrack0.GetPointCount() - 1;
2381 : 0 : return rTrack0[nSiz];
2382 : : }
2383 : : }
2384 : : else
2385 : : {
2386 [ # # ]: 0 : if(bTail)
2387 : 0 : return aOutRect.TopLeft();
2388 : : else
2389 : 0 : return aOutRect.BottomRight();
2390 : : }
2391 : :
2392 : : }
2393 : :
2394 : 0 : void SdrEdgeObj::SetTailPoint( sal_Bool bTail, const Point& rPt )
2395 : : {
2396 : 0 : ImpSetTailPoint( bTail, rPt );
2397 : 0 : SetChanged();
2398 : 0 : }
2399 : :
2400 : : /** this method is used by the api to set a glue point for a connection
2401 : : nId == -1 : The best default point is automatically chosen
2402 : : 0 <= nId <= 3 : One of the default points is chosen
2403 : : nId >= 4 : A user defined glue point is chosen
2404 : : */
2405 : 0 : void SdrEdgeObj::setGluePointIndex( sal_Bool bTail, sal_Int32 nIndex /* = -1 */ )
2406 : : {
2407 [ # # ][ # # ]: 0 : Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetCurrentBoundRect();
[ # # ]
2408 : :
2409 : 0 : SdrObjConnection& rConn1 = GetConnection( bTail );
2410 : :
2411 [ # # ][ # # ]: 0 : rConn1.SetAutoVertex( nIndex >= 0 && nIndex <= 3 );
2412 : 0 : rConn1.SetBestConnection( nIndex < 0 );
2413 : 0 : rConn1.SetBestVertex( nIndex < 0 );
2414 : :
2415 [ # # ]: 0 : if( nIndex > 3 )
2416 : : {
2417 : 0 : nIndex -= 3; // the start api index is 0, whereas the implementation in svx starts from 1
2418 : :
2419 : : // for user defined glue points we have
2420 : : // to get the id for this index first
2421 [ # # ][ # # ]: 0 : const SdrGluePointList* pList = rConn1.GetObject() ? rConn1.GetObject()->GetGluePointList() : NULL;
2422 [ # # ][ # # ]: 0 : if( pList == NULL || SDRGLUEPOINT_NOTFOUND == pList->FindGluePoint((sal_uInt16)nIndex) )
[ # # ][ # # ]
2423 : 0 : return;
2424 : : }
2425 [ # # ]: 0 : else if( nIndex < 0 )
2426 : : {
2427 : 0 : nIndex = 0;
2428 : : }
2429 : :
2430 : 0 : rConn1.SetConnectorId( (sal_uInt16)nIndex );
2431 : :
2432 [ # # ]: 0 : SetChanged();
2433 [ # # ]: 0 : SetRectsDirty();
2434 [ # # ]: 0 : ImpRecalcEdgeTrack();
2435 : : }
2436 : :
2437 : : /** this method is used by the api to return a glue point id for a connection.
2438 : : See setGluePointId for possible return values */
2439 : 0 : sal_Int32 SdrEdgeObj::getGluePointIndex( sal_Bool bTail )
2440 : : {
2441 : 0 : SdrObjConnection& rConn1 = GetConnection( bTail );
2442 : 0 : sal_Int32 nId = -1;
2443 [ # # ]: 0 : if( !rConn1.IsBestConnection() )
2444 : : {
2445 : 0 : nId = rConn1.GetConnectorId();
2446 [ # # ]: 0 : if( !rConn1.IsAutoVertex() )
2447 : 0 : nId += 3; // the start api index is 0, whereas the implementation in svx starts from 1
2448 : : }
2449 : 0 : return nId;
2450 : : }
2451 : :
2452 : : // Implementation was missing; edge track needs to be invalidated additionally.
2453 : 0 : void SdrEdgeObj::NbcSetAnchorPos(const Point& rPnt)
2454 : : {
2455 : : // call parent functionality
2456 : 0 : SdrTextObj::NbcSetAnchorPos(rPnt);
2457 : :
2458 : : // Additionally, invalidate edge track
2459 : 0 : ImpDirtyEdgeTrack();
2460 : 0 : }
2461 : :
2462 : 0 : sal_Bool SdrEdgeObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& rPolyPolygon) const
2463 : : {
2464 : : // use base method from SdrObject, it's not rotatable and
2465 : : // a call to GetSnapRect() is used. That's what we need for Connector.
2466 : 0 : return SdrObject::TRGetBaseGeometry(rMatrix, rPolyPolygon);
2467 : : }
2468 : :
2469 : 0 : void SdrEdgeObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& rPolyPolygon)
2470 : : {
2471 : : // where appropriate take care for existing connections. For now, just use the
2472 : : // implementation from SdrObject.
2473 : 0 : SdrObject::TRSetBaseGeometry(rMatrix, rPolyPolygon);
2474 : 0 : }
2475 : :
2476 : : // for geometry access
2477 : 0 : ::basegfx::B2DPolygon SdrEdgeObj::getEdgeTrack() const
2478 : : {
2479 [ # # ]: 0 : if(bEdgeTrackDirty)
2480 : : {
2481 : 0 : const_cast< SdrEdgeObj* >(this)->ImpRecalcEdgeTrack();
2482 : : }
2483 : :
2484 [ # # ]: 0 : if(pEdgeTrack)
2485 : : {
2486 : 0 : return pEdgeTrack->getB2DPolygon();
2487 : : }
2488 : : else
2489 : : {
2490 : 0 : return ::basegfx::B2DPolygon();
2491 : : }
2492 : : }
2493 : :
2494 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|