Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/svx/svdsnpv.hxx
Line
Count
Source
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
#pragma once
21
22
#include <svx/svdpntv.hxx>
23
#include <svx/svdhlpln.hxx>
24
#include <svx/svxdllapi.h>
25
#include <tools/degree.hxx>
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
92
class SVXCORE_DLLPUBLIC SdrSnapView : public SdrPaintView
93
{
94
protected:
95
    // #114409#-1 Migrate PageOrigin
96
    class ImplPageOriginOverlay*            mpPageOriginOverlay;
97
98
    // #114409#-2 Migrate HelpLine
99
    class ImplHelpLineOverlay*              mpHelpLineOverlay;
100
101
    Size maMagnSiz;
102
    Fraction maSnapWdtX;
103
    Fraction maSnapWdtY;
104
105
    sal_uInt16 mnMagnSizPix;
106
    Degree100 mnSnapAngle;
107
    Degree100 mnEliminatePolyPointLimitAngle;
108
109
    SdrCrookMode meCrookMode;
110
111
    bool mbSnapEnab : 1;
112
    bool mbGridSnap : 1;
113
    bool mbBordSnap : 1;
114
    bool mbHlplSnap : 1;
115
    bool mbOFrmSnap : 1;
116
    bool mbOPntSnap : 1;
117
    bool mbOConSnap : 1;
118
    bool mbMoveSnapOnlyTopLeft : 1;    //  Special for dialogeditor
119
    bool mbOrtho : 1;
120
    bool mbBigOrtho : 1;
121
    bool mbAngleSnapEnab : 1;
122
    bool mbMoveOnlyDragging : 1;       // only move objects while Resize/Rotate/...
123
    bool mbSlantButShear : 1;          // use slant instead of shear
124
    bool mbCrookNoContortion : 1;      // no contorsion while Crook
125
    bool mbEliminatePolyPoints : 1;
126
127
protected:
128
    // #i71538# make constructors of SdrView sub-components protected to avoid incomplete incarnations which may get casted to SdrView
129
    SdrSnapView(
130
        SdrModel& rSdrModel,
131
        OutputDevice* pOut);
132
133
    virtual ~SdrSnapView() override;
134
135
public:
136
    virtual bool IsAction() const override;
137
    virtual void MovAction(const Point& rPnt) override;
138
    virtual void EndAction() override;
139
    virtual void BckAction() override;
140
    virtual void BrkAction() override; // break actions for derived classes e.g. interrupt dragging.
141
    virtual void TakeActionRect(tools::Rectangle& rRect) const override;
142
143
83.4k
    void SetSnapGridWidth(const Fraction& rX, const Fraction& rY) { maSnapWdtX=rX; maSnapWdtY=rY; }
144
1.50k
    const Fraction& GetSnapGridWidthX() const { return maSnapWdtX; }
145
1.50k
    const Fraction& GetSnapGridWidthY() const { return maSnapWdtY; }
146
147
116
    void SetSnapMagnetic(const Size& rSiz) { if (rSiz!=maMagnSiz) { maMagnSiz=rSiz; } }
148
8.56k
    void SetSnapMagneticPixel(sal_uInt16 nPix) { mnMagnSizPix=nPix; }
149
5
    sal_uInt16 GetSnapMagneticPixel() const { return mnMagnSizPix; }
150
151
    // RecalcLogicSnapMagnetic has to be called for every change of OutputDevices and every change of the MapMode!
152
116
    void RecalcLogicSnapMagnetic(const OutputDevice& rOut) { SetSnapMagnetic(rOut.PixelToLogic(Size(mnMagnSizPix,mnMagnSizPix))); }
153
116
    void SetActualWin(const OutputDevice* pWin) { SdrPaintView::SetActualWin(pWin); if (pWin!=nullptr) RecalcLogicSnapMagnetic(*pWin); }
154
155
    // Coordinates referred to the view!
156
    // Returnvalues are SdrSnap::NOTSNAPPED,SdrSnap::XSNAPPED,
157
    // SdrSnap::YSNAPPED or SdrSnap::XYSNAPPED
158
    SdrSnap SnapPos(Point& rPnt, const SdrPageView* pPV) const;
159
    Point GetSnapPos(const Point& rPnt, const SdrPageView* pPV) const;
160
    void CheckSnap(const Point& rPt, tools::Long& nBestXSnap, tools::Long& nBestYSnap, bool& bXSnapped, bool& bYSnapped) const;
161
162
    // All attitudes to snap are persistent.
163
0
    bool IsSnapEnabled() const { return mbSnapEnab; }
164
6.83k
    bool IsGridSnap() const { return mbGridSnap; } // Snap to grid
165
5
    bool IsBordSnap() const { return mbBordSnap; } // Snap to border
166
5
    bool IsHlplSnap() const { return mbHlplSnap; } // Snap to auxiliary line
167
5
    bool IsOFrmSnap() const { return mbOFrmSnap; } // Snap to LogFram from surrounding drawing objects
168
5
    bool IsOPntSnap() const { return mbOPntSnap; } // Snap to distinct points from surrounding drawing objects
169
5
    bool IsOConSnap() const { return mbOConSnap; } // Snap to connectors of the drawing objects
170
0
    void SetSnapEnabled(bool bOn) { mbSnapEnab=bOn; }
171
67.7k
    void SetGridSnap(bool bOn) { mbGridSnap=bOn; }
172
8.94k
    void SetBordSnap(bool bOn) { mbBordSnap=bOn; }
173
8.96k
    void SetHlplSnap(bool bOn) { mbHlplSnap=bOn; }
174
8.96k
    void SetOFrmSnap(bool bOn) { mbOFrmSnap=bOn; }
175
8.95k
    void SetOPntSnap(bool bOn) { mbOPntSnap=bOn; }
176
8.57k
    void SetOConSnap(bool bOn) { mbOConSnap=bOn; }
177
178
    // Usually every 4 corners of Object-SnapRects are snapped for Move-Dragging.
179
    // The following attitudes e.g. if you only want to snap the left corner on the top (e.g. DialogEditor)
180
    // persistent, Default=FALSE.
181
0
    void SetMoveSnapOnlyTopLeft(bool bOn) { mbMoveSnapOnlyTopLeft=bOn; }
182
0
    bool IsMoveSnapOnlyTopLeft() const { return mbMoveSnapOnlyTopLeft; }
183
184
    // #114409#-1 Migrate PageOrigin
185
    void BegSetPageOrg(const Point& rPnt);
186
    void MovSetPageOrg(const Point& rPnt);
187
    void EndSetPageOrg();
188
    void BrkSetPageOrg();
189
388k
    bool IsSetPageOrg() const { return (nullptr != mpPageOriginOverlay); }
190
191
    // HitTest. If sal_True, in rnHelpLineNum is the number of the auxiliary line and in rpPv
192
    // the appended PageView.
193
    bool PickHelpLine(const Point& rPnt, short nTol, const OutputDevice& rOut, sal_uInt16& rnHelpLineNum, SdrPageView*& rpPV) const;
194
195
    // Move of an available auxiliary line. Use nHelpLineNum and pPV from PickHelpLine.
196
    bool BegDragHelpLine(sal_uInt16 nHelpLineNum, SdrPageView* pPV);
197
    // interactive insertion of a new auxiliary line
198
    void BegDragHelpLine(const Point& rPnt, SdrHelpLineKind eNewKind);
199
    PointerStyle GetDraggedHelpLinePointer() const;
200
201
    // change the type of auxiliary line while dragging
202
    // void SetDraggedHelpLineKind(SdrHelpLineKind eNewKind);
203
    void MovDragHelpLine(const Point& rPnt);
204
    bool EndDragHelpLine();
205
    void BrkDragHelpLine();
206
388k
    bool IsDragHelpLine() const { return (nullptr != mpHelpLineOverlay); }
207
208
    // SnapAngle is for angles in circle, RotateDragging, ...
209
    // The snapping of an angle is beared down, if it is switched off
210
    // with SetAngleSnapEnabled(sal_False)
211
    // The snapping angles is independent of snapping coordinates
212
    // and so independent of the attitude IsSnapEnabled()
213
    // Only values should be specified for them is applied:
214
    //     36000 modulo nAngle = 0
215
    // Implemented for:
216
    // - Rotate (Dragging)
217
    // - Shear (Dragging)
218
    // - circular arc/-sector/-section angle (Create and Dragging)
219
    // persistent.
220
9.09k
    void SetAngleSnapEnabled(bool bOn) { mbAngleSnapEnab=bOn; }
221
5
    bool IsAngleSnapEnabled() const { return mbAngleSnapEnab; }
222
9.25k
    void SetSnapAngle(Degree100 nAngle) { mnSnapAngle=nAngle; }
223
5
    Degree100 GetSnapAngle() const { return mnSnapAngle; }
224
225
    // different effects from Ortho (depending on the context):
226
    // - Create
227
    //   - only lines in 45deg grid
228
    //   - instead of rectangles squares are created
229
    //   - instead of ellipse circles are created
230
    // - Dragging
231
    //   - general Dragging
232
    //     - Move only horizontal, vertical or 45deg
233
    //     - Resize proportional
234
    //     - Mirror: nothing
235
    //     - Shear without Resize
236
    //     - Crook without Resize
237
    //   - move handles
238
    //     - mirror axis only 45deg grid
239
    //   - object-specific Dragging
240
    //     - rectangle corner radius: nothing
241
    //     - circle object angle: nothing
242
    //     - line keeps while Dragging the angle and is only stretched/ contracted
243
    // Default value for Ortho is off. persistent.
244
8.56k
    void SetOrtho(bool bOn) { mbOrtho=bOn; } // incomplete
245
5
    bool IsOrtho() const { return mbOrtho; }
246
247
    // BigOrtho is only relevant if Ortho is switched on.
248
    // Example: rectangle is created and ortho is switched on (--> square)
249
    //   and the Mouse was dragged from zero to the coordinates
250
    //   (80,30). Now there are 2 alternatives to determine the edge length
251
    //   of the square: 30 and 80.
252
    //   The standard Ortho-Function took 30 (every time the smaller length)
253
    //   If BigOrtho is switched on, you get a square with edge length of 80.
254
    // The same also applies to Resize.
255
    // Default value for BigOrtho is on. persistent.
256
8.56k
    void SetBigOrtho(bool bOn) { mbBigOrtho=bOn; }
257
5
    bool IsBigOrtho() const { return mbBigOrtho; }
258
259
    // If MoveOnlyDragging=sal_True only the center of the marked objects is
260
    // transformed when Resize/Rotate/Shear/Mirror/Crook is executed.
261
    // Size, form and rotation angle of the objects are conserved only their positions
262
    // are changed. persistent. Default=FALSE. (ni)
263
8.56k
    void SetMoveOnlyDragging(bool bOn) { mbMoveOnlyDragging=bOn; }
264
5
    bool IsMoveOnlyDragging() const { return mbMoveOnlyDragging; }
265
266
    // Use Slant instead of Shear. persistent. Default=FALSE.
267
8.56k
    void SetSlantButShear(bool bOn) { mbSlantButShear=bOn; }
268
5
    bool IsSlantButShear() const { return mbSlantButShear; }
269
270
    // Don't contort object while Crook. persistent. Default=FALSE. (ni)
271
8.56k
    void SetCrookNoContortion(bool bOn) { mbCrookNoContortion=bOn; }
272
5
    bool IsCrookNoContortion() const { return mbCrookNoContortion; }
273
274
    // Crook-Mode. persistent. Default=SdrCrookMode::Rotate. (ni)
275
0
    void SetCrookMode(SdrCrookMode eMode) { meCrookMode=eMode; }
276
0
    SdrCrookMode GetCrookMode() const { return meCrookMode; }
277
278
    // Special for IBM: While Dragging of a traverse station, it is deleted
279
    // if its adjacent lines are almost a solid line.
280
8.97k
    void SetEliminatePolyPoints(bool bOn) { mbEliminatePolyPoints=bOn; }
281
5
    bool IsEliminatePolyPoints() const { return mbEliminatePolyPoints; }
282
8.97k
    void SetEliminatePolyPointLimitAngle(Degree100 nAngle) { mnEliminatePolyPointLimitAngle=nAngle; }
283
5
    Degree100 GetEliminatePolyPointLimitAngle() const { return mnEliminatePolyPointLimitAngle; }
284
};
285
286
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */