diff options
Diffstat (limited to 'include/svx/svdoedge.hxx')
-rw-r--r-- | include/svx/svdoedge.hxx | 412 |
1 files changed, 412 insertions, 0 deletions
diff --git a/include/svx/svdoedge.hxx b/include/svx/svdoedge.hxx new file mode 100644 index 000000000..2320091ab --- /dev/null +++ b/include/svx/svdoedge.hxx @@ -0,0 +1,412 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_SVX_SVDOEDGE_HXX +#define INCLUDED_SVX_SVDOEDGE_HXX + +#include <memory> +#include <svx/svdotext.hxx> +#include <svx/svdglue.hxx> +#include <svx/svxdllapi.h> + + +class SdrDragMethod; +class SdrPageView; + +namespace sdr::properties { + class ConnectorProperties; +} + + +/// Utility class SdrObjConnection +class SdrObjConnection final +{ + friend class SdrEdgeObj; + friend class ImpEdgeHdl; + friend class SdrCreateView; + + Point aObjOfs; // set during dragging of a node + SdrObject* pObj; // referenced object + sal_uInt16 nConId; // connector number + + bool bBestConn : 1; // true -> the best-matching connector is searched for + bool bBestVertex : 1; // true -> the best-matching vertex to connect is searched for + bool bAutoVertex : 1; // autoConnector at apex nCon + bool bAutoCorner : 1; // autoConnector at corner nCon + +public: + SdrObjConnection() { ResetVars(); } + + void ResetVars(); + bool TakeGluePoint(SdrGluePoint& rGP) const; + + void SetBestConnection( bool rB ) { bBestConn = rB; }; + void SetBestVertex( bool rB ) { bBestVertex = rB; }; + void SetAutoVertex( bool rB ) { bAutoVertex = rB; }; + void SetConnectorId( sal_uInt16 nId ) { nConId = nId; }; + + bool IsBestConnection() const { return bBestConn; }; + bool IsAutoVertex() const { return bAutoVertex; }; + sal_uInt16 GetConnectorId() const { return nConId; }; + SdrObject* GetObject() const { return pObj; } +}; + + +enum class SdrEdgeLineCode { Obj1Line2, Obj1Line3, Obj2Line2, Obj2Line3, MiddleLine }; + +/// Utility class SdrEdgeInfoRec +class SdrEdgeInfoRec +{ +public: + // The 5 distances are set on dragging or via SetAttr and are + // evaluated by ImpCalcEdgeTrack. Only 0-3 longs are transported + // via Get/SetAttr/Get/SetStyleSh though. + Point aObj1Line2; + Point aObj1Line3; + Point aObj2Line2; + Point aObj2Line3; + Point aMiddleLine; + + // Following values are set by ImpCalcEdgeTrack + long nAngle1; // exit angle at Obj1 + long nAngle2; // exit angle at Obj2 + sal_uInt16 nObj1Lines; // 1..3 + sal_uInt16 nObj2Lines; // 1..3 + sal_uInt16 nMiddleLine; // 0xFFFF=none, otherwise point number of the beginning of the line + +public: + SdrEdgeInfoRec() + : nAngle1(0), + nAngle2(0), + nObj1Lines(0), + nObj2Lines(0), + nMiddleLine(0xFFFF) + {} + + Point& ImpGetLineOffsetPoint(SdrEdgeLineCode eLineCode); + sal_uInt16 ImpGetPolyIdx(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const; + bool ImpIsHorzLine(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const; + void ImpSetLineOffset(SdrEdgeLineCode eLineCode, const XPolygon& rXP, long nVal); + long ImpGetLineOffset(SdrEdgeLineCode eLineCode, const XPolygon& rXP) const; +}; + + +/// Utility class SdrEdgeObjGeoData +class SdrEdgeObjGeoData final : public SdrTextObjGeoData +{ +public: + SdrObjConnection aCon1; // connection status of the beginning of the line + SdrObjConnection aCon2; // connection status of the end of the line + std::unique_ptr<XPolygon> pEdgeTrack; + bool bEdgeTrackDirty; // true -> connector track needs to be recalculated + bool bEdgeTrackUserDefined; + SdrEdgeInfoRec aEdgeInfo; + +public: + SdrEdgeObjGeoData(); + virtual ~SdrEdgeObjGeoData() override; +}; + + +/// Utility class SdrEdgeObj +class SVXCORE_DLLPUBLIC SdrEdgeObj : public SdrTextObj +{ +private: + // to allow sdr::properties::ConnectorProperties access to ImpSetAttrToEdgeInfo() + friend class sdr::properties::ConnectorProperties; + + friend class SdrCreateView; + friend class ImpEdgeHdl; + +protected: + virtual std::unique_ptr<sdr::contact::ViewContact> CreateObjectSpecificViewContact() override; + virtual std::unique_ptr<sdr::properties::BaseProperties> CreateObjectSpecificProperties() override; + + SdrObjConnection aCon1; // Connection status of the beginning of the line + SdrObjConnection aCon2; // Connection status of the end of the line + + std::unique_ptr<XPolygon> pEdgeTrack; + sal_uInt16 nNotifyingCount; // Locking + SdrEdgeInfoRec aEdgeInfo; + + bool bEdgeTrackDirty : 1; // true -> Connection track needs to be recalculated + bool bEdgeTrackUserDefined : 1; + + // Bool to allow suppression of default connects at object + // inside test (HitTest) and object center test (see ImpFindConnector()) + bool mbSuppressDefaultConnect : 1; + + // Flag value for avoiding infinite loops when calculating + // BoundRects from ring-connected connectors. A coloring algorithm + // is used here. When the GetCurrentBoundRect() calculation of a + // SdrEdgeObj is running, the flag is set, else it is always + // false. + bool mbBoundRectCalculationRunning : 1; + + // #i123048# need to remember if layouting was suppressed before to get + // to a correct state for first real layouting + bool mbSuppressed : 1; + +public: + // Interface to default connect suppression + void SetSuppressDefaultConnect(bool bNew) { mbSuppressDefaultConnect = bNew; } + bool GetSuppressDefaultConnect() const { return mbSuppressDefaultConnect; } + +protected: + virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override; + + static XPolygon ImpCalcObjToCenter(const Point& rStPt, long nEscAngle, const tools::Rectangle& rRect, const Point& rCenter); + void ImpRecalcEdgeTrack(); // recalculation of the connection track + XPolygon ImpCalcEdgeTrack(const XPolygon& rTrack0, SdrObjConnection& rCon1, SdrObjConnection& rCon2, SdrEdgeInfoRec* pInfo) const; + XPolygon ImpCalcEdgeTrack(const Point& rPt1, long nAngle1, const tools::Rectangle& rBoundRect1, const tools::Rectangle& rBewareRect1, + const Point& rPt2, long nAngle2, const tools::Rectangle& rBoundRect2, const tools::Rectangle& rBewareRect2, + sal_uIntPtr* pnQuality, SdrEdgeInfoRec* pInfo) const; + static bool ImpFindConnector(const Point& rPt, const SdrPageView& rPV, SdrObjConnection& rCon, const SdrEdgeObj* pThis, OutputDevice* pOut=nullptr); + static SdrEscapeDirection ImpCalcEscAngle(SdrObject const * pObj, const Point& aPt2); + void ImpSetTailPoint(bool bTail1, const Point& rPt); + void ImpUndirtyEdgeTrack(); // potential recalculation of the connection track + void ImpDirtyEdgeTrack(); // invalidate connector path, so it will be recalculated next time + void ImpSetAttrToEdgeInfo(); // copying values from the pool to aEdgeInfo + void ImpSetEdgeInfoToAttr(); // copying values from the aEdgeInfo to the pool + + // protected destructor + virtual ~SdrEdgeObj() override; + +public: + SdrEdgeObj(SdrModel& rSdrModel); + + // react on model/page change + virtual void handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage) override; + + SdrObjConnection& GetConnection(bool bTail1) { return *(bTail1 ? &aCon1 : &aCon2); } + virtual void TakeObjInfo(SdrObjTransformInfoRec& rInfo) const override; + virtual sal_uInt16 GetObjIdentifier() const override; + virtual const tools::Rectangle& GetCurrentBoundRect() const override; + virtual const tools::Rectangle& GetSnapRect() const override; + virtual SdrGluePoint GetVertexGluePoint(sal_uInt16 nNum) const override; + virtual SdrGluePoint GetCornerGluePoint(sal_uInt16 nNum) const override; + virtual const SdrGluePointList* GetGluePointList() const override; + virtual SdrGluePointList* ForceGluePointList() override; + + // * for all of the below: bTail1=true: beginning of the line, + // otherwise end of the line + // * pObj=NULL: disconnect connector + void SetEdgeTrackDirty() { bEdgeTrackDirty=true; } + void ConnectToNode(bool bTail1, SdrObject* pObj) override; + void DisconnectFromNode(bool bTail1) override; + SdrObject* GetConnectedNode(bool bTail1) const override; + const SdrObjConnection& GetConnection(bool bTail1) const { return *(bTail1 ? &aCon1 : &aCon2); } + bool CheckNodeConnection(bool bTail1) const; + + virtual void RecalcSnapRect() override; + virtual void TakeUnrotatedSnapRect(tools::Rectangle& rRect) const override; + virtual SdrEdgeObj* CloneSdrObject(SdrModel& rTargetModel) const override; + SdrEdgeObj& operator=(const SdrEdgeObj& rObj); + virtual OUString TakeObjNameSingul() const override; + virtual OUString TakeObjNamePlural() const override; + + void SetEdgeTrackPath( const basegfx::B2DPolyPolygon& rPoly ); + basegfx::B2DPolyPolygon GetEdgeTrackPath() const; + + virtual basegfx::B2DPolyPolygon TakeXorPoly() const override; + virtual sal_uInt32 GetHdlCount() const override; + virtual void AddToHdlList(SdrHdlList& rHdlList) const override; + + // special drag methods + virtual bool hasSpecialDrag() const override; + virtual bool beginSpecialDrag(SdrDragStat& rDrag) const override; + virtual bool applySpecialDrag(SdrDragStat& rDrag) override; + virtual OUString getSpecialDragComment(const SdrDragStat& rDrag) const override; + + // FullDrag support + virtual SdrObjectUniquePtr getFullDragClone() const override; + + virtual void NbcSetSnapRect(const tools::Rectangle& rRect) override; + virtual void NbcMove(const Size& aSize) override; + virtual void NbcResize(const Point& rRefPnt, const Fraction& aXFact, const Fraction& aYFact) override; + + // #i54102# added rotate, mirror and shear support + virtual void NbcRotate(const Point& rRef, long nAngle, double sn, double cs) override; + virtual void NbcMirror(const Point& rRef1, const Point& rRef2) override; + virtual void NbcShear(const Point& rRef, long nAngle, double tn, bool bVShear) override; + + // #102344# Added missing implementation + virtual void NbcSetAnchorPos(const Point& rPnt) override; + + virtual bool BegCreate(SdrDragStat& rStat) override; + virtual bool MovCreate(SdrDragStat& rStat) override; + virtual bool EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) override; + virtual bool BckCreate(SdrDragStat& rStat) override; + virtual void BrkCreate(SdrDragStat& rStat) override; + virtual basegfx::B2DPolyPolygon TakeCreatePoly(const SdrDragStat& rDrag) const override; + virtual PointerStyle GetCreatePointer() const override; + virtual SdrObjectUniquePtr DoConvertToPolyObj(bool bBezier, bool bAddText) const override; + + virtual sal_uInt32 GetSnapPointCount() const override; + virtual Point GetSnapPoint(sal_uInt32 i) const override; + virtual bool IsPolyObj() const override; + virtual sal_uInt32 GetPointCount() const override; + virtual Point GetPoint(sal_uInt32 i) const override; + virtual void NbcSetPoint(const Point& rPnt, sal_uInt32 i) override; + + virtual SdrObjGeoData* NewGeoData() const override; + virtual void SaveGeoData(SdrObjGeoData& rGeo) const override; + virtual void RestGeoData(const SdrObjGeoData& rGeo) override; + + /** updates edges that are connected to the edges of this object + as if the connected objects send a repaint broadcast + #103122# + */ + void Reformat(); + + // helper methods for the StarOffice api + Point GetTailPoint( bool bTail ) const; + void SetTailPoint( bool bTail, const Point& rPt ); + void setGluePointIndex( bool bTail, sal_Int32 nId = -1 ); + sal_Int32 getGluePointIndex( bool bTail ); + + virtual bool TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& rPolyPolygon) const override; + virtual void TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& rPolyPolygon) override; + + // for geometry access + ::basegfx::B2DPolygon getEdgeTrack() const; + + // helper method for SdrDragMethod::AddConnectorOverlays. Adds an overlay polygon for + // this connector to rResult. + basegfx::B2DPolygon ImplAddConnectorOverlay(SdrDragMethod& rDragMethod, bool bTail1, bool bTail2, bool bDetail) const; +}; + + // The following item parameters of the SdrItemPool are used to + // determine the actual connector line routing: + // + // sal_uInt16 EdgeFlowAngle default 9000 (= 90.00 deg), min 0, max 9000 + // Clearance angle. + // The angle at which the connecting line may run. + // + // sal_uInt16 EdgeEscAngle default 9000 (= 90.00 Deg), min 0, max 9000 + // Object exit angle. + // The angle at which the connection line may exit from the object. + // + // bool EdgeEscAsRay default false + // true -> the connecting line emerges from the object radially. + // Thus, angle specification by the line ObjCenter / connector. + // + // bool EdgeEscUseObjAngle default false + // Object rotation angle is considered + // true -> when determining the connector exit angle, angle for + // object rotation is taken as an offset. + // + // sal_uIntPtr EdgeFlowDefDist default 0, min 0, max ? + // This is the default minimum distance on calculation of the + // connection Line to the docked objects is in logical units. + // This distance is overridden within the object, as soon as the + // user drags on the lines. When docking onto a new object, + // however, this default is used again. + // + // + // General Information About Connectors: + // + // There are nodes and edge objects. Two nodes can be joined by an + // edge. If a connector is connected to a node only at one end, the + // other end is fixed to an absolute position in the document. It is + // of course also possible for a connector to be "free" at both ends, + // i.e. not connected to a node object on each side. + // + // A connector object can also theoretically be a node object at the + // same time. In the first version, however, this will not yet be + // realized. + // + // A connection between node and connector edge can be established by: + // - Interactive creation of a new edge object at the SdrView where + // the beginning or end point of the edge is placed on a connector + // (glueing point) of an already existing node object. + // - Interactive dragging of the beginning or end point of an + // existing connector edge object on the SdrView to a connector + // (glueing point) of an already existing node object. + // - Undo/Redo + // Moving node objects does not make any connections. Also not the + // direct shifting of edge endpoints on the SdrModel... Connections + // can also be established, if the connectors are not configured to + // be visible in the view. + // + // An existing connection between node and edge is retained for: + // - Dragging (Move/Resize/Rotate/...) of the node object + // - Moving a connector position in the node object + // - Simultaneous dragging (Move/Resize/Rotate/...) of the node and the + // edge + // + // A connection between node and edge can be removed by: + // - Deleting one of the objects + // - Dragging the edge object without simultaneously dragging the node + // - Deleting the connector at the node object + // - Undo/Redo/Repeat + // When dragging, the request to remove the connection must be + // requested from outside of the model (for example, from the + // SdrView). SdrEdgeObj::Move() itself does not remove the + // connection. + // + // Each node object can have connectors, so-called glue points. These + // are the geometric points at which the connecting edge object ends + // when the connection is established. By default, each object has no + // connectors. Nevertheless, one can dock an edge in certain view + // settings since then, e.g., connectors can be automatically + // generated at the 4 vertices of the node object when needed. Each + // object provides 2x4 so-called default connector positions, 4 at + // the vertices and 4 at the corner positions. In the normal case, + // these are located at the 8 handle positions; exceptions here are + // ellipses, parallelograms, ... . In addition, user-specific + // connectors can be set for each node object. + // + // Then there is also the possibility to dock an edge on an object + // with the attribute "bUseBestConnector". The best-matching + // connector position for the routing of the connection line is then + // used from the offering of connectors of the object or/and of the + // vertices. The user assigns this attribute by docking the node in + // its center (see, e.g., Visio). + // 09-06-1996: bUseBestConnector uses vertex glue points only. + // + // And here is some terminology: + // Connector : The connector object (edge object) + // Node : Any object to which a connector can be glued to, e.g., a rectangle, + // etc. + // Glue point: The point at which the connector is glued to the node object. + // There are: + // Vertex glue points: Each node object presents these glue + // points inherently. Perhaps there is already the option + // "automatically glue to object vertex" in Draw (default is + // on). + // Corner glue points: These glue points, too, are already + // auto-enabled on objects. Similar to the ones above, + // there may already be an option for them in Draw (default is + // off). + // In contrast to Visio, vertex glue points and corner glue + // points are not displayed in the UI; they are simply there (if + // the option is activated). + // Custom glue points: Any number of them are present on each + // node object. They can be made visible using the option + // (always visible when editing). At the moment, however, they + // are not yet fully implemented. + // Automatic glue point selection: If the connector is docked + // to the node object so that the black frame encompasses the + // entire object, then the connector tries to find the most + // convenient of the 4 vertex glue points (and only of those). + +#endif // INCLUDED_SVX_SVDOEDGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |