Coverage Report

Created: 2025-12-31 10:39

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