Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/svdraw/svddrgv.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
21
#include <osl/diagnose.h>
22
#include <tools/debug.hxx>
23
#include <svx/svddrgv.hxx>
24
#include <svx/svdview.hxx>
25
#include <svx/svdundo.hxx>
26
#include <svx/svdocapt.hxx>
27
#include <svx/svdpagv.hxx>
28
#include <svx/svdopath.hxx>
29
#include <svx/svdoedge.hxx>
30
#include <svx/strings.hrc>
31
#include <svx/dialmgr.hxx>
32
#include "svddrgm1.hxx"
33
#include <svx/svdoashp.hxx>
34
#include <svx/sdrpaintwindow.hxx>
35
#include <basegfx/matrix/b2dhommatrix.hxx>
36
#include <svx/sdr/overlay/overlaymanager.hxx>
37
#include <svx/sdrpagewindow.hxx>
38
#include <unotools/configmgr.hxx>
39
#include <comphelper/lok.hxx>
40
#include <officecfg/Office/Common.hxx>
41
#include <sfx2/objsh.hxx>
42
#include <sfx2/viewsh.hxx>
43
#include <svl/cryptosign.hxx>
44
45
using namespace sdr;
46
47
SdrDragView::SdrDragView(SdrModel& rSdrModel, OutputDevice* pOut)
48
320k
    : SdrExchangeView(rSdrModel, pOut)
49
320k
    , mpDragHdl(nullptr)
50
320k
    , meDragHdl(SdrHdlKind::Move)
51
320k
    , mnDragThresholdPixels(6)
52
320k
    , mbFramDrag(false)
53
320k
    , mbMarkedHitMovesAlways(false)
54
320k
    , mbDragLimit(false)
55
320k
    , mbDragHdl(false)
56
320k
    , mbDragStripes(false)
57
320k
    , mbSolidDragging(comphelper::IsFuzzing() || officecfg::Office::Common::Drawinglayer::SolidDragCreate::get())
58
320k
    , mbResizeAtCenter(false)
59
320k
    , mbCrookAtCenter(false)
60
320k
    , mbDragWithCopy(false)
61
320k
    , mbInsGluePoint(false)
62
320k
    , mbInsObjPointMode(false)
63
320k
    , mbInsGluePointMode(false)
64
320k
    , mbNoDragXorPolys(false)
65
320k
{
66
320k
    meDragMode = SdrDragMode::Move;
67
320k
}
68
69
SdrDragView::~SdrDragView()
70
320k
{
71
320k
}
72
73
bool SdrDragView::IsAction() const
74
0
{
75
0
    return (mpCurrentSdrDragMethod || SdrExchangeView::IsAction());
76
0
}
77
78
void SdrDragView::MovAction(const Point& rPnt)
79
0
{
80
0
    SdrExchangeView::MovAction(rPnt);
81
0
    if (mpCurrentSdrDragMethod)
82
0
    {
83
0
        MovDragObj(rPnt);
84
0
    }
85
0
}
86
87
void SdrDragView::EndAction()
88
0
{
89
0
    if (mpCurrentSdrDragMethod)
90
0
    {
91
0
        EndDragObj();
92
0
    }
93
0
    SdrExchangeView::EndAction();
94
0
}
95
96
void SdrDragView::BckAction()
97
0
{
98
0
    SdrExchangeView::BckAction();
99
0
    BrkDragObj();
100
0
}
101
102
void SdrDragView::BrkAction()
103
60.3k
{
104
60.3k
    SdrExchangeView::BrkAction();
105
60.3k
    BrkDragObj();
106
60.3k
}
107
108
void SdrDragView::TakeActionRect(tools::Rectangle& rRect) const
109
0
{
110
0
    if (mpCurrentSdrDragMethod)
111
0
    {
112
0
        rRect=maDragStat.GetActionRect();
113
0
        if (rRect.IsEmpty())
114
0
        {
115
0
            SdrPageView* pPV = GetSdrPageView();
116
117
0
            if(pPV&& pPV->HasMarkedObjPageView())
118
0
            {
119
                // #i95646# is this used..?
120
0
                const basegfx::B2DRange aBoundRange(mpCurrentSdrDragMethod->getCurrentRange());
121
0
                if (aBoundRange.isEmpty())
122
0
                {
123
0
                    rRect.SetEmpty();
124
0
                }
125
0
                else
126
0
                {
127
0
                    rRect = tools::Rectangle(
128
0
                        basegfx::fround<tools::Long>(aBoundRange.getMinX()), basegfx::fround<tools::Long>(aBoundRange.getMinY()),
129
0
                        basegfx::fround<tools::Long>(aBoundRange.getMaxX()), basegfx::fround<tools::Long>(aBoundRange.getMaxY()));
130
0
                }
131
0
            }
132
0
        }
133
0
        if (rRect.IsEmpty())
134
0
        {
135
0
            rRect=tools::Rectangle(maDragStat.GetNow(),maDragStat.GetNow());
136
0
        }
137
0
    }
138
0
    else
139
0
    {
140
0
        SdrExchangeView::TakeActionRect(rRect);
141
0
    }
142
0
}
143
144
bool SdrDragView::TakeDragObjAnchorPos(Point& rPos, bool bTR ) const
145
0
{
146
0
    tools::Rectangle aR;
147
0
    TakeActionRect(aR);
148
0
    rPos = bTR ? aR.TopRight() : aR.TopLeft();
149
0
    const SdrMarkList& rMarkList = GetMarkedObjectList();
150
0
    if (rMarkList.GetMarkCount()==1 && IsDragObj() && // only on single selection
151
0
        !IsDraggingPoints() && !IsDraggingGluePoints() && // not when moving points
152
0
        dynamic_cast<const SdrDragMovHdl*>( mpCurrentSdrDragMethod.get() ) ==  nullptr) // not when moving handles
153
0
    {
154
0
        SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
155
0
        if (auto pCaptionObj = dynamic_cast<SdrCaptionObj*>(pObj))
156
0
        {
157
0
            Point aPt(pCaptionObj->GetTailPos());
158
0
            bool bTail=meDragHdl==SdrHdlKind::Poly; // drag tail
159
0
            bool bOwn=dynamic_cast<const SdrDragObjOwn*>( mpCurrentSdrDragMethod.get() ) !=  nullptr; // specific to object
160
0
            if (!bTail)
161
0
            { // for bTail, TakeActionRect already does the right thing
162
0
                if (bOwn)
163
0
                { // bOwn may be MoveTextFrame, ResizeTextFrame, but may not (any more) be DragTail
164
0
                    rPos=aPt;
165
0
                }
166
0
                else
167
0
                {
168
                    // drag the whole Object (Move, Resize, ...)
169
0
                    const basegfx::B2DPoint aTransformed(mpCurrentSdrDragMethod->getCurrentTransformation() * basegfx::B2DPoint(aPt.X(), aPt.Y()));
170
0
                    rPos.setX( basegfx::fround<tools::Long>(aTransformed.getX()) );
171
0
                    rPos.setY( basegfx::fround<tools::Long>(aTransformed.getY()) );
172
0
                }
173
0
            }
174
0
        }
175
0
        return true;
176
0
    }
177
0
    return false;
178
0
}
179
180
181
bool SdrDragView::TakeDragLimit(SdrDragMode /*eMode*/, tools::Rectangle& /*rRect*/) const
182
0
{
183
0
    return false;
184
0
}
185
186
bool SdrDragView::BegDragObj(const Point& rPnt, OutputDevice* pOut, SdrHdl* pHdl, short nMinMov, SdrDragMethod* _pForcedMeth)
187
0
{
188
0
    BrkAction();
189
190
    // so we don't leak the object on early return
191
0
    std::unique_ptr<SdrDragMethod> pForcedMeth(_pForcedMeth);
192
193
0
    bool bRet=false;
194
0
    {
195
0
        SetDragWithCopy(false);
196
        //TODO: aAni.Reset();
197
0
        mpCurrentSdrDragMethod=nullptr;
198
0
        SdrDragMode eTmpMode=meDragMode;
199
0
        if (eTmpMode==SdrDragMode::Move && pHdl!=nullptr && pHdl->GetKind()!=SdrHdlKind::Move) {
200
0
            eTmpMode=SdrDragMode::Resize;
201
0
        }
202
0
        mbDragLimit=TakeDragLimit(eTmpMode,maDragLimit);
203
0
        mbFramDrag=ImpIsFrameHandles();
204
0
        if (!mbFramDrag &&
205
0
            (mpMarkedObj==nullptr || !mpMarkedObj->hasSpecialDrag()) &&
206
0
            (pHdl==nullptr || pHdl->GetObj()==nullptr)) {
207
0
            mbFramDrag=true;
208
0
        }
209
210
0
        Point aPnt(rPnt);
211
0
        basegfx::B2DVector aGridOffset(0.0, 0.0);
212
0
        const SdrMarkList& rMarkList = GetMarkedObjectList();
213
214
        // Coordinate maybe affected by GridOffset, so we may need to
215
        // adapt to Model-coordinates here
216
0
        if((comphelper::LibreOfficeKit::isActive() && mpMarkedObj
217
0
            && getPossibleGridOffsetForSdrObject(aGridOffset, rMarkList.GetMark(0)->GetMarkedSdrObj(), GetSdrPageView()))
218
0
            || (getPossibleGridOffsetForPosition(
219
0
            aGridOffset,
220
0
            basegfx::B2DPoint(aPnt.X(), aPnt.Y()),
221
0
            GetSdrPageView())))
222
0
        {
223
0
            aPnt.AdjustX(basegfx::fround<tools::Long>(-aGridOffset.getX()));
224
0
            aPnt.AdjustY(basegfx::fround<tools::Long>(-aGridOffset.getY()));
225
0
        }
226
227
0
        if(pHdl == nullptr
228
0
            || pHdl->GetKind() == SdrHdlKind::Move
229
0
            || pHdl->GetKind() == SdrHdlKind::MirrorAxis
230
0
            || pHdl->GetKind() == SdrHdlKind::Transparence
231
0
            || pHdl->GetKind() == SdrHdlKind::Gradient)
232
0
        {
233
0
            maDragStat.Reset(aPnt);
234
0
        }
235
0
        else
236
0
        {
237
0
            maDragStat.Reset(pHdl->GetPos());
238
0
        }
239
240
0
        maDragStat.SetView(static_cast<SdrView*>(this));
241
0
        maDragStat.SetPageView(mpMarkedPV);  // <<-- DragPV has to go here!!!
242
0
        maDragStat.SetMinMove(ImpGetMinMovLogic(nMinMov,pOut));
243
0
        maDragStat.SetHdl(pHdl);
244
0
        maDragStat.NextPoint();
245
0
        mpDragWin=pOut;
246
0
        mpDragHdl=pHdl;
247
0
        meDragHdl= pHdl==nullptr ? SdrHdlKind::Move : pHdl->GetKind();
248
0
        mbDragHdl=meDragHdl==SdrHdlKind::Ref1 || meDragHdl==SdrHdlKind::Ref2 || meDragHdl==SdrHdlKind::MirrorAxis;
249
250
        // Expand test for SdrHdlKind::Anchor_TR
251
0
        bool bNotDraggable = (SdrHdlKind::Anchor == meDragHdl || SdrHdlKind::Anchor_TR == meDragHdl);
252
253
0
        if(pHdl && (pHdl->GetKind() == SdrHdlKind::SmartTag) && pForcedMeth )
254
0
        {
255
            // just use the forced method for smart tags
256
0
        }
257
0
        else if(mbDragHdl)
258
0
        {
259
0
            mpCurrentSdrDragMethod.reset(new SdrDragMovHdl(*this));
260
0
        }
261
0
        else if(!bNotDraggable)
262
0
        {
263
0
            switch (meDragMode)
264
0
            {
265
0
                case SdrDragMode::Rotate: case SdrDragMode::Shear:
266
0
                {
267
0
                    switch (meDragHdl)
268
0
                    {
269
0
                        case SdrHdlKind::Left:  case SdrHdlKind::Right:
270
0
                        case SdrHdlKind::Upper: case SdrHdlKind::Lower:
271
0
                        {
272
                            // are 3D objects selected?
273
0
                            bool b3DObjSelected = false;
274
0
                            for(size_t a=0; !b3DObjSelected && a<rMarkList.GetMarkCount(); ++a)
275
0
                            {
276
0
                                SdrObject* pObj = rMarkList.GetMark(a)->GetMarkedSdrObj();
277
0
                                if(DynCastE3dObject(pObj))
278
0
                                    b3DObjSelected = true;
279
0
                            }
280
                            // If yes, allow shear even when !IsShearAllowed,
281
                            // because 3D objects are limited rotations
282
0
                            if (!b3DObjSelected && !IsShearAllowed())
283
0
                                return false;
284
0
                            mpCurrentSdrDragMethod.reset(new SdrDragShear(*this,meDragMode==SdrDragMode::Rotate));
285
0
                        } break;
286
0
                        case SdrHdlKind::UpperLeft: case SdrHdlKind::UpperRight:
287
0
                        case SdrHdlKind::LowerLeft: case SdrHdlKind::LowerRight:
288
0
                        {
289
0
                            if (meDragMode==SdrDragMode::Shear)
290
0
                            {
291
0
                                if (!IsDistortAllowed(true) && !IsDistortAllowed()) return false;
292
0
                                mpCurrentSdrDragMethod.reset(new SdrDragDistort(*this));
293
0
                            }
294
0
                            else
295
0
                            {
296
0
                                if (!IsRotateAllowed(true)) return false;
297
0
                                mpCurrentSdrDragMethod.reset(new SdrDragRotate(*this));
298
0
                            }
299
0
                        } break;
300
0
                        default:
301
0
                        {
302
0
                            if (IsMarkedHitMovesAlways() && meDragHdl==SdrHdlKind::Move)
303
0
                            { // SdrHdlKind::Move is true, even if Obj is hit directly
304
0
                                if (!IsMoveAllowed()) return false;
305
0
                                mpCurrentSdrDragMethod.reset(new SdrDragMove(*this));
306
0
                            }
307
0
                            else
308
0
                            {
309
0
                                if (!IsRotateAllowed(true)) return false;
310
0
                                mpCurrentSdrDragMethod.reset(new SdrDragRotate(*this));
311
0
                            }
312
0
                        }
313
0
                    }
314
0
                } break;
315
0
                case SdrDragMode::Mirror:
316
0
                {
317
0
                    if (meDragHdl==SdrHdlKind::Move && IsMarkedHitMovesAlways())
318
0
                    {
319
0
                        if (!IsMoveAllowed()) return false;
320
0
                        mpCurrentSdrDragMethod.reset(new SdrDragMove(*this));
321
0
                    }
322
0
                    else
323
0
                    {
324
0
                        if (!IsMirrorAllowed(true,true)) return false;
325
0
                        mpCurrentSdrDragMethod.reset(new SdrDragMirror(*this));
326
0
                    }
327
0
                } break;
328
329
0
                case SdrDragMode::Crop:
330
0
                {
331
0
                    if (meDragHdl==SdrHdlKind::Move && IsMarkedHitMovesAlways())
332
0
                    {
333
0
                        if (!IsMoveAllowed())
334
0
                            return false;
335
0
                        mpCurrentSdrDragMethod.reset(new SdrDragMove(*this));
336
0
                    }
337
0
                    else
338
0
                    {
339
0
                        if (!IsCropAllowed())
340
0
                            return false;
341
0
                        mpCurrentSdrDragMethod.reset(new SdrDragCrop(*this));
342
0
                    }
343
0
                }
344
0
                break;
345
346
0
                case SdrDragMode::Transparence:
347
0
                {
348
0
                    if(meDragHdl == SdrHdlKind::Move && IsMarkedHitMovesAlways())
349
0
                    {
350
0
                        if(!IsMoveAllowed())
351
0
                            return false;
352
0
                        mpCurrentSdrDragMethod.reset(new SdrDragMove(*this));
353
0
                    }
354
0
                    else
355
0
                    {
356
0
                        if(!IsTransparenceAllowed())
357
0
                            return false;
358
359
0
                        mpCurrentSdrDragMethod.reset(new SdrDragGradient(*this, false));
360
0
                    }
361
0
                    break;
362
0
                }
363
0
                case SdrDragMode::Gradient:
364
0
                {
365
0
                    if(meDragHdl == SdrHdlKind::Move && IsMarkedHitMovesAlways())
366
0
                    {
367
0
                        if(!IsMoveAllowed())
368
0
                            return false;
369
0
                        mpCurrentSdrDragMethod.reset(new SdrDragMove(*this));
370
0
                    }
371
0
                    else
372
0
                    {
373
0
                        if(!IsGradientAllowed())
374
0
                            return false;
375
376
0
                        mpCurrentSdrDragMethod.reset(new SdrDragGradient(*this));
377
0
                    }
378
0
                    break;
379
0
                }
380
381
0
                case SdrDragMode::Crook :
382
0
                {
383
0
                    if (meDragHdl==SdrHdlKind::Move && IsMarkedHitMovesAlways())
384
0
                    {
385
0
                        if (!IsMoveAllowed()) return false;
386
0
                        mpCurrentSdrDragMethod.reset( new SdrDragMove(*this) );
387
0
                    }
388
0
                    else
389
0
                    {
390
0
                        if (!IsCrookAllowed(true) && !IsCrookAllowed()) return false;
391
0
                        mpCurrentSdrDragMethod.reset( new SdrDragCrook(*this) );
392
0
                    }
393
0
                } break;
394
395
0
                default:
396
0
                {
397
                    // SdrDragMode::Move
398
0
                    if((meDragHdl == SdrHdlKind::Move) && !IsMoveAllowed())
399
0
                    {
400
0
                        return false;
401
0
                    }
402
0
                    else if(meDragHdl == SdrHdlKind::Glue)
403
0
                    {
404
0
                        mpCurrentSdrDragMethod.reset( new SdrDragMove(*this) );
405
0
                    }
406
0
                    else
407
0
                    {
408
0
                        if(mbFramDrag)
409
0
                        {
410
0
                            if(meDragHdl == SdrHdlKind::Move)
411
0
                            {
412
0
                                mpCurrentSdrDragMethod.reset( new SdrDragMove(*this) );
413
0
                            }
414
0
                            else
415
0
                            {
416
0
                                bool bResizeAllowed = IsResizeAllowed(true);
417
0
                                SfxViewShell* pViewShell = GetSfxViewShell();
418
0
                                if (!bResizeAllowed && pViewShell && pViewShell->GetSignPDFCertificate().Is())
419
0
                                {
420
                                    // If the just added signature line shape is selected, allow resizing it.
421
0
                                    bResizeAllowed = true;
422
0
                                }
423
0
                                if(!bResizeAllowed)
424
0
                                {
425
0
                                    return false;
426
0
                                }
427
428
0
                                bool bSingleTextObjMark = false;    // SJ: #i100490#
429
0
                                if ( rMarkList.GetMarkCount() == 1 )
430
0
                                {
431
0
                                    mpMarkedObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
432
0
                                    if ( mpMarkedObj &&
433
0
                                        DynCastSdrTextObj( mpMarkedObj) !=  nullptr &&
434
0
                                        static_cast<SdrTextObj*>(mpMarkedObj)->IsTextFrame() )
435
0
                                        bSingleTextObjMark = true;
436
0
                                }
437
0
                                if ( bSingleTextObjMark )
438
0
                                    mpCurrentSdrDragMethod.reset( new SdrDragObjOwn(*this) );
439
0
                                else
440
0
                                    mpCurrentSdrDragMethod.reset( new SdrDragResize(*this) );
441
0
                            }
442
0
                        }
443
0
                        else
444
0
                        {
445
0
                            if(SdrHdlKind::Move == meDragHdl)
446
0
                            {
447
0
                                const bool bCustomShapeSelected(1 == rMarkList.GetMarkCount() && dynamic_cast<const SdrObjCustomShape*>(rMarkList.GetMark(0)->GetMarkedSdrObj()) != nullptr);
448
449
0
                                if(bCustomShapeSelected)
450
0
                                {
451
0
                                    mpCurrentSdrDragMethod.reset( new SdrDragMove( *this ) );
452
0
                                }
453
0
                            }
454
0
                            else if(SdrHdlKind::Poly == meDragHdl)
455
0
                            {
456
0
                                const bool bConnectorSelected(1 == rMarkList.GetMarkCount() && dynamic_cast<const SdrEdgeObj*>(rMarkList.GetMark(0)->GetMarkedSdrObj()) != nullptr);
457
458
0
                                if(bConnectorSelected)
459
0
                                {
460
                                    // #i97784#
461
                                    // fallback to old behaviour for connectors (see
462
                                    // text in task description for more details)
463
0
                                }
464
0
                                else if(!IsMoveAllowed() || !IsResizeAllowed())
465
0
                                {
466
                                    // #i77187#
467
                                    // do not allow move of polygon points if object is move or size protected
468
0
                                    return false;
469
0
                                }
470
0
                            }
471
472
0
                            if(!mpCurrentSdrDragMethod)
473
0
                            {
474
                                // fallback to DragSpecial if no interaction defined
475
0
                                mpCurrentSdrDragMethod.reset( new SdrDragObjOwn(*this) );
476
0
                            }
477
0
                        }
478
0
                    }
479
0
                }
480
0
            }
481
0
        }
482
0
        if (pForcedMeth)
483
0
        {
484
0
            mpCurrentSdrDragMethod = std::move(pForcedMeth);
485
0
        }
486
0
        maDragStat.SetDragMethod(mpCurrentSdrDragMethod.get());
487
0
        if (mpCurrentSdrDragMethod)
488
0
        {
489
0
            bRet = mpCurrentSdrDragMethod->BeginSdrDrag();
490
0
            if (!bRet)
491
0
            {
492
0
                if (pHdl==nullptr && dynamic_cast< const SdrDragObjOwn* >(mpCurrentSdrDragMethod.get()) !=  nullptr)
493
0
                {
494
                    // Obj may not Move SpecialDrag, so try with MoveFrameDrag
495
0
                    mpCurrentSdrDragMethod.reset();
496
497
0
                    if (!IsMoveAllowed())
498
0
                        return false;
499
500
0
                    mbFramDrag=true;
501
0
                    mpCurrentSdrDragMethod.reset( new SdrDragMove(*this) );
502
0
                    maDragStat.SetDragMethod(mpCurrentSdrDragMethod.get());
503
0
                    bRet = mpCurrentSdrDragMethod->BeginSdrDrag();
504
0
                }
505
0
            }
506
0
            if (!bRet)
507
0
            {
508
0
                mpCurrentSdrDragMethod.reset();
509
0
                maDragStat.SetDragMethod(mpCurrentSdrDragMethod.get());
510
0
            }
511
0
        }
512
0
    }
513
514
0
    return bRet;
515
0
}
516
517
void SdrDragView::MovDragObj(const Point& rPnt)
518
0
{
519
0
    if (!mpCurrentSdrDragMethod)
520
0
        return;
521
522
0
    Point aPnt(rPnt);
523
0
    basegfx::B2DVector aGridOffset(0.0, 0.0);
524
525
    // Coordinate maybe affected by GridOffset, so we may need to
526
    // adapt to Model-coordinates here
527
0
    const SdrMarkList& rMarkList = GetMarkedObjectList();
528
0
    if((comphelper::LibreOfficeKit::isActive() && mpMarkedObj
529
0
        && getPossibleGridOffsetForSdrObject(aGridOffset, rMarkList.GetMark(0)->GetMarkedSdrObj(), GetSdrPageView()))
530
0
        || (getPossibleGridOffsetForPosition(
531
0
        aGridOffset,
532
0
        basegfx::B2DPoint(aPnt.X(), aPnt.Y()),
533
0
        GetSdrPageView())))
534
0
    {
535
0
        aPnt.AdjustX(basegfx::fround<tools::Long>(-aGridOffset.getX()));
536
0
        aPnt.AdjustY(basegfx::fround<tools::Long>(-aGridOffset.getY()));
537
0
    }
538
539
0
    ImpLimitToWorkArea(aPnt);
540
0
    mpCurrentSdrDragMethod->MoveSdrDrag(aPnt); // this call already makes a Hide()/Show combination
541
0
}
542
543
bool SdrDragView::EndDragObj(bool bCopy)
544
0
{
545
0
    bool bRet(false);
546
547
    // #i73341# If inserting GluePoint, do not insist on last points being different
548
0
    if(mpCurrentSdrDragMethod && maDragStat.IsMinMoved() && (IsInsertGluePoint() || maDragStat.GetNow() != maDragStat.GetPrev()))
549
0
    {
550
0
        sal_Int32 nSavedHdlCount=0;
551
552
0
        if (mbEliminatePolyPoints)
553
0
        {
554
0
            nSavedHdlCount=GetMarkablePointCount();
555
0
        }
556
557
0
        const bool bUndo = IsUndoEnabled();
558
0
        if (IsInsertGluePoint() && bUndo)
559
0
        {
560
0
            BegUndo(maInsPointUndoStr);
561
0
            AddUndo(std::move(mpInsPointUndo));
562
0
        }
563
564
0
        bRet = mpCurrentSdrDragMethod->EndSdrDrag(bCopy);
565
566
0
        if( IsInsertGluePoint() && bUndo)
567
0
            EndUndo();
568
569
0
        mpCurrentSdrDragMethod.reset();
570
571
0
        if (mbEliminatePolyPoints)
572
0
        {
573
0
            if (nSavedHdlCount!=GetMarkablePointCount())
574
0
            {
575
0
                UnmarkAllPoints();
576
0
            }
577
0
        }
578
579
0
        if (mbInsPolyPoint)
580
0
        {
581
0
            SetMarkHandles(nullptr);
582
0
            mbInsPolyPoint=false;
583
0
            if( bUndo )
584
0
            {
585
0
                BegUndo(maInsPointUndoStr);
586
0
                AddUndo(std::move(mpInsPointUndo));
587
0
                EndUndo();
588
0
            }
589
0
        }
590
591
0
        meDragHdl=SdrHdlKind::Move;
592
0
        mpDragHdl=nullptr;
593
594
0
        if (!mbSomeObjChgdFlag)
595
0
        {
596
            // Obj did not broadcast (e. g. Writer FlyFrames)
597
0
            if(!mbDragHdl)
598
0
            {
599
0
                AdjustMarkHdl();
600
0
            }
601
0
        }
602
0
    }
603
0
    else
604
0
    {
605
0
        BrkDragObj();
606
0
    }
607
608
0
    mbInsPolyPoint=false;
609
0
    SetInsertGluePoint(false);
610
611
0
    return bRet;
612
0
}
613
614
void SdrDragView::BrkDragObj()
615
60.3k
{
616
60.3k
    if (!mpCurrentSdrDragMethod)
617
60.3k
        return;
618
619
0
    mpCurrentSdrDragMethod->CancelSdrDrag();
620
621
0
    mpCurrentSdrDragMethod.reset();
622
623
0
    if (mbInsPolyPoint)
624
0
    {
625
0
        mpInsPointUndo->Undo(); // delete inserted point again
626
0
        mpInsPointUndo.reset();
627
0
        SetMarkHandles(nullptr);
628
0
        mbInsPolyPoint=false;
629
0
    }
630
0
    else if (IsInsertGluePoint())
631
0
    {
632
0
        mpInsPointUndo->Undo(); // delete inserted gluepoint again
633
0
        mpInsPointUndo.reset();
634
0
        SetInsertGluePoint(false);
635
0
    }
636
637
0
    meDragHdl=SdrHdlKind::Move;
638
0
    mpDragHdl=nullptr;
639
0
}
640
641
bool SdrDragView::IsInsObjPointPossible() const
642
0
{
643
0
    return mpMarkedObj!=nullptr && mpMarkedObj->IsPolyObj();
644
0
}
645
646
bool SdrDragView::ImpBegInsObjPoint(bool bIdxZwang, const Point& rPnt, bool bNewObj, OutputDevice* pOut)
647
0
{
648
0
    bool bRet(false);
649
650
0
    if(auto pMarkedPath = dynamic_cast<SdrPathObj*>( mpMarkedObj))
651
0
    {
652
0
        BrkAction();
653
0
        mpInsPointUndo = GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*mpMarkedObj);
654
0
        DBG_ASSERT( mpInsPointUndo, "svx::SdrDragView::BegInsObjPoint(), could not create correct undo object!" );
655
656
0
        OUString aStr(SvxResId(STR_DragInsertPoint));
657
658
0
        maInsPointUndoStr = aStr.replaceFirst("%1", mpMarkedObj->TakeObjNameSingul() );
659
660
0
        Point aPt(rPnt);
661
662
0
        if(bNewObj)
663
0
            aPt = GetSnapPos(aPt,mpMarkedPV);
664
665
0
        bool bClosed0 = pMarkedPath->IsClosedObj();
666
667
0
        const sal_uInt32 nInsPointNum { bIdxZwang
668
0
            ? pMarkedPath->NbcInsPoint(aPt, bNewObj)
669
0
            : pMarkedPath->NbcInsPointOld(aPt, bNewObj)
670
0
        };
671
672
0
        if(bClosed0 != pMarkedPath->IsClosedObj())
673
0
        {
674
            // Obj was closed implicitly
675
            // object changed
676
0
            pMarkedPath->SetChanged();
677
0
            pMarkedPath->BroadcastObjectChange();
678
0
        }
679
680
0
        if (nInsPointNum != SAL_MAX_UINT32)
681
0
        {
682
0
            mbInsPolyPoint = true;
683
0
            UnmarkAllPoints();
684
0
            AdjustMarkHdl();
685
686
0
            bRet = BegDragObj(rPnt, pOut, maHdlList.GetHdl(nInsPointNum), 0);
687
688
0
            if (bRet)
689
0
            {
690
0
                maDragStat.SetMinMoved();
691
0
                MovDragObj(rPnt);
692
0
            }
693
0
        }
694
0
        else
695
0
        {
696
0
            mpInsPointUndo.reset();
697
0
        }
698
0
    }
699
700
0
    return bRet;
701
0
}
702
703
bool SdrDragView::EndInsObjPoint(SdrCreateCmd eCmd)
704
0
{
705
0
    if(IsInsObjPoint())
706
0
    {
707
0
        Point aPnt(maDragStat.GetNow());
708
0
        bool bOk=EndDragObj();
709
0
        if (bOk && eCmd!=SdrCreateCmd::ForceEnd)
710
0
        {
711
            // Ret=True means: Action is over.
712
0
            bOk = ! ImpBegInsObjPoint(true, aPnt, eCmd == SdrCreateCmd::NextObject, mpDragWin);
713
0
        }
714
715
0
        return bOk;
716
0
    } else return false;
717
0
}
718
719
bool SdrDragView::IsInsGluePointPossible() const
720
0
{
721
0
    bool bRet=false;
722
0
    const SdrMarkList& rMarkList = GetMarkedObjectList();
723
0
    if (IsInsGluePointMode() && rMarkList.GetMarkCount() != 0)
724
0
    {
725
0
        if (rMarkList.GetMarkCount()==1)
726
0
        {
727
            // return sal_False, if only 1 object which is a connector.
728
0
            const SdrObject* pObj=rMarkList.GetMark(0)->GetMarkedSdrObj();
729
0
            if (dynamic_cast<const SdrEdgeObj *>(pObj) == nullptr)
730
0
            {
731
0
               bRet=true;
732
0
            }
733
0
        }
734
0
        else
735
0
        {
736
0
            bRet=true;
737
0
        }
738
0
    }
739
0
    return bRet;
740
0
}
741
742
bool SdrDragView::BegInsGluePoint(const Point& rPnt)
743
0
{
744
0
    bool bRet=false;
745
0
    SdrObject* pObj;
746
0
    SdrPageView* pPV;
747
0
    if (PickMarkedObj(rPnt,pObj,pPV,SdrSearchOptions::PASS2BOUND))
748
0
    {
749
0
        BrkAction();
750
0
        UnmarkAllGluePoints();
751
0
        mpInsPointUndo = GetModel().GetSdrUndoFactory().CreateUndoGeoObject(*pObj);
752
0
        DBG_ASSERT( mpInsPointUndo, "svx::SdrDragView::BegInsObjPoint(), could not create correct undo object!" );
753
0
        OUString aStr(SvxResId(STR_DragInsertGluePoint));
754
755
0
        maInsPointUndoStr = aStr.replaceFirst("%1", pObj->TakeObjNameSingul() );
756
757
0
        SdrGluePointList* pGPL=pObj->ForceGluePointList();
758
0
        if (pGPL!=nullptr)
759
0
        {
760
0
            sal_uInt16 nGlueIdx=pGPL->Insert(SdrGluePoint());
761
0
            SdrGluePoint& rGP=(*pGPL)[nGlueIdx];
762
0
            sal_uInt16 nGlueId=rGP.GetId();
763
0
            rGP.SetAbsolutePos(rPnt,*pObj);
764
765
0
            SdrHdl* pHdl=nullptr;
766
0
            if (MarkGluePoint(pObj,nGlueId,false))
767
0
            {
768
0
                pHdl=GetGluePointHdl(pObj,nGlueId);
769
0
            }
770
0
            if (pHdl!=nullptr && pHdl->GetKind()==SdrHdlKind::Glue && pHdl->GetObj()==pObj && pHdl->GetObjHdlNum()==nGlueId)
771
0
            {
772
0
                SetInsertGluePoint(true);
773
0
                bRet=BegDragObj(rPnt,nullptr,pHdl,0);
774
0
                if (bRet)
775
0
                {
776
0
                    maDragStat.SetMinMoved();
777
0
                    MovDragObj(rPnt);
778
0
                }
779
0
                else
780
0
                {
781
0
                    SetInsertGluePoint(false);
782
0
                    mpInsPointUndo.reset();
783
0
                }
784
0
            }
785
0
            else
786
0
            {
787
0
                OSL_FAIL("BegInsGluePoint(): GluePoint handle not found.");
788
0
            }
789
0
        }
790
0
        else
791
0
        {
792
            // no gluepoints possible for this object (e. g. Edge)
793
0
            SetInsertGluePoint(false);
794
0
            mpInsPointUndo.reset();
795
0
        }
796
0
    }
797
798
0
    return bRet;
799
0
}
800
801
void SdrDragView::ShowDragObj(bool IsSizeValid)
802
0
{
803
0
    if(!mpCurrentSdrDragMethod || maDragStat.IsShown())
804
0
        return;
805
806
    // Changed for the GridOffset stuff: No longer iterate over
807
    // SdrPaintWindow(s), but now over SdrPageWindow(s), so doing the
808
    // same as the SdrHdl visualizations (see ::CreateB2dIAObject) do.
809
    // This is needed to get access to an ObjectContact which is needed
810
    // to evtl. process that GridOffset in CreateOverlayGeometry
811
0
    SdrPageView* pPageView(GetSdrPageView());
812
813
0
    if(nullptr != pPageView)
814
0
    {
815
0
        for(sal_uInt32 a(0); a < pPageView->PageWindowCount(); a++)
816
0
        {
817
0
            const SdrPageWindow& rPageWindow(*pPageView->GetPageWindow(a));
818
0
            const SdrPaintWindow& rPaintWindow(rPageWindow.GetPaintWindow());
819
820
0
            if(rPaintWindow.OutputToWindow())
821
0
            {
822
0
                const rtl::Reference<sdr::overlay::OverlayManager>& xOverlayManager(
823
0
                    rPaintWindow.GetOverlayManager());
824
825
0
                if(xOverlayManager.is())
826
0
                {
827
0
                    mpCurrentSdrDragMethod->CreateOverlayGeometry(
828
0
                        *xOverlayManager,
829
0
                        rPageWindow.GetObjectContact(), IsSizeValid);
830
0
                }
831
0
            }
832
0
        }
833
0
    }
834
835
0
    maDragStat.SetShown(true);
836
0
}
837
838
void SdrDragView::HideDragObj()
839
0
{
840
0
    if(mpCurrentSdrDragMethod && maDragStat.IsShown())
841
0
    {
842
0
        mpCurrentSdrDragMethod->destroyOverlayGeometry();
843
0
        maDragStat.SetShown(false);
844
0
    }
845
0
}
846
847
848
void SdrDragView::SetNoDragXorPolys(bool bOn)
849
8.77k
{
850
8.77k
    if (IsNoDragXorPolys()==bOn)
851
0
        return;
852
853
8.77k
    const bool bDragging(mpCurrentSdrDragMethod);
854
8.77k
    const bool bShown(bDragging && maDragStat.IsShown());
855
856
8.77k
    if(bShown)
857
0
    {
858
0
        HideDragObj();
859
0
    }
860
861
8.77k
    mbNoDragXorPolys = bOn;
862
863
8.77k
    if(bDragging)
864
0
    {
865
        // force recreation of drag content
866
0
        mpCurrentSdrDragMethod->resetSdrDragEntries();
867
0
    }
868
869
8.77k
    if(bShown)
870
0
    {
871
0
        ShowDragObj();
872
0
    }
873
8.77k
}
874
875
void SdrDragView::SetDragStripes(bool bOn)
876
66.6k
{
877
66.6k
    if (mpCurrentSdrDragMethod && maDragStat.IsShown())
878
0
    {
879
0
        HideDragObj();
880
0
        mbDragStripes=bOn;
881
0
        ShowDragObj();
882
0
    }
883
66.6k
    else
884
66.6k
    {
885
66.6k
        mbDragStripes=bOn;
886
66.6k
    }
887
66.6k
}
888
889
bool SdrDragView::IsOrthoDesired() const
890
0
{
891
0
    if( dynamic_cast< const SdrDragObjOwn* >( mpCurrentSdrDragMethod.get() )
892
0
       || dynamic_cast< const SdrDragResize* >(mpCurrentSdrDragMethod.get() ))
893
0
    {
894
0
        return m_bOrthoDesiredOnMarked;
895
0
    }
896
897
0
    return false;
898
0
}
899
900
void SdrDragView::SetMarkHandles(SfxViewShell* pOtherShell)
901
243k
{
902
243k
    if( mpDragHdl )
903
0
        mpDragHdl = nullptr;
904
905
243k
    SdrExchangeView::SetMarkHandles(pOtherShell);
906
243k
}
907
908
void SdrDragView::SetSolidDragging(bool bOn)
909
8.77k
{
910
8.77k
    if(mbSolidDragging != bOn)
911
6
    {
912
6
        mbSolidDragging = bOn;
913
6
    }
914
8.77k
}
915
916
bool SdrDragView::IsSolidDragging() const
917
6
{
918
    // allow each user to disable by having a local setting, but using AND for
919
    // checking allowance
920
6
    return mbSolidDragging && officecfg::Office::Common::Drawinglayer::SolidDragCreate::get();
921
6
}
922
923
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */