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