1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svdoedge.hxx,v $
10 * $Revision: 1.5.18.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
34 #include <svx/svdotext.hxx>
35 #include <svx/svdglue.hxx>
36 #include "svx/svxdllapi.h"
38 //************************************************************
39 // Vorausdeklarationen
40 //************************************************************
45 namespace sdr
{ namespace properties
{
46 class ConnectorProperties
;
49 //************************************************************
50 // Hilfsklasse SdrObjConnection
51 //************************************************************
53 class SdrObjConnection
55 friend class SdrEdgeObj
;
56 friend class ImpEdgeHdl
;
57 friend class SdrCreateView
;
60 Point aObjOfs
; // Wird beim Draggen eines Knotens gesetzt
61 SdrObject
* pObj
; // Referenziertes Objekt
62 long nXDist
; // Hor. Objektabstand wenn bXDistOvr=TRUE
63 long nYDist
; // Vert. Objektabstand wenn bYDistOvr=TRUE
64 USHORT nConId
; // Konnektornummer
67 unsigned bBestConn
: 1; // TRUE= es wird der guenstigste Konnektor gesucht
68 unsigned bBestVertex
: 1; // TRUE= es wird der guenstigste Scheitelpunkt zum konnekten gesucht
69 unsigned bXDistOvr
: 1; // TRUE= Hor. Objektabstand wurde gedragt (Overwrite)
70 unsigned bYDistOvr
: 1; // TRUE= Vert. Objektabstand wurde gedragt (Overwrite)
71 unsigned bAutoVertex
: 1; // AutoConnector am Scheitelpunkt nCon
72 unsigned bAutoCorner
: 1; // AutoConnector am Eckpunkt nCon
75 SdrObjConnection() { ResetVars(); }
76 SVX_DLLPUBLIC
~SdrObjConnection();
79 FASTBOOL
TakeGluePoint(SdrGluePoint
& rGP
, FASTBOOL bSetAbsolutePos
) const;
81 inline void SetBestConnection( BOOL rB
) { bBestConn
= rB
; };
82 inline void SetBestVertex( BOOL rB
) { bBestVertex
= rB
; };
83 inline void SetAutoVertex( BOOL rB
) { bAutoVertex
= rB
; };
84 inline void SetConnectorId( USHORT nId
) { nConId
= nId
; };
86 inline BOOL
IsBestConnection() const { return bBestConn
; };
87 inline BOOL
IsBestVertex() const { return bBestVertex
; };
88 inline BOOL
IsAutoVertex() const { return bAutoVertex
; };
89 inline sal_uInt16
GetConnectorId() const { return nConId
; };
90 inline SdrObject
* GetObject() const { return pObj
; }
93 //************************************************************
94 // Hilfsklasse SdrEdgeInfoRec
95 //************************************************************
97 enum SdrEdgeLineCode
{OBJ1LINE2
,OBJ1LINE3
,OBJ2LINE2
,OBJ2LINE3
,MIDDLELINE
};
102 // Die 5 Distanzen werden beim draggen bzw. per SetAttr gesetzt und von
103 // ImpCalcEdgeTrack ausgewertet. Per Get/SetAttr/Get/SetStyleSh werden
104 // jedoch nur 0-3 longs transportiert.
111 // Nachfolgende Werte werden von ImpCalcEdgeTrack gesetzt
112 long nAngle1
; // Austrittswinkel am Obj1
113 long nAngle2
; // Austrittswinkel am Obj2
114 USHORT nObj1Lines
; // 1..3
115 USHORT nObj2Lines
; // 1..3
116 USHORT nMiddleLine
; // 0xFFFF=keine, sonst Punktnummer des Linienbeginns
117 char cOrthoForm
; // Form des Ortho-Verbindes, z.B. 'Z','U',I','L','S',...
129 Point
& ImpGetLineVersatzPoint(SdrEdgeLineCode eLineCode
);
130 const Point
& ImpGetLineVersatzPoint(SdrEdgeLineCode eLineCode
) const { return ((SdrEdgeInfoRec
*)this)->ImpGetLineVersatzPoint(eLineCode
); }
131 USHORT
ImpGetPolyIdx(SdrEdgeLineCode eLineCode
, const XPolygon
& rXP
) const;
132 FASTBOOL
ImpIsHorzLine(SdrEdgeLineCode eLineCode
, const XPolygon
& rXP
) const;
133 void ImpSetLineVersatz(SdrEdgeLineCode eLineCode
, const XPolygon
& rXP
, long nVal
);
134 long ImpGetLineVersatz(SdrEdgeLineCode eLineCode
, const XPolygon
& rXP
) const;
137 //************************************************************
138 // Hilfsklasse SdrEdgeObjGeoData
139 //************************************************************
141 class SdrEdgeObjGeoData
: public SdrTextObjGeoData
144 SdrObjConnection aCon1
; // Verbindungszustand des Linienanfangs
145 SdrObjConnection aCon2
; // Verbindungszustand des Linienendes
146 XPolygon
* pEdgeTrack
;
147 sal_Bool bEdgeTrackDirty
;// TRUE=Verbindungsverlauf muss neu berechnet werden.
148 sal_Bool bEdgeTrackUserDefined
;
149 SdrEdgeInfoRec aEdgeInfo
;
153 virtual ~SdrEdgeObjGeoData();
156 //************************************************************
157 // Hilfsklasse SdrEdgeObj
158 //************************************************************
160 class SVX_DLLPUBLIC SdrEdgeObj
: public SdrTextObj
163 virtual sdr::properties::BaseProperties
* CreateObjectSpecificProperties();
165 // to allow sdr::properties::ConnectorProperties access to ImpSetAttrToEdgeInfo()
166 friend class sdr::properties::ConnectorProperties
;
168 friend class SdrCreateView
;
169 friend class ImpEdgeHdl
;
171 // DrawContact section
173 virtual sdr::contact::ViewContact
* CreateObjectSpecificViewContact();
176 SdrObjConnection aCon1
; // Verbindungszustand des Linienanfangs
177 SdrObjConnection aCon2
; // Verbindungszustand des Linienendes
179 XPolygon
* pEdgeTrack
;
180 sal_uInt16 nNotifyingCount
; // Verrieglung
181 SdrEdgeInfoRec aEdgeInfo
;
184 unsigned bEdgeTrackDirty
: 1; // TRUE=Verbindungsverlauf muss neu berechnet werden.
185 unsigned bEdgeTrackUserDefined
: 1;
188 // Bool to allow supporession of default connects at object
189 // inside test (HitTest) and object center test (see ImpFindConnector())
190 unsigned mbSuppressDefaultConnect
: 1;
193 // Flag value for avoiding death loops when calculating BoundRects
194 // from circularly connected connectors. A coloring algorythm is used
195 // here. When the GetCurrentBoundRect() calculation of a SdrEdgeObj
196 // is running, the flag is set, else it is always sal_False.
197 unsigned mbBoundRectCalculationRunning
: 1;
201 // Interface to default connect suppression
202 void SetSuppressDefaultConnect(sal_Bool bNew
) { mbSuppressDefaultConnect
= bNew
; }
203 sal_Bool
GetSuppressDefaultConnect() const { return mbSuppressDefaultConnect
; }
206 sal_Bool
IsBoundRectCalculationRunning() const { return mbBoundRectCalculationRunning
; }
209 virtual void Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
);
211 XPolygon
ImpCalcObjToCenter(const Point
& rStPt
, long nEscAngle
, const Rectangle
& rRect
, const Point
& rCenter
) const;
212 void ImpRecalcEdgeTrack(); // Neuberechnung des Verbindungsverlaufs
213 XPolygon
ImpCalcEdgeTrack(const XPolygon
& rTrack0
, SdrObjConnection
& rCon1
, SdrObjConnection
& rCon2
, SdrEdgeInfoRec
* pInfo
) const;
214 XPolygon
ImpCalcEdgeTrack(const Point
& rPt1
, long nAngle1
, const Rectangle
& rBoundRect1
, const Rectangle
& rBewareRect1
,
215 const Point
& rPt2
, long nAngle2
, const Rectangle
& rBoundRect2
, const Rectangle
& rBewareRect2
,
216 ULONG
* pnQuality
, SdrEdgeInfoRec
* pInfo
) const;
217 static FASTBOOL
ImpFindConnector(const Point
& rPt
, const SdrPageView
& rPV
, SdrObjConnection
& rCon
, const SdrEdgeObj
* pThis
, OutputDevice
* pOut
=NULL
);
218 USHORT
ImpCalcEscAngle(SdrObject
* pObj
, const Point
& aPt2
) const;
219 FASTBOOL
ImpStripPolyPoints(XPolygon
& rXP
) const; // entfernen ueberfluessiger Punkte
220 void ImpSetTailPoint(FASTBOOL bTail1
, const Point
& rPt
);
221 void ImpUndirtyEdgeTrack(); // eventuelle Neuberechnung des Verbindungsverlaufs
222 void ImpDirtyEdgeTrack(); // invalidate connector path, so it will be recalculated next time
223 void ImpSetAttrToEdgeInfo(); // Werte vom Pool nach aEdgeInfo kopieren
224 void ImpSetEdgeInfoToAttr(); // Werte vom aEdgeInfo in den Pool kopieren
230 virtual ~SdrEdgeObj();
232 SdrObjConnection
& GetConnection(FASTBOOL bTail1
) { return *(bTail1
? &aCon1
: &aCon2
); }
233 virtual void TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const;
234 virtual UINT16
GetObjIdentifier() const;
235 virtual const Rectangle
& GetCurrentBoundRect() const;
236 virtual const Rectangle
& GetSnapRect() const;
237 virtual FASTBOOL
IsNode() const;
238 virtual SdrGluePoint
GetVertexGluePoint(USHORT nNum
) const;
239 virtual SdrGluePoint
GetCornerGluePoint(USHORT nNum
) const;
240 virtual const SdrGluePointList
* GetGluePointList() const;
241 virtual SdrGluePointList
* ForceGluePointList();
242 virtual FASTBOOL
IsEdge() const;
244 // bTail1=TRUE: Linienanfang, sonst LinienEnde
245 // pObj=NULL: Disconnect
246 void SetEdgeTrackDirty() { bEdgeTrackDirty
=TRUE
; }
247 void ConnectToNode(FASTBOOL bTail1
, SdrObject
* pObj
);
248 void DisconnectFromNode(FASTBOOL bTail1
);
249 SdrObject
* GetConnectedNode(FASTBOOL bTail1
) const;
250 const SdrObjConnection
& GetConnection(FASTBOOL bTail1
) const { return *(bTail1
? &aCon1
: &aCon2
); }
251 FASTBOOL
CheckNodeConnection(FASTBOOL bTail1
) const;
253 virtual void RecalcSnapRect();
254 virtual void TakeUnrotatedSnapRect(Rectangle
& rRect
) const;
255 virtual void operator=(const SdrObject
& rObj
);
256 virtual void TakeObjNameSingul(String
& rName
) const;
257 virtual void TakeObjNamePlural(String
& rName
) const;
259 void SetEdgeTrackPath( const basegfx::B2DPolyPolygon
& rPoly
);
260 basegfx::B2DPolyPolygon
GetEdgeTrackPath() const;
262 virtual basegfx::B2DPolyPolygon
TakeXorPoly() const;
263 virtual sal_uInt32
GetHdlCount() const;
264 virtual SdrHdl
* GetHdl(sal_uInt32 nHdlNum
) const;
266 // special drag methods
267 virtual bool hasSpecialDrag() const;
268 virtual bool beginSpecialDrag(SdrDragStat
& rDrag
) const;
269 virtual bool applySpecialDrag(SdrDragStat
& rDrag
);
270 virtual String
getSpecialDragComment(const SdrDragStat
& rDrag
) const;
273 virtual SdrObject
* getFullDragClone() const;
275 virtual void NbcSetSnapRect(const Rectangle
& rRect
);
276 virtual void NbcMove(const Size
& aSize
);
277 virtual void NbcResize(const Point
& rRefPnt
, const Fraction
& aXFact
, const Fraction
& aYFact
);
279 // #102344# Added missing implementation
280 virtual void NbcSetAnchorPos(const Point
& rPnt
);
282 virtual FASTBOOL
BegCreate(SdrDragStat
& rStat
);
283 virtual FASTBOOL
MovCreate(SdrDragStat
& rStat
);
284 virtual FASTBOOL
EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
);
285 virtual FASTBOOL
BckCreate(SdrDragStat
& rStat
);
286 virtual void BrkCreate(SdrDragStat
& rStat
);
287 virtual basegfx::B2DPolyPolygon
TakeCreatePoly(const SdrDragStat
& rDrag
) const;
288 virtual Pointer
GetCreatePointer() const;
289 virtual SdrObject
* DoConvertToPolyObj(BOOL bBezier
) const;
291 virtual sal_uInt32
GetSnapPointCount() const;
292 virtual Point
GetSnapPoint(sal_uInt32 i
) const;
293 virtual sal_Bool
IsPolyObj() const;
294 virtual sal_uInt32
GetPointCount() const;
295 virtual Point
GetPoint(sal_uInt32 i
) const;
296 virtual void NbcSetPoint(const Point
& rPnt
, sal_uInt32 i
);
298 virtual SdrObjGeoData
* NewGeoData() const;
299 virtual void SaveGeoData(SdrObjGeoData
& rGeo
) const;
300 virtual void RestGeoData(const SdrObjGeoData
& rGeo
);
302 /** updates edges that are connected to the edges of this object
303 as if the connected objects send a repaint broadcast
308 // helper methods for the StarOffice api
309 Point
GetTailPoint( BOOL bTail
) const;
310 void SetTailPoint( BOOL bTail
, const Point
& rPt
);
311 void setGluePointIndex( sal_Bool bTail
, sal_Int32 nId
= -1 );
312 sal_Int32
getGluePointIndex( sal_Bool bTail
);
314 virtual sal_Bool
TRGetBaseGeometry(basegfx::B2DHomMatrix
& rMatrix
, basegfx::B2DPolyPolygon
& rPolyPolygon
) const;
315 virtual void TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& rPolyPolygon
);
317 // for geometry access
318 ::basegfx::B2DPolygon
getEdgeTrack() const;
320 // helper method for SdrDragMethod::AddConnectorOverlays. Adds a overlay polygon for
321 // this connector to rResult.
322 basegfx::B2DPolygon
ImplAddConnectorOverlay(SdrDragMethod
& rDragMethod
, bool bTail1
, bool bTail2
, bool bDetail
) const;
325 ////////////////////////////////////////////////////////////////////////////////////////////////////
327 // Zur Bestimmung der Verlaufslinie werden folgende Item-Parameter des SdrItemPool verwendet:
329 // USHORT EdgeFlowAngle Default 9000 (=90.00 Deg), min 0, max 9000
330 // Verlauffreiheitswinkel.
331 // Der Winkel, in dem die Verbindungslinie verlaufen darf.
333 // USHORT EdgeEscAngle Default 9000 (=90.00 Deg), min 0, max 9000
334 // Objektaustrittswinkel.
335 // Der Winkel, in dem die Verbindungslinie aus dem Objekt austreten darf.
337 // BOOL EdgeEscAsRay Default FALSE
338 // TRUE= die Verbindungslinie tritt aus dem Obj Strahlenfoermig aus.
339 // Also Winkelvorgabe durch die Strecke ObjMitte/Konnektor.
341 // BOOL EdgeEscUseObjAngle Default FALSE
342 // Objektdrehwinkelberuecksichtigung.
343 // TRUE= Bei der Bestimmung des Objektaustrittswinkels wird der
344 // Drehwinkel des Objekts als Offset beruecksichtigt.
346 // ULONG EdgeFlowDefDist Default 0, min 0, max ?
347 // Das ist der Default-Mindestabstand der bei der Berechnung der
348 // Verbindungslinie zu den angedockten Objekten in logischen Einheiten.
349 // Dieser Abstand wird innerhalb des Objektes "ueberschrieben", sobald
350 // der User an den Linien draggd. Beim Andocken an ein neues Objekt wird
351 // dann jedoch wieder dieser Default verwendet.
354 // Allgemeines zu Konnektoren:
356 // Es gibt Knoten und Kantenobjekte. Zwei Knoten koennen durch eine Kante
357 // miteinander verbunden werden. Ist eine Kante nur an einem Ende an einen
358 // Knoten geklebt, ist das andere Ende auf einer absoluten Position im Doc
359 // fixiert. Ebenso ist es natuerlich auch moeglich, dass eine Kante an beiden
360 // Enden "frei", also nicht mit einem Knotenobjekt verbunden ist.
362 // Ein Kantenobjekt kann theoretisch auch gleichzeitig Knotenobjekt sein. In
363 // der ersten Version wird das jedoch noch nicht realisiert werden.
365 // Eine Verbindung zwischen Knoten und Kante kann hergestellt werden durch:
366 // - Interaktives erzeugen eines neuen Kantenobjekts an der SdrView wobei
367 // Anfangs- bzw. Endpunkt der Kante auf ein Konnektor (Klebestelle) eines
368 // bereits vorhandenen Knotenobjekts gelegt wird.
369 // - Interaktives draggen des Anfangs- bzw. Endpunkts eines bestehenden
370 // Kantenobjekts an der SdrView auf ein Konnektor (Klebestelle) eines
371 // bereits vorhandenen Knotenobjekts.
373 // Verschieben von Knotenobjekten stellt keine Verbindungen her. Ebenso auch
374 // nicht das direkte Verschieben von Kantenendpunkten am SdrModel...
375 // Verbindungen koennen auch hergestellt werden, wenn die Konnektoren an der
376 // View nicht sichtbar geschaltet sind.
378 // Eine vorhandene Verbindung zwischen Knoten und Kante bleibt erhalten bei:
379 // - Draggen (Move/Resize/Rotate/...) des Knotenobjekts
380 // - Verschieben einer Konnektorposition im Knotemobjekt
381 // - gleichzeitiges Draggen (Move/Resize/Rotate/...) von Knoten und Kante
383 // Eine Verbindung zwischen Knoten und Kante kann geloesst werden durch:
384 // - Loeschen eines der Objekte
385 // - Draggen des Kantenobjekts ohne gleichzeitiges Draggen des Knotens
386 // - Loeschen des Konnektors am Knotenobjekt
387 // - Undo/Redo/Repeat
388 // Beim Draggen muss die Aufforderung zum loesen der Verbindung von ausserhalb
389 // des Models befohlen werden (z.B. von der SdrView). SdrEdgeObj::Move() loesst
390 // die Verbindung nicht selbsttaetig.
392 // Jedes Knotenobjekt kann Konnektoren, sog. Klebestellen besitzen. Das sind die
393 // geometrischen Punkte, an denen das verbindende Kantenobjekt bei hergestellter
394 // Verbindung endet. Defaultmaessig hat jedes Objekt keine Konnektoren. Trotzdem
395 // kann man bei bestimmten View-Einstellungen eine Kante andocken, da dann z.B.
396 // an den 4 Scheitelpunkten des Knotenobjekts bei Bedarf automatisch Konnektoren
397 // generiert werden. Jedes Objekt liefert dafuer 2x4 sog. Default-Konnektorposi-
398 // tionen, 4 an den Scheitelpunkten und 4 an den Eckpositionen. Im Normalfall
399 // liegen diese an den 8 Handlepositionen; Ausnahmen bilden hier Ellipsen,
400 // Parallelogramme, ... . Darueberhinaus koennen auch an jedem Knotenobjekt
401 // anwenderspeziefische Konnektoren gesetzt werden.
403 // Dann gibt es noch die Moeglichkeit, ein Kante an einem Objekt mit dem
404 // Attribut "bUseBestConnector" anzudocken. Es wird dann aus dem Angebot der
405 // Konnektoren des Objekts oder/und der Scheitelpunkte, jeweils die fuer den
406 // Verlauf der Verbindungslinie guenstigste Konnektorposition verwendet. Der
407 // Anwender vergibt dieses Attribut, indem er den Knoten in seiner Mitte
408 // andockt (siehe z.B. Visio).
409 // 09-06-1996: bUseBestConnector verwendet nur Scheitelpunktklebepunkte.
411 // Und hier noch etwas Begriffsdefinition:
412 // Verbinder : Eben das Verbinderobjekt (Kantenobjekt)
413 // Knoten : Ein beliebiges Objekt, an dem ein Verbinder drangeklebt
414 // werden kann, z.B. ein Rechteck, ...
415 // Klebepunkt: Der Punkt, an dem der Verbinder an das Knotenobjekt
416 // geklebt wird. Hierbei gibt es:
417 // Scheitelpunktklebepunkte: Jedes Knotenobjekt hat diese
418 // Klebepunkte von Natur aus. Moeglicherweise gibt es
419 // im Draw bereits die Option "Automatisch ankleben an
420 // Objektscheitelpunkte" (default an)
421 // Eckpunktklebepunkte: Auch diese Klebepunkte sind den
422 // Objekten von mir bereits mitgegeben. Wie die oben
423 // erwaehnten gibt es fuer diese moeglicherweise
424 // bereits auch eine Option im Draw. (default aus)
425 // Scheitelpunktklebepunkte und Eckpunktklebepunkte sind
426 // im Gegensatz zu Visio nicht optisch sichtbar; sie
427 // sind eben einfach da (wenn Option eingeschaltet).
428 // Benutzerdefinierte Klebepunkte: Gibt es an jedem
429 // Knotenobjekt beliebig viele. Per Option koennen sie
430 // sichtbar geschaltet werden (beim editieren immer
431 // sichtbar). Zur Zeit sind die jedoch noch nicht ganz
432 // fertigimplementiert.
433 // Automatische Klebepunktwahl: Wird der Verbinder so an
434 // das Knotenobjekt gedockt, dass der schwarke Rahmen
435 // das gesamte Objekt umfasst, so versucht der
436 // Verbinder von den 4 Scheitelpunktklebepunkten (und
437 // zwar nur von denen) den guenstigsten herauszufinden.
439 //////////////////////////////////////////////////////////////////////////////////////////////////
441 #endif //_SVDOEDGE_HXX