1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_SVX_SVDOEDGE_HXX
21 #define INCLUDED_SVX_SVDOEDGE_HXX
23 #include <svx/svdotext.hxx>
24 #include <svx/svdglue.hxx>
25 #include <svx/svxdllapi.h>
28 // Vorausdeklarationen
34 namespace sdr
{ namespace properties
{
35 class ConnectorProperties
;
39 // Hilfsklasse SdrObjConnection
42 class SdrObjConnection
44 friend class SdrEdgeObj
;
45 friend class ImpEdgeHdl
;
46 friend class SdrCreateView
;
49 Point aObjOfs
; // Wird beim Draggen eines Knotens gesetzt
50 SdrObject
* pObj
; // Referenziertes Objekt
51 long nXDist
; // Hor. Objektabstand wenn bXDistOvr=TRUE
52 long nYDist
; // Vert. Objektabstand wenn bYDistOvr=TRUE
53 sal_uInt16 nConId
; // Konnektornummer
56 bool bBestConn
: 1; // sal_True= es wird der guenstigste Konnektor gesucht
57 bool bBestVertex
: 1; // sal_True= es wird der guenstigste Scheitelpunkt zum konnekten gesucht
58 bool bXDistOvr
: 1; // sal_True= Hor. Objektabstand wurde gedragt (Overwrite)
59 bool bYDistOvr
: 1; // sal_True= Vert. Objektabstand wurde gedragt (Overwrite)
60 bool bAutoVertex
: 1; // AutoConnector am Scheitelpunkt nCon
61 bool bAutoCorner
: 1; // AutoConnector am Eckpunkt nCon
64 SdrObjConnection() { ResetVars(); }
65 SVX_DLLPUBLIC
~SdrObjConnection();
68 bool TakeGluePoint(SdrGluePoint
& rGP
, bool bSetAbsolutePos
) const;
70 inline void SetBestConnection( bool rB
) { bBestConn
= rB
; };
71 inline void SetBestVertex( bool rB
) { bBestVertex
= rB
; };
72 inline void SetAutoVertex( bool rB
) { bAutoVertex
= rB
; };
73 inline void SetConnectorId( sal_uInt16 nId
) { nConId
= nId
; };
75 inline bool IsBestConnection() const { return bBestConn
; };
76 inline bool IsBestVertex() const { return bBestVertex
; };
77 inline bool IsAutoVertex() const { return bAutoVertex
; };
78 inline sal_uInt16
GetConnectorId() const { return nConId
; };
79 inline SdrObject
* GetObject() const { return pObj
; }
83 // Hilfsklasse SdrEdgeInfoRec
86 enum SdrEdgeLineCode
{OBJ1LINE2
,OBJ1LINE3
,OBJ2LINE2
,OBJ2LINE3
,MIDDLELINE
};
91 // Die 5 Distanzen werden beim draggen bzw. per SetAttr gesetzt und von
92 // ImpCalcEdgeTrack ausgewertet. Per Get/SetAttr/Get/SetStyleSh werden
93 // jedoch nur 0-3 longs transportiert.
100 // Nachfolgende Werte werden von ImpCalcEdgeTrack gesetzt
101 long nAngle1
; // Austrittswinkel am Obj1
102 long nAngle2
; // Austrittswinkel am Obj2
103 sal_uInt16 nObj1Lines
; // 1..3
104 sal_uInt16 nObj2Lines
; // 1..3
105 sal_uInt16 nMiddleLine
; // 0xFFFF=keine, sonst Punktnummer des Linienbeginns
106 char cOrthoForm
; // Form des Ortho-Verbindes, z.B. 'Z','U',I','L','S',...
118 Point
& ImpGetLineVersatzPoint(SdrEdgeLineCode eLineCode
);
119 const Point
& ImpGetLineVersatzPoint(SdrEdgeLineCode eLineCode
) const { return const_cast<SdrEdgeInfoRec
*>(this)->ImpGetLineVersatzPoint(eLineCode
); }
120 sal_uInt16
ImpGetPolyIdx(SdrEdgeLineCode eLineCode
, const XPolygon
& rXP
) const;
121 bool ImpIsHorzLine(SdrEdgeLineCode eLineCode
, const XPolygon
& rXP
) const;
122 void ImpSetLineVersatz(SdrEdgeLineCode eLineCode
, const XPolygon
& rXP
, long nVal
);
123 long ImpGetLineVersatz(SdrEdgeLineCode eLineCode
, const XPolygon
& rXP
) const;
127 // Hilfsklasse SdrEdgeObjGeoData
130 class SdrEdgeObjGeoData
: public SdrTextObjGeoData
133 SdrObjConnection aCon1
; // Verbindungszustand des Linienanfangs
134 SdrObjConnection aCon2
; // Verbindungszustand des Linienendes
135 XPolygon
* pEdgeTrack
;
136 bool bEdgeTrackDirty
;// sal_True=Verbindungsverlauf muss neu berechnet werden.
137 bool bEdgeTrackUserDefined
;
138 SdrEdgeInfoRec aEdgeInfo
;
142 virtual ~SdrEdgeObjGeoData();
146 // Hilfsklasse SdrEdgeObj
149 class SVX_DLLPUBLIC SdrEdgeObj
: public SdrTextObj
152 // to allow sdr::properties::ConnectorProperties access to ImpSetAttrToEdgeInfo()
153 friend class sdr::properties::ConnectorProperties
;
155 friend class SdrCreateView
;
156 friend class ImpEdgeHdl
;
159 virtual sdr::contact::ViewContact
* CreateObjectSpecificViewContact() SAL_OVERRIDE
;
160 virtual sdr::properties::BaseProperties
* CreateObjectSpecificProperties() SAL_OVERRIDE
;
162 SdrObjConnection aCon1
; // Verbindungszustand des Linienanfangs
163 SdrObjConnection aCon2
; // Verbindungszustand des Linienendes
165 XPolygon
* pEdgeTrack
;
166 sal_uInt16 nNotifyingCount
; // Verrieglung
167 SdrEdgeInfoRec aEdgeInfo
;
170 bool bEdgeTrackDirty
: 1; // sal_True=Verbindungsverlauf muss neu berechnet werden.
171 bool bEdgeTrackUserDefined
: 1;
174 // Bool to allow supporession of default connects at object
175 // inside test (HitTest) and object center test (see ImpFindConnector())
176 bool mbSuppressDefaultConnect
: 1;
179 // Flag value for avoiding death loops when calculating BoundRects
180 // from circularly connected connectors. A coloring algorithm is used
181 // here. When the GetCurrentBoundRect() calculation of a SdrEdgeObj
182 // is running, the flag is set, else it is always sal_False.
183 bool mbBoundRectCalculationRunning
: 1;
185 // #i123048# need to remember if layouting was suppressed before to get
186 // to a correct state for first real layouting
187 bool mbSuppressed
: 1;
191 // Interface to default connect suppression
192 void SetSuppressDefaultConnect(bool bNew
) { mbSuppressDefaultConnect
= bNew
; }
193 bool GetSuppressDefaultConnect() const { return mbSuppressDefaultConnect
; }
196 bool IsBoundRectCalculationRunning() const { return mbBoundRectCalculationRunning
; }
199 virtual void Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
) SAL_OVERRIDE
;
201 static XPolygon
ImpCalcObjToCenter(const Point
& rStPt
, long nEscAngle
, const Rectangle
& rRect
, const Point
& rCenter
);
202 void ImpRecalcEdgeTrack(); // Neuberechnung des Verbindungsverlaufs
203 XPolygon
ImpCalcEdgeTrack(const XPolygon
& rTrack0
, SdrObjConnection
& rCon1
, SdrObjConnection
& rCon2
, SdrEdgeInfoRec
* pInfo
) const;
204 XPolygon
ImpCalcEdgeTrack(const Point
& rPt1
, long nAngle1
, const Rectangle
& rBoundRect1
, const Rectangle
& rBewareRect1
,
205 const Point
& rPt2
, long nAngle2
, const Rectangle
& rBoundRect2
, const Rectangle
& rBewareRect2
,
206 sal_uIntPtr
* pnQuality
, SdrEdgeInfoRec
* pInfo
) const;
207 static bool ImpFindConnector(const Point
& rPt
, const SdrPageView
& rPV
, SdrObjConnection
& rCon
, const SdrEdgeObj
* pThis
, OutputDevice
* pOut
=NULL
);
208 static SdrEscapeDirection
ImpCalcEscAngle(SdrObject
* pObj
, const Point
& aPt2
);
209 void ImpSetTailPoint(bool bTail1
, const Point
& rPt
);
210 void ImpUndirtyEdgeTrack(); // eventuelle Neuberechnung des Verbindungsverlaufs
211 void ImpDirtyEdgeTrack(); // invalidate connector path, so it will be recalculated next time
212 void ImpSetAttrToEdgeInfo(); // Werte vom Pool nach aEdgeInfo kopieren
213 void ImpSetEdgeInfoToAttr(); // Werte vom aEdgeInfo in den Pool kopieren
219 virtual ~SdrEdgeObj();
221 SdrObjConnection
& GetConnection(bool bTail1
) { return *(bTail1
? &aCon1
: &aCon2
); }
222 virtual void TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const SAL_OVERRIDE
;
223 virtual sal_uInt16
GetObjIdentifier() const SAL_OVERRIDE
;
224 virtual const Rectangle
& GetCurrentBoundRect() const SAL_OVERRIDE
;
225 virtual const Rectangle
& GetSnapRect() const SAL_OVERRIDE
;
226 virtual bool IsNode() const SAL_OVERRIDE
;
227 virtual SdrGluePoint
GetVertexGluePoint(sal_uInt16 nNum
) const SAL_OVERRIDE
;
228 virtual SdrGluePoint
GetCornerGluePoint(sal_uInt16 nNum
) const SAL_OVERRIDE
;
229 virtual const SdrGluePointList
* GetGluePointList() const SAL_OVERRIDE
;
230 virtual SdrGluePointList
* ForceGluePointList() SAL_OVERRIDE
;
231 virtual bool IsEdge() const SAL_OVERRIDE
;
233 // bTail1=TRUE: Linienanfang, sonst LinienEnde
234 // pObj=NULL: Disconnect
235 void SetEdgeTrackDirty() { bEdgeTrackDirty
=true; }
236 void ConnectToNode(bool bTail1
, SdrObject
* pObj
) SAL_OVERRIDE
;
237 void DisconnectFromNode(bool bTail1
) SAL_OVERRIDE
;
238 SdrObject
* GetConnectedNode(bool bTail1
) const SAL_OVERRIDE
;
239 const SdrObjConnection
& GetConnection(bool bTail1
) const { return *(bTail1
? &aCon1
: &aCon2
); }
240 bool CheckNodeConnection(bool bTail1
) const;
242 virtual void RecalcSnapRect() SAL_OVERRIDE
;
243 virtual void TakeUnrotatedSnapRect(Rectangle
& rRect
) const SAL_OVERRIDE
;
244 virtual SdrEdgeObj
* Clone() const SAL_OVERRIDE
;
245 SdrEdgeObj
& operator=(const SdrEdgeObj
& rObj
);
246 virtual OUString
TakeObjNameSingul() const SAL_OVERRIDE
;
247 virtual OUString
TakeObjNamePlural() const SAL_OVERRIDE
;
249 void SetEdgeTrackPath( const basegfx::B2DPolyPolygon
& rPoly
);
250 basegfx::B2DPolyPolygon
GetEdgeTrackPath() const;
252 virtual basegfx::B2DPolyPolygon
TakeXorPoly() const SAL_OVERRIDE
;
253 virtual sal_uInt32
GetHdlCount() const SAL_OVERRIDE
;
254 virtual SdrHdl
* GetHdl(sal_uInt32 nHdlNum
) const SAL_OVERRIDE
;
256 // special drag methods
257 virtual bool hasSpecialDrag() const SAL_OVERRIDE
;
258 virtual bool beginSpecialDrag(SdrDragStat
& rDrag
) const SAL_OVERRIDE
;
259 virtual bool applySpecialDrag(SdrDragStat
& rDrag
) SAL_OVERRIDE
;
260 virtual OUString
getSpecialDragComment(const SdrDragStat
& rDrag
) const SAL_OVERRIDE
;
263 virtual SdrObject
* getFullDragClone() const SAL_OVERRIDE
;
265 virtual void NbcSetSnapRect(const Rectangle
& rRect
) SAL_OVERRIDE
;
266 virtual void NbcMove(const Size
& aSize
) SAL_OVERRIDE
;
267 virtual void NbcResize(const Point
& rRefPnt
, const Fraction
& aXFact
, const Fraction
& aYFact
) SAL_OVERRIDE
;
269 // #i54102# added rotate, mirrorn and shear support
270 virtual void NbcRotate(const Point
& rRef
, long nAngle
, double sn
, double cs
) SAL_OVERRIDE
;
271 virtual void NbcMirror(const Point
& rRef1
, const Point
& rRef2
) SAL_OVERRIDE
;
272 virtual void NbcShear(const Point
& rRef
, long nAngle
, double tn
, bool bVShear
) SAL_OVERRIDE
;
274 // #102344# Added missing implementation
275 virtual void NbcSetAnchorPos(const Point
& rPnt
) SAL_OVERRIDE
;
277 virtual bool BegCreate(SdrDragStat
& rStat
) SAL_OVERRIDE
;
278 virtual bool MovCreate(SdrDragStat
& rStat
) SAL_OVERRIDE
;
279 virtual bool EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
) SAL_OVERRIDE
;
280 virtual bool BckCreate(SdrDragStat
& rStat
) SAL_OVERRIDE
;
281 virtual void BrkCreate(SdrDragStat
& rStat
) SAL_OVERRIDE
;
282 virtual basegfx::B2DPolyPolygon
TakeCreatePoly(const SdrDragStat
& rDrag
) const SAL_OVERRIDE
;
283 virtual Pointer
GetCreatePointer() const SAL_OVERRIDE
;
284 virtual SdrObject
* DoConvertToPolyObj(bool bBezier
, bool bAddText
) const SAL_OVERRIDE
;
286 virtual sal_uInt32
GetSnapPointCount() const SAL_OVERRIDE
;
287 virtual Point
GetSnapPoint(sal_uInt32 i
) const SAL_OVERRIDE
;
288 virtual bool IsPolyObj() const SAL_OVERRIDE
;
289 virtual sal_uInt32
GetPointCount() const SAL_OVERRIDE
;
290 virtual Point
GetPoint(sal_uInt32 i
) const SAL_OVERRIDE
;
291 virtual void NbcSetPoint(const Point
& rPnt
, sal_uInt32 i
) SAL_OVERRIDE
;
293 virtual SdrObjGeoData
* NewGeoData() const SAL_OVERRIDE
;
294 virtual void SaveGeoData(SdrObjGeoData
& rGeo
) const SAL_OVERRIDE
;
295 virtual void RestGeoData(const SdrObjGeoData
& rGeo
) SAL_OVERRIDE
;
297 /** updates edges that are connected to the edges of this object
298 as if the connected objects send a repaint broadcast
303 // helper methods for the StarOffice api
304 Point
GetTailPoint( bool bTail
) const;
305 void SetTailPoint( bool bTail
, const Point
& rPt
);
306 void setGluePointIndex( bool bTail
, sal_Int32 nId
= -1 );
307 sal_Int32
getGluePointIndex( bool bTail
);
309 virtual bool TRGetBaseGeometry(basegfx::B2DHomMatrix
& rMatrix
, basegfx::B2DPolyPolygon
& rPolyPolygon
) const SAL_OVERRIDE
;
310 virtual void TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& rPolyPolygon
) SAL_OVERRIDE
;
312 // for geometry access
313 ::basegfx::B2DPolygon
getEdgeTrack() const;
315 // helper method for SdrDragMethod::AddConnectorOverlays. Adds a overlay polygon for
316 // this connector to rResult.
317 basegfx::B2DPolygon
ImplAddConnectorOverlay(SdrDragMethod
& rDragMethod
, bool bTail1
, bool bTail2
, bool bDetail
) const;
320 // Zur Bestimmung der Verlaufslinie werden folgende Item-Parameter des SdrItemPool verwendet:
322 // sal_uInt16 EdgeFlowAngle Default 9000 (=90.00 Deg), min 0, max 9000
323 // Verlauffreiheitswinkel.
324 // Der Winkel, in dem die Verbindungslinie verlaufen darf.
326 // sal_uInt16 EdgeEscAngle Default 9000 (=90.00 Deg), min 0, max 9000
327 // Objektaustrittswinkel.
328 // Der Winkel, in dem die Verbindungslinie aus dem Objekt austreten darf.
330 // bool EdgeEscAsRay Default FALSE
331 // sal_True= die Verbindungslinie tritt aus dem Obj Strahlenfoermig aus.
332 // Also Winkelvorgabe durch die Strecke ObjMitte/Konnektor.
334 // bool EdgeEscUseObjAngle Default FALSE
335 // Objektdrehwinkelberuecksichtigung.
336 // sal_True= Bei der Bestimmung des Objektaustrittswinkels wird der
337 // Drehwinkel des Objekts als Offset beruecksichtigt.
339 // sal_uIntPtr EdgeFlowDefDist Default 0, min 0, max ?
340 // Das ist der Default-Mindestabstand der bei der Berechnung der
341 // Verbindungslinie zu den angedockten Objekten in logischen Einheiten.
342 // Dieser Abstand wird innerhalb des Objektes "ueberschrieben", sobald
343 // der User an den Linien draggd. Beim Andocken an ein neues Objekt wird
344 // dann jedoch wieder dieser Default verwendet.
347 // Allgemeines zu Konnektoren:
349 // Es gibt Knoten und Kantenobjekte. Zwei Knoten koennen durch eine Kante
350 // miteinander verbunden werden. Ist eine Kante nur an einem Ende an einen
351 // Knoten geklebt, ist das andere Ende auf einer absoluten Position im Doc
352 // fixiert. Ebenso ist es natuerlich auch moeglich, dass eine Kante an beiden
353 // Enden "frei", also nicht mit einem Knotenobjekt verbunden ist.
355 // Ein Kantenobjekt kann theoretisch auch gleichzeitig Knotenobjekt sein. In
356 // der ersten Version wird das jedoch noch nicht realisiert werden.
358 // Eine Verbindung zwischen Knoten und Kante kann hergestellt werden durch:
359 // - Interaktives erzeugen eines neuen Kantenobjekts an der SdrView wobei
360 // Anfangs- bzw. Endpunkt der Kante auf ein Konnektor (Klebestelle) eines
361 // bereits vorhandenen Knotenobjekts gelegt wird.
362 // - Interaktives draggen des Anfangs- bzw. Endpunkts eines bestehenden
363 // Kantenobjekts an der SdrView auf ein Konnektor (Klebestelle) eines
364 // bereits vorhandenen Knotenobjekts.
366 // Verschieben von Knotenobjekten stellt keine Verbindungen her. Ebenso auch
367 // nicht das direkte Verschieben von Kantenendpunkten am SdrModel...
368 // Verbindungen koennen auch hergestellt werden, wenn die Konnektoren an der
369 // View nicht sichtbar geschaltet sind.
371 // Eine vorhandene Verbindung zwischen Knoten und Kante bleibt erhalten bei:
372 // - Draggen (Move/Resize/Rotate/...) des Knotenobjekts
373 // - Verschieben einer Konnektorposition im Knotemobjekt
374 // - gleichzeitiges Draggen (Move/Resize/Rotate/...) von Knoten und Kante
376 // Eine Verbindung zwischen Knoten und Kante kann geloesst werden durch:
377 // - Loeschen eines der Objekte
378 // - Draggen des Kantenobjekts ohne gleichzeitiges Draggen des Knotens
379 // - Loeschen des Konnektors am Knotenobjekt
380 // - Undo/Redo/Repeat
381 // Beim Draggen muss die Aufforderung zum loesen der Verbindung von ausserhalb
382 // des Models befohlen werden (z.B. von der SdrView). SdrEdgeObj::Move() loesst
383 // die Verbindung nicht selbsttaetig.
385 // Jedes Knotenobjekt kann Konnektoren, sog. Klebestellen besitzen. Das sind die
386 // geometrischen Punkte, an denen das verbindende Kantenobjekt bei hergestellter
387 // Verbindung endet. Defaultmaessig hat jedes Objekt keine Konnektoren. Trotzdem
388 // kann man bei bestimmten View-Einstellungen eine Kante andocken, da dann z.B.
389 // an den 4 Scheitelpunkten des Knotenobjekts bei Bedarf automatisch Konnektoren
390 // generiert werden. Jedes Objekt liefert dafuer 2x4 sog. Default-Konnektorposi-
391 // tionen, 4 an den Scheitelpunkten und 4 an den Eckpositionen. Im Normalfall
392 // liegen diese an den 8 Handlepositionen; Ausnahmen bilden hier Ellipsen,
393 // Parallelogramme, ... . Darueberhinaus koennen auch an jedem Knotenobjekt
394 // anwenderspeziefische Konnektoren gesetzt werden.
396 // Dann gibt es noch die Moeglichkeit, ein Kante an einem Objekt mit dem
397 // Attribut "bUseBestConnector" anzudocken. Es wird dann aus dem Angebot der
398 // Konnektoren des Objekts oder/und der Scheitelpunkte, jeweils die fuer den
399 // Verlauf der Verbindungslinie guenstigste Konnektorposition verwendet. Der
400 // Anwender vergibt dieses Attribut, indem er den Knoten in seiner Mitte
401 // andockt (siehe z.B. Visio).
402 // 09-06-1996: bUseBestConnector verwendet nur Scheitelpunktklebepunkte.
404 // Und hier noch etwas Begriffsdefinition:
405 // Verbinder : Eben das Verbinderobjekt (Kantenobjekt)
406 // Knoten : Ein beliebiges Objekt, an dem ein Verbinder drangeklebt
407 // werden kann, z.B. ein Rechteck, ...
408 // Klebepunkt: Der Punkt, an dem der Verbinder an das Knotenobjekt
409 // geklebt wird. Hierbei gibt es:
410 // Scheitelpunktklebepunkte: Jedes Knotenobjekt hat diese
411 // Klebepunkte von Natur aus. Moeglicherweise gibt es
412 // im Draw bereits die Option "Automatisch ankleben an
413 // Objektscheitelpunkte" (default an)
414 // Eckpunktklebepunkte: Auch diese Klebepunkte sind den
415 // Objekten von mir bereits mitgegeben. Wie die oben
416 // erwaehnten gibt es fuer diese moeglicherweise
417 // bereits auch eine Option im Draw. (default aus)
418 // Scheitelpunktklebepunkte und Eckpunktklebepunkte sind
419 // im Gegensatz zu Visio nicht optisch sichtbar; sie
420 // sind eben einfach da (wenn Option eingeschaltet).
421 // Benutzerdefinierte Klebepunkte: Gibt es an jedem
422 // Knotenobjekt beliebig viele. Per Option koennen sie
423 // sichtbar geschaltet werden (beim editieren immer
424 // sichtbar). Zur Zeit sind die jedoch noch nicht ganz
425 // fertigimplementiert.
426 // Automatische Klebepunktwahl: Wird der Verbinder so an
427 // das Knotenobjekt gedockt, dass der schwarke Rahmen
428 // das gesamte Objekt umfasst, so versucht der
429 // Verbinder von den 4 Scheitelpunktklebepunkten (und
430 // zwar nur von denen) den guenstigsten herauszufinden.
432 #endif // INCLUDED_SVX_SVDOEDGE_HXX
434 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */