summaryrefslogtreecommitdiffstats
path: root/include/svx/svdoedge.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'include/svx/svdoedge.hxx')
-rw-r--r--include/svx/svdoedge.hxx411
1 files changed, 411 insertions, 0 deletions
diff --git a/include/svx/svdoedge.hxx b/include/svx/svdoedge.hxx
new file mode 100644
index 000000000..6e3acb339
--- /dev/null
+++ b/include/svx/svdoedge.hxx
@@ -0,0 +1,411 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <memory>
+#include <optional>
+#include <svx/svdotext.hxx>
+#include <svx/svdglue.hxx>
+#include <svx/svxdllapi.h>
+#include <svx/xpoly.hxx>
+
+
+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
+ tools::Long nAngle1; // exit angle at Obj1
+ tools::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, tools::Long nVal);
+ tools::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::optional<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 final : public SdrTextObj
+{
+private:
+ // to allow sdr::properties::ConnectorProperties access to ImpSetAttrToEdgeInfo()
+ friend class sdr::properties::ConnectorProperties;
+
+ friend class SdrCreateView;
+ friend class ImpEdgeHdl;
+
+ 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::optional<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; }
+
+private:
+ virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
+
+ static XPolygon ImpCalcObjToCenter(const Point& rStPt, tools::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, tools::Long nAngle1, const tools::Rectangle& rBoundRect1, const tools::Rectangle& rBewareRect1,
+ const Point& rPt2, tools::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, SdrDragStat* pDragStat = 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);
+ // Copy constructor
+ SdrEdgeObj(SdrModel& rSdrModel, SdrEdgeObj const & rSource);
+
+ // 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 SdrObjKind 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;
+ 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, Degree100 nAngle, double sn, double cs) override;
+ virtual void NbcMirror(const Point& rRef1, const Point& rRef2) override;
+ virtual void NbcShear(const Point& rRef, Degree100 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 std::unique_ptr<SdrObjGeoData> NewGeoData() const override;
+ virtual void SaveGeoData(SdrObjGeoData& rGeo) const override;
+ virtual void RestoreGeoData(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(const 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 gluepoints. 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 gluepoints 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.
+ // Gluepoint: The point at which the connector is glued to the node object.
+ // There are:
+ // Vertex gluepoints: 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 gluepoints: These gluepoints, 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 gluepoints and corner glue
+ // points are not displayed in the UI; they are simply there (if
+ // the option is activated).
+ // Custom gluepoints: 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 gluepoint 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 gluepoints (and only of those).
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */