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_SVDSNPV_HXX 21 #define INCLUDED_SVX_SVDSNPV_HXX 22 23 #include <svx/svdpntv.hxx> 24 #include <svx/svdhlpln.hxx> 25 #include <svx/svxdllapi.h> 26 #include <o3tl/typed_flags_set.hxx> 27 28 /** 29 * Definition: 30 * - snap something means e.g. the mouse pointer or some marked objects in drag can be snapped 31 * - snap on something means you can e.g. snap on the grid or on auxiliary lines 32 * 33 * 34 * Basically, we only catch visible elements (borders, helper lines, connectors), 35 * with the exception of the grid. Likewise, we can only catch visible elements (i.e. connectors). 36 * We only catch on the grid, if nothing else is close by (magnetic behaviour). 37 * 38 * The cursor which is used during creation of objects, while dragging polygon points 39 * etc. (i.e. the mouse cursor) is always caught on all enabled catch alternatives (max 6). 40 * 41 * This is different, when moving selected objects. Instead of one mouse cursor, there are 42 * four alternatives, which can be caught at the selected objects: 43 * 1. the logically enclosing frame of every single object 44 * 2. the logically enclosing frame of all selected objects 45 * 3. highlighted points of all selected objects (polygon points, ...) 46 * 4. the connectors of the selected objects 47 * 48 * As the first and second case exclude each other (the second is a refinement of the first one) 49 * three alternatives remain, which are independent from each other. For 6 possible values for the 50 * caught ones, we would end up with max. 18 different possible combinations! 51 * 52 * Therefore, we introduce the following simplifications: 53 * 1. Connectors only catch on connectors 54 * 55 * Only max. 2*5+1 = 11 combinations remain for MoveDrag: 56 * 1-3. enclosing frame on grid/border/helper lines 57 * 4. enclosing frame on highlighted object points 58 * 5. enclosing frame on enclosing frame 59 * 6-8. highlighted points on grid/border/helper lines 60 * 7. highlighted points on highlighted object points 61 * 8-10. highlighted points on enclosing frame 62 * 11. connectors on connectors 63 * 64 * We test for all of these possible 11 combinations in the MouseMove event in the DragMove 65 * and those with the least need of correction are carried out. 66 * 67 * In the Resize() etc. methods we only catch the logically enclosing frame of the highlighted objects. 68 */ 69 70 /** Return value for SnapPos() method */ 71 enum class SdrSnap 72 { 73 NOTSNAPPED = 0x00, 74 XSNAPPED = 0x01, 75 YSNAPPED = 0x02 76 }; 77 namespace o3tl 78 { 79 template<> struct typed_flags<SdrSnap> : is_typed_flags<SdrSnap, 3> {}; 80 } 81 82 // TODO SdrCrookMode::Stretch is not implemented yet! 83 enum class SdrCrookMode { 84 Rotate, 85 Slant, 86 Stretch 87 }; 88 89 90 // #114409#-1 Migrate PageOrigin 91 class ImplPageOriginOverlay; 92 93 class SVX_DLLPUBLIC SdrSnapView : public SdrPaintView 94 { 95 protected: 96 // #114409#-1 Migrate PageOrigin 97 class ImplPageOriginOverlay* mpPageOriginOverlay; 98 99 // #114409#-2 Migrate HelpLine 100 class ImplHelpLineOverlay* mpHelpLineOverlay; 101 102 Size aMagnSiz; 103 Fraction aSnapWdtX; 104 Fraction aSnapWdtY; 105 106 sal_uInt16 nMagnSizPix; 107 long nSnapAngle; 108 long nEliminatePolyPointLimitAngle; 109 110 SdrCrookMode eCrookMode; 111 112 bool bSnapEnab : 1; 113 bool bGridSnap : 1; 114 bool bBordSnap : 1; 115 bool bHlplSnap : 1; 116 bool bOFrmSnap : 1; 117 bool bOPntSnap : 1; 118 bool bOConSnap : 1; 119 bool bMoveSnapOnlyTopLeft : 1; // Special for dialogeditor 120 bool bOrtho : 1; 121 bool bBigOrtho : 1; 122 bool bAngleSnapEnab : 1; 123 bool bMoveOnlyDragging : 1; // only move objects while Resize/Rotate/... 124 bool bSlantButShear : 1; // use slant instead of shear 125 bool bCrookNoContortion : 1; // no contorsion while Crook 126 bool bEliminatePolyPoints : 1; 127 128 protected: 129 // #i71538# make constructors of SdrView sub-components protected to avoid incomplete incarnations which may get casted to SdrView 130 SdrSnapView( 131 SdrModel& rSdrModel, 132 OutputDevice* pOut); 133 134 virtual ~SdrSnapView() override; 135 136 public: 137 virtual bool IsAction() const override; 138 virtual void MovAction(const Point& rPnt) override; 139 virtual void EndAction() override; 140 virtual void BckAction() override; 141 virtual void BrkAction() override; // break actions for derived classes e.g. interrupt dragging. 142 virtual void TakeActionRect(tools::Rectangle& rRect) const override; 143 SetSnapGridWidth(const Fraction & rX,const Fraction & rY)144 void SetSnapGridWidth(const Fraction& rX, const Fraction& rY) { aSnapWdtX=rX; aSnapWdtY=rY; } GetSnapGridWidthX() const145 const Fraction& GetSnapGridWidthX() const { return aSnapWdtX; } GetSnapGridWidthY() const146 const Fraction& GetSnapGridWidthY() const { return aSnapWdtY; } 147 SetSnapMagnetic(const Size & rSiz)148 void SetSnapMagnetic(const Size& rSiz) { if (rSiz!=aMagnSiz) { aMagnSiz=rSiz; } } SetSnapMagneticPixel(sal_uInt16 nPix)149 void SetSnapMagneticPixel(sal_uInt16 nPix) { nMagnSizPix=nPix; } GetSnapMagneticPixel() const150 sal_uInt16 GetSnapMagneticPixel() const { return nMagnSizPix; } 151 152 // RecalcLogicSnapMagnetic has to be called for every change of OutputDevices and every change of the MapMode! RecalcLogicSnapMagnetic(const OutputDevice & rOut)153 void RecalcLogicSnapMagnetic(const OutputDevice& rOut) { SetSnapMagnetic(rOut.PixelToLogic(Size(nMagnSizPix,nMagnSizPix))); } SetActualWin(const OutputDevice * pWin)154 void SetActualWin(const OutputDevice* pWin) { SdrPaintView::SetActualWin(pWin); if (pWin!=nullptr) RecalcLogicSnapMagnetic(*pWin); } 155 156 // Coordinates referred to the view! 157 // Returnvalues are SdrSnap::NOTSNAPPED,SdrSnap::XSNAPPED, 158 // SdrSnap::YSNAPPED or SdrSnap::XYSNAPPED 159 SdrSnap SnapPos(Point& rPnt, const SdrPageView* pPV) const; 160 Point GetSnapPos(const Point& rPnt, const SdrPageView* pPV) const; 161 void CheckSnap(const Point& rPt, long& nBestXSnap, long& nBestYSnap, bool& bXSnapped, bool& bYSnapped) const; 162 163 // All attitudes to snap are persistent. IsSnapEnabled() const164 bool IsSnapEnabled() const { return bSnapEnab; } IsGridSnap() const165 bool IsGridSnap() const { return bGridSnap; } // Snap to grid IsBordSnap() const166 bool IsBordSnap() const { return bBordSnap; } // Snap to border IsHlplSnap() const167 bool IsHlplSnap() const { return bHlplSnap; } // Snap to auxiliary line IsOFrmSnap() const168 bool IsOFrmSnap() const { return bOFrmSnap; } // Snap to LogFram from surrounding drawing objects IsOPntSnap() const169 bool IsOPntSnap() const { return bOPntSnap; } // Snap to distinct points from surrounding drawing objects IsOConSnap() const170 bool IsOConSnap() const { return bOConSnap; } // Snap to connectors of the drawing objects SetSnapEnabled(bool bOn)171 void SetSnapEnabled(bool bOn) { bSnapEnab=bOn; } SetGridSnap(bool bOn)172 void SetGridSnap(bool bOn) { bGridSnap=bOn; } SetBordSnap(bool bOn)173 void SetBordSnap(bool bOn) { bBordSnap=bOn; } SetHlplSnap(bool bOn)174 void SetHlplSnap(bool bOn) { bHlplSnap=bOn; } SetOFrmSnap(bool bOn)175 void SetOFrmSnap(bool bOn) { bOFrmSnap=bOn; } SetOPntSnap(bool bOn)176 void SetOPntSnap(bool bOn) { bOPntSnap=bOn; } SetOConSnap(bool bOn)177 void SetOConSnap(bool bOn) { bOConSnap=bOn; } 178 179 // Usually every 4 corners of Object-SnapRects are snapped for Move-Dragging. 180 // The following attitudes e.g. if you only want to snap the left corner on the top (e.g. DialogEditor) 181 // persistent, Default=FALSE. SetMoveSnapOnlyTopLeft(bool bOn)182 void SetMoveSnapOnlyTopLeft(bool bOn) { bMoveSnapOnlyTopLeft=bOn; } IsMoveSnapOnlyTopLeft() const183 bool IsMoveSnapOnlyTopLeft() const { return bMoveSnapOnlyTopLeft; } 184 185 // #114409#-1 Migrate PageOrigin 186 void BegSetPageOrg(const Point& rPnt); 187 void MovSetPageOrg(const Point& rPnt); 188 void EndSetPageOrg(); 189 void BrkSetPageOrg(); IsSetPageOrg() const190 bool IsSetPageOrg() const { return (nullptr != mpPageOriginOverlay); } 191 192 // HitTest. If sal_True, in rnHelpLineNum is the number of the auxiliary line and in rpPv 193 // the appended PageView. 194 bool PickHelpLine(const Point& rPnt, short nTol, const OutputDevice& rOut, sal_uInt16& rnHelpLineNum, SdrPageView*& rpPV) const; 195 196 // Move of an available auxiliary line. Use nHelpLineNum and pPV from PickHelpLine. 197 bool BegDragHelpLine(sal_uInt16 nHelpLineNum, SdrPageView* pPV); 198 // interactive insertion of a new auxiliary line 199 void BegDragHelpLine(const Point& rPnt, SdrHelpLineKind eNewKind); 200 PointerStyle GetDraggedHelpLinePointer() const; 201 202 // change the type of auxiliary line while dragging 203 // void SetDraggedHelpLineKind(SdrHelpLineKind eNewKind); 204 void MovDragHelpLine(const Point& rPnt); 205 bool EndDragHelpLine(); 206 void BrkDragHelpLine(); IsDragHelpLine() const207 bool IsDragHelpLine() const { return (nullptr != mpHelpLineOverlay); } 208 209 // SnapAngle is for angles in circle, RotateDragging, ... 210 // The snapping of an angle is beared down, if it is switched off 211 // with SetAngleSnapEnabled(sal_False) 212 // The snapping angles is independent of snapping coordinates 213 // and so independent of the attitude IsSnapEnabled() 214 // Only values should be specified for them is applied: 215 // 36000 modulo nAngle = 0 216 // Implemented for: 217 // - Rotate (Dragging) 218 // - Shear (Dragging) 219 // - circular arc/-sector/-section angle (Create and Dragging) 220 // persistent. SetAngleSnapEnabled(bool bOn)221 void SetAngleSnapEnabled(bool bOn) { bAngleSnapEnab=bOn; } IsAngleSnapEnabled() const222 bool IsAngleSnapEnabled() const { return bAngleSnapEnab; } SetSnapAngle(long nAngle)223 void SetSnapAngle(long nAngle) { nSnapAngle=nAngle; } GetSnapAngle() const224 long GetSnapAngle() const { return nSnapAngle; } 225 226 // different effects from Ortho (depending on the context): 227 // - Create 228 // - only lines in 45deg grid 229 // - instead of rectangles squares are created 230 // - instead of ellipse circles are created 231 // - Dragging 232 // - general Dragging 233 // - Move only horizontal, vertical or 45deg 234 // - Resize proportional 235 // - Mirror: nothing 236 // - Shear without Resize 237 // - Crook without Resize 238 // - move handles 239 // - mirror axis only 45deg grid 240 // - object-specific Dragging 241 // - rectangle corner radius: nothing 242 // - circle object angle: nothing 243 // - line keeps while Dragging the angle and is only stretched/ contracted 244 // Default value for Ortho is off. persistent. SetOrtho(bool bOn)245 void SetOrtho(bool bOn) { bOrtho=bOn; } // incomplete IsOrtho() const246 bool IsOrtho() const { return bOrtho; } 247 248 // BigOrtho is only relevant if Ortho is switched on. 249 // Example: rectangle is created and ortho is switched on (--> square) 250 // and the Mouse was dragged from zero to the coordinates 251 // (80,30). Now there are 2 alternatives to determine the edge length 252 // of the square: 30 and 80. 253 // The standard Ortho-Function took 30 (every time the smaller length) 254 // If BigOrtho is switched on, you get a square with edge length of 80. 255 // The same also applies to Resize. 256 // Default value for BigOrtho is on. persistent. SetBigOrtho(bool bOn)257 void SetBigOrtho(bool bOn) { bBigOrtho=bOn; } IsBigOrtho() const258 bool IsBigOrtho() const { return bBigOrtho; } 259 260 // If MoveOnlyDragging=sal_True only the center of the marked objects is 261 // transformed when Resize/Rotate/Shear/Mirror/Crook is executed. 262 // Size, form and rotation angle of the objects are conserved only their positions 263 // are changed. persistent. Default=FALSE. (ni) SetMoveOnlyDragging(bool bOn)264 void SetMoveOnlyDragging(bool bOn) { bMoveOnlyDragging=bOn; } IsMoveOnlyDragging() const265 bool IsMoveOnlyDragging() const { return bMoveOnlyDragging; } 266 267 // Use Slant instead of Shear. persistent. Default=FALSE. SetSlantButShear(bool bOn)268 void SetSlantButShear(bool bOn) { bSlantButShear=bOn; } IsSlantButShear() const269 bool IsSlantButShear() const { return bSlantButShear; } 270 271 // Don't contort objecte while Crook. persistent. Default=FALSE. (ni) SetCrookNoContortion(bool bOn)272 void SetCrookNoContortion(bool bOn) { bCrookNoContortion=bOn; } IsCrookNoContortion() const273 bool IsCrookNoContortion() const { return bCrookNoContortion; } 274 275 // Crook-Mode. persistent. Default=SdrCrookMode::Rotate. (ni) SetCrookMode(SdrCrookMode eMode)276 void SetCrookMode(SdrCrookMode eMode) { eCrookMode=eMode; } GetCrookMode() const277 SdrCrookMode GetCrookMode() const { return eCrookMode; } 278 279 // Special for IBM: While Dragging of a traverse station, it is deleted 280 // if its adjacent lines are almost a solid line. SetEliminatePolyPoints(bool bOn)281 void SetEliminatePolyPoints(bool bOn) { bEliminatePolyPoints=bOn; } IsEliminatePolyPoints() const282 bool IsEliminatePolyPoints() const { return bEliminatePolyPoints; } SetEliminatePolyPointLimitAngle(long nAngle)283 void SetEliminatePolyPointLimitAngle(long nAngle) { nEliminatePolyPointLimitAngle=nAngle; } GetEliminatePolyPointLimitAngle() const284 long GetEliminatePolyPointLimitAngle() const { return nEliminatePolyPointLimitAngle; } 285 }; 286 287 #endif // INCLUDED_SVX_SVDSNPV_HXX 288 289 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 290