1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 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/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 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 . 18 */ 19 20 #ifndef INCLUDED_SVX_SVDOEDGE_HXX 21 #define INCLUDED_SVX_SVDOEDGE_HXX 22 23 #include <memory> 24 #include <svx/svdotext.hxx> 25 #include <svx/svdglue.hxx> 26 #include <svx/svxdllapi.h> 27 28 29 class SdrDragMethod; 30 class SdrPageView; 31 32 namespace sdr::properties { 33 class ConnectorProperties; 34 } 35 36 37 /// Utility class SdrObjConnection 38 class SdrObjConnection final 39 { 40 friend class SdrEdgeObj; 41 friend class ImpEdgeHdl; 42 friend class SdrCreateView; 43 44 Point aObjOfs; // set during dragging of a node 45 SdrObject* pObj; // referenced object 46 sal_uInt16 nConId; // connector number 47 48 bool bBestConn : 1; // true -> the best-matching connector is searched for 49 bool bBestVertex : 1; // true -> the best-matching vertex to connect is searched for 50 bool bAutoVertex : 1; // autoConnector at apex nCon 51 bool bAutoCorner : 1; // autoConnector at corner nCon 52 53 public: SdrObjConnection()54 SdrObjConnection() { ResetVars(); } 55 56 void ResetVars(); 57 bool TakeGluePoint(SdrGluePoint& rGP) const; 58 SetBestConnection(bool rB)59 void SetBestConnection( bool rB ) { bBestConn = rB; }; SetBestVertex(bool rB)60 void SetBestVertex( bool rB ) { bBestVertex = rB; }; SetAutoVertex(bool rB)61 void SetAutoVertex( bool rB ) { bAutoVertex = rB; }; SetConnectorId(sal_uInt16 nId)62 void SetConnectorId( sal_uInt16 nId ) { nConId = nId; }; 63 IsBestConnection() const64 bool IsBestConnection() const { return bBestConn; }; IsAutoVertex() const65 bool IsAutoVertex() const { return bAutoVertex; }; GetConnectorId() const66 sal_uInt16 GetConnectorId() const { return nConId; }; GetObject() const67 SdrObject* GetObject() const { return pObj; } 68 }; 69 70 71 enum class SdrEdgeLineCode { Obj1Line2, Obj1Line3, Obj2Line2, Obj2Line3, MiddleLine }; 72 73 /// Utility class SdrEdgeInfoRec 74 class SdrEdgeInfoRec 75 { 76 public: 77 // The 5 distances are set on dragging or via SetAttr and are 78 // evaluated by ImpCalcEdgeTrack. Only 0-3 longs are transported 79 // via Get/SetAttr/Get/SetStyleSh though. 80 Point aObj1Line2; 81 Point aObj1Line3; 82 Point aObj2Line2; 83 Point aObj2Line3; 84 Point aMiddleLine; 85 86 // Following values are set by ImpCalcEdgeTrack 87 tools::Long nAngle1; // exit angle at Obj1 88 tools::Long nAngle2; // exit angle at Obj2 89 sal_uInt16 nObj1Lines; // 1..3 90 sal_uInt16 nObj2Lines; // 1..3 91 sal_uInt16 nMiddleLine; // 0xFFFF=none, otherwise point number of the beginning of the line 92 93 public: SdrEdgeInfoRec()94 SdrEdgeInfoRec() 95 : nAngle1(0), 96 nAngle2(0), 97 nObj1Lines(0), 98 nObj2Lines(0), 99 nMiddleLine(0xFFFF) 100 {} 101 102 Point& ImpGetLineOffsetPoint(SdrEdgeLineCode eLineCode); 103 sal_uInt16 ImpGetPolyIdx(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const; 104 bool ImpIsHorzLine(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const; 105 void ImpSetLineOffset(SdrEdgeLineCode eLineCode, const XPolygon& rXP, tools::Long nVal); 106 tools::Long ImpGetLineOffset(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const; 107 }; 108 109 110 /// Utility class SdrEdgeObjGeoData 111 class SdrEdgeObjGeoData final : public SdrTextObjGeoData 112 { 113 public: 114 SdrObjConnection aCon1; // connection status of the beginning of the line 115 SdrObjConnection aCon2; // connection status of the end of the line 116 std::unique_ptr<XPolygon> pEdgeTrack; 117 bool bEdgeTrackDirty; // true -> connector track needs to be recalculated 118 bool bEdgeTrackUserDefined; 119 SdrEdgeInfoRec aEdgeInfo; 120 121 public: 122 SdrEdgeObjGeoData(); 123 virtual ~SdrEdgeObjGeoData() override; 124 }; 125 126 127 /// Utility class SdrEdgeObj 128 class SVXCORE_DLLPUBLIC SdrEdgeObj : public SdrTextObj 129 { 130 private: 131 // to allow sdr::properties::ConnectorProperties access to ImpSetAttrToEdgeInfo() 132 friend class sdr::properties::ConnectorProperties; 133 134 friend class SdrCreateView; 135 friend class ImpEdgeHdl; 136 137 protected: 138 virtual std::unique_ptr<sdr::contact::ViewContact> CreateObjectSpecificViewContact() override; 139 virtual std::unique_ptr<sdr::properties::BaseProperties> CreateObjectSpecificProperties() override; 140 141 SdrObjConnection aCon1; // Connection status of the beginning of the line 142 SdrObjConnection aCon2; // Connection status of the end of the line 143 144 std::unique_ptr<XPolygon> pEdgeTrack; 145 sal_uInt16 nNotifyingCount; // Locking 146 SdrEdgeInfoRec aEdgeInfo; 147 148 bool bEdgeTrackDirty : 1; // true -> Connection track needs to be recalculated 149 bool bEdgeTrackUserDefined : 1; 150 151 // Bool to allow suppression of default connects at object 152 // inside test (HitTest) and object center test (see ImpFindConnector()) 153 bool mbSuppressDefaultConnect : 1; 154 155 // Flag value for avoiding infinite loops when calculating 156 // BoundRects from ring-connected connectors. A coloring algorithm 157 // is used here. When the GetCurrentBoundRect() calculation of a 158 // SdrEdgeObj is running, the flag is set, else it is always 159 // false. 160 bool mbBoundRectCalculationRunning : 1; 161 162 // #i123048# need to remember if layouting was suppressed before to get 163 // to a correct state for first real layouting 164 bool mbSuppressed : 1; 165 166 public: 167 // Interface to default connect suppression SetSuppressDefaultConnect(bool bNew)168 void SetSuppressDefaultConnect(bool bNew) { mbSuppressDefaultConnect = bNew; } GetSuppressDefaultConnect() const169 bool GetSuppressDefaultConnect() const { return mbSuppressDefaultConnect; } 170 171 protected: 172 virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override; 173 174 static XPolygon ImpCalcObjToCenter(const Point& rStPt, tools::Long nEscAngle, const tools::Rectangle& rRect, const Point& rCenter); 175 void ImpRecalcEdgeTrack(); // recalculation of the connection track 176 XPolygon ImpCalcEdgeTrack(const XPolygon& rTrack0, SdrObjConnection& rCon1, SdrObjConnection& rCon2, SdrEdgeInfoRec* pInfo) const; 177 XPolygon ImpCalcEdgeTrack(const Point& rPt1, tools::Long nAngle1, const tools::Rectangle& rBoundRect1, const tools::Rectangle& rBewareRect1, 178 const Point& rPt2, tools::Long nAngle2, const tools::Rectangle& rBoundRect2, const tools::Rectangle& rBewareRect2, 179 sal_uIntPtr* pnQuality, SdrEdgeInfoRec* pInfo) const; 180 static bool ImpFindConnector(const Point& rPt, const SdrPageView& rPV, SdrObjConnection& rCon, const SdrEdgeObj* pThis, OutputDevice* pOut=nullptr, SdrDragStat* pDragStat = nullptr); 181 static SdrEscapeDirection ImpCalcEscAngle(SdrObject const * pObj, const Point& aPt2); 182 void ImpSetTailPoint(bool bTail1, const Point& rPt); 183 void ImpUndirtyEdgeTrack(); // potential recalculation of the connection track 184 void ImpDirtyEdgeTrack(); // invalidate connector path, so it will be recalculated next time 185 void ImpSetAttrToEdgeInfo(); // copying values from the pool to aEdgeInfo 186 void ImpSetEdgeInfoToAttr(); // copying values from the aEdgeInfo to the pool 187 188 // protected destructor 189 virtual ~SdrEdgeObj() override; 190 191 public: 192 SdrEdgeObj(SdrModel& rSdrModel); 193 // Copy constructor 194 SdrEdgeObj(SdrModel& rSdrModel, SdrEdgeObj const & rSource); 195 196 // react on model/page change 197 virtual void handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage) override; 198 GetConnection(bool bTail1)199 SdrObjConnection& GetConnection(bool bTail1) { return *(bTail1 ? &aCon1 : &aCon2); } 200 virtual void TakeObjInfo(SdrObjTransformInfoRec& rInfo) const override; 201 virtual SdrObjKind GetObjIdentifier() const override; 202 virtual const tools::Rectangle& GetCurrentBoundRect() const override; 203 virtual const tools::Rectangle& GetSnapRect() const override; 204 virtual SdrGluePoint GetVertexGluePoint(sal_uInt16 nNum) const override; 205 virtual SdrGluePoint GetCornerGluePoint(sal_uInt16 nNum) const override; 206 virtual const SdrGluePointList* GetGluePointList() const override; 207 virtual SdrGluePointList* ForceGluePointList() override; 208 209 // * for all of the below: bTail1=true: beginning of the line, 210 // otherwise end of the line 211 // * pObj=NULL: disconnect connector SetEdgeTrackDirty()212 void SetEdgeTrackDirty() { bEdgeTrackDirty=true; } 213 void ConnectToNode(bool bTail1, SdrObject* pObj) override; 214 void DisconnectFromNode(bool bTail1) override; 215 SdrObject* GetConnectedNode(bool bTail1) const override; GetConnection(bool bTail1) const216 const SdrObjConnection& GetConnection(bool bTail1) const { return *(bTail1 ? &aCon1 : &aCon2); } 217 bool CheckNodeConnection(bool bTail1) const; 218 219 virtual void RecalcSnapRect() override; 220 virtual void TakeUnrotatedSnapRect(tools::Rectangle& rRect) const override; 221 virtual SdrEdgeObj* CloneSdrObject(SdrModel& rTargetModel) const override; 222 virtual OUString TakeObjNameSingul() const override; 223 virtual OUString TakeObjNamePlural() const override; 224 225 void SetEdgeTrackPath( const basegfx::B2DPolyPolygon& rPoly ); 226 basegfx::B2DPolyPolygon GetEdgeTrackPath() const; 227 228 virtual basegfx::B2DPolyPolygon TakeXorPoly() const override; 229 virtual sal_uInt32 GetHdlCount() const override; 230 virtual void AddToHdlList(SdrHdlList& rHdlList) const override; 231 232 // special drag methods 233 virtual bool hasSpecialDrag() const override; 234 virtual bool beginSpecialDrag(SdrDragStat& rDrag) const override; 235 virtual bool applySpecialDrag(SdrDragStat& rDrag) override; 236 virtual OUString getSpecialDragComment(const SdrDragStat& rDrag) const override; 237 238 // FullDrag support 239 virtual SdrObjectUniquePtr getFullDragClone() const override; 240 241 virtual void NbcSetSnapRect(const tools::Rectangle& rRect) override; 242 virtual void NbcMove(const Size& aSize) override; 243 virtual void NbcResize(const Point& rRefPnt, const Fraction& aXFact, const Fraction& aYFact) override; 244 245 // #i54102# added rotate, mirror and shear support 246 virtual void NbcRotate(const Point& rRef, Degree100 nAngle, double sn, double cs) override; 247 virtual void NbcMirror(const Point& rRef1, const Point& rRef2) override; 248 virtual void NbcShear(const Point& rRef, Degree100 nAngle, double tn, bool bVShear) override; 249 250 // #102344# Added missing implementation 251 virtual void NbcSetAnchorPos(const Point& rPnt) override; 252 253 virtual bool BegCreate(SdrDragStat& rStat) override; 254 virtual bool MovCreate(SdrDragStat& rStat) override; 255 virtual bool EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) override; 256 virtual bool BckCreate(SdrDragStat& rStat) override; 257 virtual void BrkCreate(SdrDragStat& rStat) override; 258 virtual basegfx::B2DPolyPolygon TakeCreatePoly(const SdrDragStat& rDrag) const override; 259 virtual PointerStyle GetCreatePointer() const override; 260 virtual SdrObjectUniquePtr DoConvertToPolyObj(bool bBezier, bool bAddText) const override; 261 262 virtual sal_uInt32 GetSnapPointCount() const override; 263 virtual Point GetSnapPoint(sal_uInt32 i) const override; 264 virtual bool IsPolyObj() const override; 265 virtual sal_uInt32 GetPointCount() const override; 266 virtual Point GetPoint(sal_uInt32 i) const override; 267 virtual void NbcSetPoint(const Point& rPnt, sal_uInt32 i) override; 268 269 virtual std::unique_ptr<SdrObjGeoData> NewGeoData() const override; 270 virtual void SaveGeoData(SdrObjGeoData& rGeo) const override; 271 virtual void RestoreGeoData(const SdrObjGeoData& rGeo) override; 272 273 /** updates edges that are connected to the edges of this object 274 as if the connected objects send a repaint broadcast 275 #103122# 276 */ 277 void Reformat(); 278 279 // helper methods for the StarOffice api 280 Point GetTailPoint( bool bTail ) const; 281 void SetTailPoint( bool bTail, const Point& rPt ); 282 void setGluePointIndex( bool bTail, sal_Int32 nId = -1 ); 283 sal_Int32 getGluePointIndex( bool bTail ); 284 285 virtual bool TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& rPolyPolygon) const override; 286 virtual void TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& rPolyPolygon) override; 287 288 // for geometry access 289 ::basegfx::B2DPolygon getEdgeTrack() const; 290 291 // helper method for SdrDragMethod::AddConnectorOverlays. Adds an overlay polygon for 292 // this connector to rResult. 293 basegfx::B2DPolygon ImplAddConnectorOverlay(SdrDragMethod& rDragMethod, bool bTail1, bool bTail2, bool bDetail) const; 294 }; 295 296 // The following item parameters of the SdrItemPool are used to 297 // determine the actual connector line routing: 298 // 299 // sal_uInt16 EdgeFlowAngle default 9000 (= 90.00 deg), min 0, max 9000 300 // Clearance angle. 301 // The angle at which the connecting line may run. 302 // 303 // sal_uInt16 EdgeEscAngle default 9000 (= 90.00 Deg), min 0, max 9000 304 // Object exit angle. 305 // The angle at which the connection line may exit from the object. 306 // 307 // bool EdgeEscAsRay default false 308 // true -> the connecting line emerges from the object radially. 309 // Thus, angle specification by the line ObjCenter / connector. 310 // 311 // bool EdgeEscUseObjAngle default false 312 // Object rotation angle is considered 313 // true -> when determining the connector exit angle, angle for 314 // object rotation is taken as an offset. 315 // 316 // sal_uIntPtr EdgeFlowDefDist default 0, min 0, max ? 317 // This is the default minimum distance on calculation of the 318 // connection Line to the docked objects is in logical units. 319 // This distance is overridden within the object, as soon as the 320 // user drags on the lines. When docking onto a new object, 321 // however, this default is used again. 322 // 323 // 324 // General Information About Connectors: 325 // 326 // There are nodes and edge objects. Two nodes can be joined by an 327 // edge. If a connector is connected to a node only at one end, the 328 // other end is fixed to an absolute position in the document. It is 329 // of course also possible for a connector to be "free" at both ends, 330 // i.e. not connected to a node object on each side. 331 // 332 // A connector object can also theoretically be a node object at the 333 // same time. In the first version, however, this will not yet be 334 // realized. 335 // 336 // A connection between node and connector edge can be established by: 337 // - Interactive creation of a new edge object at the SdrView where 338 // the beginning or end point of the edge is placed on a connector 339 // (glueing point) of an already existing node object. 340 // - Interactive dragging of the beginning or end point of an 341 // existing connector edge object on the SdrView to a connector 342 // (glueing point) of an already existing node object. 343 // - Undo/Redo 344 // Moving node objects does not make any connections. Also not the 345 // direct shifting of edge endpoints on the SdrModel... Connections 346 // can also be established, if the connectors are not configured to 347 // be visible in the view. 348 // 349 // An existing connection between node and edge is retained for: 350 // - Dragging (Move/Resize/Rotate/...) of the node object 351 // - Moving a connector position in the node object 352 // - Simultaneous dragging (Move/Resize/Rotate/...) of the node and the 353 // edge 354 // 355 // A connection between node and edge can be removed by: 356 // - Deleting one of the objects 357 // - Dragging the edge object without simultaneously dragging the node 358 // - Deleting the connector at the node object 359 // - Undo/Redo/Repeat 360 // When dragging, the request to remove the connection must be 361 // requested from outside of the model (for example, from the 362 // SdrView). SdrEdgeObj::Move() itself does not remove the 363 // connection. 364 // 365 // Each node object can have connectors, so-called glue points. These 366 // are the geometric points at which the connecting edge object ends 367 // when the connection is established. By default, each object has no 368 // connectors. Nevertheless, one can dock an edge in certain view 369 // settings since then, e.g., connectors can be automatically 370 // generated at the 4 vertices of the node object when needed. Each 371 // object provides 2x4 so-called default connector positions, 4 at 372 // the vertices and 4 at the corner positions. In the normal case, 373 // these are located at the 8 handle positions; exceptions here are 374 // ellipses, parallelograms, ... . In addition, user-specific 375 // connectors can be set for each node object. 376 // 377 // Then there is also the possibility to dock an edge on an object 378 // with the attribute "bUseBestConnector". The best-matching 379 // connector position for the routing of the connection line is then 380 // used from the offering of connectors of the object or/and of the 381 // vertices. The user assigns this attribute by docking the node in 382 // its center (see, e.g., Visio). 383 // 09-06-1996: bUseBestConnector uses vertex glue points only. 384 // 385 // And here is some terminology: 386 // Connector : The connector object (edge object) 387 // Node : Any object to which a connector can be glued to, e.g., a rectangle, 388 // etc. 389 // Glue point: The point at which the connector is glued to the node object. 390 // There are: 391 // Vertex glue points: Each node object presents these glue 392 // points inherently. Perhaps there is already the option 393 // "automatically glue to object vertex" in Draw (default is 394 // on). 395 // Corner glue points: These glue points, too, are already 396 // auto-enabled on objects. Similar to the ones above, 397 // there may already be an option for them in Draw (default is 398 // off). 399 // In contrast to Visio, vertex glue points and corner glue 400 // points are not displayed in the UI; they are simply there (if 401 // the option is activated). 402 // Custom glue points: Any number of them are present on each 403 // node object. They can be made visible using the option 404 // (always visible when editing). At the moment, however, they 405 // are not yet fully implemented. 406 // Automatic glue point selection: If the connector is docked 407 // to the node object so that the black frame encompasses the 408 // entire object, then the connector tries to find the most 409 // convenient of the 4 vertex glue points (and only of those). 410 411 #endif // INCLUDED_SVX_SVDOEDGE_HXX 412 413 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 414