Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/svdraw/svddrgmt.cxx
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
#include "svddrgm1.hxx"
21
#include <math.h>
22
23
#include <o3tl/numeric.hxx>
24
#include <osl/diagnose.h>
25
#include <utility>
26
#include <vcl/canvastools.hxx>
27
#include <vcl/svapp.hxx>
28
#include <vcl/settings.hxx>
29
#include <vcl/ptrstyle.hxx>
30
#include <svx/xpoly.hxx>
31
#include <svx/svdtrans.hxx>
32
#include <svx/svdundo.hxx>
33
#include <svx/svdmark.hxx>
34
#include <svx/svdpagv.hxx>
35
#include <svx/svddrgv.hxx>
36
#include <svx/svdograf.hxx>
37
#include <svx/strings.hrc>
38
#include <svx/dialmgr.hxx>
39
#include <svx/sdgcpitm.hxx>
40
#include <svx/sdooitm.hxx>
41
#include <svx/sdtagitm.hxx>
42
#include <basegfx/polygon/b2dpolygon.hxx>
43
#include <basegfx/polygon/b2dpolygontools.hxx>
44
#include <svx/sdr/overlay/overlaymanager.hxx>
45
#include <sdr/overlay/overlayrollingrectangle.hxx>
46
#include <svx/sdrpagewindow.hxx>
47
#include <svx/sdrpaintwindow.hxx>
48
#include <basegfx/matrix/b2dhommatrix.hxx>
49
#include <basegfx/polygon/b2dpolypolygontools.hxx>
50
#include <svx/sdr/contact/viewcontact.hxx>
51
#include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
52
#include <svx/svdocapt.hxx>
53
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
54
#include <svx/sdr/contact/objectcontact.hxx>
55
#include <svx/svditer.hxx>
56
#include <svx/svdopath.hxx>
57
#include <svx/polypolygoneditor.hxx>
58
#include <drawinglayer/primitive2d/PolygonMarkerPrimitive2D.hxx>
59
#include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx>
60
#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
61
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
62
#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
63
#include <sdr/primitive2d/sdrattributecreator.hxx>
64
#include <sdr/primitive2d/sdrdecompositiontools.hxx>
65
#include <sdr/primitive2d/sdrprimitivetools.hxx>
66
#include <basegfx/matrix/b2dhommatrixtools.hxx>
67
#include <drawinglayer/attribute/sdrlineattribute.hxx>
68
#include <drawinglayer/attribute/sdrlinestartendattribute.hxx>
69
#include <svl/itempool.hxx>
70
#include <svtools/optionsdrawinglayer.hxx>
71
#include <officecfg/Office/Common.hxx>
72
#include <comphelper/lok.hxx>
73
#include <map>
74
#include <vector>
75
76
77
SdrDragEntry::SdrDragEntry()
78
0
:   mbAddToTransparent(false)
79
0
{
80
0
}
81
82
SdrDragEntry::~SdrDragEntry()
83
0
{
84
0
}
85
86
87
SdrDragEntryPolyPolygon::SdrDragEntryPolyPolygon(basegfx::B2DPolyPolygon aOriginalPolyPolygon)
88
0
:   maOriginalPolyPolygon(std::move(aOriginalPolyPolygon))
89
0
{
90
0
}
91
92
SdrDragEntryPolyPolygon::~SdrDragEntryPolyPolygon()
93
0
{
94
0
}
95
96
drawinglayer::primitive2d::Primitive2DContainer SdrDragEntryPolyPolygon::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod, bool IsDragSizeValid)
97
0
{
98
0
    drawinglayer::primitive2d::Primitive2DContainer aRetval;
99
100
0
    if(maOriginalPolyPolygon.count())
101
0
    {
102
0
        basegfx::B2DPolyPolygon aCopy(maOriginalPolyPolygon);
103
104
0
        rDragMethod.applyCurrentTransformationToPolyPolygon(aCopy);
105
0
        basegfx::BColor aColA(SvtOptionsDrawinglayer::GetStripeColorA().getBColor());
106
0
        basegfx::BColor aColB(SvtOptionsDrawinglayer::GetStripeColorB().getBColor());
107
0
        const double fStripeLength(officecfg::Office::Common::Drawinglayer::StripeLength::get());
108
109
0
        if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
110
0
        {
111
0
            aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
112
0
            aColB.invert();
113
0
        }
114
115
0
        aRetval.resize(2);
116
0
        aRetval[0] = new drawinglayer::primitive2d::PolyPolygonMarkerPrimitive2D(
117
0
            aCopy,
118
0
            aColA,
119
0
            aColB,
120
0
            fStripeLength);
121
122
0
        basegfx::BColor aHilightColor;
123
0
        if (IsDragSizeValid)
124
0
            aHilightColor = SvtOptionsDrawinglayer::getHilightColor().getBColor();
125
0
        else
126
0
            aHilightColor = basegfx::BColor(1.0, 0, 0);
127
128
0
        const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01);
129
0
        aRetval[1] = new drawinglayer::primitive2d::PolyPolygonSelectionPrimitive2D(
130
0
            std::move(aCopy),
131
0
            aHilightColor,
132
0
            fTransparence,
133
0
            3.0,
134
0
            false);
135
0
    }
136
137
0
    return aRetval;
138
0
}
139
140
141
SdrDragEntrySdrObject::SdrDragEntrySdrObject(
142
    const SdrObject& rOriginal,
143
    bool bModify)
144
0
:   maOriginal(rOriginal),
145
0
    mbModify(bModify)
146
0
{
147
    // add SdrObject parts to transparent overlay stuff
148
0
    setAddToTransparent(true);
149
0
}
150
151
SdrDragEntrySdrObject::~SdrDragEntrySdrObject()
152
0
{
153
0
}
154
155
void SdrDragEntrySdrObject::prepareCurrentState(SdrDragMethod& rDragMethod)
156
0
{
157
    // for the moment, i need to re-create the clone in all cases. I need to figure
158
    // out when clone and original have the same class, so that i can use operator=
159
    // in those cases
160
161
0
    mxClone.clear();
162
163
0
    if(mbModify)
164
0
    {
165
0
        mxClone = maOriginal.getFullDragClone();
166
167
        // apply original transformation, implemented at the DragMethods
168
0
        rDragMethod.applyCurrentTransformationToSdrObject(*mxClone);
169
0
    }
170
0
}
171
172
drawinglayer::primitive2d::Primitive2DContainer SdrDragEntrySdrObject::createPrimitive2DSequenceInCurrentState(SdrDragMethod&, bool /* IsDragSizeValid */)
173
0
{
174
0
    const SdrObject* pSource = &maOriginal;
175
176
0
    if(mbModify && mxClone)
177
0
    {
178
        // choose source for geometry data
179
0
        pSource = mxClone.get();
180
0
    }
181
182
    // use the view-independent primitive representation (without
183
    // evtl. GridOffset, that may be applied to the DragEntry individually)
184
0
    drawinglayer::primitive2d::Primitive2DContainer xRetval;
185
0
    pSource->GetViewContact().getViewIndependentPrimitive2DContainer(xRetval);
186
0
    return xRetval;
187
0
}
188
189
190
SdrDragEntryPrimitive2DSequence::SdrDragEntryPrimitive2DSequence(
191
    drawinglayer::primitive2d::Primitive2DContainer&& rSequence)
192
0
:   maPrimitive2DSequence(std::move(rSequence))
193
0
{
194
    // add parts to transparent overlay stuff if necessary
195
0
    setAddToTransparent(true);
196
0
}
197
198
SdrDragEntryPrimitive2DSequence::~SdrDragEntryPrimitive2DSequence()
199
0
{
200
0
}
201
202
drawinglayer::primitive2d::Primitive2DContainer SdrDragEntryPrimitive2DSequence::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod, bool /* IsDragSizeValid */)
203
0
{
204
0
    return drawinglayer::primitive2d::Primitive2DContainer {
205
0
            new drawinglayer::primitive2d::TransformPrimitive2D(
206
0
                rDragMethod.getCurrentTransformation(),
207
0
                drawinglayer::primitive2d::Primitive2DContainer(maPrimitive2DSequence))
208
0
    };
209
0
}
210
211
SdrDragEntryPointGlueDrag::SdrDragEntryPointGlueDrag(std::vector< basegfx::B2DPoint >&& rPositions, bool bIsPointDrag)
212
0
:   maPositions(std::move(rPositions)),
213
0
    mbIsPointDrag(bIsPointDrag)
214
0
{
215
    // add SdrObject parts to transparent overlay stuff
216
0
    setAddToTransparent(true);
217
0
}
218
219
SdrDragEntryPointGlueDrag::~SdrDragEntryPointGlueDrag()
220
0
{
221
0
}
222
223
drawinglayer::primitive2d::Primitive2DContainer SdrDragEntryPointGlueDrag::createPrimitive2DSequenceInCurrentState(SdrDragMethod& rDragMethod, bool /* IsDragSizeValid */)
224
0
{
225
0
    drawinglayer::primitive2d::Primitive2DContainer aRetval;
226
227
0
    if(!maPositions.empty())
228
0
    {
229
0
        basegfx::B2DPolygon aPolygon;
230
231
0
        for(auto const & a: maPositions)
232
0
        {
233
0
            aPolygon.append(a);
234
0
        }
235
236
0
        basegfx::B2DPolyPolygon aPolyPolygon(aPolygon);
237
238
0
        rDragMethod.applyCurrentTransformationToPolyPolygon(aPolyPolygon);
239
240
0
        const basegfx::B2DPolygon aTransformed(aPolyPolygon.getB2DPolygon(0));
241
0
        std::vector< basegfx::B2DPoint > aTransformedPositions;
242
243
0
        aTransformedPositions.reserve(aTransformed.count());
244
245
0
        for(sal_uInt32 a = 0; a < aTransformed.count(); a++)
246
0
        {
247
0
            aTransformedPositions.push_back(aTransformed.getB2DPoint(a));
248
0
        }
249
250
0
        if(mbIsPointDrag)
251
0
        {
252
0
            basegfx::BColor aColor(SvtOptionsDrawinglayer::GetStripeColorA().getBColor());
253
254
0
            if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
255
0
            {
256
0
                aColor = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
257
0
            }
258
259
0
            aRetval = drawinglayer::primitive2d::Primitive2DContainer {
260
0
                    new drawinglayer::primitive2d::MarkerArrayPrimitive2D(std::move(aTransformedPositions),
261
0
                        drawinglayer::primitive2d::createDefaultCross_3x3(aColor))
262
0
            };
263
0
        }
264
0
        else
265
0
        {
266
0
            aRetval = drawinglayer::primitive2d::Primitive2DContainer {
267
0
                    new drawinglayer::primitive2d::MarkerArrayPrimitive2D(std::move(aTransformedPositions),
268
0
                                                                          SdrHdl::createGluePointBitmap())
269
0
             };
270
0
        }
271
0
    }
272
273
0
    return aRetval;
274
0
}
275
276
277
void SdrDragMethod::resetSdrDragEntries()
278
0
{
279
    // clear entries; creation is on demand
280
0
    clearSdrDragEntries();
281
0
}
282
283
basegfx::B2DRange SdrDragMethod::getCurrentRange() const
284
0
{
285
0
    return maOverlayObjectList.getBaseRange();
286
0
}
287
288
void SdrDragMethod::clearSdrDragEntries()
289
0
{
290
0
    maSdrDragEntries.clear();
291
0
}
292
293
void SdrDragMethod::addSdrDragEntry(std::unique_ptr<SdrDragEntry> pNew)
294
0
{
295
0
    assert(pNew);
296
0
    maSdrDragEntries.push_back(std::move(pNew));
297
0
}
298
299
void SdrDragMethod::createSdrDragEntries()
300
0
{
301
0
    if(!(getSdrDragView().GetSdrPageView() && getSdrDragView().GetSdrPageView()->HasMarkedObjPageView()))
302
0
        return;
303
304
0
    if(getSdrDragView().IsDraggingPoints())
305
0
    {
306
0
        createSdrDragEntries_PointDrag();
307
0
    }
308
0
    else if(getSdrDragView().IsDraggingGluePoints())
309
0
    {
310
0
        createSdrDragEntries_GlueDrag();
311
0
    }
312
0
    else
313
0
    {
314
0
        if(getSolidDraggingActive())
315
0
        {
316
0
            createSdrDragEntries_SolidDrag();
317
0
        }
318
0
        else
319
0
        {
320
0
            createSdrDragEntries_PolygonDrag();
321
0
        }
322
0
    }
323
0
}
324
325
void SdrDragMethod::createSdrDragEntryForSdrObject(const SdrObject& rOriginal)
326
0
{
327
    // add full object drag; Clone() at the object has to work
328
    // for this
329
0
    addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntrySdrObject(rOriginal, true/*bModify*/)));
330
0
}
331
332
void SdrDragMethod::insertNewlyCreatedOverlayObjectForSdrDragMethod(
333
    std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject,
334
    const sdr::contact::ObjectContact& rObjectContact,
335
    sdr::overlay::OverlayManager& rOverlayManager)
336
0
{
337
    // check if we have an OverlayObject
338
0
    if(!pOverlayObject)
339
0
    {
340
0
        return;
341
0
    }
342
343
    // add to OverlayManager
344
0
    rOverlayManager.add(*pOverlayObject);
345
346
    // Add GridOffset for non-linear ViewToDevice transformation (calc)
347
0
    if(rObjectContact.supportsGridOffsets())
348
0
    {
349
0
        const basegfx::B2DRange& rNewRange(pOverlayObject->getBaseRange());
350
351
0
        if(!rNewRange.isEmpty())
352
0
        {
353
0
            basegfx::B2DVector aOffset(0.0, 0.0);
354
0
            rObjectContact.calculateGridOffsetForB2DRange(aOffset, rNewRange);
355
356
0
            if(!aOffset.equalZero())
357
0
            {
358
0
                pOverlayObject->setOffset(aOffset);
359
0
            }
360
0
        }
361
0
    }
362
363
    // add to local OverlayObjectList - ownership change (!)
364
0
    maOverlayObjectList.append(std::move(pOverlayObject));
365
0
}
366
367
void SdrDragMethod::createSdrDragEntries_SolidDrag()
368
0
{
369
0
    const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
370
0
    const size_t nMarkCount(rMarkList.GetMarkCount());
371
0
    SdrPageView* pPV = getSdrDragView().GetSdrPageView();
372
373
0
    if(!pPV)
374
0
        return;
375
376
0
    for(size_t a = 0; a < nMarkCount; ++a)
377
0
    {
378
0
        SdrMark* pM = rMarkList.GetMark(a);
379
380
0
        if(pM->GetPageView() == pPV)
381
0
        {
382
0
            const SdrObject* pObject = pM->GetMarkedSdrObj();
383
384
0
            if(pObject)
385
0
            {
386
0
                if(pPV->PageWindowCount())
387
0
                {
388
0
                    SdrObjListIter aIter(*pObject);
389
390
0
                    while(aIter.IsMore())
391
0
                    {
392
0
                        SdrObject* pCandidate = aIter.Next();
393
394
0
                        if(pCandidate)
395
0
                        {
396
0
                            const bool bSuppressFullDrag(!pCandidate->supportsFullDrag());
397
0
                            bool bAddWireframe(bSuppressFullDrag);
398
399
0
                            if(!bAddWireframe && !pCandidate->HasLineStyle())
400
0
                            {
401
                                // add wireframe for objects without outline
402
0
                                bAddWireframe = true;
403
0
                            }
404
405
0
                            if(!bSuppressFullDrag)
406
0
                            {
407
                                // add full object drag; Clone() at the object has to work
408
                                // for this
409
0
                                createSdrDragEntryForSdrObject(*pCandidate);
410
0
                            }
411
412
0
                            if(bAddWireframe)
413
0
                            {
414
                                // when dragging a 50% transparent copy of a filled or not filled object without
415
                                // outline, this is normally hard to see. Add extra wireframe in that case. This
416
                                // works nice e.g. with text frames etc.
417
0
                                addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPolyPolygon(pCandidate->TakeXorPoly())));
418
0
                            }
419
0
                        }
420
0
                    }
421
0
                }
422
0
            }
423
0
        }
424
0
    }
425
0
}
426
427
void SdrDragMethod::createSdrDragEntries_PolygonDrag()
428
0
{
429
0
    const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
430
0
    const size_t nMarkCount(rMarkList.GetMarkCount());
431
0
    bool bNoPolygons(getSdrDragView().IsNoDragXorPolys() || nMarkCount > SdrDragView::GetDragXorPolyLimit());
432
0
    basegfx::B2DPolyPolygon aResult;
433
0
    sal_uInt32 nPointCount(0);
434
435
0
    for(size_t a = 0; !bNoPolygons && a < nMarkCount; ++a)
436
0
    {
437
0
        SdrMark* pM = rMarkList.GetMark(a);
438
439
0
        if(pM->GetPageView() == getSdrDragView().GetSdrPageView())
440
0
        {
441
0
            const basegfx::B2DPolyPolygon aNewPolyPolygon(pM->GetMarkedSdrObj()->TakeXorPoly());
442
443
0
            for(auto const& rPolygon : aNewPolyPolygon)
444
0
            {
445
0
                nPointCount += rPolygon.count();
446
0
            }
447
448
0
            if(nPointCount > SdrDragView::GetDragXorPointLimit())
449
0
            {
450
0
                bNoPolygons = true;
451
0
            }
452
453
0
            if(!bNoPolygons)
454
0
            {
455
0
                aResult.append(aNewPolyPolygon);
456
0
            }
457
0
        }
458
0
    }
459
460
0
    if(bNoPolygons)
461
0
    {
462
0
        const tools::Rectangle aR(getSdrDragView().GetSdrPageView()->MarkSnap());
463
0
        const basegfx::B2DRange aNewRectangle = vcl::unotools::b2DRectangleFromRectangle(aR);
464
0
        basegfx::B2DPolygon aNewPolygon(basegfx::utils::createPolygonFromRect(aNewRectangle));
465
466
0
        aResult = basegfx::B2DPolyPolygon(basegfx::utils::expandToCurve(aNewPolygon));
467
0
    }
468
469
0
    if(aResult.count())
470
0
    {
471
0
        addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPolyPolygon(std::move(aResult))));
472
0
    }
473
0
}
474
475
void SdrDragMethod::createSdrDragEntries_PointDrag()
476
0
{
477
0
    const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
478
0
    const size_t nMarkCount(rMarkList.GetMarkCount());
479
0
    std::vector< basegfx::B2DPoint > aPositions;
480
481
0
    for(size_t nm = 0; nm < nMarkCount; ++nm)
482
0
    {
483
0
        SdrMark* pM = rMarkList.GetMark(nm);
484
485
0
        if(pM->GetPageView() == getSdrDragView().GetSdrPageView())
486
0
        {
487
0
            const SdrUShortCont& rPts = pM->GetMarkedPoints();
488
489
0
            if (!rPts.empty())
490
0
            {
491
0
                const SdrObject* pObj = pM->GetMarkedSdrObj();
492
0
                const SdrPathObj* pPath = dynamic_cast< const SdrPathObj* >(pObj);
493
494
0
                if(pPath)
495
0
                {
496
0
                    const basegfx::B2DPolyPolygon& aPathXPP = pPath->GetPathPoly();
497
498
0
                    if(aPathXPP.count())
499
0
                    {
500
0
                        for(const sal_uInt16 nObjPt : rPts)
501
0
                        {
502
0
                            sal_uInt32 nPolyNum, nPointNum;
503
504
0
                            if(sdr::PolyPolygonEditor::GetRelativePolyPoint(aPathXPP, nObjPt, nPolyNum, nPointNum))
505
0
                            {
506
0
                                aPositions.push_back(aPathXPP.getB2DPolygon(nPolyNum).getB2DPoint(nPointNum));
507
0
                            }
508
0
                        }
509
0
                    }
510
0
                }
511
0
            }
512
0
        }
513
0
    }
514
515
0
    if(!aPositions.empty())
516
0
    {
517
0
        addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPointGlueDrag(std::move(aPositions), true)));
518
0
    }
519
0
}
520
521
void SdrDragMethod::createSdrDragEntries_GlueDrag()
522
0
{
523
0
    const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
524
0
    const size_t nMarkCount(rMarkList.GetMarkCount());
525
0
    std::vector< basegfx::B2DPoint > aPositions;
526
527
0
    for(size_t nm = 0; nm < nMarkCount; ++nm)
528
0
    {
529
0
        SdrMark* pM = rMarkList.GetMark(nm);
530
531
0
        if(pM->GetPageView() == getSdrDragView().GetSdrPageView())
532
0
        {
533
0
            const SdrUShortCont& rPts = pM->GetMarkedGluePoints();
534
535
0
            if (!rPts.empty())
536
0
            {
537
0
                const SdrObject* pObj = pM->GetMarkedSdrObj();
538
0
                const SdrGluePointList* pGPL = pObj->GetGluePointList();
539
540
0
                if (pGPL)
541
0
                {
542
0
                    for(const sal_uInt16 nObjPt : rPts)
543
0
                    {
544
0
                        const sal_uInt16 nGlueNum(pGPL->FindGluePoint(nObjPt));
545
546
0
                        if(SDRGLUEPOINT_NOTFOUND != nGlueNum)
547
0
                        {
548
0
                            const Point aPoint((*pGPL)[nGlueNum].GetAbsolutePos(*pObj));
549
0
                            aPositions.emplace_back(aPoint.X(), aPoint.Y());
550
0
                        }
551
0
                    }
552
0
                }
553
0
            }
554
0
        }
555
0
    }
556
557
0
    if(!aPositions.empty())
558
0
    {
559
0
        addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPointGlueDrag(std::move(aPositions), false)));
560
0
    }
561
0
}
562
563
OUString SdrDragMethod::ImpGetDescriptionStr(TranslateId pStrCacheID) const
564
0
{
565
0
    ImpGetDescriptionOptions nOpt=ImpGetDescriptionOptions::NONE;
566
0
    if (IsDraggingPoints()) {
567
0
        nOpt=ImpGetDescriptionOptions::POINTS;
568
0
    } else if (IsDraggingGluePoints()) {
569
0
        nOpt=ImpGetDescriptionOptions::GLUEPOINTS;
570
0
    }
571
0
    return getSdrDragView().ImpGetDescriptionString(pStrCacheID, nOpt);
572
0
}
573
574
SdrObject* SdrDragMethod::GetDragObj() const
575
0
{
576
0
    SdrObject* pObj=nullptr;
577
0
    if (getSdrDragView().mpDragHdl!=nullptr) pObj=getSdrDragView().mpDragHdl->GetObj();
578
0
    if (pObj==nullptr) pObj=getSdrDragView().mpMarkedObj;
579
0
    return pObj;
580
0
}
581
582
SdrPageView* SdrDragMethod::GetDragPV() const
583
0
{
584
0
    SdrPageView* pPV=nullptr;
585
0
    if (getSdrDragView().mpDragHdl!=nullptr) pPV=getSdrDragView().mpDragHdl->GetPageView();
586
0
    if (pPV==nullptr) pPV=getSdrDragView().mpMarkedPV;
587
0
    return pPV;
588
0
}
589
590
void SdrDragMethod::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
591
0
{
592
    // the original applies the transformation using TRGetBaseGeometry/TRSetBaseGeometry.
593
    // Later this should be the only needed one for linear transforms (not for SdrDragCrook and
594
    // SdrDragDistort, those are NOT linear). Currently, this can not yet be used since the
595
    // special handling of rotate/mirror due to the not-being-able to handle it in the old
596
    // drawinglayer stuff. Text would currently not correctly be mirrored in the preview.
597
0
    basegfx::B2DHomMatrix aObjectTransform;
598
0
    basegfx::B2DPolyPolygon aObjectPolyPolygon;
599
0
    bool bPolyUsed(rTarget.TRGetBaseGeometry(aObjectTransform, aObjectPolyPolygon));
600
601
    // apply transform to object transform
602
0
    aObjectTransform *= getCurrentTransformation();
603
604
0
    if(bPolyUsed)
605
0
    {
606
        // do something special since the object size is in the polygon
607
        // break up matrix to get the scale
608
0
        const basegfx::utils::B2DHomMatrixBufferedDecompose aTmpDecomp(aObjectTransform);
609
610
        // get polygon's position and size
611
0
        const basegfx::B2DRange aPolyRange(aObjectPolyPolygon.getB2DRange());
612
613
        // get the scaling factors (do not mirror, this is in the object transformation)
614
0
        const double fScaleX(fabs(aTmpDecomp.getScale().getX()) / (basegfx::fTools::equalZero(aPolyRange.getWidth()) ? 1.0 : aPolyRange.getWidth()));
615
0
        const double fScaleY(fabs(aTmpDecomp.getScale().getY()) / (basegfx::fTools::equalZero(aPolyRange.getHeight()) ? 1.0 : aPolyRange.getHeight()));
616
617
        // prepare transform matrix for polygon
618
0
        basegfx::B2DHomMatrix aPolyTransform(
619
0
            basegfx::utils::createTranslateB2DHomMatrix(
620
0
                -aPolyRange.getMinX(),
621
0
                -aPolyRange.getMinY()));
622
0
        aPolyTransform.scale(fScaleX, fScaleY);
623
624
        // transform the polygon
625
0
        aObjectPolyPolygon.transform(aPolyTransform);
626
0
    }
627
628
0
    rTarget.TRSetBaseGeometry(getCurrentTransformation() * aObjectTransform, aObjectPolyPolygon);
629
0
}
630
631
void SdrDragMethod::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget)
632
0
{
633
    // original uses CurrentTransformation
634
0
    rTarget.transform(getCurrentTransformation());
635
0
}
636
637
SdrDragMethod::SdrDragMethod(SdrDragView& rNewView)
638
0
:   mrSdrDragView(rNewView),
639
0
    mbMoveOnly(false),
640
0
    mbSolidDraggingActive(getSdrDragView().IsSolidDragging()),
641
0
    mbShiftPressed(false)
642
0
{
643
0
    if(mbSolidDraggingActive && Application::GetSettings().GetStyleSettings().GetHighContrastMode())
644
0
    {
645
        // fallback to wireframe when high contrast is used
646
0
        mbSolidDraggingActive = false;
647
0
    }
648
0
}
649
650
SdrDragMethod::~SdrDragMethod()
651
0
{
652
0
    clearSdrDragEntries();
653
0
}
654
655
void SdrDragMethod::Show(bool IsValidSize)
656
0
{
657
0
    getSdrDragView().ShowDragObj(IsValidSize);
658
0
}
659
660
void SdrDragMethod::Hide()
661
0
{
662
0
    getSdrDragView().HideDragObj();
663
0
}
664
665
basegfx::B2DHomMatrix SdrDragMethod::getCurrentTransformation() const
666
0
{
667
0
    return basegfx::B2DHomMatrix();
668
0
}
669
670
void SdrDragMethod::CancelSdrDrag()
671
0
{
672
0
    Hide();
673
0
}
674
675
typedef std::map< const SdrObject*, SdrObject* > SdrObjectAndCloneMap;
676
677
void SdrDragMethod::CreateOverlayGeometry(
678
    sdr::overlay::OverlayManager& rOverlayManager,
679
    const sdr::contact::ObjectContact& rObjectContact, bool bIsGeometrySizeValid)
680
0
{
681
    // We do client-side object manipulation with the Kit API
682
0
    if (comphelper::LibreOfficeKit::isActive())
683
0
        return;
684
685
    // create SdrDragEntries on demand
686
0
    if(maSdrDragEntries.empty())
687
0
    {
688
0
        createSdrDragEntries();
689
0
    }
690
691
    // if there are entries, derive OverlayObjects from the entries, including
692
    // modification from current interactive state
693
0
    if(!maSdrDragEntries.empty())
694
0
    {
695
        // #i54102# SdrDragEntrySdrObject creates clones of SdrObjects as base for creating the needed
696
        // primitives, holding the original and the clone. If connectors (Edges) are involved,
697
        // the cloned connectors need to be connected to the cloned SdrObjects (after cloning
698
        // they are connected to the original SdrObjects). To do so, trigger the preparation
699
        // steps for SdrDragEntrySdrObject, save an association of (orig, clone) in a helper
700
        // and evtl. remember if it was an edge
701
0
        SdrObjectAndCloneMap aOriginalAndClones;
702
0
        std::vector< SdrEdgeObj* > aEdges;
703
704
        // #i54102# execute prepareCurrentState for all SdrDragEntrySdrObject, register pair of original and
705
        // clone, remember edges
706
0
        for(auto const & a: maSdrDragEntries)
707
0
        {
708
0
            SdrDragEntrySdrObject* pSdrDragEntrySdrObject = dynamic_cast< SdrDragEntrySdrObject*>(a.get());
709
710
0
            if(pSdrDragEntrySdrObject)
711
0
            {
712
0
                pSdrDragEntrySdrObject->prepareCurrentState(*this);
713
714
0
                SdrEdgeObj* pSdrEdgeObj = dynamic_cast< SdrEdgeObj* >(pSdrDragEntrySdrObject->getClone());
715
716
0
                if(pSdrEdgeObj)
717
0
                {
718
0
                    aEdges.push_back(pSdrEdgeObj);
719
0
                }
720
721
0
                if(pSdrDragEntrySdrObject->getClone())
722
0
                {
723
0
                    aOriginalAndClones[&pSdrDragEntrySdrObject->getOriginal()] = pSdrDragEntrySdrObject->getClone();
724
0
                }
725
0
            }
726
0
        }
727
728
        // #i54102# if there are edges, reconnect their ends to the corresponding clones (if found)
729
0
        for(SdrEdgeObj* pSdrEdgeObj: aEdges)
730
0
        {
731
0
            SdrObject* pConnectedTo = pSdrEdgeObj->GetConnectedNode(true);
732
733
0
            if(pConnectedTo)
734
0
            {
735
0
                SdrObjectAndCloneMap::iterator aEntry = aOriginalAndClones.find(pConnectedTo);
736
737
0
                if(aEntry != aOriginalAndClones.end())
738
0
                {
739
0
                    pSdrEdgeObj->ConnectToNode(true, aEntry->second);
740
0
                }
741
0
            }
742
743
0
            pConnectedTo = pSdrEdgeObj->GetConnectedNode(false);
744
745
0
            if(pConnectedTo)
746
0
            {
747
0
                SdrObjectAndCloneMap::iterator aEntry = aOriginalAndClones.find(pConnectedTo);
748
749
0
                if(aEntry != aOriginalAndClones.end())
750
0
                {
751
0
                    pSdrEdgeObj->ConnectToNode(false, aEntry->second);
752
0
                }
753
0
            }
754
0
        }
755
756
        // collect primitives for visualisation
757
0
        drawinglayer::primitive2d::Primitive2DContainer aResult;
758
0
        drawinglayer::primitive2d::Primitive2DContainer aResultTransparent;
759
760
0
        for(auto & pCandidate: maSdrDragEntries)
761
0
        {
762
0
            const drawinglayer::primitive2d::Primitive2DContainer aCandidateResult(
763
0
                    pCandidate->createPrimitive2DSequenceInCurrentState(*this, bIsGeometrySizeValid));
764
765
0
            if(!aCandidateResult.empty())
766
0
            {
767
0
                if(pCandidate->getAddToTransparent())
768
0
                {
769
0
                    aResultTransparent.append(aCandidateResult);
770
0
                }
771
0
                else
772
0
                {
773
0
                    aResult.append(aCandidateResult);
774
0
                }
775
0
            }
776
0
        }
777
778
0
        if(DoAddConnectorOverlays())
779
0
        {
780
0
            drawinglayer::primitive2d::Primitive2DContainer aConnectorOverlays(AddConnectorOverlays());
781
782
0
            if(!aConnectorOverlays.empty())
783
0
            {
784
                // add connector overlays to transparent part
785
0
                aResultTransparent.append(std::move(aConnectorOverlays));
786
0
            }
787
0
        }
788
789
0
        if(!aResult.empty())
790
0
        {
791
0
            std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(
792
0
                new sdr::overlay::OverlayPrimitive2DSequenceObject(
793
0
                    std::move(aResult)));
794
795
0
            insertNewlyCreatedOverlayObjectForSdrDragMethod(
796
0
                std::move(pNewOverlayObject),
797
0
                rObjectContact,
798
0
                rOverlayManager);
799
0
        }
800
801
0
        if(!aResultTransparent.empty())
802
0
        {
803
0
            aResultTransparent = drawinglayer::primitive2d::Primitive2DContainer {
804
0
                new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(std::move(aResultTransparent), 0.5)
805
0
            };
806
807
0
            std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(
808
0
                new sdr::overlay::OverlayPrimitive2DSequenceObject(
809
0
                    std::move(aResultTransparent)));
810
811
0
            insertNewlyCreatedOverlayObjectForSdrDragMethod(
812
0
                std::move(pNewOverlayObject),
813
0
                rObjectContact,
814
0
                rOverlayManager);
815
0
        }
816
0
    }
817
818
    // add DragStripes if necessary (help lines cross the page when dragging)
819
0
    if(!getSdrDragView().IsDragStripes())
820
0
        return;
821
822
0
    tools::Rectangle aActionRectangle;
823
0
    getSdrDragView().TakeActionRect(aActionRectangle);
824
825
0
    const basegfx::B2DPoint aTopLeft(aActionRectangle.Left(), aActionRectangle.Top());
826
0
    const basegfx::B2DPoint aBottomRight(aActionRectangle.Right(), aActionRectangle.Bottom());
827
0
    std::unique_ptr<sdr::overlay::OverlayRollingRectangleStriped> pNew(
828
0
        new sdr::overlay::OverlayRollingRectangleStriped(
829
0
            aTopLeft,
830
0
            aBottomRight,
831
0
            true,
832
0
            false));
833
834
0
    insertNewlyCreatedOverlayObjectForSdrDragMethod(
835
0
        std::move(pNew),
836
0
        rObjectContact,
837
0
        rOverlayManager);
838
0
}
839
840
void SdrDragMethod::destroyOverlayGeometry()
841
0
{
842
0
    maOverlayObjectList.clear();
843
0
}
844
845
bool SdrDragMethod::DoAddConnectorOverlays()
846
0
{
847
    // these conditions are translated from SdrDragView::ImpDrawEdgeXor
848
0
    const SdrMarkList& rMarkedNodes = getSdrDragView().GetEdgesOfMarkedNodes();
849
850
0
    if(!rMarkedNodes.GetMarkCount())
851
0
    {
852
0
        return false;
853
0
    }
854
855
0
    if(getSdrDragView().IsDraggingPoints() || getSdrDragView().IsDraggingGluePoints())
856
0
    {
857
0
        return false;
858
0
    }
859
860
0
    if(!getMoveOnly() && !(
861
0
        dynamic_cast<const SdrDragMove*>(this) != nullptr || dynamic_cast<const SdrDragResize*>(this) != nullptr ||
862
0
        dynamic_cast<const SdrDragRotate*>(this) != nullptr || dynamic_cast<const SdrDragMirror*>(this) != nullptr ))
863
0
    {
864
0
        return false;
865
0
    }
866
867
    // one more migrated from SdrEdgeObj::NspToggleEdgeXor
868
0
    if( dynamic_cast< const SdrDragObjOwn* >(this) != nullptr || dynamic_cast< const SdrDragMovHdl* >(this) != nullptr )
869
0
    {
870
0
        return false;
871
0
    }
872
873
0
    return true;
874
0
}
875
876
drawinglayer::primitive2d::Primitive2DContainer SdrDragMethod::AddConnectorOverlays()
877
0
{
878
0
    drawinglayer::primitive2d::Primitive2DContainer aRetval;
879
0
    const bool bDetail(getMoveOnly());
880
0
    const SdrMarkList& rMarkedNodes = getSdrDragView().GetEdgesOfMarkedNodes();
881
882
0
    for(size_t a = 0; a < rMarkedNodes.GetMarkCount(); ++a)
883
0
    {
884
0
        SdrMark* pEM = rMarkedNodes.GetMark(a);
885
886
0
        if(pEM && pEM->GetMarkedSdrObj())
887
0
        {
888
0
            SdrEdgeObj* pEdge = dynamic_cast< SdrEdgeObj* >(pEM->GetMarkedSdrObj());
889
890
0
            if(pEdge)
891
0
            {
892
0
                basegfx::B2DPolygon aEdgePolygon(pEdge->ImplAddConnectorOverlay(*this, pEM->IsCon1(), pEM->IsCon2(), bDetail));
893
894
0
                if(aEdgePolygon.count())
895
0
                {
896
                    // this polygon is a temporary calculated connector path, so it is not possible to fetch
897
                    // the needed primitives directly from the pEdge object which does not get changed. If full
898
                    // drag is on, use the SdrObjects ItemSet to create an adequate representation
899
0
                    bool bUseSolidDragging(getSolidDraggingActive());
900
901
0
                    if(bUseSolidDragging)
902
0
                    {
903
                        // switch off solid dragging if connector is not visible
904
0
                        if(!pEdge->HasLineStyle())
905
0
                        {
906
0
                            bUseSolidDragging = false;
907
0
                        }
908
0
                    }
909
910
0
                    if(bUseSolidDragging)
911
0
                    {
912
0
                        const SfxItemSet& rItemSet = pEdge->GetMergedItemSet();
913
0
                        const drawinglayer::attribute::SdrLineAttribute aLine(
914
0
                            drawinglayer::primitive2d::createNewSdrLineAttribute(rItemSet));
915
916
0
                        if(!aLine.isDefault())
917
0
                        {
918
0
                            const drawinglayer::attribute::SdrLineStartEndAttribute aLineStartEnd(
919
0
                                drawinglayer::primitive2d::createNewSdrLineStartEndAttribute(
920
0
                                    rItemSet,
921
0
                                    aLine.getWidth()));
922
923
0
                            aRetval.push_back(drawinglayer::primitive2d::createPolygonLinePrimitive(
924
0
                                    aEdgePolygon,
925
0
                                    aLine,
926
0
                                    aLineStartEnd));
927
0
                        }
928
0
                    }
929
0
                    else
930
0
                    {
931
0
                        basegfx::BColor aColA(SvtOptionsDrawinglayer::GetStripeColorA().getBColor());
932
0
                        basegfx::BColor aColB(SvtOptionsDrawinglayer::GetStripeColorB().getBColor());
933
0
                        const double fStripeLength(officecfg::Office::Common::Drawinglayer::StripeLength::get());
934
935
0
                        if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
936
0
                        {
937
0
                            aColA = aColB = Application::GetSettings().GetStyleSettings().GetHighlightColor().getBColor();
938
0
                            aColB.invert();
939
0
                        }
940
941
0
                        drawinglayer::primitive2d::Primitive2DReference aPolyPolygonMarkerPrimitive2D(
942
0
                            new drawinglayer::primitive2d::PolygonMarkerPrimitive2D(
943
0
                                std::move(aEdgePolygon), aColA, aColB, fStripeLength));
944
0
                        aRetval.push_back(aPolyPolygonMarkerPrimitive2D);
945
0
                    }
946
0
                }
947
0
            }
948
0
        }
949
0
    }
950
951
0
    return aRetval;
952
0
}
953
954
955
SdrDragMovHdl::SdrDragMovHdl(SdrDragView& rNewView)
956
0
:   SdrDragMethod(rNewView)
957
0
{
958
0
}
959
960
void SdrDragMovHdl::createSdrDragEntries()
961
0
{
962
    // SdrDragMovHdl does not use the default drags,
963
    // but creates nothing
964
0
}
965
966
OUString SdrDragMovHdl::GetSdrDragComment() const
967
0
{
968
0
    OUString aStr=SvxResId(STR_DragMethMovHdl);
969
0
    if (getSdrDragView().IsDragWithCopy()) aStr+=SvxResId(STR_EditWithCopy);
970
0
    return aStr;
971
0
}
972
973
bool SdrDragMovHdl::BeginSdrDrag()
974
0
{
975
0
    if( !GetDragHdl() )
976
0
        return false;
977
978
0
    DragStat().SetRef1(GetDragHdl()->GetPos());
979
0
    DragStat().SetShown(!DragStat().IsShown());
980
0
    SdrHdlKind eKind=GetDragHdl()->GetKind();
981
0
    SdrHdl* pH1=GetHdlList().GetHdl(SdrHdlKind::Ref1);
982
0
    SdrHdl* pH2=GetHdlList().GetHdl(SdrHdlKind::Ref2);
983
984
0
    if (eKind==SdrHdlKind::MirrorAxis)
985
0
    {
986
0
        if (pH1==nullptr || pH2==nullptr)
987
0
        {
988
0
            OSL_FAIL("SdrDragMovHdl::BeginSdrDrag(): Moving the axis of reflection: reference handles not found.");
989
0
            return false;
990
0
        }
991
992
0
        DragStat().SetActionRect(tools::Rectangle(pH1->GetPos(),pH2->GetPos()));
993
0
    }
994
0
    else
995
0
    {
996
0
        Point aPt(GetDragHdl()->GetPos());
997
0
        DragStat().SetActionRect(tools::Rectangle(aPt,aPt));
998
0
    }
999
1000
0
    return true;
1001
0
}
1002
1003
void SdrDragMovHdl::MoveSdrDrag(const Point& rNoSnapPnt)
1004
0
{
1005
0
    Point aPnt(rNoSnapPnt);
1006
1007
0
    if ( !(GetDragHdl() && DragStat().CheckMinMoved(rNoSnapPnt)))
1008
0
        return;
1009
1010
0
    if (GetDragHdl()->GetKind()==SdrHdlKind::MirrorAxis)
1011
0
    {
1012
0
        SdrHdl* pH1=GetHdlList().GetHdl(SdrHdlKind::Ref1);
1013
0
        SdrHdl* pH2=GetHdlList().GetHdl(SdrHdlKind::Ref2);
1014
1015
0
        if (pH1==nullptr || pH2==nullptr)
1016
0
            return;
1017
1018
0
        if (!DragStat().IsNoSnap())
1019
0
        {
1020
0
            tools::Long nBestXSnap=0;
1021
0
            tools::Long nBestYSnap=0;
1022
0
            bool bXSnapped=false;
1023
0
            bool bYSnapped=false;
1024
0
            Point aDif(aPnt-DragStat().GetStart());
1025
0
            getSdrDragView().CheckSnap(Ref1()+aDif,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped);
1026
0
            getSdrDragView().CheckSnap(Ref2()+aDif,nBestXSnap,nBestYSnap,bXSnapped,bYSnapped);
1027
0
            aPnt.AdjustX(nBestXSnap );
1028
0
            aPnt.AdjustY(nBestYSnap );
1029
0
        }
1030
1031
0
        if (aPnt!=DragStat().GetNow())
1032
0
        {
1033
0
            Hide();
1034
0
            DragStat().NextMove(aPnt);
1035
0
            Point aDif(DragStat().GetNow()-DragStat().GetStart());
1036
0
            pH1->SetPos(Ref1()+aDif);
1037
0
            pH2->SetPos(Ref2()+aDif);
1038
1039
0
            SdrHdl* pHM = GetHdlList().GetHdl(SdrHdlKind::MirrorAxis);
1040
1041
0
            if(pHM)
1042
0
                pHM->Touch();
1043
1044
0
            Show();
1045
0
            DragStat().SetActionRect(tools::Rectangle(pH1->GetPos(),pH2->GetPos()));
1046
0
        }
1047
0
    }
1048
0
    else
1049
0
    {
1050
0
        if (!DragStat().IsNoSnap()) SnapPos(aPnt);
1051
0
        Degree100 nSA(0);
1052
1053
0
        if (getSdrDragView().IsAngleSnapEnabled())
1054
0
            nSA=getSdrDragView().GetSnapAngle();
1055
1056
0
        if (getSdrDragView().IsMirrorAllowed(true,true))
1057
0
        { // limited
1058
0
            if (!getSdrDragView().IsMirrorAllowed()) nSA=4500_deg100;
1059
0
            if (!getSdrDragView().IsMirrorAllowed(true)) nSA=9000_deg100;
1060
0
        }
1061
1062
0
        if (getSdrDragView().IsOrtho() && nSA!=9000_deg100)
1063
0
            nSA=4500_deg100;
1064
1065
0
        if (nSA)
1066
0
        { // angle snapping
1067
0
            SdrHdlKind eRef=SdrHdlKind::Ref1;
1068
1069
0
            if (GetDragHdl()->GetKind()==SdrHdlKind::Ref1)
1070
0
                eRef=SdrHdlKind::Ref2;
1071
1072
0
            SdrHdl* pH=GetHdlList().GetHdl(eRef);
1073
1074
0
            if (pH!=nullptr)
1075
0
            {
1076
0
                Point aRef(pH->GetPos());
1077
0
                Degree100 nAngle=NormAngle36000(GetAngle(aPnt-aRef));
1078
0
                Degree100 nNewAngle=nAngle;
1079
0
                nNewAngle+=nSA/2_deg100;
1080
0
                nNewAngle/=nSA;
1081
0
                nNewAngle*=nSA;
1082
0
                nNewAngle=NormAngle36000(nNewAngle);
1083
0
                double a=toRadians(nNewAngle-nAngle);
1084
0
                double nSin=sin(a);
1085
0
                double nCos=cos(a);
1086
0
                RotatePoint(aPnt,aRef,nSin,nCos);
1087
1088
                // eliminate rounding errors for certain values
1089
0
                if (nSA==9000_deg100)
1090
0
                {
1091
0
                    if (nNewAngle==0_deg100    || nNewAngle==18000_deg100) aPnt.setY(aRef.Y() );
1092
0
                    if (nNewAngle==9000_deg100 || nNewAngle==27000_deg100) aPnt.setX(aRef.X() );
1093
0
                }
1094
1095
0
                if (nSA==4500_deg100)
1096
0
                    OrthoDistance8(aRef,aPnt,true);
1097
0
            }
1098
0
        }
1099
1100
0
        if (aPnt!=DragStat().GetNow())
1101
0
        {
1102
0
            Hide();
1103
0
            DragStat().NextMove(aPnt);
1104
0
            GetDragHdl()->SetPos(DragStat().GetNow());
1105
0
            SdrHdl* pHM = GetHdlList().GetHdl(SdrHdlKind::MirrorAxis);
1106
1107
0
            if(pHM)
1108
0
                pHM->Touch();
1109
1110
0
            Show();
1111
0
            DragStat().SetActionRect(tools::Rectangle(aPnt,aPnt));
1112
0
        }
1113
0
    }
1114
0
}
1115
1116
bool SdrDragMovHdl::EndSdrDrag(bool /*bCopy*/)
1117
0
{
1118
0
    if( GetDragHdl() )
1119
0
    {
1120
0
        switch (GetDragHdl()->GetKind())
1121
0
        {
1122
0
            case SdrHdlKind::Ref1:
1123
0
                Ref1()=DragStat().GetNow();
1124
0
                break;
1125
1126
0
            case SdrHdlKind::Ref2:
1127
0
                Ref2()=DragStat().GetNow();
1128
0
                break;
1129
1130
0
            case SdrHdlKind::MirrorAxis:
1131
0
                Ref1()+=DragStat().GetNow()-DragStat().GetStart();
1132
0
                Ref2()+=DragStat().GetNow()-DragStat().GetStart();
1133
0
                break;
1134
1135
0
            default: break;
1136
0
        }
1137
0
    }
1138
1139
0
    return true;
1140
0
}
1141
1142
void SdrDragMovHdl::CancelSdrDrag()
1143
0
{
1144
0
    Hide();
1145
1146
0
    SdrHdl* pHdl = GetDragHdl();
1147
0
    if( pHdl )
1148
0
        pHdl->SetPos(DragStat().GetRef1());
1149
1150
0
    SdrHdl* pHM = GetHdlList().GetHdl(SdrHdlKind::MirrorAxis);
1151
1152
0
    if(pHM)
1153
0
        pHM->Touch();
1154
0
}
1155
1156
PointerStyle SdrDragMovHdl::GetSdrDragPointer() const
1157
0
{
1158
0
    const SdrHdl* pHdl = GetDragHdl();
1159
1160
0
    if (pHdl!=nullptr)
1161
0
    {
1162
0
        return pHdl->GetPointer();
1163
0
    }
1164
1165
0
    return PointerStyle::RefHand;
1166
0
}
1167
1168
1169
SdrDragObjOwn::SdrDragObjOwn(SdrDragView& rNewView)
1170
0
:   SdrDragMethod(rNewView)
1171
0
{
1172
0
    const SdrObject* pObj = GetDragObj();
1173
1174
0
    if(pObj)
1175
0
    {
1176
        // suppress full drag for some object types
1177
0
        setSolidDraggingActive(pObj->supportsFullDrag());
1178
0
    }
1179
0
}
1180
1181
SdrDragObjOwn::~SdrDragObjOwn()
1182
0
{
1183
0
}
1184
1185
void SdrDragObjOwn::createSdrDragEntries()
1186
0
{
1187
0
    if(!mxClone)
1188
0
        return;
1189
1190
0
    basegfx::B2DPolyPolygon aDragPolyPolygon;
1191
0
    bool bAddWireframe(true);
1192
1193
0
    if(getSolidDraggingActive())
1194
0
    {
1195
0
        SdrPageView* pPV = getSdrDragView().GetSdrPageView();
1196
1197
0
        if(pPV && pPV->PageWindowCount())
1198
0
        {
1199
0
            addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntrySdrObject(*mxClone, false)));
1200
1201
            // potentially no wireframe needed, full drag works
1202
0
            bAddWireframe = false;
1203
0
        }
1204
0
    }
1205
1206
0
    if(!bAddWireframe)
1207
0
    {
1208
        // check for extra conditions for wireframe, e.g. no border at
1209
        // objects
1210
0
        if(!mxClone->HasLineStyle())
1211
0
        {
1212
0
            bAddWireframe = true;
1213
0
        }
1214
0
    }
1215
1216
0
    if(bAddWireframe)
1217
0
    {
1218
        // use wireframe poly when full drag is off or did not work
1219
0
        aDragPolyPolygon = mxClone->TakeXorPoly();
1220
0
    }
1221
1222
    // add evtl. extra DragPolyPolygon
1223
0
    const basegfx::B2DPolyPolygon aSpecialDragPolyPolygon(mxClone->getSpecialDragPoly(DragStat()));
1224
1225
0
    if(aSpecialDragPolyPolygon.count())
1226
0
    {
1227
0
        aDragPolyPolygon.append(aSpecialDragPolyPolygon);
1228
0
    }
1229
1230
0
    if(aDragPolyPolygon.count())
1231
0
    {
1232
0
        addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPolyPolygon(std::move(aDragPolyPolygon))));
1233
0
    }
1234
0
}
1235
1236
OUString SdrDragObjOwn::GetSdrDragComment() const
1237
0
{
1238
0
    OUString aStr;
1239
    // #i103058# get info string from the clone preferred, the original will
1240
    // not be changed. For security, use original as fallback
1241
0
    if(mxClone)
1242
0
    {
1243
0
        aStr = mxClone->getSpecialDragComment(DragStat());
1244
0
    }
1245
0
    else
1246
0
    {
1247
0
        const SdrObject* pObj = GetDragObj();
1248
1249
0
        if(pObj)
1250
0
        {
1251
0
            aStr = pObj->getSpecialDragComment(DragStat());
1252
0
        }
1253
0
    }
1254
0
    return aStr;
1255
0
}
1256
1257
bool SdrDragObjOwn::BeginSdrDrag()
1258
0
{
1259
0
    if(!mxClone)
1260
0
    {
1261
0
        const SdrObject* pObj = GetDragObj();
1262
1263
0
        if(pObj && !pObj->IsResizeProtect())
1264
0
        {
1265
0
            if(pObj->beginSpecialDrag(DragStat()))
1266
0
            {
1267
                // create initial clone to have a start visualization
1268
0
                mxClone = pObj->getFullDragClone();
1269
0
                mxClone->applySpecialDrag(DragStat());
1270
1271
0
                return true;
1272
0
            }
1273
0
        }
1274
0
    }
1275
1276
0
    return false;
1277
0
}
1278
1279
void SdrDragObjOwn::MoveSdrDrag(const Point& rNoSnapPnt)
1280
0
{
1281
0
    const SdrObject* pObj = GetDragObj();
1282
1283
0
    if (!pObj)
1284
        // No object to drag.  Bail out.
1285
0
        return;
1286
1287
0
    Point aPnt(rNoSnapPnt);
1288
0
    SdrPageView* pPV = GetDragPV();
1289
1290
0
    if (!pPV)
1291
        // No page view available.  Bail out.
1292
0
        return;
1293
1294
0
    if(!DragStat().IsNoSnap())
1295
0
    {
1296
0
        SnapPos(aPnt);
1297
0
    }
1298
0
    if(getSdrDragView().IsOrtho())
1299
0
    {
1300
0
        if (DragStat().IsOrtho8Possible())
1301
0
        {
1302
0
            OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
1303
0
        }
1304
0
        else if (DragStat().IsOrtho4Possible())
1305
0
        {
1306
0
            OrthoDistance4(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
1307
0
        }
1308
0
    }
1309
1310
0
    if (!DragStat().CheckMinMoved(rNoSnapPnt))
1311
        // Not moved by the minimum threshold. Nothing to do.
1312
0
        return;
1313
1314
0
    Hide();
1315
0
    DragStat().NextMove(aPnt);
1316
1317
    // since SdrDragObjOwn currently supports no transformation of
1318
    // existing SdrDragEntries but only their recreation, a recreation
1319
    // after every move is needed in this mode. Delete existing
1320
    // SdrDragEntries here  to force their recreation in the following Show().
1321
0
    clearSdrDragEntries();
1322
1323
    // delete current clone (after the last reference to it is deleted above)
1324
0
    mxClone.clear();
1325
1326
    // create a new clone and modify to current drag state
1327
0
    mxClone = pObj->getFullDragClone();
1328
0
    mxClone->applySpecialDrag(DragStat());
1329
1330
    // AutoGrowWidth may change for SdrTextObj due to the automatism used
1331
    // with bDisableAutoWidthOnDragging, so not only geometry changes but
1332
    // also this (pretty indirect) property change is possible. If it gets
1333
    // changed, it needs to be copied to the original since nothing will
1334
    // happen when it only changes in the drag clone
1335
0
    const bool bOldAutoGrowWidth(pObj->GetMergedItem(SDRATTR_TEXT_AUTOGROWWIDTH).GetValue());
1336
0
    const bool bNewAutoGrowWidth(mxClone->GetMergedItem(SDRATTR_TEXT_AUTOGROWWIDTH).GetValue());
1337
1338
0
    if (bOldAutoGrowWidth != bNewAutoGrowWidth)
1339
0
    {
1340
0
        GetDragObj()->SetMergedItem(makeSdrTextAutoGrowWidthItem(bNewAutoGrowWidth));
1341
0
    }
1342
1343
0
    Show();
1344
0
}
1345
1346
bool SdrDragObjOwn::EndSdrDrag(bool /*bCopy*/)
1347
0
{
1348
0
    Hide();
1349
0
    std::vector< std::unique_ptr<SdrUndoAction> > vConnectorUndoActions;
1350
0
    bool bRet = false;
1351
0
    SdrObject* pObj = GetDragObj();
1352
1353
0
    if(pObj)
1354
0
    {
1355
0
        std::unique_ptr<SdrUndoAction> pUndo;
1356
0
        std::unique_ptr<SdrUndoAction> pUndo2;
1357
0
        const bool bUndo = getSdrDragView().IsUndoEnabled();
1358
1359
0
        if( bUndo )
1360
0
        {
1361
0
            getSdrDragView().EndTextEditCurrentView();
1362
0
            if(!getSdrDragView().IsInsObjPoint() && pObj->IsInserted() )
1363
0
            {
1364
0
                if (DragStat().IsEndDragChangesAttributes())
1365
0
                {
1366
0
                    pUndo=getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoAttrObject(*pObj);
1367
1368
0
                    if (DragStat().IsEndDragChangesGeoAndAttributes())
1369
0
                    {
1370
0
                        vConnectorUndoActions = getSdrDragView().CreateConnectorUndo( *pObj );
1371
0
                        pUndo2 = getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj);
1372
0
                    }
1373
0
                }
1374
0
                else
1375
0
                {
1376
0
                    vConnectorUndoActions = getSdrDragView().CreateConnectorUndo( *pObj );
1377
0
                    pUndo= getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj);
1378
0
                }
1379
0
            }
1380
1381
0
            if( pUndo )
1382
0
            {
1383
0
                getSdrDragView().BegUndo( pUndo->GetComment() );
1384
0
            }
1385
0
            else
1386
0
            {
1387
0
                getSdrDragView().BegUndo();
1388
0
            }
1389
0
        }
1390
1391
        // Maybe use operator = for setting changed object data (do not change selection in
1392
        // view, this will destroy the interactor). This is possible since a clone is now
1393
        // directly modified by the modifiers. Only SdrTableObj is adding own UNDOs
1394
        // in its SdrTableObj::endSpecialDrag, so currently not possible. OTOH it uses
1395
        // a CreateUndoGeoObject(), so maybe setting SetEndDragChangesAttributes is okay. I
1396
        // will test this now
1397
0
        tools::Rectangle aBoundRect0;
1398
1399
0
        if(pObj->GetUserCall())
1400
0
        {
1401
0
            aBoundRect0 = pObj->GetLastBoundRect();
1402
0
        }
1403
1404
0
        bRet = pObj->applySpecialDrag(DragStat());
1405
0
        if (DragStat().IsEndDragChangesLayout())
1406
0
        {
1407
0
            auto pGeoUndo = dynamic_cast<SdrUndoGeoObj*>(pUndo.get());
1408
0
            if (pGeoUndo)
1409
0
                pGeoUndo->SetSkipChangeLayout(true);
1410
0
        }
1411
1412
0
        if(bRet)
1413
0
        {
1414
0
            pObj->SetChanged();
1415
0
            pObj->BroadcastObjectChange();
1416
0
            pObj->SendUserCall( SdrUserCallType::Resize, aBoundRect0 );
1417
0
        }
1418
1419
0
        if(bRet && bUndo )
1420
0
        {
1421
0
            getSdrDragView().AddUndoActions( std::move(vConnectorUndoActions) );
1422
1423
0
            if ( pUndo )
1424
0
            {
1425
0
                getSdrDragView().AddUndo(std::move(pUndo));
1426
0
            }
1427
1428
0
            if ( pUndo2 )
1429
0
            {
1430
0
                getSdrDragView().AddUndo(std::move(pUndo2));
1431
0
            }
1432
0
        }
1433
1434
0
        if( bUndo )
1435
0
            getSdrDragView().EndUndo();
1436
0
    }
1437
1438
0
    return bRet;
1439
0
}
1440
1441
PointerStyle SdrDragObjOwn::GetSdrDragPointer() const
1442
0
{
1443
0
    const SdrHdl* pHdl=GetDragHdl();
1444
1445
0
    if (pHdl)
1446
0
    {
1447
0
        return pHdl->GetPointer();
1448
0
    }
1449
1450
0
    return PointerStyle::Move;
1451
0
}
1452
1453
1454
void SdrDragMove::createSdrDragEntryForSdrObject(const SdrObject& rOriginal)
1455
0
{
1456
    // tdf#123441 - use clone-based drag for fixed-tail captions to keep the arrow anchored to the cell
1457
0
    if (const auto* pCaption = dynamic_cast<const SdrCaptionObj*>(&rOriginal))
1458
0
        if (pCaption->IsFixedTail())
1459
0
        {
1460
0
            SdrDragMethod::createSdrDragEntryForSdrObject(rOriginal);
1461
0
            return;
1462
0
        }
1463
1464
    // use the view-independent primitive representation (without
1465
    // evtl. GridOffset, that may be applied to the DragEntry individually)
1466
0
    drawinglayer::primitive2d::Primitive2DContainer xRetval;
1467
0
    rOriginal.GetViewContact().getViewIndependentPrimitive2DContainer(xRetval);
1468
0
    addSdrDragEntry(
1469
0
        std::unique_ptr<SdrDragEntry>(
1470
0
            new SdrDragEntryPrimitive2DSequence(
1471
0
                std::move(xRetval))));
1472
1473
0
}
1474
1475
void SdrDragMove::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
1476
0
{
1477
0
    rTarget.Move(Size(DragStat().GetDX(), DragStat().GetDY()));
1478
0
}
1479
1480
SdrDragMove::SdrDragMove(SdrDragView& rNewView)
1481
0
    : SdrDragMethod(rNewView)
1482
0
    , m_nBestXSnap(0)
1483
0
    , m_nBestYSnap(0)
1484
0
    , m_bXSnapped(false)
1485
0
    , m_bYSnapped(false)
1486
0
{
1487
0
    setMoveOnly(true);
1488
0
}
1489
1490
OUString SdrDragMove::GetSdrDragComment() const
1491
0
{
1492
0
    OUString aStr = ImpGetDescriptionStr(STR_DragMethMove)
1493
0
            + " (x="
1494
0
            + getSdrDragView().GetModel().GetMetricString(DragStat().GetDX())
1495
0
            + " y="
1496
0
            + getSdrDragView().GetModel().GetMetricString(DragStat().GetDY())
1497
0
            + ")";
1498
1499
0
    if(getSdrDragView().IsDragWithCopy())
1500
0
    {
1501
0
        if(!getSdrDragView().IsInsObjPoint() && !getSdrDragView().IsInsGluePoint())
1502
0
        {
1503
0
            aStr += SvxResId(STR_EditWithCopy);
1504
0
        }
1505
0
    }
1506
0
    return aStr;
1507
0
}
1508
1509
bool SdrDragMove::BeginSdrDrag()
1510
0
{
1511
0
    DragStat().SetActionRect(GetMarkedRect());
1512
0
    Show();
1513
1514
0
    return true;
1515
0
}
1516
1517
basegfx::B2DHomMatrix SdrDragMove::getCurrentTransformation() const
1518
0
{
1519
0
    return basegfx::utils::createTranslateB2DHomMatrix(DragStat().GetDX(), DragStat().GetDY());
1520
0
}
1521
1522
void SdrDragMove::ImpCheckSnap(const Point& rPt)
1523
0
{
1524
0
    Point aPt(rPt);
1525
0
    SdrSnap nRet=SnapPos(aPt);
1526
0
    aPt-=rPt;
1527
1528
0
    if (nRet & SdrSnap::XSNAPPED)
1529
0
    {
1530
0
        if (m_bXSnapped)
1531
0
        {
1532
0
            if (std::abs(aPt.X())<std::abs(m_nBestXSnap))
1533
0
            {
1534
0
                m_nBestXSnap=aPt.X();
1535
0
            }
1536
0
        }
1537
0
        else
1538
0
        {
1539
0
            m_nBestXSnap=aPt.X();
1540
0
            m_bXSnapped=true;
1541
0
        }
1542
0
    }
1543
1544
0
    if (!(nRet & SdrSnap::YSNAPPED))
1545
0
        return;
1546
1547
0
    if (m_bYSnapped)
1548
0
    {
1549
0
        if (std::abs(aPt.Y())<std::abs(m_nBestYSnap))
1550
0
        {
1551
0
            m_nBestYSnap=aPt.Y();
1552
0
        }
1553
0
    }
1554
0
    else
1555
0
    {
1556
0
        m_nBestYSnap=aPt.Y();
1557
0
        m_bYSnapped=true;
1558
0
    }
1559
0
}
1560
1561
void SdrDragMove::MoveSdrDrag(const Point& rNoSnapPnt_)
1562
0
{
1563
0
    m_nBestXSnap=0;
1564
0
    m_nBestYSnap=0;
1565
0
    m_bXSnapped=false;
1566
0
    m_bYSnapped=false;
1567
0
    Point aNoSnapPnt(rNoSnapPnt_);
1568
0
    const tools::Rectangle& aSR=GetMarkedRect();
1569
0
    tools::Long nMovedx=aNoSnapPnt.X()-DragStat().GetStart().X();
1570
0
    tools::Long nMovedy=aNoSnapPnt.Y()-DragStat().GetStart().Y();
1571
0
    Point aLO(aSR.TopLeft());      aLO.AdjustX(nMovedx ); aLO.AdjustY(nMovedy );
1572
0
    Point aRU(aSR.BottomRight());  aRU.AdjustX(nMovedx ); aRU.AdjustY(nMovedy );
1573
0
    Point aLU(aLO.X(),aRU.Y());
1574
0
    Point aRO(aRU.X(),aLO.Y());
1575
0
    ImpCheckSnap(aLO);
1576
1577
0
    if (!getSdrDragView().IsMoveSnapOnlyTopLeft())
1578
0
    {
1579
0
        ImpCheckSnap(aRO);
1580
0
        ImpCheckSnap(aLU);
1581
0
        ImpCheckSnap(aRU);
1582
0
    }
1583
1584
0
    Point aPnt(aNoSnapPnt.X()+m_nBestXSnap,aNoSnapPnt.Y()+m_nBestYSnap);
1585
0
    bool bOrtho=getSdrDragView().IsOrtho();
1586
1587
0
    if (bOrtho)
1588
0
        OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
1589
1590
0
    if (!DragStat().CheckMinMoved(aNoSnapPnt))
1591
0
        return;
1592
1593
0
    Point aPt1(aPnt);
1594
0
    tools::Rectangle aLR(getSdrDragView().GetWorkArea());
1595
0
    bool bWorkArea=!aLR.IsEmpty();
1596
0
    bool bDragLimit=IsDragLimit();
1597
1598
0
    if (bDragLimit || bWorkArea)
1599
0
    {
1600
0
        tools::Rectangle aSR2(GetMarkedRect());
1601
0
        Point aD(aPt1-DragStat().GetStart());
1602
1603
0
        if (bDragLimit)
1604
0
        {
1605
0
            tools::Rectangle aR2(GetDragLimitRect());
1606
1607
0
            if (bWorkArea)
1608
0
                aLR.Intersection(aR2);
1609
0
            else
1610
0
                aLR=aR2;
1611
0
        }
1612
1613
0
        if (aSR2.Left()>aLR.Left() || aSR2.Right()<aLR.Right())
1614
0
        { // any space to move to?
1615
0
            aSR2.Move(aD.X(),0);
1616
1617
0
            if (aSR2.Left()<aLR.Left())
1618
0
            {
1619
0
                aPt1.AdjustX( -(aSR2.Left()-aLR.Left()) );
1620
0
            }
1621
0
            else if (aSR2.Right()>aLR.Right())
1622
0
            {
1623
0
                aPt1.AdjustX( -(aSR2.Right()-aLR.Right()) );
1624
0
            }
1625
0
        }
1626
0
        else
1627
0
            aPt1.setX(DragStat().GetStart().X() ); // no space to move to
1628
1629
0
        if (aSR2.Top()>aLR.Top() || aSR2.Bottom()<aLR.Bottom())
1630
0
        { // any space to move to?
1631
0
            aSR2.Move(0,aD.Y());
1632
1633
0
            if (aSR2.Top()<aLR.Top())
1634
0
            {
1635
0
                aPt1.AdjustY( -(aSR2.Top()-aLR.Top()) );
1636
0
            }
1637
0
            else if (aSR2.Bottom()>aLR.Bottom())
1638
0
            {
1639
0
                aPt1.AdjustY( -(aSR2.Bottom()-aLR.Bottom()) );
1640
0
            }
1641
0
        }
1642
0
        else
1643
0
            aPt1.setY(DragStat().GetStart().Y() ); // no space to move to
1644
0
    }
1645
1646
0
    if (getSdrDragView().IsDraggingGluePoints())
1647
0
    { // restrict gluepoints to the BoundRect of the Obj
1648
0
        aPt1-=DragStat().GetStart();
1649
0
        const SdrMarkList& rMarkList = GetMarkedObjectList();
1650
0
        const size_t nMarkCount = rMarkList.GetMarkCount();
1651
1652
0
        for (size_t nMarkNum=0; nMarkNum<nMarkCount; ++nMarkNum)
1653
0
        {
1654
0
            const SdrMark* pM = rMarkList.GetMark(nMarkNum);
1655
0
            const SdrUShortCont& rPts = pM->GetMarkedGluePoints();
1656
1657
0
            if (!rPts.empty())
1658
0
            {
1659
0
                const SdrObject* pObj=pM->GetMarkedSdrObj();
1660
0
                const SdrGluePointList* pGPL=pObj->GetGluePointList();
1661
0
                tools::Rectangle aBound(pObj->GetCurrentBoundRect());
1662
1663
0
                for (sal_uInt16 nId : rPts)
1664
0
                {
1665
0
                    sal_uInt16 nGlueNum=pGPL->FindGluePoint(nId);
1666
1667
0
                    if (nGlueNum!=SDRGLUEPOINT_NOTFOUND)
1668
0
                    {
1669
0
                        Point aPt((*pGPL)[nGlueNum].GetAbsolutePos(*pObj));
1670
0
                        aPt+=aPt1; // move by this much
1671
0
                        if (aPt.X()<aBound.Left()  ) aPt1.AdjustX( -(aPt.X()-aBound.Left()) )  ;
1672
0
                        if (aPt.X()>aBound.Right() ) aPt1.AdjustX( -(aPt.X()-aBound.Right()) ) ;
1673
0
                        if (aPt.Y()<aBound.Top()   ) aPt1.AdjustY( -(aPt.Y()-aBound.Top()) )   ;
1674
0
                        if (aPt.Y()>aBound.Bottom()) aPt1.AdjustY( -(aPt.Y()-aBound.Bottom()) );
1675
0
                    }
1676
0
                }
1677
0
            }
1678
0
        }
1679
1680
0
        aPt1+=DragStat().GetStart();
1681
0
    }
1682
1683
0
    if (bOrtho)
1684
0
        OrthoDistance8(DragStat().GetStart(),aPt1,false);
1685
1686
0
    if (aPt1!=DragStat().GetNow())
1687
0
    {
1688
0
        Hide();
1689
0
        DragStat().NextMove(aPt1);
1690
0
        tools::Rectangle aAction(GetMarkedRect());
1691
0
        aAction.Move(DragStat().GetDX(),DragStat().GetDY());
1692
0
        DragStat().SetActionRect(aAction);
1693
0
        Show();
1694
0
    }
1695
0
}
1696
1697
bool SdrDragMove::EndSdrDrag(bool bCopy)
1698
0
{
1699
0
    Hide();
1700
1701
0
    if (getSdrDragView().IsInsObjPoint() || getSdrDragView().IsInsGluePoint())
1702
0
        bCopy=false;
1703
1704
0
    if (IsDraggingPoints())
1705
0
    {
1706
0
        getSdrDragView().MoveMarkedPoints(Size(DragStat().GetDX(),DragStat().GetDY()));
1707
0
    }
1708
0
    else if (IsDraggingGluePoints())
1709
0
    {
1710
0
        getSdrDragView().MoveMarkedGluePoints(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy);
1711
0
    }
1712
0
    else
1713
0
    {
1714
0
        getSdrDragView().MoveMarkedObj(Size(DragStat().GetDX(),DragStat().GetDY()),bCopy);
1715
0
    }
1716
1717
0
    return true;
1718
0
}
1719
1720
PointerStyle SdrDragMove::GetSdrDragPointer() const
1721
0
{
1722
0
    if (IsDraggingPoints() || IsDraggingGluePoints())
1723
0
    {
1724
0
        return PointerStyle::MovePoint;
1725
0
    }
1726
0
    else
1727
0
    {
1728
0
        return PointerStyle::Move;
1729
0
    }
1730
0
}
1731
1732
1733
SdrDragResize::SdrDragResize(SdrDragView& rNewView)
1734
0
:   SdrDragMethod(rNewView),
1735
0
    m_aXFact(1),
1736
0
    m_aYFact(1)
1737
0
{
1738
0
}
1739
1740
OUString SdrDragResize::GetSdrDragComment() const
1741
0
{
1742
0
    OUString aStr = ImpGetDescriptionStr(STR_DragMethResize);
1743
0
    double aFact1(1);
1744
0
    Point aStart(DragStat().GetStart());
1745
0
    Point aRef(DragStat().GetRef1());
1746
0
    sal_Int32 nXDiv(aStart.X() - aRef.X());
1747
1748
0
    if(!nXDiv)
1749
0
        nXDiv = 1;
1750
1751
0
    sal_Int32 nYDiv(aStart.Y() - aRef.Y());
1752
1753
0
    if(!nYDiv)
1754
0
        nYDiv = 1;
1755
1756
0
    bool bX(m_aXFact != aFact1 && std::abs(nXDiv) > 1);
1757
0
    bool bY(m_aYFact != aFact1 && std::abs(nYDiv) > 1);
1758
1759
0
    if(bX || bY)
1760
0
    {
1761
0
        aStr += " (";
1762
1763
0
        bool bEqual(m_aXFact == m_aYFact);
1764
0
        if(bX)
1765
0
        {
1766
0
            if(!bEqual)
1767
0
                aStr += "x=";
1768
1769
0
            aStr += SdrModel::GetPercentString(m_aXFact);
1770
0
        }
1771
1772
0
        if(bY && !bEqual)
1773
0
        {
1774
0
            if(bX)
1775
0
                aStr += " ";
1776
1777
0
            aStr += "y=" + SdrModel::GetPercentString(m_aYFact);
1778
0
        }
1779
1780
0
        aStr += ")";
1781
0
    }
1782
1783
0
    if(getSdrDragView().IsDragWithCopy())
1784
0
        aStr += SvxResId(STR_EditWithCopy);
1785
0
    return aStr;
1786
0
}
1787
1788
bool SdrDragResize::BeginSdrDrag()
1789
0
{
1790
0
    SdrHdlKind eRefHdl=SdrHdlKind::Move;
1791
0
    SdrHdl* pRefHdl=nullptr;
1792
1793
0
    switch (GetDragHdlKind())
1794
0
    {
1795
0
        case SdrHdlKind::UpperLeft: eRefHdl=SdrHdlKind::LowerRight; break;
1796
0
        case SdrHdlKind::Upper: eRefHdl=SdrHdlKind::Lower; DragStat().SetHorFixed(true); break;
1797
0
        case SdrHdlKind::UpperRight: eRefHdl=SdrHdlKind::LowerLeft; break;
1798
0
        case SdrHdlKind::Left : eRefHdl=SdrHdlKind::Right; DragStat().SetVerFixed(true); break;
1799
0
        case SdrHdlKind::Right: eRefHdl=SdrHdlKind::Left ; DragStat().SetVerFixed(true); break;
1800
0
        case SdrHdlKind::LowerLeft: eRefHdl=SdrHdlKind::UpperRight; break;
1801
0
        case SdrHdlKind::Lower: eRefHdl=SdrHdlKind::Upper; DragStat().SetHorFixed(true); break;
1802
0
        case SdrHdlKind::LowerRight: eRefHdl=SdrHdlKind::UpperLeft; break;
1803
0
        default: break;
1804
0
    }
1805
1806
0
    if (eRefHdl!=SdrHdlKind::Move)
1807
0
        pRefHdl=GetHdlList().GetHdl(eRefHdl);
1808
1809
0
    if (pRefHdl!=nullptr && !getSdrDragView().IsResizeAtCenter())
1810
0
    {
1811
0
        DragStat().SetRef1(pRefHdl->GetPos());
1812
0
    }
1813
0
    else
1814
0
    {
1815
0
        SdrHdl* pRef1=GetHdlList().GetHdl(SdrHdlKind::UpperLeft);
1816
0
        SdrHdl* pRef2=GetHdlList().GetHdl(SdrHdlKind::LowerRight);
1817
1818
0
        if (pRef1!=nullptr && pRef2!=nullptr)
1819
0
        {
1820
0
            DragStat().SetRef1(tools::Rectangle(pRef1->GetPos(),pRef2->GetPos()).Center());
1821
0
        }
1822
0
        else
1823
0
        {
1824
0
            DragStat().SetRef1(GetMarkedRect().Center());
1825
0
        }
1826
0
    }
1827
1828
0
    Show();
1829
1830
0
    return true;
1831
0
}
1832
1833
basegfx::B2DHomMatrix SdrDragResize::getCurrentTransformation() const
1834
0
{
1835
0
    basegfx::B2DHomMatrix aRetval(basegfx::utils::createTranslateB2DHomMatrix(
1836
0
        -DragStat().GetRef1().X(), -DragStat().GetRef1().Y()));
1837
0
    aRetval.scale(m_aXFact, m_aYFact);
1838
0
    aRetval.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
1839
1840
0
    return aRetval;
1841
0
}
1842
1843
void SdrDragResize::MoveSdrDrag(const Point& rNoSnapPnt)
1844
0
{
1845
0
    Point aPnt(GetSnapPos(rNoSnapPnt));
1846
0
    Point aStart(DragStat().GetStart());
1847
0
    Point aRef(DragStat().GetRef1());
1848
0
    double aMaxFact(0x7FFFFFFF);
1849
0
    tools::Rectangle aLR(getSdrDragView().GetWorkArea());
1850
0
    bool bWorkArea=!aLR.IsEmpty();
1851
0
    bool bDragLimit=IsDragLimit();
1852
1853
0
    if (bDragLimit || bWorkArea)
1854
0
    {
1855
0
        tools::Rectangle aSR(GetMarkedRect());
1856
1857
0
        if (bDragLimit)
1858
0
        {
1859
0
            tools::Rectangle aR2(GetDragLimitRect());
1860
1861
0
            if (bWorkArea)
1862
0
                aLR.Intersection(aR2);
1863
0
            else
1864
0
                aLR=aR2;
1865
0
        }
1866
1867
0
        if (aPnt.X()<aLR.Left())
1868
0
            aPnt.setX(aLR.Left() );
1869
0
        else if (aPnt.X()>aLR.Right())
1870
0
            aPnt.setX(aLR.Right() );
1871
1872
0
        if (aPnt.Y()<aLR.Top())
1873
0
            aPnt.setY(aLR.Top() );
1874
0
        else if (aPnt.Y()>aLR.Bottom())
1875
0
            aPnt.setY(aLR.Bottom() );
1876
1877
0
        if (aRef.X()>aSR.Left())
1878
0
        {
1879
0
            double aMax = double(aRef.X()-aLR.Left()) / (aRef.X()-aSR.Left());
1880
1881
0
            if (aMax<aMaxFact)
1882
0
                aMaxFact=aMax;
1883
0
        }
1884
1885
0
        if (aRef.X()<aSR.Right())
1886
0
        {
1887
0
            double aMax = double(aLR.Right()-aRef.X()) / (aSR.Right()-aRef.X());
1888
1889
0
            if (aMax<aMaxFact)
1890
0
                aMaxFact=aMax;
1891
0
        }
1892
1893
0
        if (aRef.Y()>aSR.Top())
1894
0
        {
1895
0
            double aMax = double(aRef.Y()-aLR.Top()) / (aRef.Y()-aSR.Top());
1896
1897
0
            if (aMax<aMaxFact)
1898
0
                aMaxFact=aMax;
1899
0
        }
1900
1901
0
        if (aRef.Y()<aSR.Bottom())
1902
0
        {
1903
0
            double aMax = double(aLR.Bottom()-aRef.Y()) / (aSR.Bottom()-aRef.Y());
1904
1905
0
            if (aMax<aMaxFact)
1906
0
                aMaxFact=aMax;
1907
0
        }
1908
0
    }
1909
1910
0
    tools::Long nXDiv=aStart.X()-aRef.X(); if (nXDiv==0) nXDiv=1;
1911
0
    tools::Long nYDiv=aStart.Y()-aRef.Y(); if (nYDiv==0) nYDiv=1;
1912
0
    tools::Long nXMul=aPnt.X()-aRef.X();
1913
0
    tools::Long nYMul=aPnt.Y()-aRef.Y();
1914
1915
0
    if (nXDiv<0)
1916
0
    {
1917
0
        nXDiv=-nXDiv;
1918
0
        nXMul=-nXMul;
1919
0
    }
1920
1921
0
    if (nYDiv<0)
1922
0
    {
1923
0
        nYDiv=-nYDiv;
1924
0
        nYMul=-nYMul;
1925
0
    }
1926
1927
0
    bool bXNeg=nXMul<0; if (bXNeg) nXMul=-nXMul;
1928
0
    bool bYNeg=nYMul<0; if (bYNeg) nYMul=-nYMul;
1929
0
    bool bOrtho=getSdrDragView().IsOrtho() || !getSdrDragView().IsResizeAllowed();
1930
1931
0
    if (!DragStat().IsHorFixed() && !DragStat().IsVerFixed())
1932
0
    {
1933
0
        if (std::abs(nXDiv)<=1 || std::abs(nYDiv)<=1)
1934
0
            bOrtho=false;
1935
1936
0
        if (bOrtho)
1937
0
        {
1938
0
            if ((Fraction(nXMul,nXDiv)>Fraction(nYMul,nYDiv)) !=getSdrDragView().IsBigOrtho())
1939
0
            {
1940
0
                nXMul=nYMul;
1941
0
                nXDiv=nYDiv;
1942
0
            }
1943
0
            else
1944
0
            {
1945
0
                nYMul=nXMul;
1946
0
                nYDiv=nXDiv;
1947
0
            }
1948
0
        }
1949
0
    }
1950
0
    else
1951
0
    {
1952
0
        if (bOrtho)
1953
0
        {
1954
0
            if (DragStat().IsHorFixed())
1955
0
            {
1956
0
                bXNeg=false;
1957
0
                nXMul=nYMul;
1958
0
                nXDiv=nYDiv;
1959
0
            }
1960
1961
0
            if (DragStat().IsVerFixed())
1962
0
            {
1963
0
                bYNeg=false;
1964
0
                nYMul=nXMul;
1965
0
                nYDiv=nXDiv;
1966
0
            }
1967
0
        }
1968
0
        else
1969
0
        {
1970
0
            if (DragStat().IsHorFixed())
1971
0
            {
1972
0
                bXNeg=false;
1973
0
                nXMul=1;
1974
0
                nXDiv=1;
1975
0
            }
1976
1977
0
            if (DragStat().IsVerFixed())
1978
0
            {
1979
0
                bYNeg=false;
1980
0
                nYMul=1;
1981
0
                nYDiv=1;
1982
0
            }
1983
0
        }
1984
0
    }
1985
1986
0
    double aNewXFact(double(nXMul)/nXDiv);
1987
0
    double aNewYFact(double(nYMul)/nYDiv);
1988
1989
0
    if (bOrtho)
1990
0
    {
1991
0
        if (aNewXFact>aMaxFact)
1992
0
        {
1993
0
            aNewXFact=aMaxFact;
1994
0
            aNewYFact=aMaxFact;
1995
0
        }
1996
1997
0
        if (aNewYFact>aMaxFact)
1998
0
        {
1999
0
            aNewXFact=aMaxFact;
2000
0
            aNewYFact=aMaxFact;
2001
0
        }
2002
0
    }
2003
2004
0
    if (bXNeg)
2005
0
        aNewXFact = -aNewXFact;
2006
2007
0
    if (bYNeg)
2008
0
        aNewYFact = -aNewYFact;
2009
2010
0
    if (DragStat().CheckMinMoved(aPnt))
2011
0
    {
2012
0
        if ((!DragStat().IsHorFixed() && aPnt.X()!=DragStat().GetNow().X()) ||
2013
0
            (!DragStat().IsVerFixed() && aPnt.Y()!=DragStat().GetNow().Y()))
2014
0
        {
2015
0
            Hide();
2016
0
            DragStat().NextMove(aPnt);
2017
0
            m_aXFact=aNewXFact;
2018
0
            m_aYFact=aNewYFact;
2019
2020
0
            aNewXFact = aNewXFact > 0 ? aNewXFact : 1.0;
2021
0
            aNewYFact = aNewYFact > 0 ? aNewYFact : 1.0;
2022
0
            Size aTargetSize(
2023
0
                    GetMarkedRect().GetSize().scale(aNewXFact, aNewYFact));
2024
0
            Show(getSdrDragView().IsMarkedObjSizeValid(aTargetSize));
2025
0
        }
2026
0
    }
2027
0
}
2028
2029
void SdrDragResize::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2030
0
{
2031
0
    rTarget.Resize(DragStat().GetRef1(),m_aXFact,m_aYFact);
2032
0
}
2033
2034
bool SdrDragResize::EndSdrDrag(bool bCopy)
2035
0
{
2036
0
    Hide();
2037
2038
0
    if (IsDraggingPoints())
2039
0
    {
2040
0
        getSdrDragView().ResizeMarkedPoints(DragStat().GetRef1(),m_aXFact,m_aYFact);
2041
0
    }
2042
0
    else if (IsDraggingGluePoints())
2043
0
    {
2044
0
        getSdrDragView().ResizeMarkedGluePoints(DragStat().GetRef1(),m_aXFact,m_aYFact,bCopy);
2045
0
    }
2046
0
    else
2047
0
    {
2048
0
        getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),m_aXFact,m_aYFact,bCopy);
2049
0
    }
2050
2051
0
    return true;
2052
0
}
2053
2054
PointerStyle SdrDragResize::GetSdrDragPointer() const
2055
0
{
2056
0
    const SdrHdl* pHdl=GetDragHdl();
2057
2058
0
    if (pHdl!=nullptr)
2059
0
    {
2060
0
        return pHdl->GetPointer();
2061
0
    }
2062
2063
0
    return PointerStyle::Move;
2064
0
}
2065
2066
2067
void SdrDragRotate::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2068
0
{
2069
0
    rTarget.Rotate(DragStat().GetRef1(), nAngle, nSin, nCos);
2070
0
}
2071
2072
SdrDragRotate::SdrDragRotate(SdrDragView& rNewView)
2073
0
:   SdrDragMethod(rNewView),
2074
0
    nSin(0.0),
2075
0
    nCos(1.0),
2076
0
    nAngle0(0),
2077
0
    nAngle(0),
2078
0
    bRight(false)
2079
0
{
2080
0
}
2081
2082
OUString SdrDragRotate::GetSdrDragComment() const
2083
0
{
2084
0
    OUString aStr = ImpGetDescriptionStr(STR_DragMethRotate) +
2085
0
        " (";
2086
0
    Degree100 nTmpAngle(NormAngle36000(nAngle));
2087
2088
0
    if(bRight && nAngle)
2089
0
    {
2090
0
        nTmpAngle -= 36000_deg100;
2091
0
    }
2092
2093
0
    aStr += SdrModel::GetAngleString(nTmpAngle) + ")";
2094
2095
0
    if(getSdrDragView().IsDragWithCopy())
2096
0
        aStr += SvxResId(STR_EditWithCopy);
2097
0
    return aStr;
2098
0
}
2099
2100
bool SdrDragRotate::BeginSdrDrag()
2101
0
{
2102
0
    SdrHdl* pH=GetHdlList().GetHdl(SdrHdlKind::Ref1);
2103
2104
0
    if (nullptr != pH)
2105
0
    {
2106
0
        Show();
2107
0
        DragStat().SetRef1(pH->GetPos());
2108
0
        nAngle0=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2109
0
        return true;
2110
0
    }
2111
2112
    // RotGrfFlyFrame: Support rotation around center *without* Ref1 (normally
2113
    // the rotation point)
2114
0
    const tools::Rectangle aLocalMarkRect(getSdrDragView().GetMarkedObjRect());
2115
2116
0
    if(!aLocalMarkRect.IsEmpty())
2117
0
    {
2118
0
        Show();
2119
0
        DragStat().SetRef1(aLocalMarkRect.Center());
2120
0
        nAngle0=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2121
0
        return true;
2122
0
    }
2123
2124
0
    OSL_FAIL("SdrDragRotate::BeginSdrDrag(): No reference point handle found.");
2125
0
    return false;
2126
0
}
2127
2128
basegfx::B2DHomMatrix SdrDragRotate::getCurrentTransformation() const
2129
0
{
2130
0
    return basegfx::utils::createRotateAroundPoint(
2131
0
        DragStat().GetRef1().X(), DragStat().GetRef1().Y(),
2132
0
        -atan2(nSin, nCos));
2133
0
}
2134
2135
void SdrDragRotate::MoveSdrDrag(const Point& rPnt_)
2136
0
{
2137
0
    Point aPnt(rPnt_);
2138
0
    if (!DragStat().CheckMinMoved(aPnt))
2139
0
        return;
2140
2141
0
    Degree100 nNewAngle=NormAngle36000(GetAngle(aPnt-DragStat().GetRef1())-nAngle0);
2142
0
    Degree100 nSA(0);
2143
2144
0
    if (getSdrDragView().IsAngleSnapEnabled())
2145
0
        nSA=getSdrDragView().GetSnapAngle();
2146
2147
0
    if (!getSdrDragView().IsRotateAllowed())
2148
0
        nSA=9000_deg100;
2149
2150
0
    if (nSA)
2151
0
    { // angle snapping
2152
0
        nNewAngle += nSA / 2_deg100;
2153
0
        nNewAngle /= nSA;
2154
0
        nNewAngle *= nSA;
2155
0
    }
2156
2157
0
    nNewAngle=NormAngle18000(nNewAngle);
2158
2159
0
    if (nAngle==nNewAngle)
2160
0
        return;
2161
2162
0
    sal_uInt16 nSekt0=GetAngleSector(nAngle);
2163
0
    sal_uInt16 nSekt1=GetAngleSector(nNewAngle);
2164
2165
0
    if (nSekt0==0 && nSekt1==3)
2166
0
        bRight=true;
2167
2168
0
    if (nSekt0==3 && nSekt1==0)
2169
0
        bRight=false;
2170
2171
0
    nAngle=nNewAngle;
2172
0
    double a = toRadians(nAngle);
2173
0
    double nSin1=sin(a); // calculate now, so as little time as possible
2174
0
    double nCos1=cos(a); // passes between Hide() and Show()
2175
0
    Hide();
2176
0
    nSin=nSin1;
2177
0
    nCos=nCos1;
2178
0
    DragStat().NextMove(aPnt);
2179
0
    Show();
2180
0
}
2181
2182
bool SdrDragRotate::EndSdrDrag(bool bCopy)
2183
0
{
2184
0
    Hide();
2185
2186
0
    if (nAngle!=0_deg100)
2187
0
    {
2188
0
        if (IsDraggingPoints())
2189
0
        {
2190
0
            getSdrDragView().RotateMarkedPoints(DragStat().GetRef1(),nAngle);
2191
0
        }
2192
0
        else if (IsDraggingGluePoints())
2193
0
        {
2194
0
            getSdrDragView().RotateMarkedGluePoints(DragStat().GetRef1(),nAngle,bCopy);
2195
0
        }
2196
0
        else
2197
0
        {
2198
0
            getSdrDragView().RotateMarkedObj(DragStat().GetRef1(),nAngle,bCopy);
2199
0
        }
2200
0
    }
2201
0
    return true;
2202
0
}
2203
2204
PointerStyle SdrDragRotate::GetSdrDragPointer() const
2205
0
{
2206
0
    return PointerStyle::Rotate;
2207
0
}
2208
2209
2210
SdrDragShear::SdrDragShear(SdrDragView& rNewView, bool bSlant1)
2211
0
:   SdrDragMethod(rNewView),
2212
0
    aFact(1.0),
2213
0
    nAngle0(0),
2214
0
    nAngle(0),
2215
0
    nTan(0.0),
2216
0
    bVertical(false),
2217
0
    bResize(false),
2218
0
    bUpSideDown(false),
2219
0
    bSlant(bSlant1)
2220
0
{
2221
0
}
2222
2223
OUString SdrDragShear::GetSdrDragComment() const
2224
0
{
2225
0
    OUString aStr = ImpGetDescriptionStr(STR_DragMethShear) +
2226
0
        " (";
2227
2228
0
    Degree100 nTmpAngle(nAngle);
2229
2230
0
    if(bUpSideDown)
2231
0
        nTmpAngle += 18000_deg100;
2232
2233
0
    nTmpAngle = NormAngle18000(nTmpAngle);
2234
2235
0
    aStr += SdrModel::GetAngleString(nTmpAngle) + ")";
2236
2237
0
    if(getSdrDragView().IsDragWithCopy())
2238
0
        aStr += SvxResId(STR_EditWithCopy);
2239
0
    return aStr;
2240
0
}
2241
2242
bool SdrDragShear::BeginSdrDrag()
2243
0
{
2244
0
    SdrHdlKind eRefHdl=SdrHdlKind::Move;
2245
0
    SdrHdl* pRefHdl=nullptr;
2246
2247
0
    switch (GetDragHdlKind())
2248
0
    {
2249
0
        case SdrHdlKind::Upper: eRefHdl=SdrHdlKind::Lower; break;
2250
0
        case SdrHdlKind::Lower: eRefHdl=SdrHdlKind::Upper; break;
2251
0
        case SdrHdlKind::Left : eRefHdl=SdrHdlKind::Right; bVertical=true; break;
2252
0
        case SdrHdlKind::Right: eRefHdl=SdrHdlKind::Left ; bVertical=true; break;
2253
0
        default: break;
2254
0
    }
2255
2256
0
    if (eRefHdl!=SdrHdlKind::Move)
2257
0
        pRefHdl=GetHdlList().GetHdl(eRefHdl);
2258
2259
0
    if (pRefHdl!=nullptr)
2260
0
    {
2261
0
        DragStat().SetRef1(pRefHdl->GetPos());
2262
0
        nAngle0=GetAngle(DragStat().GetStart()-DragStat().GetRef1());
2263
0
    }
2264
0
    else
2265
0
    {
2266
0
        OSL_FAIL("SdrDragShear::BeginSdrDrag(): No reference point handle for shearing found.");
2267
0
        return false;
2268
0
    }
2269
2270
0
    Show();
2271
0
    return true;
2272
0
}
2273
2274
basegfx::B2DHomMatrix SdrDragShear::getCurrentTransformation() const
2275
0
{
2276
0
    basegfx::B2DHomMatrix aRetval(basegfx::utils::createTranslateB2DHomMatrix(
2277
0
        -DragStat().GetRef1().X(), -DragStat().GetRef1().Y()));
2278
2279
0
    if (bResize)
2280
0
    {
2281
0
        if (bVertical)
2282
0
        {
2283
0
            aRetval.scale(aFact, 1.0);
2284
0
            aRetval.shearY(-nTan);
2285
0
        }
2286
0
        else
2287
0
        {
2288
0
            aRetval.scale(1.0, aFact);
2289
0
            aRetval.shearX(-nTan);
2290
0
        }
2291
0
    }
2292
2293
0
    aRetval.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2294
2295
0
    return aRetval;
2296
0
}
2297
2298
void SdrDragShear::MoveSdrDrag(const Point& rPnt)
2299
0
{
2300
0
    if (!DragStat().CheckMinMoved(rPnt))
2301
0
        return;
2302
2303
0
    bResize=!getSdrDragView().IsOrtho();
2304
0
    Degree100 nSA(0);
2305
2306
0
    if (getSdrDragView().IsAngleSnapEnabled())
2307
0
        nSA=getSdrDragView().GetSnapAngle();
2308
2309
0
    Point aP0(DragStat().GetStart());
2310
0
    Point aPnt(rPnt);
2311
0
    double aNewFract(1.0);
2312
2313
    // if angle snapping not activated, snap to raster (except when using slant)
2314
0
    if (nSA==0_deg100 && !bSlant)
2315
0
        aPnt=GetSnapPos(aPnt);
2316
2317
0
    if (!bSlant && !bResize)
2318
0
    { // shear, but no resize
2319
0
        if (bVertical)
2320
0
            aPnt.setX(aP0.X() );
2321
0
        else
2322
0
            aPnt.setY(aP0.Y() );
2323
0
    }
2324
2325
0
    Point aRef(DragStat().GetRef1());
2326
0
    Point aDif(aPnt-aRef);
2327
2328
0
    Degree100 nNewAngle(0);
2329
2330
0
    if (bSlant)
2331
0
    {
2332
0
        nNewAngle=NormAngle18000(-(GetAngle(aDif)-nAngle0));
2333
2334
0
        if (bVertical)
2335
0
            nNewAngle=NormAngle18000(-nNewAngle);
2336
0
    }
2337
0
    else
2338
0
    {
2339
0
        if (bVertical)
2340
0
            nNewAngle=NormAngle18000(GetAngle(aDif));
2341
0
        else
2342
0
            nNewAngle=NormAngle18000(-(GetAngle(aDif)-9000_deg100));
2343
2344
0
        if (nNewAngle<Degree100(-9000) || nNewAngle>9000_deg100)
2345
0
            nNewAngle=NormAngle18000(nNewAngle+18000_deg100);
2346
2347
0
        if (bResize)
2348
0
        {
2349
0
            Point aPt2(aPnt);
2350
2351
0
            if (nSA!=0_deg100)
2352
0
                aPt2=GetSnapPos(aPnt); // snap this one in any case
2353
2354
0
            if (bVertical)
2355
0
            {
2356
0
                aNewFract = double(aPt2.X()-aRef.X()) / (aP0.X()-aRef.X());
2357
0
            }
2358
0
            else
2359
0
            {
2360
0
                aNewFract = double(aPt2.Y()-aRef.Y()) / (aP0.Y()-aRef.Y());
2361
0
            }
2362
0
        }
2363
0
    }
2364
2365
0
    bool bNeg=nNewAngle<0_deg100;
2366
2367
0
    if (bNeg)
2368
0
        nNewAngle=-nNewAngle;
2369
2370
0
    if (nSA)
2371
0
    { // angle snapping
2372
0
        nNewAngle += nSA / 2_deg100;
2373
0
        nNewAngle /= nSA;
2374
0
        nNewAngle *= nSA;
2375
0
    }
2376
2377
0
    nNewAngle=NormAngle36000(nNewAngle);
2378
0
    bUpSideDown=nNewAngle>9000_deg100 && nNewAngle<27000_deg100;
2379
2380
0
    if (bSlant)
2381
0
    { // calculate resize for slant
2382
        // when angle snapping is activated, disable 89 degree limit
2383
0
        Degree100 nTmpAngle=nNewAngle;
2384
0
        if (bUpSideDown) nNewAngle -= 18000_deg100;
2385
0
        if (bNeg) nTmpAngle=-nTmpAngle;
2386
0
        bResize=true;
2387
0
        aNewFract = cos(toRadians(nTmpAngle));
2388
0
    }
2389
2390
0
    if (nNewAngle > 8900_deg100)
2391
0
        nNewAngle = 8900_deg100;
2392
2393
0
    if (bNeg)
2394
0
        nNewAngle=-nNewAngle;
2395
2396
0
    if (nAngle!=nNewAngle || aFact!=aNewFract)
2397
0
    {
2398
0
        nAngle=nNewAngle;
2399
0
        aFact=aNewFract;
2400
0
        double a = toRadians(nAngle);
2401
0
        double nTan1=tan(a); // calculate now, so as little time as possible passes between Hide() and Show()
2402
0
        Hide();
2403
0
        nTan=nTan1;
2404
0
        DragStat().NextMove(rPnt);
2405
0
        Show();
2406
0
    }
2407
0
}
2408
2409
void SdrDragShear::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2410
0
{
2411
0
    if (bResize)
2412
0
    {
2413
0
        if (bVertical)
2414
0
        {
2415
0
            rTarget.Resize(DragStat().GetRef1(),aFact,1);
2416
0
        }
2417
0
        else
2418
0
        {
2419
0
            rTarget.Resize(DragStat().GetRef1(),1,aFact);
2420
0
        }
2421
0
    }
2422
2423
0
    if (nAngle)
2424
0
    {
2425
0
        rTarget.Shear(DragStat().GetRef1(), nAngle, nTan, bVertical);
2426
0
    }
2427
0
}
2428
2429
bool SdrDragShear::EndSdrDrag(bool bCopy)
2430
0
{
2431
0
    Hide();
2432
2433
0
    if (bResize && aFact==1.0)
2434
0
        bResize=false;
2435
2436
0
    if (nAngle || bResize)
2437
0
    {
2438
0
        if (nAngle && bResize)
2439
0
        {
2440
0
            OUString aStr = ImpGetDescriptionStr(STR_EditShear);
2441
2442
0
            if (bCopy)
2443
0
                aStr += SvxResId(STR_EditWithCopy);
2444
2445
0
            getSdrDragView().BegUndo(aStr);
2446
0
        }
2447
2448
0
        if (bResize)
2449
0
        {
2450
0
            if (bVertical)
2451
0
            {
2452
0
                getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),aFact,1.0,bCopy);
2453
0
            }
2454
0
            else
2455
0
            {
2456
0
                getSdrDragView().ResizeMarkedObj(DragStat().GetRef1(),1.0,aFact,bCopy);
2457
0
            }
2458
2459
0
            bCopy=false;
2460
0
        }
2461
2462
0
        if (nAngle)
2463
0
        {
2464
0
            getSdrDragView().ShearMarkedObj(DragStat().GetRef1(),nAngle,bVertical,bCopy);
2465
0
        }
2466
2467
0
        if (nAngle && bResize)
2468
0
            getSdrDragView().EndUndo();
2469
2470
0
        return true;
2471
0
    }
2472
2473
0
    return false;
2474
0
}
2475
2476
PointerStyle SdrDragShear::GetSdrDragPointer() const
2477
0
{
2478
0
    if (bVertical)
2479
0
        return PointerStyle::VShear;
2480
0
    else
2481
0
        return PointerStyle::HShear;
2482
0
}
2483
2484
2485
void SdrDragMirror::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
2486
0
{
2487
0
    if(bMirrored)
2488
0
    {
2489
0
        rTarget.Mirror(DragStat().GetRef1(), DragStat().GetRef2());
2490
0
    }
2491
0
}
2492
2493
SdrDragMirror::SdrDragMirror(SdrDragView& rNewView)
2494
0
:   SdrDragMethod(rNewView),
2495
0
    nAngle(0),
2496
0
    bMirrored(false),
2497
0
    bSide0(false)
2498
0
{
2499
0
}
2500
2501
bool SdrDragMirror::ImpCheckSide(const Point& rPnt) const
2502
0
{
2503
0
    Degree100 nAngle1=GetAngle(rPnt-DragStat().GetRef1());
2504
0
    nAngle1-=nAngle;
2505
0
    nAngle1=NormAngle36000(nAngle1);
2506
2507
0
    return nAngle1<18000_deg100;
2508
0
}
2509
2510
OUString SdrDragMirror::GetSdrDragComment() const
2511
0
{
2512
0
    OUString aStr;
2513
0
    if (aDif.X()==0)
2514
0
        aStr = ImpGetDescriptionStr(STR_DragMethMirrorHori);
2515
0
    else if (aDif.Y()==0)
2516
0
        aStr = ImpGetDescriptionStr(STR_DragMethMirrorVert);
2517
0
    else if (std::abs(aDif.X()) == std::abs(aDif.Y()))
2518
0
        aStr = ImpGetDescriptionStr(STR_DragMethMirrorDiag);
2519
0
    else
2520
0
        aStr = ImpGetDescriptionStr(STR_DragMethMirrorFree);
2521
2522
0
    if (getSdrDragView().IsDragWithCopy())
2523
0
        aStr+=SvxResId(STR_EditWithCopy);
2524
0
    return aStr;
2525
0
}
2526
2527
bool SdrDragMirror::BeginSdrDrag()
2528
0
{
2529
0
    SdrHdl* pH1=GetHdlList().GetHdl(SdrHdlKind::Ref1);
2530
0
    SdrHdl* pH2=GetHdlList().GetHdl(SdrHdlKind::Ref2);
2531
2532
0
    if (pH1!=nullptr && pH2!=nullptr)
2533
0
    {
2534
0
        DragStat().SetRef1(pH1->GetPos());
2535
0
        DragStat().SetRef2(pH2->GetPos());
2536
0
        Ref1()=pH1->GetPos();
2537
0
        Ref2()=pH2->GetPos();
2538
0
        aDif=pH2->GetPos()-pH1->GetPos();
2539
0
        bool b90=(aDif.X()==0) || aDif.Y()==0;
2540
0
        bool b45=b90 || (std::abs(aDif.X()) == std::abs(aDif.Y()));
2541
0
        nAngle=NormAngle36000(GetAngle(aDif));
2542
2543
0
        if (!getSdrDragView().IsMirrorAllowed() && !b45)
2544
0
            return false; // free choice of axis angle not allowed
2545
2546
0
        if (!getSdrDragView().IsMirrorAllowed() && !b90)
2547
0
            return false;  // 45 degrees not allowed either
2548
2549
0
        bSide0=ImpCheckSide(DragStat().GetStart());
2550
0
        Show();
2551
0
        return true;
2552
0
    }
2553
0
    else
2554
0
    {
2555
0
        OSL_FAIL("SdrDragMirror::BeginSdrDrag(): Axis of reflection not found.");
2556
0
        return false;
2557
0
    }
2558
0
}
2559
2560
basegfx::B2DHomMatrix SdrDragMirror::getCurrentTransformation() const
2561
0
{
2562
0
    basegfx::B2DHomMatrix aRetval;
2563
2564
0
    if (bMirrored)
2565
0
    {
2566
0
        const double fDeltaX(DragStat().GetRef2().X() - DragStat().GetRef1().X());
2567
0
        const double fDeltaY(DragStat().GetRef2().Y() - DragStat().GetRef1().Y());
2568
0
        const double fRotation(atan2(fDeltaY, fDeltaX));
2569
2570
0
        aRetval = basegfx::utils::createTranslateB2DHomMatrix(-DragStat().GetRef1().X(), -DragStat().GetRef1().Y());
2571
0
        aRetval.rotate(-fRotation);
2572
0
        aRetval.scale(1.0, -1.0);
2573
0
        aRetval.rotate(fRotation);
2574
0
        aRetval.translate(DragStat().GetRef1().X(), DragStat().GetRef1().Y());
2575
0
    }
2576
2577
0
    return aRetval;
2578
0
}
2579
2580
void SdrDragMirror::MoveSdrDrag(const Point& rPnt)
2581
0
{
2582
0
    if (!DragStat().CheckMinMoved(rPnt))
2583
0
        return;
2584
2585
0
    bool bNewSide=ImpCheckSide(rPnt);
2586
0
    bool bNewMirrored=bSide0!=bNewSide;
2587
2588
0
    if (bMirrored!=bNewMirrored)
2589
0
    {
2590
0
        Hide();
2591
0
        bMirrored=bNewMirrored;
2592
0
        DragStat().NextMove(rPnt);
2593
0
        Show();
2594
0
    }
2595
0
}
2596
2597
bool SdrDragMirror::EndSdrDrag(bool bCopy)
2598
0
{
2599
0
    Hide();
2600
2601
0
    if (bMirrored)
2602
0
    {
2603
0
        getSdrDragView().MirrorMarkedObj(DragStat().GetRef1(),DragStat().GetRef2(),bCopy);
2604
0
    }
2605
2606
0
    return true;
2607
0
}
2608
2609
PointerStyle SdrDragMirror::GetSdrDragPointer() const
2610
0
{
2611
0
    return PointerStyle::Mirror;
2612
0
}
2613
2614
2615
SdrDragGradient::SdrDragGradient(SdrDragView& rNewView, bool bGrad)
2616
0
:   SdrDragMethod(rNewView),
2617
0
    pIAOHandle(nullptr),
2618
0
    bIsGradient(bGrad)
2619
0
{
2620
0
}
2621
2622
OUString SdrDragGradient::GetSdrDragComment() const
2623
0
{
2624
0
    if(IsGradient())
2625
0
        return ImpGetDescriptionStr(STR_DragMethGradient);
2626
0
    else
2627
0
        return ImpGetDescriptionStr(STR_DragMethTransparence);
2628
0
}
2629
2630
bool SdrDragGradient::BeginSdrDrag()
2631
0
{
2632
0
    bool bRetval(false);
2633
2634
0
    pIAOHandle = static_cast<SdrHdlGradient*>(GetHdlList().GetHdl(IsGradient() ? SdrHdlKind::Gradient : SdrHdlKind::Transparence));
2635
2636
0
    if(pIAOHandle)
2637
0
    {
2638
        // save old values
2639
0
        DragStat().SetRef1( pIAOHandle->GetPos() );
2640
0
        DragStat().SetRef2( pIAOHandle->Get2ndPos() );
2641
2642
        // what was hit?
2643
0
        bool bHit(false);
2644
0
        SdrHdlColor* pColHdl = pIAOHandle->GetColorHdl1();
2645
2646
        // init handling flags
2647
0
        pIAOHandle->SetMoveSingleHandle(false);
2648
0
        pIAOHandle->SetMoveFirstHandle(false);
2649
2650
        // test first color handle
2651
0
        if(pColHdl)
2652
0
        {
2653
0
            basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2654
2655
0
            if(pColHdl->getOverlayObjectList().isHitLogic(aPosition))
2656
0
            {
2657
0
                bHit = true;
2658
0
                pIAOHandle->SetMoveSingleHandle(true);
2659
0
                pIAOHandle->SetMoveFirstHandle(true);
2660
0
            }
2661
0
        }
2662
2663
        // test second color handle
2664
0
        pColHdl = pIAOHandle->GetColorHdl2();
2665
2666
0
        if(!bHit && pColHdl)
2667
0
        {
2668
0
            basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2669
2670
0
            if(pColHdl->getOverlayObjectList().isHitLogic(aPosition))
2671
0
            {
2672
0
                bHit = true;
2673
0
                pIAOHandle->SetMoveSingleHandle(true);
2674
0
            }
2675
0
        }
2676
2677
        // test gradient handle itself
2678
0
        if(!bHit)
2679
0
        {
2680
0
            basegfx::B2DPoint aPosition(DragStat().GetStart().X(), DragStat().GetStart().Y());
2681
2682
0
            if(pIAOHandle->getOverlayObjectList().isHitLogic(aPosition))
2683
0
            {
2684
0
                bHit = true;
2685
0
            }
2686
0
        }
2687
2688
        // everything up and running :o}
2689
0
        bRetval = bHit;
2690
0
    }
2691
0
    else
2692
0
    {
2693
0
        OSL_FAIL("SdrDragGradient::BeginSdrDrag(): IAOGradient not found.");
2694
0
    }
2695
2696
0
    return bRetval;
2697
0
}
2698
2699
void SdrDragGradient::MoveSdrDrag(const Point& rPnt)
2700
0
{
2701
0
    if(!(pIAOHandle && DragStat().CheckMinMoved(rPnt)))
2702
0
        return;
2703
2704
0
    DragStat().NextMove(rPnt);
2705
2706
    // Do the Move here!!! DragStat().GetStart()
2707
0
    Point aMoveDiff = rPnt - DragStat().GetStart();
2708
2709
0
    if(pIAOHandle->IsMoveSingleHandle())
2710
0
    {
2711
0
        if(pIAOHandle->IsMoveFirstHandle())
2712
0
        {
2713
0
            pIAOHandle->SetPos(DragStat().GetRef1() + aMoveDiff);
2714
0
            if(pIAOHandle->GetColorHdl1())
2715
0
                pIAOHandle->GetColorHdl1()->SetPos(DragStat().GetRef1() + aMoveDiff);
2716
0
        }
2717
0
        else
2718
0
        {
2719
0
            pIAOHandle->Set2ndPos(DragStat().GetRef2() + aMoveDiff);
2720
0
            if(pIAOHandle->GetColorHdl2())
2721
0
                pIAOHandle->GetColorHdl2()->SetPos(DragStat().GetRef2() + aMoveDiff);
2722
0
        }
2723
0
    }
2724
0
    else
2725
0
    {
2726
0
        pIAOHandle->SetPos(DragStat().GetRef1() + aMoveDiff);
2727
0
        pIAOHandle->Set2ndPos(DragStat().GetRef2() + aMoveDiff);
2728
2729
0
        if(pIAOHandle->GetColorHdl1())
2730
0
            pIAOHandle->GetColorHdl1()->SetPos(DragStat().GetRef1() + aMoveDiff);
2731
2732
0
        if(pIAOHandle->GetColorHdl2())
2733
0
            pIAOHandle->GetColorHdl2()->SetPos(DragStat().GetRef2() + aMoveDiff);
2734
0
    }
2735
2736
    // new state
2737
0
    const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
2738
0
    pIAOHandle->FromIAOToItem(rMarkList.GetMark(0)->GetMarkedSdrObj(), false, false);
2739
0
}
2740
2741
bool SdrDragGradient::EndSdrDrag(bool /*bCopy*/)
2742
0
{
2743
0
    Ref1() = pIAOHandle->GetPos();
2744
0
    Ref2() = pIAOHandle->Get2ndPos();
2745
2746
    // new state
2747
0
    const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
2748
0
    pIAOHandle->FromIAOToItem(rMarkList.GetMark(0)->GetMarkedSdrObj(), true, true);
2749
2750
0
    return true;
2751
0
}
2752
2753
void SdrDragGradient::CancelSdrDrag()
2754
0
{
2755
    // restore old values
2756
0
    pIAOHandle->SetPos(DragStat().GetRef1());
2757
0
    pIAOHandle->Set2ndPos(DragStat().GetRef2());
2758
2759
0
    if(pIAOHandle->GetColorHdl1())
2760
0
        pIAOHandle->GetColorHdl1()->SetPos(DragStat().GetRef1());
2761
2762
0
    if(pIAOHandle->GetColorHdl2())
2763
0
        pIAOHandle->GetColorHdl2()->SetPos(DragStat().GetRef2());
2764
2765
    // new state
2766
0
    const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
2767
0
    pIAOHandle->FromIAOToItem(rMarkList.GetMark(0)->GetMarkedSdrObj(), true, false);
2768
0
}
2769
2770
PointerStyle SdrDragGradient::GetSdrDragPointer() const
2771
0
{
2772
0
    return PointerStyle::RefHand;
2773
0
}
2774
2775
2776
SdrDragCrook::SdrDragCrook(SdrDragView& rNewView)
2777
0
:   SdrDragMethod(rNewView),
2778
0
    aFact(1.0),
2779
0
    bContortionAllowed(false),
2780
0
    bNoContortionAllowed(false),
2781
0
    bContortion(false),
2782
0
    bResizeAllowed(false),
2783
0
    bResize(false),
2784
0
    bRotateAllowed(false),
2785
0
    bRotate(false),
2786
0
    bVertical(false),
2787
0
    bValid(false),
2788
0
    bLft(false),
2789
0
    bRgt(false),
2790
0
    bUpr(false),
2791
0
    bLwr(false),
2792
0
    bAtCenter(false),
2793
0
    nAngle(0),
2794
0
    nMarkSize(0),
2795
0
    eMode(SdrCrookMode::Rotate)
2796
0
{
2797
0
}
2798
2799
OUString SdrDragCrook::GetSdrDragComment() const
2800
0
{
2801
0
    OUString aStr = ImpGetDescriptionStr(!bContortion ? STR_DragMethCrook : STR_DragMethCrookContortion);
2802
2803
0
    if(bValid)
2804
0
    {
2805
0
        aStr += " (";
2806
2807
0
        sal_Int32 nVal(nAngle);
2808
2809
0
        if(bAtCenter)
2810
0
            nVal *= 2;
2811
2812
0
        nVal = std::abs(nVal);
2813
0
        aStr += SdrModel::GetAngleString(Degree100(nVal)) + ")";
2814
0
    }
2815
2816
0
    if(getSdrDragView().IsDragWithCopy())
2817
0
        aStr += SvxResId(STR_EditWithCopy);
2818
0
    return aStr;
2819
0
}
2820
2821
// These defines parametrize the created raster
2822
// for interactions
2823
0
#define DRAG_CROOK_RASTER_MINIMUM   (4)
2824
0
#define DRAG_CROOK_RASTER_MAXIMUM   (15)
2825
0
#define DRAG_CROOK_RASTER_DISTANCE  (30)
2826
2827
static basegfx::B2DPolyPolygon impCreateDragRaster(SdrPageView const & rPageView, const tools::Rectangle& rMarkRect)
2828
0
{
2829
0
    basegfx::B2DPolyPolygon aRetval;
2830
2831
0
    if(rPageView.PageWindowCount())
2832
0
    {
2833
0
        OutputDevice& rOut = rPageView.GetPageWindow(0)->GetPaintWindow().GetOutputDevice();
2834
0
        tools::Rectangle aPixelSize = rOut.LogicToPixel(rMarkRect);
2835
0
        sal_uInt32 nHorDiv(aPixelSize.GetWidth() / DRAG_CROOK_RASTER_DISTANCE);
2836
0
        sal_uInt32 nVerDiv(aPixelSize.GetHeight() / DRAG_CROOK_RASTER_DISTANCE);
2837
2838
0
        if(nHorDiv > DRAG_CROOK_RASTER_MAXIMUM)
2839
0
            nHorDiv = DRAG_CROOK_RASTER_MAXIMUM;
2840
0
        if(nHorDiv < DRAG_CROOK_RASTER_MINIMUM)
2841
0
            nHorDiv = DRAG_CROOK_RASTER_MINIMUM;
2842
2843
0
        if(nVerDiv > DRAG_CROOK_RASTER_MAXIMUM)
2844
0
            nVerDiv = DRAG_CROOK_RASTER_MAXIMUM;
2845
0
        if(nVerDiv < DRAG_CROOK_RASTER_MINIMUM)
2846
0
            nVerDiv = DRAG_CROOK_RASTER_MINIMUM;
2847
2848
0
        const double fXLen(rMarkRect.GetWidth() / static_cast<double>(nHorDiv));
2849
0
        const double fYLen(rMarkRect.GetHeight() / static_cast<double>(nVerDiv));
2850
0
        double fYPos(rMarkRect.Top());
2851
0
        sal_uInt32 a, b;
2852
2853
0
        for(a = 0; a <= nVerDiv; a++)
2854
0
        {
2855
            // horizontal lines
2856
0
            for(b = 0; b < nHorDiv; b++)
2857
0
            {
2858
0
                basegfx::B2DPolygon aHorLineSegment;
2859
2860
0
                const double fNewX(rMarkRect.Left() + (b * fXLen));
2861
0
                aHorLineSegment.append(basegfx::B2DPoint(fNewX, fYPos));
2862
0
                aHorLineSegment.appendBezierSegment(
2863
0
                    basegfx::B2DPoint(fNewX + (fXLen * (1.0 / 3.0)), fYPos),
2864
0
                    basegfx::B2DPoint(fNewX + (fXLen * (2.0 / 3.0)), fYPos),
2865
0
                    basegfx::B2DPoint(fNewX + fXLen, fYPos));
2866
0
                aRetval.append(aHorLineSegment);
2867
0
            }
2868
2869
            // increments
2870
0
            fYPos += fYLen;
2871
0
        }
2872
2873
0
        double fXPos(rMarkRect.Left());
2874
2875
0
        for(a = 0; a <= nHorDiv; a++)
2876
0
        {
2877
            // vertical lines
2878
0
            for(b = 0; b < nVerDiv; b++)
2879
0
            {
2880
0
                basegfx::B2DPolygon aVerLineSegment;
2881
2882
0
                const double fNewY(rMarkRect.Top() + (b * fYLen));
2883
0
                aVerLineSegment.append(basegfx::B2DPoint(fXPos, fNewY));
2884
0
                aVerLineSegment.appendBezierSegment(
2885
0
                    basegfx::B2DPoint(fXPos, fNewY + (fYLen * (1.0 / 3.0))),
2886
0
                    basegfx::B2DPoint(fXPos, fNewY + (fYLen * (2.0 / 3.0))),
2887
0
                    basegfx::B2DPoint(fXPos, fNewY + fYLen));
2888
0
                aRetval.append(aVerLineSegment);
2889
0
            }
2890
2891
            // increments
2892
0
            fXPos += fXLen;
2893
0
        }
2894
0
    }
2895
2896
0
    return aRetval;
2897
0
}
2898
2899
void SdrDragCrook::createSdrDragEntries()
2900
0
{
2901
    // Add extended frame raster first, so it will be behind objects
2902
0
    if(getSdrDragView().GetSdrPageView())
2903
0
    {
2904
0
        const basegfx::B2DPolyPolygon aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
2905
2906
0
        if(aDragRaster.count())
2907
0
        {
2908
0
            addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPolyPolygon(aDragRaster)));
2909
0
        }
2910
0
    }
2911
2912
    // call parent
2913
0
    SdrDragMethod::createSdrDragEntries();
2914
0
}
2915
2916
bool SdrDragCrook::BeginSdrDrag()
2917
0
{
2918
0
    bContortionAllowed=getSdrDragView().IsCrookAllowed();
2919
0
    bNoContortionAllowed=getSdrDragView().IsCrookAllowed(true);
2920
0
    bResizeAllowed=getSdrDragView().IsResizeAllowed();
2921
0
    bRotateAllowed=getSdrDragView().IsRotateAllowed();
2922
2923
0
    if (bContortionAllowed || bNoContortionAllowed)
2924
0
    {
2925
0
        bVertical=(GetDragHdlKind()==SdrHdlKind::Lower || GetDragHdlKind()==SdrHdlKind::Upper);
2926
0
        aMarkRect=GetMarkedRect();
2927
0
        aMarkCenter=aMarkRect.Center();
2928
0
        nMarkSize=bVertical ? (aMarkRect.GetHeight()-1) : (aMarkRect.GetWidth()-1);
2929
0
        aCenter=aMarkCenter;
2930
0
        aStart=DragStat().GetStart();
2931
0
        Show();
2932
0
        return true;
2933
0
    }
2934
0
    else
2935
0
    {
2936
0
        return false;
2937
0
    }
2938
0
}
2939
2940
void SdrDragCrook::MovAllPoints(basegfx::B2DPolyPolygon& rTarget)
2941
0
{
2942
0
    SdrPageView* pPV = getSdrDragView().GetSdrPageView();
2943
2944
0
    if(!pPV)
2945
0
        return;
2946
2947
0
    XPolyPolygon aTempPolyPoly(rTarget);
2948
2949
0
    if (pPV->HasMarkedObjPageView())
2950
0
    {
2951
0
        sal_uInt16 nPolyCount=aTempPolyPoly.Count();
2952
2953
0
        if (!bContortion && !getSdrDragView().IsNoDragXorPolys())
2954
0
        {
2955
0
            sal_uInt16 n1st=0,nLast=0;
2956
0
            Point aC(aCenter);
2957
2958
0
            while (n1st<nPolyCount)
2959
0
            {
2960
0
                nLast=n1st;
2961
0
                while (nLast<nPolyCount && aTempPolyPoly[nLast].GetPointCount()!=0) nLast++;
2962
0
                tools::Rectangle aBound(aTempPolyPoly[n1st].GetBoundRect());
2963
0
                sal_uInt16 i;
2964
2965
0
                for (i=n1st+1; i<nLast; i++)
2966
0
                {
2967
0
                    aBound.Union(aTempPolyPoly[n1st].GetBoundRect());
2968
0
                }
2969
2970
0
                Point aCtr0(aBound.Center());
2971
0
                Point aCtr1(aCtr0);
2972
2973
0
                if (bResize)
2974
0
                {
2975
0
                    double aFact1(1.0);
2976
2977
0
                    if (bVertical)
2978
0
                    {
2979
0
                        ResizePoint(aCtr1,aC,aFact1,aFact);
2980
0
                    }
2981
0
                    else
2982
0
                    {
2983
0
                        ResizePoint(aCtr1,aC,aFact,aFact1);
2984
0
                    }
2985
0
                }
2986
2987
0
                bool bRotOk=false;
2988
0
                double nSin=0,nCos=0;
2989
2990
0
                if (aRad.X()!=0 && aRad.Y()!=0)
2991
0
                {
2992
0
                    bRotOk=bRotate;
2993
2994
0
                    switch (eMode)
2995
0
                    {
2996
0
                        case SdrCrookMode::Rotate : CrookRotateXPoint (aCtr1,nullptr,nullptr,aC,aRad,nSin,nCos,bVertical);           break;
2997
0
                        case SdrCrookMode::Slant  : CrookSlantXPoint  (aCtr1,nullptr,nullptr,aC,aRad,nSin,nCos,bVertical);           break;
2998
0
                        case SdrCrookMode::Stretch: CrookStretchXPoint(aCtr1,nullptr,nullptr,aC,aRad,nSin,nCos,bVertical,aMarkRect); break;
2999
0
                    } // switch
3000
0
                }
3001
3002
0
                aCtr1-=aCtr0;
3003
3004
0
                for (i=n1st; i<nLast; i++)
3005
0
                {
3006
0
                    if (bRotOk)
3007
0
                    {
3008
0
                        RotateXPoly(aTempPolyPoly[i],aCtr0,nSin,nCos);
3009
0
                    }
3010
3011
0
                    aTempPolyPoly[i].Move(aCtr1.X(),aCtr1.Y());
3012
0
                }
3013
3014
0
                n1st=nLast+1;
3015
0
            }
3016
0
        }
3017
0
        else
3018
0
        {
3019
0
            sal_uInt16 i,j;
3020
3021
0
            for (j=0; j<nPolyCount; j++)
3022
0
            {
3023
0
                XPolygon& aPol=aTempPolyPoly[j];
3024
0
                sal_uInt16 nPointCount=aPol.GetPointCount();
3025
0
                i=0;
3026
3027
0
                while (i<nPointCount)
3028
0
                {
3029
0
                    Point* pPnt=&aPol[i];
3030
0
                    Point* pC1=nullptr;
3031
0
                    Point* pC2=nullptr;
3032
3033
0
                    if (i+1<nPointCount && aPol.IsControl(i))
3034
0
                    { // control point on the left
3035
0
                        pC1=pPnt;
3036
0
                        i++;
3037
0
                        pPnt=&aPol[i];
3038
0
                    }
3039
3040
0
                    i++;
3041
3042
0
                    if (i<nPointCount && aPol.IsControl(i))
3043
0
                    { // control point on the right
3044
0
                        pC2=&aPol[i];
3045
0
                        i++;
3046
0
                    }
3047
3048
0
                    MovCrookPoint(*pPnt,pC1,pC2);
3049
0
                }
3050
0
            }
3051
0
        }
3052
0
    }
3053
3054
0
    rTarget = aTempPolyPoly.getB2DPolyPolygon();
3055
0
}
3056
3057
void SdrDragCrook::MovCrookPoint(Point& rPnt, Point* pC1, Point* pC2)
3058
0
{
3059
0
    bool bVert=bVertical;
3060
0
    bool bC1=pC1!=nullptr;
3061
0
    bool bC2=pC2!=nullptr;
3062
0
    Point aC(aCenter);
3063
3064
0
    if (bResize)
3065
0
    {
3066
0
        double aFact1(1.0);
3067
3068
0
        if (bVert)
3069
0
        {
3070
0
            ResizePoint(rPnt,aC,aFact1,aFact);
3071
3072
0
            if (bC1)
3073
0
                ResizePoint(*pC1,aC,aFact1,aFact);
3074
3075
0
            if (bC2)
3076
0
                ResizePoint(*pC2,aC,aFact1,aFact);
3077
0
        }
3078
0
        else
3079
0
        {
3080
0
            ResizePoint(rPnt,aC,aFact,aFact1);
3081
3082
0
            if (bC1)
3083
0
                ResizePoint(*pC1,aC,aFact,aFact1);
3084
3085
0
            if (bC2)
3086
0
                ResizePoint(*pC2,aC,aFact,aFact1);
3087
0
        }
3088
0
    }
3089
3090
0
    if (aRad.X()!=0 && aRad.Y()!=0)
3091
0
    {
3092
0
        double nSin,nCos;
3093
3094
0
        switch (eMode)
3095
0
        {
3096
0
            case SdrCrookMode::Rotate : CrookRotateXPoint (rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert);           break;
3097
0
            case SdrCrookMode::Slant  : CrookSlantXPoint  (rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert);           break;
3098
0
            case SdrCrookMode::Stretch: CrookStretchXPoint(rPnt,pC1,pC2,aC,aRad,nSin,nCos,bVert,aMarkRect); break;
3099
0
        } // switch
3100
0
    }
3101
0
}
3102
3103
void SdrDragCrook::MoveSdrDrag(const Point& rPnt)
3104
0
{
3105
0
    if (!DragStat().CheckMinMoved(rPnt))
3106
0
        return;
3107
3108
0
    bool bNewMoveOnly=getSdrDragView().IsMoveOnlyDragging();
3109
0
    bAtCenter=false;
3110
0
    SdrCrookMode eNewMode=getSdrDragView().GetCrookMode();
3111
0
    bool bNewContortion=!bNewMoveOnly && ((bContortionAllowed && !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed);
3112
0
    bResize=!getSdrDragView().IsOrtho() && bResizeAllowed && !bNewMoveOnly;
3113
0
    bool bNewRotate=bRotateAllowed && !bNewContortion && !bNewMoveOnly && eNewMode==SdrCrookMode::Rotate;
3114
3115
0
    Point aPnt(GetSnapPos(rPnt));
3116
3117
0
    Point aNewCenter(aMarkCenter.X(),aStart.Y());
3118
3119
0
    if (bVertical)
3120
0
    {
3121
0
        aNewCenter.setX(aStart.X() );
3122
0
        aNewCenter.setY(aMarkCenter.Y() );
3123
0
    }
3124
3125
0
    if (!getSdrDragView().IsCrookAtCenter())
3126
0
    {
3127
0
        switch (GetDragHdlKind())
3128
0
        {
3129
0
            case SdrHdlKind::UpperLeft: aNewCenter.setX(aMarkRect.Right() );  bLft=true; break;
3130
0
            case SdrHdlKind::Upper: aNewCenter.setY(aMarkRect.Bottom() ); bUpr=true; break;
3131
0
            case SdrHdlKind::UpperRight: aNewCenter.setX(aMarkRect.Left() );   bRgt=true; break;
3132
0
            case SdrHdlKind::Left : aNewCenter.setX(aMarkRect.Right() );  bLft=true; break;
3133
0
            case SdrHdlKind::Right: aNewCenter.setX(aMarkRect.Left() );   bRgt=true; break;
3134
0
            case SdrHdlKind::LowerLeft: aNewCenter.setX(aMarkRect.Right() );  bLft=true; break;
3135
0
            case SdrHdlKind::Lower: aNewCenter.setY(aMarkRect.Top() );    bLwr=true; break;
3136
0
            case SdrHdlKind::LowerRight: aNewCenter.setX(aMarkRect.Left() );   bRgt=true; break;
3137
0
            default: bAtCenter=true;
3138
0
        }
3139
0
    }
3140
0
    else
3141
0
        bAtCenter=true;
3142
3143
0
    double aNewFract(1.0);
3144
0
    tools::Long dx1=aPnt.X()-aNewCenter.X();
3145
0
    tools::Long dy1=aPnt.Y()-aNewCenter.Y();
3146
0
    bValid=bVertical ? dx1!=0 : dy1!=0;
3147
3148
0
    if (bValid)
3149
0
    {
3150
0
        if (bVertical)
3151
0
            bValid = std::abs(dx1)*100>std::abs(dy1);
3152
0
        else
3153
0
            bValid = std::abs(dy1)*100>std::abs(dx1);
3154
0
    }
3155
3156
0
    tools::Long nNewRad=0;
3157
0
    nAngle=0_deg100;
3158
3159
0
    if (bValid)
3160
0
    {
3161
0
        double a=0; // slope of the radius
3162
0
        Degree100 nPntAngle(0);
3163
3164
0
        if (bVertical)
3165
0
        {
3166
0
            a=static_cast<double>(dy1)/static_cast<double>(dx1); // slope of the radius
3167
0
            nNewRad=(static_cast<tools::Long>(dy1*a)+dx1) /2;
3168
0
            aNewCenter.AdjustX(nNewRad );
3169
0
            nPntAngle=GetAngle(aPnt-aNewCenter);
3170
0
        }
3171
0
        else
3172
0
        {
3173
0
            a=static_cast<double>(dx1)/static_cast<double>(dy1); // slope of the radius
3174
0
            nNewRad=(static_cast<tools::Long>(dx1*a)+dy1) /2;
3175
0
            aNewCenter.AdjustY(nNewRad );
3176
0
            nPntAngle=GetAngle(aPnt-aNewCenter)-9000_deg100;
3177
0
        }
3178
3179
0
        if (!bAtCenter)
3180
0
        {
3181
0
            if (nNewRad<0)
3182
0
            {
3183
0
                if (bRgt) nPntAngle += 18000_deg100;
3184
0
                if (bLft) nPntAngle = 18000_deg100 - nPntAngle;
3185
0
                if (bLwr) nPntAngle =- nPntAngle;
3186
0
            }
3187
0
            else
3188
0
            {
3189
0
                if (bRgt) nPntAngle = -nPntAngle;
3190
0
                if (bUpr) nPntAngle = 18000_deg100 - nPntAngle;
3191
0
                if (bLwr) nPntAngle += 18000_deg100;
3192
0
            }
3193
3194
0
            nPntAngle=NormAngle36000(nPntAngle);
3195
0
        }
3196
0
        else
3197
0
        {
3198
0
            if (nNewRad<0) nPntAngle += 18000_deg100;
3199
0
            if (bVertical) nPntAngle = 18000_deg100 - nPntAngle;
3200
0
            nPntAngle = NormAngle18000(nPntAngle);
3201
0
            nPntAngle = abs(nPntAngle);
3202
0
        }
3203
3204
0
        double nCircumference = 2 * std::abs(nNewRad) * M_PI;
3205
3206
0
        if (bResize)
3207
0
        {
3208
0
            tools::Long nMul=static_cast<tools::Long>(nCircumference * NormAngle36000(nPntAngle).get() / 36000.0);
3209
3210
0
            if (bAtCenter)
3211
0
                nMul*=2;
3212
3213
0
            aNewFract = double(nMul) / nMarkSize;
3214
0
            nAngle=nPntAngle;
3215
0
        }
3216
0
        else
3217
0
        {
3218
0
            nAngle = Degree100(static_cast<tools::Long>((nMarkSize*360/nCircumference)*100)/2);
3219
3220
0
            if (nAngle==0_deg100)
3221
0
                bValid=false;
3222
0
        }
3223
0
    }
3224
3225
0
    if (nAngle==0_deg100 || nNewRad==0)
3226
0
        bValid=false;
3227
3228
0
    if (!bValid)
3229
0
        nNewRad=0;
3230
3231
0
    if (!bValid && bResize)
3232
0
    {
3233
0
        tools::Long nMul=bVertical ? dy1 : dx1;
3234
3235
0
        if (bLft || bUpr)
3236
0
            nMul=-nMul;
3237
3238
0
        tools::Long nDiv=nMarkSize;
3239
3240
0
        if (bAtCenter)
3241
0
        {
3242
0
            nMul*=2;
3243
0
            nMul = std::abs(nMul);
3244
0
        }
3245
3246
0
        aNewFract = double(nMul) / nDiv;
3247
0
    }
3248
3249
0
    if (aNewCenter==aCenter && bNewContortion==bContortion && aNewFract==aFact &&
3250
0
        bNewMoveOnly == getMoveOnly() && bNewRotate==bRotate && eNewMode==eMode)
3251
0
        return;
3252
3253
0
    Hide();
3254
0
    setMoveOnly(bNewMoveOnly);
3255
0
    bRotate=bNewRotate;
3256
0
    eMode=eNewMode;
3257
0
    bContortion=bNewContortion;
3258
0
    aCenter=aNewCenter;
3259
0
    aFact=aNewFract;
3260
0
    aRad=Point(nNewRad,nNewRad);
3261
0
    bResize=aFact!=1.0 && aFact != 0.0;
3262
0
    DragStat().NextMove(aPnt);
3263
0
    Show();
3264
0
}
3265
3266
void SdrDragCrook::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
3267
0
{
3268
0
    const bool bDoResize(aFact!=1.0);
3269
0
    const bool bDoCrook(aCenter!=aMarkCenter && aRad.X()!=0 && aRad.Y()!=0);
3270
3271
0
    if (!(bDoCrook || bDoResize))
3272
0
        return;
3273
3274
0
    if (bDoResize)
3275
0
    {
3276
0
        double aFact1(1);
3277
3278
0
        if (bContortion)
3279
0
        {
3280
0
            if (bVertical)
3281
0
            {
3282
0
                rTarget.Resize(aCenter,aFact1,aFact);
3283
0
            }
3284
0
            else
3285
0
            {
3286
0
                rTarget.Resize(aCenter,aFact,aFact1);
3287
0
            }
3288
0
        }
3289
0
        else
3290
0
        {
3291
0
            Point aCtr0(rTarget.GetSnapRect().Center());
3292
0
            Point aCtr1(aCtr0);
3293
3294
0
            if (bVertical)
3295
0
            {
3296
0
                ResizePoint(aCtr1,aCenter,aFact1,aFact);
3297
0
            }
3298
0
            else
3299
0
            {
3300
0
                ResizePoint(aCtr1,aCenter,aFact,aFact1);
3301
0
            }
3302
3303
0
            Size aSiz(aCtr1.X()-aCtr0.X(),aCtr1.Y()-aCtr0.Y());
3304
3305
0
            rTarget.Move(aSiz);
3306
0
        }
3307
0
    }
3308
3309
0
    if (bDoCrook)
3310
0
    {
3311
0
        const tools::Rectangle aLocalMarkRect(getSdrDragView().GetMarkedObjRect());
3312
0
        const bool bLocalRotate(!bContortion && eMode == SdrCrookMode::Rotate && getSdrDragView().IsRotateAllowed());
3313
3314
0
        SdrEditView::ImpCrookObj(&rTarget,aCenter,aRad,eMode,bVertical,!bContortion,bLocalRotate,aLocalMarkRect);
3315
0
    }
3316
0
}
3317
3318
void SdrDragCrook::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget)
3319
0
{
3320
    // use helper derived from old stuff
3321
0
    MovAllPoints(rTarget);
3322
0
}
3323
3324
bool SdrDragCrook::EndSdrDrag(bool bCopy)
3325
0
{
3326
0
    Hide();
3327
3328
0
    if (bResize && aFact==1.0)
3329
0
        bResize=false;
3330
3331
0
    const bool bUndo = getSdrDragView().IsUndoEnabled();
3332
3333
0
    bool bDoCrook=aCenter!=aMarkCenter && aRad.X()!=0 && aRad.Y()!=0;
3334
3335
0
    if (bDoCrook || bResize)
3336
0
    {
3337
0
        if (bResize && bUndo)
3338
0
        {
3339
0
            OUString aStr = ImpGetDescriptionStr(!bContortion?STR_EditCrook:STR_EditCrookContortion);
3340
3341
0
            if (bCopy)
3342
0
                aStr += SvxResId(STR_EditWithCopy);
3343
3344
0
            getSdrDragView().BegUndo(aStr);
3345
0
        }
3346
3347
0
        if (bResize)
3348
0
        {
3349
0
            double aFact1(1.0);
3350
3351
0
            if (bContortion)
3352
0
            {
3353
0
                if (bVertical)
3354
0
                    getSdrDragView().ResizeMarkedObj(aCenter,aFact1,aFact,bCopy);
3355
0
                else
3356
0
                    getSdrDragView().ResizeMarkedObj(aCenter,aFact,aFact1,bCopy);
3357
0
            }
3358
0
            else
3359
0
            {
3360
0
                if (bCopy)
3361
0
                    getSdrDragView().CopyMarkedObj();
3362
3363
0
                const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
3364
0
                const size_t nMarkCount=rMarkList.GetMarkCount();
3365
3366
0
                for (size_t nm=0; nm<nMarkCount; ++nm)
3367
0
                {
3368
0
                    SdrMark* pM=rMarkList.GetMark(nm);
3369
0
                    SdrObject* pO=pM->GetMarkedSdrObj();
3370
0
                    Point aCtr0(pO->GetSnapRect().Center());
3371
0
                    Point aCtr1(aCtr0);
3372
3373
0
                    if (bVertical)
3374
0
                        ResizePoint(aCtr1,aCenter,aFact1,aFact);
3375
0
                    else
3376
0
                        ResizePoint(aCtr1,aCenter,aFact,aFact1);
3377
3378
0
                    Size aSiz(aCtr1.X()-aCtr0.X(),aCtr1.Y()-aCtr0.Y());
3379
0
                    if( bUndo )
3380
0
                        AddUndo(getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoMoveObject(*pO,aSiz));
3381
0
                    pO->Move(aSiz);
3382
0
                }
3383
0
            }
3384
3385
0
            bCopy=false;
3386
0
        }
3387
3388
0
        if (bDoCrook)
3389
0
        {
3390
0
            getSdrDragView().CrookMarkedObj(aCenter,aRad,eMode,bVertical,!bContortion,bCopy);
3391
0
        }
3392
3393
0
        if (bResize && bUndo)
3394
0
            getSdrDragView().EndUndo();
3395
3396
0
        return true;
3397
0
    }
3398
3399
0
    return false;
3400
0
}
3401
3402
PointerStyle SdrDragCrook::GetSdrDragPointer() const
3403
0
{
3404
0
    return PointerStyle::Crook;
3405
0
}
3406
3407
3408
SdrDragDistort::SdrDragDistort(SdrDragView& rNewView)
3409
0
:   SdrDragMethod(rNewView),
3410
0
    nPolyPt(0),
3411
0
    bContortionAllowed(false),
3412
0
    bNoContortionAllowed(false),
3413
0
    bContortion(false)
3414
0
{
3415
0
}
3416
3417
OUString SdrDragDistort::GetSdrDragComment() const
3418
0
{
3419
0
    OUString aStr = ImpGetDescriptionStr(STR_DragMethDistort)
3420
0
            + " (x="
3421
0
            + getSdrDragView().GetModel().GetMetricString(DragStat().GetDX())
3422
0
            + " y="
3423
0
            + getSdrDragView().GetModel().GetMetricString(DragStat().GetDY())
3424
0
            + ")";
3425
3426
0
    if(getSdrDragView().IsDragWithCopy())
3427
0
        aStr += SvxResId(STR_EditWithCopy);
3428
0
    return aStr;
3429
0
}
3430
3431
void SdrDragDistort::createSdrDragEntries()
3432
0
{
3433
    // Add extended frame raster first, so it will be behind objects
3434
0
    if(getSdrDragView().GetSdrPageView())
3435
0
    {
3436
0
        const basegfx::B2DPolyPolygon aDragRaster(impCreateDragRaster(*getSdrDragView().GetSdrPageView(), GetMarkedRect()));
3437
3438
0
        if(aDragRaster.count())
3439
0
        {
3440
0
            addSdrDragEntry(std::unique_ptr<SdrDragEntry>(new SdrDragEntryPolyPolygon(aDragRaster)));
3441
0
        }
3442
0
    }
3443
3444
    // call parent
3445
0
    SdrDragMethod::createSdrDragEntries();
3446
0
}
3447
3448
bool SdrDragDistort::BeginSdrDrag()
3449
0
{
3450
0
    bContortionAllowed=getSdrDragView().IsDistortAllowed();
3451
0
    bNoContortionAllowed=getSdrDragView().IsDistortAllowed(true);
3452
3453
0
    if (bContortionAllowed || bNoContortionAllowed)
3454
0
    {
3455
0
        SdrHdlKind eKind=GetDragHdlKind();
3456
0
        nPolyPt=0xFFFF;
3457
3458
0
        if (eKind==SdrHdlKind::UpperLeft) nPolyPt=0;
3459
0
        if (eKind==SdrHdlKind::UpperRight) nPolyPt=1;
3460
0
        if (eKind==SdrHdlKind::LowerRight) nPolyPt=2;
3461
0
        if (eKind==SdrHdlKind::LowerLeft) nPolyPt=3;
3462
0
        if (nPolyPt>3) return false;
3463
3464
0
        aMarkRect=GetMarkedRect();
3465
0
        aDistortedRect=XPolygon(aMarkRect);
3466
0
        Show();
3467
0
        return true;
3468
0
    }
3469
0
    else
3470
0
    {
3471
0
        return false;
3472
0
    }
3473
0
}
3474
3475
void SdrDragDistort::MovAllPoints(basegfx::B2DPolyPolygon& rTarget)
3476
0
{
3477
0
    if (!bContortion)
3478
0
        return;
3479
3480
0
    SdrPageView* pPV = getSdrDragView().GetSdrPageView();
3481
3482
0
    if(pPV && pPV->HasMarkedObjPageView())
3483
0
    {
3484
0
        basegfx::B2DPolyPolygon aDragPolygon(rTarget);
3485
0
        const basegfx::B2DRange aOriginalRange = vcl::unotools::b2DRectangleFromRectangle(aMarkRect);
3486
0
        const basegfx::B2DPoint aTopLeft(aDistortedRect[0].X(), aDistortedRect[0].Y());
3487
0
        const basegfx::B2DPoint aTopRight(aDistortedRect[1].X(), aDistortedRect[1].Y());
3488
0
        const basegfx::B2DPoint aBottomLeft(aDistortedRect[3].X(), aDistortedRect[3].Y());
3489
0
        const basegfx::B2DPoint aBottomRight(aDistortedRect[2].X(), aDistortedRect[2].Y());
3490
3491
0
        rTarget = basegfx::utils::distort(aDragPolygon, aOriginalRange, aTopLeft, aTopRight, aBottomLeft, aBottomRight);
3492
0
    }
3493
0
}
3494
3495
void SdrDragDistort::MoveSdrDrag(const Point& rPnt)
3496
0
{
3497
0
    if (!DragStat().CheckMinMoved(rPnt))
3498
0
        return;
3499
3500
0
    Point aPnt(GetSnapPos(rPnt));
3501
3502
0
    if (getSdrDragView().IsOrtho())
3503
0
        OrthoDistance8(DragStat().GetStart(),aPnt,getSdrDragView().IsBigOrtho());
3504
3505
0
    bool bNewContortion=(bContortionAllowed && !getSdrDragView().IsCrookNoContortion()) || !bNoContortionAllowed;
3506
3507
0
    if (bNewContortion!=bContortion || aDistortedRect[nPolyPt]!=aPnt)
3508
0
    {
3509
0
        Hide();
3510
0
        aDistortedRect[nPolyPt]=aPnt;
3511
0
        bContortion=bNewContortion;
3512
0
        DragStat().NextMove(aPnt);
3513
0
        Show();
3514
0
    }
3515
0
}
3516
3517
bool SdrDragDistort::EndSdrDrag(bool bCopy)
3518
0
{
3519
0
    Hide();
3520
0
    bool bDoDistort=DragStat().GetDX()!=0 || DragStat().GetDY()!=0;
3521
3522
0
    if (bDoDistort)
3523
0
    {
3524
0
        getSdrDragView().DistortMarkedObj(aMarkRect,aDistortedRect,!bContortion,bCopy);
3525
0
        return true;
3526
0
    }
3527
3528
0
    return false;
3529
0
}
3530
3531
PointerStyle SdrDragDistort::GetSdrDragPointer() const
3532
0
{
3533
0
    return PointerStyle::RefHand;
3534
0
}
3535
3536
void SdrDragDistort::applyCurrentTransformationToSdrObject(SdrObject& rTarget)
3537
0
{
3538
0
    const bool bDoDistort(DragStat().GetDX()!=0 || DragStat().GetDY()!=0);
3539
3540
0
    if (bDoDistort)
3541
0
    {
3542
0
        SdrEditView::ImpDistortObj(&rTarget, aMarkRect, aDistortedRect, !bContortion);
3543
0
    }
3544
0
}
3545
3546
void SdrDragDistort::applyCurrentTransformationToPolyPolygon(basegfx::B2DPolyPolygon& rTarget)
3547
0
{
3548
    // use helper derived from old stuff
3549
0
    MovAllPoints(rTarget);
3550
0
}
3551
3552
3553
SdrDragCrop::SdrDragCrop(SdrDragView& rNewView)
3554
0
:   SdrDragObjOwn(rNewView)
3555
0
{
3556
    // switch off solid dragging for crop; it just makes no sense since showing
3557
    // a 50% transparent object above the original will not be visible
3558
0
    setSolidDraggingActive(false);
3559
0
}
3560
3561
OUString SdrDragCrop::GetSdrDragComment() const
3562
0
{
3563
0
    OUString aStr = ImpGetDescriptionStr(STR_DragMethCrop)
3564
0
            + " (x="
3565
0
            + getSdrDragView().GetModel().GetMetricString(DragStat().GetDX())
3566
0
            + " y="
3567
0
            + getSdrDragView().GetModel().GetMetricString(DragStat().GetDY())
3568
0
            + ")";
3569
3570
0
    if(getSdrDragView().IsDragWithCopy())
3571
0
        aStr += SvxResId(STR_EditWithCopy);
3572
0
    return aStr;
3573
0
}
3574
3575
bool SdrDragCrop::BeginSdrDrag()
3576
0
{
3577
    // call parent
3578
0
    bool bRetval(SdrDragObjOwn::BeginSdrDrag());
3579
3580
0
    if(!GetDragHdl())
3581
0
    {
3582
        // we need the DragHdl, break if not there
3583
0
        bRetval = false;
3584
0
    }
3585
3586
0
    return bRetval;
3587
0
}
3588
3589
bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
3590
0
{
3591
0
    Hide();
3592
3593
0
    if(0 == DragStat().GetDX() && 0 == DragStat().GetDY())
3594
0
    {
3595
        // no change, done
3596
0
        return false;
3597
0
    }
3598
3599
0
    const SdrMarkList& rMarkList = getSdrDragView().GetMarkedObjectList();
3600
3601
0
    if(1 != rMarkList.GetMarkCount())
3602
0
    {
3603
        // Crop only with single Object selected
3604
0
        return false;
3605
0
    }
3606
3607
    // prepare for SdrGrafObj or others. This code has to work with usual
3608
    // SdrGrafObj's from Draw/Impress/Calc, but also with SdrObjects from
3609
    // Writer. It would be better to handle this in Writer directly, but
3610
    // there are currently no easy mechanisms to plug an alternative interaction
3611
    // from there
3612
0
    SdrObject* pSdrObject = rMarkList.GetMark(0)->GetMarkedSdrObj();
3613
0
    rtl::Reference<SdrObject> pFullDragClone;
3614
0
    bool bExternal(false);
3615
0
    SdrObject* pExternalSdrObject(nullptr);
3616
3617
    // RotGrfFlyFrame: Crop decision for DrawingLayer/Writer now
3618
    // locally, no two-in-one methods any more
3619
0
    if (nullptr != pSdrObject && dynamic_cast< const SdrGrafObj* >(pSdrObject) ==  nullptr)
3620
0
    {
3621
        // If Writer, get the already offered for interaction SdrGrafObj
3622
        // and set up for using that replacement object that contains the
3623
        // real transformation. That SdrObject is owned and has to be deleted,
3624
        // so use a std::unique_ptr with special handling for the protected
3625
        // SDrObject destructor
3626
0
        pFullDragClone = pSdrObject->getFullDragClone();
3627
3628
0
        if(dynamic_cast< SdrGrafObj* >(pFullDragClone.get()))
3629
0
        {
3630
0
            bExternal = true;
3631
0
            pExternalSdrObject = pSdrObject;
3632
0
            pSdrObject = pFullDragClone.get();
3633
0
        }
3634
0
    }
3635
3636
    // get and check for SdrGrafObj now
3637
0
    SdrGrafObj* pObj = dynamic_cast<SdrGrafObj*>( pSdrObject );
3638
3639
0
    if(!pObj)
3640
0
    {
3641
0
        return false;
3642
0
    }
3643
3644
    // no undo for external needed, done there
3645
0
    const bool bUndo(!bExternal && getSdrDragView().IsUndoEnabled());
3646
3647
0
    if(bUndo)
3648
0
    {
3649
0
        OUString aUndoStr = ImpGetDescriptionStr(STR_DragMethCrop);
3650
3651
0
        getSdrDragView().BegUndo( aUndoStr );
3652
0
        getSdrDragView().AddUndo(getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj));
3653
        // also need attr undo, the SdrGrafCropItem will be changed
3654
0
        getSdrDragView().AddUndo(getSdrDragView().GetModel().GetSdrUndoFactory().CreateUndoAttrObject(*pObj));
3655
0
    }
3656
3657
    // get the original objects transformation
3658
0
    basegfx::B2DHomMatrix aOriginalMatrix;
3659
0
    basegfx::B2DPolyPolygon aPolyPolygon;
3660
0
    bool bShearCorrected(false);
3661
0
    pObj->TRGetBaseGeometry(aOriginalMatrix, aPolyPolygon);
3662
3663
0
    {   // correct shear, it comes currently mirrored from TRGetBaseGeometry, can be removed with aw080
3664
0
        const basegfx::utils::B2DHomMatrixBufferedDecompose aTmpDecomp(aOriginalMatrix);
3665
3666
0
        if(!basegfx::fTools::equalZero(aTmpDecomp.getShearX()))
3667
0
        {
3668
0
            bShearCorrected = true;
3669
0
            aOriginalMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
3670
0
                aTmpDecomp.getScale(),
3671
0
                -aTmpDecomp.getShearX(),
3672
0
                aTmpDecomp.getRotate(),
3673
0
                aTmpDecomp.getTranslate());
3674
0
        }
3675
0
    }
3676
3677
    // generate start point of original drag vector in unit coordinates (the
3678
    // vis-a-vis of the drag point)
3679
0
    basegfx::B2DPoint aLocalStart(0.0, 0.0);
3680
0
    bool bOnAxis(false);
3681
3682
0
    switch(GetDragHdlKind())
3683
0
    {
3684
0
        case SdrHdlKind::UpperLeft: aLocalStart.setX(1.0); aLocalStart.setY(1.0); break;
3685
0
        case SdrHdlKind::Upper: aLocalStart.setX(0.5); aLocalStart.setY(1.0); bOnAxis = true; break;
3686
0
        case SdrHdlKind::UpperRight: aLocalStart.setX(0.0); aLocalStart.setY(1.0); break;
3687
0
        case SdrHdlKind::Left : aLocalStart.setX(1.0); aLocalStart.setY(0.5); bOnAxis = true; break;
3688
0
        case SdrHdlKind::Right: aLocalStart.setX(0.0); aLocalStart.setY(0.5); bOnAxis = true; break;
3689
0
        case SdrHdlKind::LowerLeft: aLocalStart.setX(1.0); aLocalStart.setY(0.0); break;
3690
0
        case SdrHdlKind::Lower: aLocalStart.setX(0.5); aLocalStart.setY(0.0); bOnAxis = true; break;
3691
0
        case SdrHdlKind::LowerRight: aLocalStart.setX(0.0); aLocalStart.setY(0.0); break;
3692
0
        default: break;
3693
0
    }
3694
3695
    // create the current drag position in unit coordinates. To get there,
3696
    // transform back the DragPoint to UnitCoordinates
3697
0
    basegfx::B2DHomMatrix aInverse(aOriginalMatrix);
3698
0
    aInverse.invert();
3699
0
    basegfx::B2DPoint aLocalCurrent(aInverse * basegfx::B2DPoint(DragStat().GetNow().X(), DragStat().GetNow().Y()));
3700
3701
    // if one of the edge handles is used, limit to X or Y drag only
3702
0
    if(bOnAxis)
3703
0
    {
3704
0
        if(basegfx::fTools::equal(aLocalStart.getX(), 0.5))
3705
0
        {
3706
0
            aLocalCurrent.setX(aLocalStart.getX());
3707
0
        }
3708
0
        else
3709
0
        {
3710
0
            aLocalCurrent.setY(aLocalStart.getY());
3711
0
        }
3712
0
    }
3713
3714
    // create internal change in unit coordinates
3715
0
    basegfx::B2DHomMatrix aDiscreteChangeMatrix;
3716
3717
0
    if(!basegfx::fTools::equal(aLocalCurrent.getX(), aLocalStart.getX()))
3718
0
    {
3719
0
        if(aLocalStart.getX() < 0.5)
3720
0
        {
3721
0
            aDiscreteChangeMatrix.scale(aLocalCurrent.getX(), 1.0);
3722
0
        }
3723
0
        else
3724
0
        {
3725
0
            aDiscreteChangeMatrix.scale(1.0 - aLocalCurrent.getX(), 1.0);
3726
0
            aDiscreteChangeMatrix.translate(aLocalCurrent.getX(), 0.0);
3727
0
        }
3728
0
    }
3729
3730
0
    if(!basegfx::fTools::equal(aLocalCurrent.getY(), aLocalStart.getY()))
3731
0
    {
3732
0
        if(aLocalStart.getY() < 0.5)
3733
0
        {
3734
0
            aDiscreteChangeMatrix.scale(1.0, aLocalCurrent.getY());
3735
0
        }
3736
0
        else
3737
0
        {
3738
0
            aDiscreteChangeMatrix.scale(1.0, 1.0 - aLocalCurrent.getY());
3739
0
            aDiscreteChangeMatrix.translate(0.0, aLocalCurrent.getY());
3740
0
        }
3741
0
    }
3742
3743
    // We now have the whole executed Crop in UnitCoordinates in
3744
    // aDiscreteChangeMatrix, go to concrete sizes now.
3745
    // Create the unrotated original rectangle and the unrotated modified
3746
    // rectangle as Ranges
3747
0
    const basegfx::utils::B2DHomMatrixBufferedDecompose aOriginalMatrixDecomp(aOriginalMatrix);
3748
3749
    // prepare unsheared/unrotated versions of the old and new transformation
3750
0
    const basegfx::B2DHomMatrix aOriginalMatrixNoShearNoRotate(
3751
0
        basegfx::utils::createScaleTranslateB2DHomMatrix(
3752
0
            basegfx::absolute(aOriginalMatrixDecomp.getScale()),
3753
0
            aOriginalMatrixDecomp.getTranslate()));
3754
3755
    // create the ranges for these
3756
0
    basegfx::B2DRange aRangeOriginalNoShearNoRotate(0.0, 0.0, 1.0, 1.0);
3757
0
    basegfx::B2DRange aRangeNewNoShearNoRotate(0.0, 0.0, 1.0, 1.0);
3758
0
    aRangeOriginalNoShearNoRotate.transform(aOriginalMatrixNoShearNoRotate);
3759
0
    aRangeNewNoShearNoRotate.transform(aOriginalMatrixNoShearNoRotate * aDiscreteChangeMatrix);
3760
3761
0
    if(bExternal)
3762
0
    {
3763
        // With aLocalStart point (opposed to dragged point), X scale and Y scale,
3764
        // we call crop (virtual method) on pSdrObject which calls VirtFlyDrawObj
3765
        // crop. Use aLocalStart unchanged, so being relative to the Crop-Action,
3766
        // the called instance knows best how to use it
3767
0
        const double fScaleX(aRangeNewNoShearNoRotate.getWidth() / aRangeOriginalNoShearNoRotate.getWidth());
3768
0
        const double fScaleY(aRangeNewNoShearNoRotate.getHeight() / aRangeOriginalNoShearNoRotate.getHeight());
3769
3770
0
        pExternalSdrObject->Crop(
3771
0
            aLocalStart,
3772
0
            fScaleX,
3773
0
            fScaleY);
3774
0
    }
3775
0
    else
3776
0
    {
3777
        // prepare matrix to apply to object; evtl. back-correct shear
3778
0
        basegfx::B2DHomMatrix aNewObjectMatrix(aOriginalMatrix * aDiscreteChangeMatrix);
3779
3780
0
        if(bShearCorrected)
3781
0
        {
3782
            // back-correct shear
3783
0
            const basegfx::utils::B2DHomMatrixBufferedDecompose aTmpDecomp(aNewObjectMatrix);
3784
3785
0
            aNewObjectMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
3786
0
                aTmpDecomp.getScale(),
3787
0
                -aTmpDecomp.getShearX(),
3788
0
                aTmpDecomp.getRotate(),
3789
0
                aTmpDecomp.getTranslate());
3790
0
        }
3791
3792
        // apply change to object by applying the unit coordinate change followed
3793
        // by the original change
3794
0
        pObj->TRSetBaseGeometry(aNewObjectMatrix, aPolyPolygon);
3795
3796
        // extract the old Rectangle structures
3797
0
        tools::Rectangle aOldRect(
3798
0
            basegfx::fround<tools::Long>(aRangeOriginalNoShearNoRotate.getMinX()),
3799
0
            basegfx::fround<tools::Long>(aRangeOriginalNoShearNoRotate.getMinY()),
3800
0
            basegfx::fround<tools::Long>(aRangeOriginalNoShearNoRotate.getMaxX()),
3801
0
            basegfx::fround<tools::Long>(aRangeOriginalNoShearNoRotate.getMaxY()));
3802
0
        tools::Rectangle aNewRect(
3803
0
            basegfx::fround<tools::Long>(aRangeNewNoShearNoRotate.getMinX()),
3804
0
            basegfx::fround<tools::Long>(aRangeNewNoShearNoRotate.getMinY()),
3805
0
            basegfx::fround<tools::Long>(aRangeNewNoShearNoRotate.getMaxX()),
3806
0
            basegfx::fround<tools::Long>(aRangeNewNoShearNoRotate.getMaxY()));
3807
3808
        // continue with the old original stuff
3809
0
        if (!aOldRect.GetWidth() || !aOldRect.GetHeight())
3810
0
        {
3811
0
            throw o3tl::divide_by_zero();
3812
0
        }
3813
3814
0
        if((pObj->GetGraphicType() == GraphicType::NONE) || (pObj->GetGraphicType() == GraphicType::Default))
3815
0
        {
3816
0
            return false;
3817
0
        }
3818
3819
0
        const GraphicObject& rGraphicObject(pObj->GetGraphicObject());
3820
        // tdf#117145 Usually Writer will go the bExternal path (see above), but more correct for
3821
        // the future is to use the MapMode from the SdrModel/SfxItemPool if the Writer's current
3822
        // special handling should be unified to this path in the future. Usually it *should* be
3823
        // MapUnit::Map100thMM, but better do not mix up Units.
3824
        // Checked now what SwVirtFlyDrawObj::NbcCrop is doing - it calculates everything forced
3825
        // to MapUnit::Map100thMM, but extracts/packs Twips to the used SdrGrafCropItem in Writer.
3826
0
        const MapMode aMapModePool(pObj->getSdrModelFromSdrObject().GetItemPool().GetMetric(0));
3827
0
        Size aGraphicSize(rGraphicObject.GetPrefSize());
3828
3829
0
        if(MapUnit::MapPixel == rGraphicObject.GetPrefMapMode().GetMapUnit())
3830
0
        {
3831
0
            aGraphicSize = Application::GetDefaultDevice()->PixelToLogic(aGraphicSize, aMapModePool);
3832
0
        }
3833
0
        else
3834
0
        {
3835
0
            aGraphicSize = OutputDevice::LogicToLogic(aGraphicSize, rGraphicObject.GetPrefMapMode(), aMapModePool);
3836
0
        }
3837
3838
0
        if(0 == aGraphicSize.Width() || 0 == aGraphicSize.Height())
3839
0
        {
3840
0
            return false;
3841
0
        }
3842
3843
0
        const SdrGrafCropItem& rOldCrop = pObj->GetMergedItem(SDRATTR_GRAFCROP);
3844
0
        double fScaleX = ( aGraphicSize.Width() - rOldCrop.GetLeft() - rOldCrop.GetRight() ) / static_cast<double>(aOldRect.GetWidth());
3845
0
        double fScaleY = ( aGraphicSize.Height() - rOldCrop.GetTop() - rOldCrop.GetBottom() ) / static_cast<double>(aOldRect.GetHeight());
3846
3847
0
        sal_Int32 nDiffLeft = aNewRect.Left() - aOldRect.Left();
3848
0
        sal_Int32 nDiffTop = aNewRect.Top() - aOldRect.Top();
3849
0
        sal_Int32 nDiffRight = aNewRect.Right() - aOldRect.Right();
3850
0
        sal_Int32 nDiffBottom = aNewRect.Bottom() - aOldRect.Bottom();
3851
3852
0
        if(pObj->IsMirrored())
3853
0
        {
3854
            // mirrored X or Y, for old stuff, exchange X
3855
            // check for aw080
3856
0
            sal_Int32 nTmp(nDiffLeft);
3857
0
            nDiffLeft = -nDiffRight;
3858
0
            nDiffRight = -nTmp;
3859
0
        }
3860
3861
0
        sal_Int32 nLeftCrop = static_cast<sal_Int32>( rOldCrop.GetLeft() + nDiffLeft * fScaleX );
3862
0
        sal_Int32 nTopCrop = static_cast<sal_Int32>( rOldCrop.GetTop() + nDiffTop * fScaleY );
3863
0
        sal_Int32 nRightCrop = static_cast<sal_Int32>( rOldCrop.GetRight() - nDiffRight * fScaleX );
3864
0
        sal_Int32 nBottomCrop = static_cast<sal_Int32>( rOldCrop.GetBottom() - nDiffBottom * fScaleY );
3865
3866
0
        SfxItemPool& rPool = getSdrDragView().GetModel().GetItemPool();
3867
0
        SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<SDRATTR_GRAFCROP, SDRATTR_GRAFCROP>( rPool ));
3868
0
        aSet.Put( SdrGrafCropItem( nLeftCrop, nTopCrop, nRightCrop, nBottomCrop ) );
3869
0
        getSdrDragView().SetAttributes( aSet, false );
3870
0
    }
3871
3872
0
    if(bUndo)
3873
0
    {
3874
0
        getSdrDragView().EndUndo();
3875
0
    }
3876
3877
0
    return true;
3878
0
}
3879
3880
PointerStyle SdrDragCrop::GetSdrDragPointer() const
3881
0
{
3882
0
    return PointerStyle::Crop;
3883
0
}
3884
3885
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */