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