Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/svdraw/svdview.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 <editeng/outlobj.hxx>
21
22
#include <svx/strings.hrc>
23
#include <svx/dialmgr.hxx>
24
#include <svx/svdpagv.hxx>
25
#include <svx/svdmrkv.hxx>
26
#include <svx/svdedxv.hxx>
27
#include <svx/svdobj.hxx>
28
#include <svx/svdopath.hxx>
29
#include <svx/svdograf.hxx>
30
#include <svx/svdomedia.hxx>
31
#include <svx/svdetc.hxx>
32
33
#include <svx/sdr/table/tablecontroller.hxx>
34
#include <svx/svdoutl.hxx>
35
#include <svx/svdview.hxx>
36
#include <editeng/flditem.hxx>
37
#include <svx/svddrgmt.hxx>
38
#include <svx/svdotable.hxx>
39
#include <tools/debug.hxx>
40
#include <svx/sdr/overlay/overlaypolypolygon.hxx>
41
#include <svx/sdr/overlay/overlaymanager.hxx>
42
#include <svx/sdrpaintwindow.hxx>
43
#include <svx/sdrpagewindow.hxx>
44
#include <svx/sdrhittesthelper.hxx>
45
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
46
#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
47
#include <svx/sdr/contact/objectcontactofpageview.hxx>
48
#include <sal/log.hxx>
49
#include <vcl/ptrstyle.hxx>
50
#include <vcl/window.hxx>
51
#include <comphelper/lok.hxx>
52
53
54
SdrViewEvent::SdrViewEvent()
55
0
    : mpHdl(nullptr),
56
0
      mpObj(nullptr),
57
0
      mpRootObj(nullptr),
58
0
      mpPV(nullptr),
59
0
      mpURLField(nullptr),
60
0
      meHit(SdrHitKind::NONE),
61
0
      meEvent(SdrEventKind::NONE),
62
0
      mnMouseClicks(0),
63
0
      mnMouseMode(MouseEventModifiers::NONE),
64
0
      mnMouseCode(0),
65
0
      mnHlplIdx(0),
66
0
      mnGlueId(0),
67
0
      mbMouseDown(false),
68
0
      mbMouseUp(false),
69
0
      mbIsAction(false),
70
0
      mbIsTextEdit(false),
71
0
      mbAddMark(false),
72
0
      mbUnmark(false),
73
0
      mbPrevNextMark(false),
74
0
      mbMarkPrev(false)
75
0
{
76
0
}
77
78
// helper class for all D&D overlays
79
80
void SdrDropMarkerOverlay::ImplCreateOverlays(
81
    const SdrView& rView,
82
    const basegfx::B2DPolyPolygon& rLinePolyPolygon)
83
0
{
84
0
    for(sal_uInt32 a(0); a < rView.PaintWindowCount(); a++)
85
0
    {
86
0
        SdrPaintWindow* pCandidate = rView.GetPaintWindow(a);
87
0
        const rtl::Reference< sdr::overlay::OverlayManager >& xTargetOverlay = pCandidate->GetOverlayManager();
88
89
0
        if (xTargetOverlay.is())
90
0
        {
91
0
            std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
92
0
                rLinePolyPolygon));
93
94
0
            xTargetOverlay->add(*pNew);
95
0
            maObjects.append(std::move(pNew));
96
0
        }
97
0
    }
98
0
}
99
100
SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const SdrObject& rObject)
101
0
{
102
0
    ImplCreateOverlays(
103
0
        rView,
104
0
        rObject.TakeXorPoly());
105
0
}
106
107
SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const tools::Rectangle& rRectangle)
108
0
{
109
0
    basegfx::B2DPolygon aB2DPolygon;
110
111
0
    aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top()));
112
0
    aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Top()));
113
0
    aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Bottom()));
114
0
    aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom()));
115
0
    aB2DPolygon.setClosed(true);
116
117
0
    ImplCreateOverlays(
118
0
        rView,
119
0
        basegfx::B2DPolyPolygon(aB2DPolygon));
120
0
}
121
122
SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const Point& rStart, const Point& rEnd)
123
0
{
124
0
    basegfx::B2DPolygon aB2DPolygon;
125
126
0
    aB2DPolygon.append(basegfx::B2DPoint(rStart.X(), rStart.Y()));
127
0
    aB2DPolygon.append(basegfx::B2DPoint(rEnd.X(), rEnd.Y()));
128
0
    aB2DPolygon.setClosed(true);
129
130
0
    ImplCreateOverlays(
131
0
        rView,
132
0
        basegfx::B2DPolyPolygon(aB2DPolygon));
133
0
}
134
135
SdrDropMarkerOverlay::~SdrDropMarkerOverlay()
136
0
{
137
    // The OverlayObjects are cleared using the destructor of OverlayObjectList.
138
    // That destructor calls clear() at the list which removes all objects from the
139
    // OverlayManager and deletes them.
140
0
}
141
142
SdrView::SdrView(
143
    SdrModel& rSdrModel,
144
    OutputDevice* pOut)
145
385k
:   SdrCreateView(rSdrModel, pOut),
146
385k
    mbNoExtendedMouseDispatcher(false),
147
385k
    mbNoExtendedKeyDispatcher(false),
148
385k
    mbMasterPagePaintCaching(false)
149
385k
{
150
385k
}
151
152
SdrView::~SdrView()
153
385k
{
154
385k
}
155
156
bool SdrView::KeyInput(const KeyEvent& rKEvt, vcl::Window* pWin)
157
0
{
158
0
    SetActualWin(pWin ? pWin->GetOutDev() : nullptr);
159
0
    bool bRet = SdrCreateView::KeyInput(rKEvt,pWin);
160
0
    if (!bRet && !IsExtendedKeyInputDispatcherEnabled()) {
161
0
        bRet = true;
162
0
        switch (rKEvt.GetKeyCode().GetFullFunction()) {
163
0
            case KeyFuncType::DELETE: DeleteMarked(); break;
164
0
            case KeyFuncType::UNDO: GetModel().Undo(); break;
165
0
            case KeyFuncType::REDO: GetModel().Redo(); break;
166
0
            default: {
167
0
                switch (rKEvt.GetKeyCode().GetFullCode()) {
168
0
                    case KEY_ESCAPE: {
169
0
                        if (IsTextEdit()) SdrEndTextEdit();
170
0
                        if (IsAction()) BrkAction();
171
0
                        if (pWin!=nullptr) pWin->ReleaseMouse();
172
0
                    } break;
173
0
                    case KEY_DELETE: DeleteMarked(); break;
174
0
                    case KEY_UNDO: case KEY_BACKSPACE+KEY_MOD2: GetModel().Undo(); break;
175
0
                    case KEY_BACKSPACE+KEY_MOD2+KEY_SHIFT: GetModel().Redo(); break;
176
0
                    case KEY_REPEAT: case KEY_BACKSPACE+KEY_MOD2+KEY_MOD1: GetModel().Repeat(*this); break;
177
0
                    case KEY_MOD1+KEY_A: MarkAll(); break;
178
0
                    default: bRet=false;
179
0
                } // switch
180
0
            }
181
0
        } // switch
182
0
        if (bRet && pWin!=nullptr) {
183
0
            pWin->SetPointer(GetPreferredPointer(
184
0
                pWin->PixelToLogic(pWin->ScreenToOutputPixel( pWin->GetPointerPosPixel() ) ),
185
0
                pWin->GetOutDev(),
186
0
                rKEvt.GetKeyCode().GetModifier()));
187
0
        }
188
0
    }
189
0
    return bRet;
190
0
}
191
192
bool SdrView::MouseButtonDown(const MouseEvent& rMEvt, OutputDevice* pWin)
193
0
{
194
0
    SetActualWin(pWin);
195
0
    if (rMEvt.IsLeft()) maDragStat.SetMouseDown(true);
196
0
    bool bRet = SdrCreateView::MouseButtonDown(rMEvt,pWin);
197
0
    if (!bRet && !IsExtendedMouseEventDispatcherEnabled()) {
198
0
        SdrViewEvent aVEvt;
199
0
        PickAnything(rMEvt,SdrMouseEventKind::BUTTONDOWN,aVEvt);
200
0
        bRet = DoMouseEvent(aVEvt);
201
0
    }
202
0
    return bRet;
203
0
}
204
205
bool SdrView::MouseButtonUp(const MouseEvent& rMEvt, OutputDevice* pWin)
206
0
{
207
0
    SetActualWin(pWin);
208
0
    if (rMEvt.IsLeft()) maDragStat.SetMouseDown(false);
209
0
    bool bAction = IsAction();
210
0
    bool bRet = !bAction && SdrCreateView::MouseButtonUp(rMEvt,pWin);
211
0
    if (!bRet && !IsExtendedMouseEventDispatcherEnabled()) {
212
0
        SdrViewEvent aVEvt;
213
0
        PickAnything(rMEvt,SdrMouseEventKind::BUTTONUP,aVEvt);
214
0
        bRet = DoMouseEvent(aVEvt);
215
0
    }
216
0
    return bRet;
217
0
}
218
219
bool SdrView::MouseMove(const MouseEvent& rMEvt, OutputDevice* pWin)
220
0
{
221
0
    SetActualWin(pWin);
222
0
    maDragStat.SetMouseDown(rMEvt.IsLeft());
223
0
    bool bRet = SdrCreateView::MouseMove(rMEvt,pWin);
224
0
    if (!IsExtendedMouseEventDispatcherEnabled() && !IsTextEditInSelectionMode()) {
225
0
        SdrViewEvent aVEvt;
226
0
        PickAnything(rMEvt,SdrMouseEventKind::MOVE,aVEvt);
227
0
        if (DoMouseEvent(aVEvt)) bRet=true;
228
0
    }
229
230
0
    return bRet;
231
0
}
232
233
bool SdrView::Command(const CommandEvent& rCEvt, vcl::Window* pWin)
234
0
{
235
0
    SetActualWin(pWin->GetOutDev());
236
0
    bool bRet = SdrCreateView::Command(rCEvt,pWin);
237
0
    return bRet;
238
0
}
239
240
void SdrView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
241
0
{
242
0
    SdrCreateView::GetAttributes(rTargetSet, bOnlyHardAttr);
243
0
}
244
245
SdrHitKind SdrView::PickAnything(const MouseEvent& rMEvt, SdrMouseEventKind nEventKind, SdrViewEvent& rVEvt) const
246
0
{
247
0
    rVEvt.mbMouseDown = nEventKind==SdrMouseEventKind::BUTTONDOWN;
248
0
    rVEvt.mbMouseUp = nEventKind==SdrMouseEventKind::BUTTONUP;
249
0
    rVEvt.mnMouseClicks = rMEvt.GetClicks();
250
0
    rVEvt.mnMouseMode = rMEvt.GetMode();
251
0
    rVEvt.mnMouseCode = rMEvt.GetButtons() | rMEvt.GetModifier();
252
0
    const OutputDevice* pOut=mpActualOutDev;
253
0
    if (pOut==nullptr)
254
0
    {
255
0
        pOut = GetFirstOutputDevice();
256
0
    }
257
0
    Point aPnt(rMEvt.GetPosPixel());
258
0
    if (pOut!=nullptr) aPnt=pOut->PixelToLogic(aPnt);
259
260
0
    if (mbNegativeX)
261
0
    {
262
        // Shape's x coordinates are all negated,
263
        // Hence negate mouse event's x coord to match.
264
0
        aPnt.setX(-aPnt.X());
265
0
    }
266
267
0
    rVEvt.maLogicPos = aPnt;
268
0
    return PickAnything(aPnt,rVEvt);
269
0
}
270
271
// Dragging with the Mouse (Move)
272
// Example when creating a rectangle: MouseDown has to happen without a ModKey,
273
// else we usually force a selection (see below).
274
// When pressing Shift, Ctrl and Alt at the same time while doing a MouseMove,
275
// a centered, not snapped square is created.
276
// The dual allocation of Ortho and Shift won't usually create a problem, as the
277
// two functions are in most cases mutually exclusive. Only shearing (the kind
278
// that happens when contorting, not when rotating) can use both functions at
279
// the same time. To get around this, the user can use e. g. help lines.
280
0
#define MODKEY_NoSnap    bCtrl  /* temporarily disable snapping */
281
0
#define MODKEY_Ortho     bShift /* ortho */
282
0
#define MODKEY_Center    bAlt   /* create/resize centeredly */
283
0
#define MODKEY_AngleSnap bShift
284
0
#define MODKEY_CopyDrag  bCtrl  /* drag and copy */
285
286
// click somewhere (MouseDown)
287
0
#define MODKEY_PolyPoly  bAlt   /* new Poly at InsPt and at Create */
288
0
#define MODKEY_MultiMark bShift /* MarkObj without doing UnmarkAll first */
289
0
#define MODKEY_Unmark    bAlt   /* deselect with a dragged frame */
290
0
#define MODKEY_ForceMark bCtrl  /* force dragging a frame, even if there's an object at cursor position */
291
0
#define MODKEY_DeepMark  bAlt   /* MarkNextObj */
292
0
#define MODKEY_DeepBackw bShift /* MarkNextObj but backwards */
293
294
SdrHitKind SdrView::PickAnything(const Point& rLogicPos, SdrViewEvent& rVEvt) const
295
0
{
296
0
    const OutputDevice* pOut=mpActualOutDev;
297
0
    if (pOut==nullptr)
298
0
    {
299
0
        pOut = GetFirstOutputDevice();
300
0
    }
301
302
    // #i73628# Use a non-changeable copy of he logic position
303
0
    const Point aLocalLogicPosition(rLogicPos);
304
305
0
    bool bEditMode=IsEditMode();
306
0
    bool bPointMode=bEditMode && HasMarkablePoints();
307
0
    bool bGluePointMode=IsGluePointEditMode();
308
0
    bool bInsPolyPt=bPointMode && IsInsObjPointMode() && IsInsObjPointPossible();
309
0
    bool bInsGluePt=bGluePointMode && IsInsGluePointMode() && IsInsGluePointPossible();
310
0
    bool bIsTextEdit=IsTextEdit();
311
0
    bool bTextEditHit=IsTextEditHit(aLocalLogicPosition);
312
0
    bool bTextEditSel=IsTextEditInSelectionMode();
313
0
    bool bShift = (rVEvt.mnMouseCode & KEY_SHIFT) != 0;
314
0
    bool bCtrl = (rVEvt.mnMouseCode & KEY_MOD1) != 0;
315
0
    bool bAlt = (rVEvt.mnMouseCode & KEY_MOD2) != 0;
316
0
    SdrHitKind eHit=SdrHitKind::NONE;
317
0
    SdrHdl* pHdl=pOut!=nullptr && !bTextEditSel ? PickHandle(aLocalLogicPosition) : nullptr;
318
0
    SdrPageView* pPV=nullptr;
319
0
    SdrObject* pObj=nullptr;
320
0
    SdrObject* pHitObj=nullptr;
321
0
    bool bHitPassDirect=true;
322
0
    sal_uInt16 nHlplIdx=0;
323
0
    sal_uInt16 nGlueId=0;
324
0
    if (bTextEditHit || bTextEditSel)
325
0
    {
326
0
        eHit=SdrHitKind::TextEdit;
327
0
    }
328
0
    else if (pHdl!=nullptr)
329
0
    {
330
0
        eHit=SdrHitKind::Handle; // handle is hit: highest priority
331
0
    }
332
0
    else if (bEditMode && IsHlplVisible() && IsHlplFront() && pOut!=nullptr && PickHelpLine(aLocalLogicPosition,mnHitTolLog,*pOut,nHlplIdx,pPV))
333
0
    {
334
0
        eHit=SdrHitKind::HelpLine; // help line in the foreground hit: can be moved now
335
0
    }
336
0
    else if (bGluePointMode && PickGluePoint(aLocalLogicPosition,pObj,nGlueId,pPV))
337
0
    {
338
0
        eHit=SdrHitKind::Gluepoint; // deselected gluepoint hit
339
0
    }
340
0
    else if ((pHitObj = PickObj(aLocalLogicPosition,mnHitTolLog,pPV,SdrSearchOptions::DEEP|SdrSearchOptions::MARKED,&pObj,&bHitPassDirect)))
341
0
    {
342
0
        eHit=SdrHitKind::MarkedObject;
343
0
        sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( pObj );
344
0
        if( pTableObj )
345
0
        {
346
0
            sal_Int32 nX = 0, nY = 0;
347
0
            switch( pTableObj->CheckTableHit( aLocalLogicPosition, nX, nY ) )
348
0
            {
349
0
                case sdr::table::TableHitKind::Cell:
350
0
                    eHit = SdrHitKind::Cell;
351
0
                    break;
352
0
                case sdr::table::TableHitKind::CellTextArea:
353
0
                    eHit = SdrHitKind::TextEditObj;
354
0
                    break;
355
0
                default:
356
0
                    break;
357
0
            }
358
0
        }
359
0
    }
360
0
    else if ((pHitObj = PickObj(aLocalLogicPosition,mnHitTolLog,pPV,SdrSearchOptions::DEEP|SdrSearchOptions::ALSOONMASTER|SdrSearchOptions::WHOLEPAGE,&pObj,&bHitPassDirect)))
361
0
    {
362
        // MasterPages and WholePage for Macro and URL
363
0
        eHit=SdrHitKind::UnmarkedObject;
364
0
        sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( pObj );
365
0
        if( pTableObj )
366
0
        {
367
0
            sal_Int32 nX = 0, nY = 0;
368
0
            switch( pTableObj->CheckTableHit( aLocalLogicPosition, nX, nY, mnHitTolLog ) )
369
0
            {
370
0
                case sdr::table::TableHitKind::Cell:
371
0
                    eHit = SdrHitKind::Cell;
372
0
                    break;
373
0
                case sdr::table::TableHitKind::CellTextArea:
374
                    // Keep state on UnmarkedObject to allow the below
375
                    // 'check for URL field' to be executed, else popups
376
                    // for e.g. URL links when hoovering and clicking
377
                    // them will not work. Tried several other changes,
378
                    // but this one safely keeps existing behaviour as-is.
379
                    // Except for the LOK. LOK doesn't have hoovering popup
380
                    // feature.
381
0
                    eHit = comphelper::LibreOfficeKit::isActive() ? SdrHitKind::TextEditObj : SdrHitKind::UnmarkedObject;
382
0
                    break;
383
0
                default:
384
0
                    break;
385
0
            }
386
0
        }
387
0
    }
388
0
    else if (bEditMode && IsHlplVisible() && !IsHlplFront() && pOut!=nullptr && PickHelpLine(aLocalLogicPosition,mnHitTolLog,*pOut,nHlplIdx,pPV))
389
0
    {
390
0
        eHit=SdrHitKind::HelpLine; // help line in foreground hit: can be moved now
391
0
    }
392
0
    if (eHit==SdrHitKind::UnmarkedObject)
393
0
    {
394
0
        bool bRoot=pObj->HasMacro();
395
0
        bool bDeep=pObj!=pHitObj && pHitObj->HasMacro();
396
0
        bool bMid=false; // Have we hit upon a grouped group with a macro?
397
0
        SdrObject* pMidObj=nullptr;
398
0
        if (pObj!=pHitObj)
399
0
        {
400
0
            SdrObject* pObjTmp=pHitObj->getParentSdrObjectFromSdrObject();
401
0
            if (pObjTmp==pObj) pObjTmp=nullptr;
402
0
            while (pObjTmp!=nullptr)
403
0
            {
404
0
                if (pObjTmp->HasMacro())
405
0
                {
406
0
                    bMid=true;
407
0
                    pMidObj=pObjTmp;
408
0
                }
409
0
                pObjTmp=pObjTmp->getParentSdrObjectFromSdrObject();
410
0
                if (pObjTmp==pObj) pObjTmp=nullptr;
411
0
            }
412
0
        }
413
414
0
        if (bDeep || bMid || bRoot)
415
0
        {
416
0
            SdrObjMacroHitRec aHitRec;
417
0
            aHitRec.aPos=aLocalLogicPosition;
418
0
            aHitRec.nTol=mnHitTolLog;
419
0
            aHitRec.pVisiLayer=&pPV->GetVisibleLayers();
420
0
            aHitRec.pPageView=pPV;
421
0
            if (bDeep) bDeep=pHitObj->IsMacroHit(aHitRec);
422
0
            if (bMid ) bMid =pMidObj->IsMacroHit(aHitRec);
423
0
            if (bRoot) bRoot=pObj->IsMacroHit(aHitRec);
424
0
            if (bRoot || bMid || bDeep)
425
0
            {
426
                // Priorities: 1. Root, 2. Mid, 3. Deep
427
0
                rVEvt.mpRootObj = pObj;
428
0
                if (!bRoot) pObj=pMidObj;
429
0
                if (!bRoot && !bMid) pObj=pHitObj;
430
0
                eHit=SdrHitKind::Macro;
431
0
            }
432
0
        }
433
0
    }
434
    // check for URL field
435
0
    if (eHit==SdrHitKind::UnmarkedObject)
436
0
    {
437
0
        SdrTextObj* pTextObj=DynCastSdrTextObj( pHitObj );
438
0
        if (pTextObj!=nullptr && pTextObj->HasText())
439
0
        {
440
            // use the primitive-based HitTest which is more accurate anyways. It
441
            // will correctly handle rotated/mirrored/sheared/scaled text and can
442
            // now return a HitContainer containing the primitive hierarchy of the
443
            // primitive that triggered the hit. The first entry is that primitive,
444
            // the others are the full stack of primitives leading to that one which
445
            // includes grouping primitives (like TextHierarchyPrimitives we deed here)
446
            // but also all decomposed ones which lead to the creation of that primitive
447
0
            drawinglayer::primitive2d::Primitive2DContainer aHitContainer;
448
0
            const bool bTEHit(pPV && SdrObjectPrimitiveHit(*pTextObj, aLocalLogicPosition, {0, 0}, *pPV, &pPV->GetVisibleLayers(), true, &aHitContainer));
449
450
0
            if (bTEHit && !aHitContainer.empty())
451
0
            {
452
                // search for TextHierarchyFieldPrimitive2D which contains the needed information
453
                // about a possible URLField
454
0
                const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D* pTextHierarchyFieldPrimitive2D = nullptr;
455
456
0
                for (const drawinglayer::primitive2d::Primitive2DReference& xReference : aHitContainer)
457
0
                {
458
0
                    auto pBasePrimitive = xReference.get();
459
0
                    if (pBasePrimitive && pBasePrimitive->getPrimitive2DID() == PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D)
460
0
                    {
461
0
                        pTextHierarchyFieldPrimitive2D = static_cast<const drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D*>(pBasePrimitive);
462
0
                        break;
463
0
                    }
464
0
                }
465
466
0
                if (nullptr != pTextHierarchyFieldPrimitive2D)
467
0
                {
468
0
                    if (drawinglayer::primitive2d::FieldType::FIELD_TYPE_URL == pTextHierarchyFieldPrimitive2D->getType())
469
0
                    {
470
                        // problem with the old code is that a *pointer* to an instance of
471
                        // SvxURLField is set in the Event which is per se not good since that
472
                        // data comes from a temporary EditEngine's data and could vanish any
473
                        // moment. Have to replace for now with a static instance that gets
474
                        // filled/initialized from the original data held in the TextHierarchyField-
475
                        // Primitive2D (see impTextBreakupHandler::impCheckFieldPrimitive).
476
                        // Unfortunately things like 'TargetFrame' are still used in Calc, so this
477
                        // can currently not get replaced. For the future the Name/Value vector or
478
                        // the TextHierarchyFieldPrimitive2D itself should/will be used for handling
479
                        // that data
480
0
                        static SvxURLField aSvxURLField;
481
482
0
                        aSvxURLField.SetURL(pTextHierarchyFieldPrimitive2D->getValue(u"URL"_ustr));
483
0
                        aSvxURLField.SetRepresentation(pTextHierarchyFieldPrimitive2D->getValue(u"Representation"_ustr));
484
0
                        aSvxURLField.SetTargetFrame(pTextHierarchyFieldPrimitive2D->getValue(u"TargetFrame"_ustr));
485
0
                        const OUString aFormat(pTextHierarchyFieldPrimitive2D->getValue(u"SvxURLFormat"_ustr));
486
487
0
                        if (!aFormat.isEmpty())
488
0
                        {
489
0
                            aSvxURLField.SetFormat(static_cast<SvxURLFormat>(aFormat.toInt32()));
490
0
                        }
491
492
                        // set HitKind and pointer to local static instance in the Event
493
                        // to comply to old stuff
494
0
                        eHit = SdrHitKind::UrlField;
495
0
                        rVEvt.mpURLField = &aSvxURLField;
496
0
                    }
497
0
                }
498
0
            }
499
0
        }
500
0
        if (eHit==SdrHitKind::UnmarkedObject && !pHitObj->getHyperlink().isEmpty())
501
0
        {
502
0
            static SvxURLField aSvxURLField;
503
0
            aSvxURLField.SetURL(pHitObj->getHyperlink());
504
0
            rVEvt.mpURLField = &aSvxURLField;
505
0
            eHit = SdrHitKind::UrlField;
506
0
        }
507
0
    }
508
509
0
    if (bHitPassDirect &&
510
0
        (eHit==SdrHitKind::MarkedObject || eHit==SdrHitKind::UnmarkedObject) &&
511
0
        (IsTextTool() || (IsEditMode() && IsQuickTextEditMode())) && pHitObj->HasTextEdit())
512
0
    {
513
0
        auto pTextObj = DynCastSdrTextObj(pHitObj);
514
515
        // Around the TextEditArea there's a border to select without going into text edit mode.
516
0
        tools::Rectangle aBoundRect;
517
        // Force to SnapRect when Fontwork
518
0
        if (pTextObj && pTextObj->IsFontwork())
519
0
            aBoundRect = pHitObj->GetSnapRect();
520
0
        else if (pTextObj && !pTextObj->GetGeoStat().m_nRotationAngle
521
0
            && !pTextObj->GetGeoStat().m_nShearAngle)
522
0
        {
523
0
            pTextObj->TakeTextEditArea(nullptr, nullptr, &aBoundRect, nullptr);
524
0
        }
525
0
        else
526
0
            aBoundRect = pHitObj->GetCurrentBoundRect();
527
528
0
        sal_Int32 nTolerance(mnHitTolLog);
529
0
        bool bBoundRectHit(false);
530
531
0
        if(pOut)
532
0
        {
533
0
            nTolerance = pOut->PixelToLogic(Size(2, 0)).Width();
534
0
        }
535
536
0
        if( (aLocalLogicPosition.X() >= aBoundRect.Left() - nTolerance && aLocalLogicPosition.X() <= aBoundRect.Left() + nTolerance)
537
0
         || (aLocalLogicPosition.X() >= aBoundRect.Right() - nTolerance && aLocalLogicPosition.X() <= aBoundRect.Right() + nTolerance)
538
0
         || (aLocalLogicPosition.Y() >= aBoundRect.Top() - nTolerance && aLocalLogicPosition.Y() <= aBoundRect.Top() + nTolerance)
539
0
         || (aLocalLogicPosition.Y() >= aBoundRect.Bottom() - nTolerance && aLocalLogicPosition.Y() <= aBoundRect.Bottom() + nTolerance))
540
0
        {
541
0
            bBoundRectHit = true;
542
0
        }
543
544
0
        if(!bBoundRectHit && aBoundRect.Contains(aLocalLogicPosition))
545
0
        {
546
0
            bool bTEHit(pPV
547
0
                        && SdrObjectPrimitiveHit(*pHitObj, aLocalLogicPosition, { 2000.0, 0.0 },
548
0
                                                 *pPV, &pPV->GetVisibleLayers(), true));
549
550
            // TextEdit attached to an object in a locked layer
551
0
            if (bTEHit && pPV->GetLockedLayers().IsSet(pHitObj->GetLayer()))
552
0
            {
553
0
                bTEHit=false;
554
0
            }
555
556
0
            if (bTEHit)
557
0
            {
558
0
                rVEvt.mpRootObj=pObj;
559
0
                pObj=pHitObj;
560
0
                eHit=SdrHitKind::TextEditObj;
561
0
            }
562
0
        }
563
0
    }
564
0
    if (!bHitPassDirect && eHit==SdrHitKind::UnmarkedObject) {
565
0
        eHit=SdrHitKind::NONE;
566
0
        pObj=nullptr;
567
0
        pPV=nullptr;
568
0
    }
569
0
    bool bMouseLeft = (rVEvt.mnMouseCode & MOUSE_LEFT) != 0;
570
0
    bool bMouseRight = (rVEvt.mnMouseCode & MOUSE_RIGHT) != 0;
571
0
    bool bMouseDown = rVEvt.mbMouseDown;
572
0
    bool bMouseUp = rVEvt.mbMouseUp;
573
0
    SdrEventKind eEvent=SdrEventKind::NONE;
574
0
    bool bIsAction=IsAction();
575
576
0
    if (bIsAction)
577
0
    {
578
0
        if (bMouseDown)
579
0
        {
580
0
            if (bMouseRight) eEvent=SdrEventKind::BackAction;
581
0
        }
582
0
        else if (bMouseUp)
583
0
        {
584
0
            if (bMouseLeft)
585
0
            {
586
0
                eEvent=SdrEventKind::EndAction;
587
0
                if (IsDragObj())
588
0
                {
589
0
                    eEvent=SdrEventKind::EndDrag;
590
0
                }
591
0
                else if (IsCreateObj() || IsInsObjPoint())
592
0
                {
593
0
                    eEvent=IsCreateObj() ? SdrEventKind::EndCreate : SdrEventKind::EndInsertObjPoint;
594
0
                }
595
0
                else if (IsMarking())
596
0
                {
597
0
                    eEvent=SdrEventKind::EndMark;
598
0
                    if (!maDragStat.IsMinMoved())
599
0
                    {
600
0
                        eEvent=SdrEventKind::BrkMark;
601
0
                        rVEvt.mbAddMark = MODKEY_MultiMark;
602
0
                    }
603
0
                }
604
0
            }
605
0
        }
606
0
        else
607
0
        {
608
0
            eEvent=SdrEventKind::MoveAction;
609
0
        }
610
0
    }
611
0
    else if (eHit==SdrHitKind::TextEdit)
612
0
    {
613
0
        eEvent=SdrEventKind::TextEdit;
614
0
    }
615
0
    else if (bMouseDown && bMouseLeft)
616
0
    {
617
0
        if (rVEvt.mnMouseClicks == 2 && rVEvt.mnMouseCode == MOUSE_LEFT && pObj!=nullptr && pHitObj!=nullptr && pHitObj->HasTextEdit() && eHit==SdrHitKind::MarkedObject)
618
0
        {
619
0
            rVEvt.mpRootObj = pObj;
620
0
            pObj=pHitObj;
621
0
            eEvent=SdrEventKind::BeginTextEdit;
622
0
        }
623
0
        else if (MODKEY_ForceMark && eHit!=SdrHitKind::UrlField)
624
0
        {
625
0
            eEvent=SdrEventKind::BeginMark; // AddMark,Unmark */
626
0
        }
627
0
        else if (eHit==SdrHitKind::HelpLine)
628
0
        {
629
0
            eEvent=SdrEventKind::BeginDragHelpline; // nothing, actually
630
0
        }
631
0
        else if (eHit==SdrHitKind::Gluepoint)
632
0
        {
633
0
            eEvent=SdrEventKind::MarkGluePoint; // AddMark+Drag
634
0
            rVEvt.mbAddMark = MODKEY_MultiMark || MODKEY_DeepMark; // if not hit with Deep
635
0
        }
636
0
        else if (eHit==SdrHitKind::Handle)
637
0
        {
638
0
            eEvent=SdrEventKind::BeginDragObj;    // Mark+Drag,AddMark+Drag,DeepMark+Drag,Unmark
639
0
            bool bGlue=pHdl->GetKind()==SdrHdlKind::Glue;
640
0
            bool bPoly=!bGlue && IsPointMarkable(*pHdl);
641
0
            bool bMarked=bGlue || (bPoly && pHdl->IsSelected());
642
0
            if (bGlue || bPoly)
643
0
            {
644
0
                eEvent=bGlue ? SdrEventKind::MarkGluePoint : SdrEventKind::MarkPoint;
645
0
                if (MODKEY_DeepMark)
646
0
                {
647
0
                    rVEvt.mbAddMark = true;
648
0
                    rVEvt.mbPrevNextMark = true;
649
0
                    rVEvt.mbMarkPrev = MODKEY_DeepBackw;
650
0
                }
651
0
                else if (MODKEY_MultiMark)
652
0
                {
653
0
                    rVEvt.mbAddMark = true;
654
0
                    rVEvt.mbUnmark = bMarked; // Toggle
655
0
                    if (bGlue)
656
0
                    {
657
0
                        pObj=pHdl->GetObj();
658
0
                        nGlueId=static_cast<sal_uInt16>(pHdl->GetObjHdlNum());
659
0
                    }
660
0
                }
661
0
                else if (bMarked)
662
0
                {
663
0
                    eEvent=SdrEventKind::BeginDragObj; // don't change MarkState, only change Drag
664
0
                }
665
0
            }
666
0
        }
667
0
        else if (bInsPolyPt && (MODKEY_PolyPoly || (!MODKEY_MultiMark && !MODKEY_DeepMark)))
668
0
        {
669
0
            eEvent=SdrEventKind::BeginInsertObjPoint;
670
0
        }
671
0
        else if (bInsGluePt && !MODKEY_MultiMark && !MODKEY_DeepMark)
672
0
        {
673
0
            eEvent=SdrEventKind::BeginInsertGluePoint;
674
0
        }
675
0
        else if (eHit==SdrHitKind::TextEditObj)
676
0
        {
677
0
            eEvent=SdrEventKind::BeginTextEdit; // AddMark+Drag,DeepMark+Drag,Unmark
678
0
            if (MODKEY_MultiMark || MODKEY_DeepMark)
679
0
            { // if not hit with Deep
680
0
                eEvent=SdrEventKind::MarkObj;
681
0
            }
682
0
        }
683
0
        else if (eHit==SdrHitKind::Macro)
684
0
        {
685
0
            eEvent=SdrEventKind::BeginMacroObj;       // AddMark+Drag
686
0
            if (MODKEY_MultiMark || MODKEY_DeepMark)
687
0
            { // if not hit with Deep
688
0
                eEvent=SdrEventKind::MarkObj;
689
0
            }
690
0
        }
691
0
        else if (eHit==SdrHitKind::UrlField)
692
0
        {
693
0
            eEvent=SdrEventKind::ExecuteUrl;       // AddMark+Drag
694
0
            if (MODKEY_MultiMark || MODKEY_DeepMark)
695
0
            { // if not hit with Deep
696
0
                eEvent=SdrEventKind::MarkObj;
697
0
            }
698
0
        }
699
0
        else if (eHit==SdrHitKind::MarkedObject)
700
0
        {
701
0
            eEvent=SdrEventKind::BeginDragObj; // DeepMark+Drag,Unmark
702
703
0
            if (MODKEY_MultiMark || MODKEY_DeepMark)
704
0
            { // if not hit with Deep
705
0
                eEvent=SdrEventKind::MarkObj;
706
0
            }
707
0
        }
708
0
        else if (IsCreateMode())
709
0
        {
710
0
            eEvent=SdrEventKind::BeginCreateObj;          // nothing, actually
711
0
        }
712
0
        else if (eHit==SdrHitKind::UnmarkedObject)
713
0
        {
714
0
            eEvent=SdrEventKind::MarkObj;  // AddMark+Drag
715
0
        }
716
0
        else
717
0
        {
718
0
            eEvent=SdrEventKind::BeginMark;
719
0
        }
720
721
0
        if (eEvent==SdrEventKind::MarkObj)
722
0
        {
723
0
            rVEvt.mbAddMark = MODKEY_MultiMark || MODKEY_DeepMark; // if not hit with Deep
724
0
            rVEvt.mbPrevNextMark = MODKEY_DeepMark;
725
0
            rVEvt.mbMarkPrev = MODKEY_DeepMark && MODKEY_DeepBackw;
726
0
        }
727
0
        if (eEvent==SdrEventKind::BeginMark)
728
0
        {
729
0
            rVEvt.mbAddMark = MODKEY_MultiMark;
730
0
            rVEvt.mbUnmark = MODKEY_Unmark;
731
0
        }
732
0
    }
733
0
    rVEvt.mbIsAction = bIsAction;
734
0
    rVEvt.mbIsTextEdit = bIsTextEdit;
735
0
    rVEvt.maLogicPos = aLocalLogicPosition;
736
0
    rVEvt.mpHdl = pHdl;
737
0
    rVEvt.mpObj = pObj;
738
0
    if (rVEvt.mpRootObj == nullptr)
739
0
        rVEvt.mpRootObj = pObj;
740
0
    rVEvt.mpPV = pPV;
741
0
    rVEvt.mnHlplIdx = nHlplIdx;
742
0
    rVEvt.mnGlueId = nGlueId;
743
0
    rVEvt.meHit = eHit;
744
0
    rVEvt.meEvent = eEvent;
745
#ifdef DGB_UTIL
746
    if (rVEvt.mpRootObj != nullptr)
747
    {
748
        if (rVEvt.mpRootObj->getParentSdrObjListFromSdrObject() != rVEvt.mpPV->GetObjList())
749
        {
750
            OSL_FAIL("SdrView::PickAnything(): pRootObj->getParentSdrObjListFromSdrObject()!=pPV->GetObjList() !");
751
        }
752
    }
753
#endif
754
0
    return eHit;
755
0
}
756
757
bool SdrView::DoMouseEvent(const SdrViewEvent& rVEvt)
758
0
{
759
0
    bool bRet=false;
760
0
    SdrHitKind eHit = rVEvt.meHit;
761
0
    Point aLogicPos(rVEvt.maLogicPos);
762
763
0
    bool bShift = (rVEvt.mnMouseCode & KEY_SHIFT) != 0;
764
0
    bool bCtrl = (rVEvt.mnMouseCode & KEY_MOD1) != 0;
765
0
    bool bAlt = (rVEvt.mnMouseCode & KEY_MOD2) != 0;
766
0
    bool bMouseLeft = (rVEvt.mnMouseCode & MOUSE_LEFT) != 0;
767
0
    bool bMouseDown = rVEvt.mbMouseDown;
768
0
    bool bMouseUp = rVEvt.mbMouseUp;
769
0
    if (bMouseDown) {
770
0
        if (bMouseLeft) maDragStat.SetMouseDown(true);
771
0
    } else if (bMouseUp) {
772
0
        if (bMouseLeft) maDragStat.SetMouseDown(false);
773
0
    } else { // else, MouseMove
774
0
        maDragStat.SetMouseDown(bMouseLeft);
775
0
    }
776
777
0
#ifdef MODKEY_NoSnap
778
0
    SetSnapEnabled(!MODKEY_NoSnap);
779
0
#endif
780
0
#ifdef MODKEY_Ortho
781
0
    SetOrtho(MODKEY_Ortho!=IsOrthoDesired());
782
0
#endif
783
0
#ifdef MODKEY_AngleSnap
784
0
    SetAngleSnapEnabled(MODKEY_AngleSnap);
785
0
#endif
786
0
#ifdef MODKEY_CopyDrag
787
0
    SetDragWithCopy(MODKEY_CopyDrag);
788
0
#endif
789
0
#ifdef MODKEY_Center
790
0
    SetCreate1stPointAsCenter(MODKEY_Center);
791
0
    SetResizeAtCenter(MODKEY_Center);
792
0
    SetCrookAtCenter(MODKEY_Center);
793
0
#endif
794
0
    if (bMouseLeft && bMouseDown && rVEvt.mbIsTextEdit && (eHit==SdrHitKind::UnmarkedObject || eHit==SdrHitKind::NONE)) {
795
0
        SdrEndTextEdit(); // User has clicked beneath object, exit edit mode.
796
        // pHdl is invalid, then, that shouldn't matter, though, as we expect
797
        // pHdl==NULL (because of eHit).
798
0
    }
799
0
    switch (rVEvt.meEvent)
800
0
    {
801
0
        case SdrEventKind::NONE: bRet=false; break;
802
0
        case SdrEventKind::TextEdit: bRet=false; break; // Events handled by the OutlinerView are not taken into account here.
803
0
        case SdrEventKind::MoveAction: MovAction(aLogicPos); bRet=true; break;
804
0
        case SdrEventKind::EndAction: EndAction(); bRet=true; break;
805
0
        case SdrEventKind::BackAction: BckAction(); bRet=true; break;
806
0
        case SdrEventKind::EndMark  : EndAction(); bRet=true; break;
807
0
        case SdrEventKind::BrkMark  : {
808
0
            BrkAction();
809
0
            if (!MarkObj(aLogicPos, mnHitTolLog, rVEvt.mbAddMark))
810
0
            {
811
                // No object hit. Do the following:
812
                // 1. deselect any selected gluepoints
813
                // 2. deselect any selected polygon points
814
                // 3. deselect any selected objects
815
0
                if (!rVEvt.mbAddMark) UnmarkAll();
816
0
            }
817
0
            bRet=true;
818
0
        } break;
819
0
        case SdrEventKind::EndCreate: { // if necessary, MarkObj
820
0
            SdrCreateCmd eCmd=SdrCreateCmd::NextPoint;
821
0
            if (MODKEY_PolyPoly) eCmd=SdrCreateCmd::NextObject;
822
0
            if (rVEvt.mnMouseClicks > 1) eCmd=SdrCreateCmd::ForceEnd;
823
0
            if (!EndCreateObj(eCmd)) { // Don't evaluate event for Create? -> Select
824
0
                if (eHit==SdrHitKind::UnmarkedObject || eHit==SdrHitKind::TextEdit) {
825
0
                    MarkObj(rVEvt.mpRootObj, rVEvt.mpPV);
826
0
                    if (eHit==SdrHitKind::TextEdit)
827
0
                    {
828
0
                        bool bRet2(mpActualOutDev && OUTDEV_WINDOW == mpActualOutDev->GetOutDevType() &&
829
0
                            SdrBeginTextEdit(rVEvt.mpObj, rVEvt.mpPV, mpActualOutDev->GetOwnerWindow()));
830
831
0
                        if(bRet2)
832
0
                        {
833
0
                            MouseEvent aMEvt(mpActualOutDev->LogicToPixel(aLogicPos), 1,
834
0
                                             rVEvt.mnMouseMode,rVEvt.mnMouseCode,rVEvt.mnMouseCode);
835
836
0
                            OutlinerView* pOLV=GetTextEditOutlinerView();
837
0
                            if (pOLV!=nullptr) {
838
0
                                pOLV->MouseButtonDown(aMEvt); // event for the Outliner, but without double-click
839
0
                                pOLV->MouseButtonUp(aMEvt); // event for the Outliner, but without double-click
840
0
                            }
841
0
                        }
842
0
                    }
843
0
                    bRet=true; // object is selected and (if necessary) TextEdit is started
844
0
                } else bRet=false; // canceled Create, nothing else
845
0
            } else bRet=true; // return true for EndCreate
846
0
        } break;
847
0
        case SdrEventKind::EndDrag: {
848
0
            bRet=EndDragObj(IsDragWithCopy());
849
0
            ForceMarkedObjToAnotherPage(); // TODO: Undo+bracing missing!
850
0
        } break;
851
0
        case SdrEventKind::MarkObj: { // + (if applicable) BegDrag
852
0
            if (!rVEvt.mbAddMark) UnmarkAllObj();
853
0
            bool bUnmark = rVEvt.mbUnmark;
854
0
            if (rVEvt.mbPrevNextMark) {
855
0
                bRet=MarkNextObj(aLogicPos, mnHitTolLog, rVEvt.mbMarkPrev);
856
0
            } else {
857
0
                const SdrMarkList& rMarkList = GetMarkedObjectList();
858
0
                rMarkList.ForceSort();
859
0
                const size_t nCount0=rMarkList.GetMarkCount();
860
0
                bRet=MarkObj(aLogicPos, mnHitTolLog, rVEvt.mbAddMark);
861
0
                rMarkList.ForceSort();
862
0
                const size_t nCount1=rMarkList.GetMarkCount();
863
0
                bUnmark=nCount1<nCount0;
864
0
            }
865
0
            if (!bUnmark) {
866
0
                BegDragObj(aLogicPos,nullptr,nullptr,mnMinMovLog);
867
0
                bRet=true;
868
0
            }
869
0
        } break;
870
0
        case SdrEventKind::MarkPoint: { // + (if applicable) BegDrag
871
0
            if (!rVEvt.mbAddMark) UnmarkAllPoints();
872
0
            if (rVEvt.mbPrevNextMark) {
873
0
                MarkNextPoint();
874
0
                bRet=false;
875
0
            } else {
876
0
                bRet = MarkPoint(*rVEvt.mpHdl, rVEvt.mbUnmark);
877
0
            }
878
0
            if (!rVEvt.mbUnmark && !rVEvt.mbPrevNextMark) {
879
0
                BegDragObj(aLogicPos, nullptr, rVEvt.mpHdl, mnMinMovLog);
880
0
                bRet=true;
881
0
            }
882
0
        } break;
883
0
        case SdrEventKind::MarkGluePoint: { // + (if applicable) BegDrag
884
0
            if (!rVEvt.mbAddMark) UnmarkAllGluePoints();
885
0
            if (rVEvt.mbPrevNextMark) {
886
0
                MarkNextGluePoint();
887
0
                bRet=false;
888
0
            } else {
889
0
                bRet=MarkGluePoint(rVEvt.mpObj,rVEvt.mnGlueId,rVEvt.mbUnmark);
890
0
            }
891
0
            if (!rVEvt.mbUnmark && !rVEvt.mbPrevNextMark) {
892
0
                SdrHdl* pHdl = GetGluePointHdl(rVEvt.mpObj, rVEvt.mnGlueId);
893
0
                BegDragObj(aLogicPos,nullptr,pHdl,mnMinMovLog);
894
0
                bRet=true;
895
0
            }
896
0
        } break;
897
0
        case SdrEventKind::BeginMark: bRet = BegMark(aLogicPos,rVEvt.mbAddMark,rVEvt.mbUnmark); break;
898
0
        case SdrEventKind::BeginInsertObjPoint: bRet = BegInsObjPoint(aLogicPos, MODKEY_PolyPoly); break;
899
0
        case SdrEventKind::EndInsertObjPoint: {
900
0
            SdrCreateCmd eCmd=SdrCreateCmd::NextPoint;
901
0
            if (MODKEY_PolyPoly) eCmd=SdrCreateCmd::NextObject;
902
0
            if (rVEvt.mnMouseClicks > 1) eCmd = SdrCreateCmd::ForceEnd;
903
0
            EndInsObjPoint(eCmd);
904
0
            bRet=true;
905
0
        } break;
906
0
        case SdrEventKind::BeginInsertGluePoint: bRet=BegInsGluePoint(aLogicPos); break;
907
0
        case SdrEventKind::BeginDragHelpline: bRet = BegDragHelpLine(rVEvt.mnHlplIdx,rVEvt.mpPV); break;
908
0
        case SdrEventKind::BeginDragObj: bRet=BegDragObj(aLogicPos, nullptr, rVEvt.mpHdl, mnMinMovLog); break;
909
0
        case SdrEventKind::BeginCreateObj: {
910
0
            if (mnCurrentInvent==SdrInventor::Default && mnCurrentIdent==SdrObjKind::Caption) {
911
0
                tools::Long nHgt=SdrEngineDefaults::GetFontHeight();
912
0
                bRet=BegCreateCaptionObj(aLogicPos,Size(5*nHgt,2*nHgt));
913
0
            } else bRet=BegCreateObj(aLogicPos);
914
0
        } break;
915
0
        case SdrEventKind::BeginMacroObj: {
916
0
            BegMacroObj(aLogicPos, mnHitTolLog, rVEvt.mpObj, rVEvt.mpPV, mpActualOutDev->GetOwnerWindow());
917
0
            bRet=false;
918
0
        } break;
919
0
        case SdrEventKind::BeginTextEdit: {
920
0
            if (!IsObjMarked(rVEvt.mpObj)) {
921
0
                UnmarkAllObj();
922
0
                MarkObj(rVEvt.mpRootObj,rVEvt.mpPV);
923
0
            }
924
925
0
            bRet = mpActualOutDev && OUTDEV_WINDOW == mpActualOutDev->GetOutDevType()&&
926
0
                 SdrBeginTextEdit(rVEvt.mpObj, rVEvt.mpPV, mpActualOutDev->GetOwnerWindow());
927
928
0
            if(bRet)
929
0
            {
930
0
                MouseEvent aMEvt(mpActualOutDev->LogicToPixel(aLogicPos),
931
0
                                 1, rVEvt.mnMouseMode, rVEvt.mnMouseCode, rVEvt.mnMouseCode);
932
0
                OutlinerView* pOLV=GetTextEditOutlinerView();
933
0
                if (pOLV!=nullptr) pOLV->MouseButtonDown(aMEvt); // event for the Outliner, but without double-click
934
0
            }
935
0
        } break;
936
0
        default: break;
937
0
    } // switch
938
0
    if (bRet && mpActualOutDev && mpActualOutDev->GetOutDevType()==OUTDEV_WINDOW) {
939
0
        vcl::Window* pWin=mpActualOutDev->GetOwnerWindow();
940
        // left mouse button pressed?
941
0
        bool bLeftDown = (rVEvt.mnMouseCode & MOUSE_LEFT) != 0 && rVEvt.mbMouseDown;
942
        // left mouse button released?
943
0
        bool bLeftUp = (rVEvt.mnMouseCode & MOUSE_LEFT) != 0 && rVEvt.mbMouseUp;
944
        // left mouse button pressed or held?
945
0
        bool bLeftDown1=(rVEvt.mnMouseCode & MOUSE_LEFT) != 0 && !rVEvt.mbMouseUp;
946
0
        pWin->SetPointer(GetPreferredPointer(rVEvt.maLogicPos, pWin->GetOutDev(),
947
0
                rVEvt.mnMouseCode & (KEY_SHIFT|KEY_MOD1|KEY_MOD2),bLeftDown1));
948
0
        bool bAction=IsAction();
949
0
        if (bLeftDown && bAction)
950
0
            pWin->CaptureMouse();
951
0
        else if (bLeftUp || (rVEvt.mbIsAction && !bAction))
952
0
            pWin->ReleaseMouse();
953
0
    }
954
0
    return bRet;
955
0
}
956
957
PointerStyle SdrView::GetPreferredPointer(const Point& rMousePos, const OutputDevice* pOut, sal_uInt16 nModifier, bool bLeftDown) const
958
0
{
959
    // Actions
960
0
    if (IsCreateObj())
961
0
    {
962
0
        return mpCurrentCreate->GetCreatePointer();
963
0
    }
964
0
    if (mpCurrentSdrDragMethod)
965
0
    {
966
0
        return mpCurrentSdrDragMethod->GetSdrDragPointer();
967
0
    }
968
0
    if (IsMarkObj() || IsMarkPoints() || IsMarkGluePoints() || IsSetPageOrg()) return PointerStyle::Arrow;
969
0
    if (IsDragHelpLine()) return GetDraggedHelpLinePointer();
970
0
    if (IsMacroObj()) {
971
0
        SdrObjMacroHitRec aHitRec;
972
0
        aHitRec.aPos=pOut->LogicToPixel(rMousePos);
973
0
        aHitRec.nTol=m_nMacroTol;
974
0
        aHitRec.pVisiLayer=&m_pMacroPV->GetVisibleLayers();
975
0
        aHitRec.pPageView=m_pMacroPV;
976
0
        return m_pMacroObj->GetMacroPointer(aHitRec);
977
0
    }
978
979
    // TextEdit, ObjEdit, Macro
980
0
    if (IsTextEdit() && (IsTextEditInSelectionMode() || IsTextEditHit(rMousePos)))
981
0
    {
982
0
        if(!pOut || IsTextEditInSelectionMode())
983
0
        {
984
0
            if (mpTextEditOutliner->IsVertical())
985
0
                return PointerStyle::TextVertical;
986
0
            else
987
0
                return PointerStyle::Text;
988
0
        }
989
        // Outliner should return something here...
990
0
        Point aPos(pOut->LogicToPixel(rMousePos));
991
0
        PointerStyle aPointer(mpTextEditOutlinerView->GetPointer(aPos));
992
0
        if (aPointer==PointerStyle::Arrow)
993
0
        {
994
0
            if (mpTextEditOutliner->IsVertical())
995
0
                aPointer = PointerStyle::TextVertical;
996
0
            else
997
0
                aPointer = PointerStyle::Text;
998
0
        }
999
0
        return aPointer;
1000
0
    }
1001
1002
0
    SdrViewEvent aVEvt;
1003
0
    aVEvt.mnMouseCode = (nModifier&(KEY_SHIFT|KEY_MOD1|KEY_MOD2))|MOUSE_LEFT; // to see what would happen on MouseLeftDown
1004
0
    aVEvt.mbMouseDown = !bLeftDown; // What if ..?
1005
0
    aVEvt.mbMouseUp = bLeftDown;    // What if ..?
1006
0
    if (pOut!=nullptr)
1007
0
        const_cast<SdrView*>(this)->SetActualWin(pOut);
1008
0
    SdrHitKind eHit=PickAnything(rMousePos,aVEvt);
1009
0
    SdrEventKind eEvent = aVEvt.meEvent;
1010
0
    switch (eEvent)
1011
0
    {
1012
0
        case SdrEventKind::BeginCreateObj:
1013
0
            return maCurrentCreatePointer;
1014
0
        case SdrEventKind::MarkObj:
1015
0
            return PointerStyle::Move;
1016
0
        case SdrEventKind::BeginMark:
1017
0
            return PointerStyle::Arrow;
1018
0
        case SdrEventKind::MarkPoint:
1019
0
        case SdrEventKind::MarkGluePoint:
1020
0
            return PointerStyle::MovePoint;
1021
0
        case SdrEventKind::BeginInsertObjPoint:
1022
0
        case SdrEventKind::BeginInsertGluePoint:
1023
0
            return PointerStyle::Cross;
1024
0
        case SdrEventKind::ExecuteUrl:
1025
0
            return PointerStyle::RefHand;
1026
0
        case SdrEventKind::BeginMacroObj:
1027
0
        {
1028
0
            SdrObjMacroHitRec aHitRec;
1029
0
            aHitRec.aPos = aVEvt.maLogicPos;
1030
0
            aHitRec.nTol=mnHitTolLog;
1031
0
            aHitRec.pVisiLayer = &aVEvt.mpPV->GetVisibleLayers();
1032
0
            aHitRec.pPageView = aVEvt.mpPV;
1033
0
            return aVEvt.mpObj->GetMacroPointer(aHitRec);
1034
0
        }
1035
0
        default: break;
1036
0
    } // switch
1037
1038
0
    switch(eHit)
1039
0
    {
1040
0
        case SdrHitKind::Cell:
1041
0
            return PointerStyle::Arrow;
1042
0
        case SdrHitKind::HelpLine :
1043
0
            return aVEvt.mpPV->GetHelpLines()[aVEvt.mnHlplIdx].GetPointer();
1044
0
        case SdrHitKind::Gluepoint:
1045
0
            return PointerStyle::MovePoint;
1046
0
        case SdrHitKind::TextEdit :
1047
0
        case SdrHitKind::TextEditObj:
1048
0
        {
1049
0
            SdrTextObj* pText = DynCastSdrTextObj(aVEvt.mpObj);
1050
0
            if(pText && pText->HasText())
1051
0
            {
1052
0
                OutlinerParaObject* pParaObj = pText->GetOutlinerParaObject();
1053
0
                if(pParaObj && pParaObj->IsEffectivelyVertical())
1054
0
                    return PointerStyle::TextVertical;
1055
0
            }
1056
0
            return PointerStyle::Text;
1057
0
        }
1058
0
        default: break;
1059
0
    }
1060
1061
0
    bool bMarkHit=eHit==SdrHitKind::MarkedObject;
1062
0
    SdrHdl* pHdl = aVEvt.mpHdl;
1063
    // now check the pointers for dragging
1064
0
    if (pHdl!=nullptr || bMarkHit) {
1065
0
        SdrHdlKind eHdl= pHdl!=nullptr ? pHdl->GetKind() : SdrHdlKind::Move;
1066
0
        bool bCorner=pHdl!=nullptr && pHdl->IsCornerHdl();
1067
0
        bool bVertex=pHdl!=nullptr && pHdl->IsVertexHdl();
1068
0
        bool bMov=eHdl==SdrHdlKind::Move;
1069
0
        if (bMov && (meDragMode==SdrDragMode::Move || meDragMode==SdrDragMode::Resize || mbMarkedHitMovesAlways)) {
1070
0
            if (!IsMoveAllowed()) return PointerStyle::Arrow; // because double click or drag & drop is possible
1071
0
            return PointerStyle::Move;
1072
0
        }
1073
0
        switch (meDragMode) {
1074
0
            case SdrDragMode::Rotate: {
1075
0
                if ((bCorner || bMov) && !IsRotateAllowed(true))
1076
0
                    return PointerStyle::NotAllowed;
1077
1078
                // are 3D objects selected?
1079
0
                bool b3DObjSelected = false;
1080
0
                const SdrMarkList& rMarkList = GetMarkedObjectList();
1081
0
                for (size_t a=0; !b3DObjSelected && a<rMarkList.GetMarkCount(); ++a) {
1082
0
                    SdrObject* pObj = rMarkList.GetMark(a)->GetMarkedSdrObj();
1083
0
                    if(DynCastE3dObject(pObj))
1084
0
                        b3DObjSelected = true;
1085
0
                }
1086
                // If we have a 3D object, go on despite !IsShearAllowed,
1087
                // because then we have a rotation instead of a shear.
1088
0
                if (bVertex && !IsShearAllowed() && !b3DObjSelected)
1089
0
                    return PointerStyle::NotAllowed;
1090
0
                if (bMov)
1091
0
                    return PointerStyle::Rotate;
1092
0
            } break;
1093
0
            case SdrDragMode::Shear: {
1094
0
                if (bCorner) {
1095
0
                    if (!IsDistortAllowed(true) && !IsDistortAllowed()) return PointerStyle::NotAllowed;
1096
0
                    else return PointerStyle::RefHand;
1097
0
                }
1098
0
                if (bVertex && !IsShearAllowed()) return PointerStyle::NotAllowed;
1099
0
                if (bMov) {
1100
0
                    if (!IsMoveAllowed()) return PointerStyle::Arrow; // because double click or drag & drop is possible
1101
0
                    return PointerStyle::Move;
1102
0
                }
1103
0
            } break;
1104
0
            case SdrDragMode::Mirror: {
1105
0
                if (bCorner || bVertex || bMov) {
1106
0
                    SdrHdl* pH1=maHdlList.GetHdl(SdrHdlKind::Ref1);
1107
0
                    SdrHdl* pH2=maHdlList.GetHdl(SdrHdlKind::Ref2);
1108
0
                    bool b90=false;
1109
0
                    bool b45=false;
1110
0
                    if (pH1!=nullptr && pH2!=nullptr) {
1111
0
                        Point aDif = pH2->GetPos()-pH1->GetPos();
1112
0
                        b90=(aDif.X()==0) || aDif.Y()==0;
1113
0
                        b45=b90 || (std::abs(aDif.X())==std::abs(aDif.Y()));
1114
0
                    }
1115
0
                    bool bNo=false;
1116
0
                    if (!IsMirrorAllowed(true,true)) bNo=true; // any mirroring is forbidden
1117
0
                    if (!IsMirrorAllowed() && !b45) bNo=true; // mirroring freely is forbidden
1118
0
                    if (!IsMirrorAllowed(true) && !b90) bNo=true;  // mirroring horizontally/vertically is allowed
1119
0
                    if (bNo) return PointerStyle::NotAllowed;
1120
0
                    if (b90) {
1121
0
                        return PointerStyle::Mirror;
1122
0
                    }
1123
0
                    return PointerStyle::Mirror;
1124
0
                }
1125
0
            } break;
1126
1127
0
            case SdrDragMode::Transparence:
1128
0
            {
1129
0
                if(!IsTransparenceAllowed())
1130
0
                    return PointerStyle::NotAllowed;
1131
1132
0
                return PointerStyle::RefHand;
1133
0
            }
1134
1135
0
            case SdrDragMode::Gradient:
1136
0
            {
1137
0
                if(!IsGradientAllowed())
1138
0
                    return PointerStyle::NotAllowed;
1139
1140
0
                return PointerStyle::RefHand;
1141
0
            }
1142
1143
0
            case SdrDragMode::Crook: {
1144
0
                if (bCorner || bVertex || bMov) {
1145
0
                    if (!IsCrookAllowed(true) && !IsCrookAllowed()) return PointerStyle::NotAllowed;
1146
0
                    return PointerStyle::Crook;
1147
0
                }
1148
0
                break;
1149
0
            }
1150
1151
0
            case SdrDragMode::Crop:
1152
0
            {
1153
0
                return PointerStyle::Crop;
1154
0
            }
1155
1156
0
            default: {
1157
0
                if ((bCorner || bVertex) && !IsResizeAllowed(true)) return PointerStyle::NotAllowed;
1158
0
            }
1159
0
        }
1160
0
        if (pHdl!=nullptr) return pHdl->GetPointer();
1161
0
        if (bMov) {
1162
0
            if (!IsMoveAllowed()) return PointerStyle::Arrow; // because double click or drag & drop is possible
1163
0
            return PointerStyle::Move;
1164
0
        }
1165
0
    }
1166
0
    if (meEditMode==SdrViewEditMode::Create) return maCurrentCreatePointer;
1167
0
    return PointerStyle::Arrow;
1168
0
}
1169
1170
constexpr OUString STR_NOTHING = u"nothing"_ustr;
1171
OUString SdrView::GetStatusText()
1172
0
{
1173
0
    OUString aName;
1174
0
    OUString aStr = STR_NOTHING;
1175
1176
0
    if (mpCurrentCreate!=nullptr)
1177
0
    {
1178
0
        aStr=mpCurrentCreate->getSpecialDragComment(maDragStat);
1179
1180
0
        if(aStr.isEmpty())
1181
0
        {
1182
0
            aName = mpCurrentCreate->TakeObjNameSingul();
1183
0
            aStr = SvxResId(STR_ViewCreateObj);
1184
0
        }
1185
0
    }
1186
0
    else if (mpCurrentSdrDragMethod)
1187
0
    {
1188
0
        if (mbInsPolyPoint || IsInsertGluePoint())
1189
0
        {
1190
0
            aStr=maInsPointUndoStr;
1191
0
        }
1192
0
        else
1193
0
        {
1194
0
            if (maDragStat.IsMinMoved())
1195
0
            {
1196
0
                SAL_INFO(
1197
0
                    "svx.svdraw",
1198
0
                    "(" << this << ") " << mpCurrentSdrDragMethod.get());
1199
0
                aStr = mpCurrentSdrDragMethod->GetSdrDragComment();
1200
0
            }
1201
0
        }
1202
0
    }
1203
0
    else if(IsMarkObj())
1204
0
    {
1205
0
        const SdrMarkList& rMarkList = GetMarkedObjectList();
1206
0
        if(rMarkList.GetMarkCount() != 0)
1207
0
        {
1208
0
            aStr = SvxResId(STR_ViewMarkMoreObjs);
1209
0
        }
1210
0
        else
1211
0
        {
1212
0
            aStr = SvxResId(STR_ViewMarkObjs);
1213
0
        }
1214
0
    }
1215
0
    else if(IsMarkPoints())
1216
0
    {
1217
0
        if(HasMarkedPoints())
1218
0
        {
1219
0
            aStr = SvxResId(STR_ViewMarkMorePoints);
1220
0
        }
1221
0
        else
1222
0
        {
1223
0
            aStr = SvxResId(STR_ViewMarkPoints);
1224
0
        }
1225
0
    } else if (IsMarkGluePoints())
1226
0
    {
1227
0
        if(HasMarkedGluePoints())
1228
0
        {
1229
0
            aStr = SvxResId(STR_ViewMarkMoreGluePoints);
1230
0
        }
1231
0
        else
1232
0
        {
1233
0
            aStr = SvxResId(STR_ViewMarkGluePoints);
1234
0
        }
1235
0
    }
1236
0
    else if (IsTextEdit() && mpTextEditOutlinerView != nullptr) {
1237
0
        aStr=SvxResId(STR_ViewTextEdit); // "TextEdit - Row y, Column x";
1238
0
        ESelection aSel(mpTextEditOutlinerView->GetSelection());
1239
0
        tools::Long nPar = aSel.end.nPara, nLin = 0, nCol = aSel.end.nIndex;
1240
0
        if (aSel.end.nPara>0) {
1241
0
            for (sal_Int32 nParaNum=0; nParaNum<aSel.end.nPara; nParaNum++) {
1242
0
                nLin += mpTextEditOutliner->GetLineCount(nParaNum);
1243
0
            }
1244
0
        }
1245
        // A little imperfection:
1246
        // At the end of a line of any multi-line paragraph, we display the
1247
        // position of the next line of the same paragraph, if there is one.
1248
0
        sal_uInt16 nParaLine = 0;
1249
0
        sal_Int32 nParaLineCount = mpTextEditOutliner->GetLineCount(aSel.end.nPara);
1250
0
        bool bBrk = false;
1251
0
        while (!bBrk)
1252
0
        {
1253
0
            sal_uInt16 nLen = mpTextEditOutliner->GetLineLen(aSel.end.nPara, nParaLine);
1254
0
            bool bLastLine = (nParaLine == nParaLineCount - 1);
1255
0
            if (nCol>nLen || (!bLastLine && nCol == nLen))
1256
0
            {
1257
0
                nCol -= nLen;
1258
0
                nLin++;
1259
0
                nParaLine++;
1260
0
            }
1261
0
            else
1262
0
                bBrk = true;
1263
1264
0
            if (nLen == 0)
1265
0
                bBrk = true; // to be sure
1266
0
        }
1267
1268
0
        aStr = aStr.replaceFirst("%1", OUString::number(nPar + 1));
1269
0
        aStr = aStr.replaceFirst("%2", OUString::number(nLin + 1));
1270
0
        aStr = aStr.replaceFirst("%3", OUString::number(nCol + 1));
1271
1272
#ifdef DBG_UTIL
1273
        aStr +=  ", Level " + OUString::number(mpTextEditOutliner->GetDepth( aSel.end.nPara ));
1274
#endif
1275
0
    }
1276
1277
0
    if(aStr == STR_NOTHING)
1278
0
    {
1279
0
        const SdrMarkList& rMarkList = GetMarkedObjectList();
1280
0
        if (rMarkList.GetMarkCount() != 0) {
1281
0
            aStr = ImpGetDescriptionString(STR_ViewMarked);
1282
0
            if (IsGluePointEditMode()) {
1283
0
                if (HasMarkedGluePoints()) {
1284
0
                    aStr = ImpGetDescriptionString(STR_ViewMarked, ImpGetDescriptionOptions::GLUEPOINTS);
1285
0
                }
1286
0
            } else {
1287
0
                if (HasMarkedPoints()) {
1288
0
                    aStr = ImpGetDescriptionString(STR_ViewMarked, ImpGetDescriptionOptions::POINTS);
1289
0
                }
1290
0
            }
1291
0
        } else {
1292
0
            aStr.clear();
1293
0
        }
1294
0
    }
1295
0
    else if(!aName.isEmpty())
1296
0
    {
1297
0
        aStr = aStr.replaceFirst("%1", aName);
1298
0
    }
1299
1300
0
    if(!aStr.isEmpty())
1301
0
    {
1302
        // capitalize first letter
1303
0
        aStr = aStr.replaceAt(0, 1, OUString(aStr[0]).toAsciiUpperCase());
1304
0
    }
1305
0
    return aStr;
1306
0
}
1307
1308
SdrViewContext SdrView::GetContext() const
1309
0
{
1310
0
    if( IsGluePointEditMode() )
1311
0
        return SdrViewContext::GluePointEdit;
1312
1313
0
    const SdrMarkList& rMarkList = GetMarkedObjectList();
1314
0
    const size_t nMarkCount = rMarkList.GetMarkCount();
1315
1316
0
    if( HasMarkablePoints() && !IsFrameHandles() )
1317
0
    {
1318
0
        bool bPath=true;
1319
0
        for( size_t nMarkNum = 0; nMarkNum < nMarkCount && bPath; ++nMarkNum )
1320
0
            if (dynamic_cast<const SdrPathObj*>(rMarkList.GetMark(nMarkNum)->GetMarkedSdrObj()) == nullptr)
1321
0
                bPath=false;
1322
1323
0
        if( bPath )
1324
0
            return SdrViewContext::PointEdit;
1325
0
    }
1326
1327
0
    if( rMarkList.GetMarkCount() )
1328
0
    {
1329
0
        bool bGraf = true, bMedia = true, bTable = true;
1330
1331
0
        for( size_t nMarkNum = 0; nMarkNum < nMarkCount && ( bGraf || bMedia ); ++nMarkNum )
1332
0
        {
1333
0
            const SdrObject* pMarkObj = rMarkList.GetMark(nMarkNum)->GetMarkedSdrObj();
1334
0
            DBG_ASSERT( pMarkObj, "SdrView::GetContext(), null pointer in mark list!" );
1335
1336
0
            if( !pMarkObj )
1337
0
                continue;
1338
1339
0
            if( dynamic_cast<const SdrGrafObj*>( pMarkObj) ==  nullptr )
1340
0
                bGraf = false;
1341
1342
0
            if( dynamic_cast<const SdrMediaObj*>( pMarkObj) ==  nullptr )
1343
0
                bMedia = false;
1344
1345
0
            if( dynamic_cast<const sdr::table::SdrTableObj* >( pMarkObj ) ==  nullptr )
1346
0
                bTable = false;
1347
0
        }
1348
1349
0
        if( bGraf )
1350
0
            return SdrViewContext::Graphic;
1351
0
        else if( bMedia )
1352
0
            return SdrViewContext::Media;
1353
0
        else if( bTable )
1354
0
            return SdrViewContext::Table;
1355
0
    }
1356
1357
0
    return SdrViewContext::Standard;
1358
0
}
1359
1360
void SdrView::MarkAll()
1361
0
{
1362
0
    if (IsTextEdit()) {
1363
0
        GetTextEditOutlinerView()->SetSelection(ESelection::All());
1364
0
    } else if (IsGluePointEditMode()) MarkAllGluePoints();
1365
0
    else if (HasMarkablePoints()) MarkAllPoints();
1366
0
    else {
1367
        // check for table
1368
0
        bool bMarkAll = true;
1369
0
        const SdrMarkList& rMarkList = GetMarkedObjectList();
1370
0
        if (rMarkList.GetMarkCount() == 1)
1371
0
        {
1372
0
            const SdrObject* pObj(rMarkList.GetMark(0)->GetMarkedSdrObj());
1373
0
            SdrView* pView = this;
1374
0
            if (pObj && (pObj->GetObjInventor() == SdrInventor::Default)
1375
0
                && (pObj->GetObjIdentifier() == SdrObjKind::Table))
1376
0
            {
1377
0
                mxSelectionController.clear();
1378
0
                mxSelectionController = sdr::table::CreateTableController(
1379
0
                    *pView, static_cast<const sdr::table::SdrTableObj&>(*pObj),
1380
0
                    mxLastSelectionController);
1381
1382
0
                if (mxSelectionController.is())
1383
0
                {
1384
0
                    mxLastSelectionController.clear();
1385
0
                    mxSelectionController->onSelectAll();
1386
0
                    bMarkAll = false;
1387
0
                }
1388
0
            }
1389
0
        }
1390
0
        if ( bMarkAll )
1391
0
            MarkAllObj();
1392
0
    }
1393
0
}
1394
1395
void SdrView::UnmarkAll()
1396
28
{
1397
28
    if (IsTextEdit()) {
1398
0
        ESelection eSel=GetTextEditOutlinerView()->GetSelection();
1399
0
        eSel.CollapseToEnd();
1400
0
        GetTextEditOutlinerView()->SetSelection(eSel);
1401
28
    } else if (HasMarkedGluePoints()) UnmarkAllGluePoints();
1402
28
    else if (HasMarkedPoints()) UnmarkAllPoints(); // Marked, not Markable!
1403
28
    else UnmarkAllObj();
1404
28
}
1405
1406
const tools::Rectangle& SdrView::GetMarkedRect() const
1407
0
{
1408
0
    if (IsGluePointEditMode() && HasMarkedGluePoints()) {
1409
0
        return GetMarkedGluePointsRect();
1410
0
    }
1411
0
    if (HasMarkedPoints()) {
1412
0
        return GetMarkedPointsRect();
1413
0
    }
1414
0
    return GetMarkedObjRect();
1415
0
}
1416
1417
void SdrView::DeleteMarked()
1418
0
{
1419
0
    if (IsTextEdit())
1420
0
    {
1421
0
        SdrObjEditView::KeyInput(KeyEvent(0, vcl::KeyCode(KeyFuncType::DELETE)), mpTextEditWin);
1422
0
    }
1423
0
    else
1424
0
    {
1425
0
        if( mxSelectionController.is() && mxSelectionController->DeleteMarked() )
1426
0
        {
1427
            // action already performed by current selection controller, do nothing
1428
0
        }
1429
0
        else if (IsGluePointEditMode() && HasMarkedGluePoints())
1430
0
        {
1431
0
            DeleteMarkedGluePoints();
1432
0
        }
1433
0
        else if (GetContext()==SdrViewContext::PointEdit && HasMarkedPoints())
1434
0
        {
1435
0
            DeleteMarkedPoints();
1436
0
        }
1437
0
        else
1438
0
        {
1439
0
            DeleteMarkedObj();
1440
0
        }
1441
0
    }
1442
0
}
1443
1444
bool SdrView::BegMark(const Point& rPnt, bool bAddMark, bool bUnmark)
1445
0
{
1446
0
    if (bUnmark) bAddMark=true;
1447
0
    if (IsGluePointEditMode()) {
1448
0
        if (!bAddMark) UnmarkAllGluePoints();
1449
0
        return BegMarkGluePoints(rPnt,bUnmark);
1450
0
    } else if (HasMarkablePoints()) {
1451
0
        if (!bAddMark) UnmarkAllPoints();
1452
0
        return BegMarkPoints(rPnt,bUnmark);
1453
0
    } else {
1454
0
        if (!bAddMark) UnmarkAllObj();
1455
0
        BegMarkObj(rPnt,bUnmark);
1456
0
        return true;
1457
0
    }
1458
0
}
1459
1460
bool SdrView::MoveShapeHandle(const sal_uInt32 handleNum, const Point& aEndPoint, const sal_Int32 aObjectOrdNum)
1461
0
{
1462
0
    if (GetHdlList().IsMoveOutside())
1463
0
        return false;
1464
1465
0
    const SdrMarkList& rMarkList = GetMarkedObjectList();
1466
0
    if (!rMarkList.GetMarkCount())
1467
0
        return false;
1468
1469
0
    SdrHdl * pHdl = GetHdlList().GetHdl(handleNum);
1470
0
    if (pHdl == nullptr)
1471
0
        return false;
1472
1473
0
    SdrDragStat& rDragStat = const_cast<SdrDragStat&>(GetDragStat());
1474
    // start dragging
1475
0
    BegDragObj(pHdl->GetPos(), nullptr, pHdl, 0);
1476
0
    if (!IsDragObj())
1477
0
        return false;
1478
1479
0
    bool bWasNoSnap = rDragStat.IsNoSnap();
1480
0
    bool bWasSnapEnabled = IsSnapEnabled();
1481
1482
    // switch snapping off
1483
0
    if(!bWasNoSnap)
1484
0
        rDragStat.SetNoSnap();
1485
0
    if(bWasSnapEnabled)
1486
0
        SetSnapEnabled(false);
1487
1488
0
    if (aObjectOrdNum != -1)
1489
0
    {
1490
0
        rDragStat.GetGlueOptions().objectOrdNum = aObjectOrdNum;
1491
0
    }
1492
0
    MovDragObj(aEndPoint);
1493
0
    EndDragObj();
1494
1495
    // Clear Glue Options
1496
0
    rDragStat.GetGlueOptions().objectOrdNum = -1;
1497
1498
0
    if (!bWasNoSnap)
1499
0
       rDragStat.SetNoSnap(bWasNoSnap);
1500
0
    if (bWasSnapEnabled)
1501
0
        SetSnapEnabled(bWasSnapEnabled);
1502
1503
0
    return true;
1504
0
}
1505
1506
void SdrView::SetMasterPagePaintCaching(bool bOn)
1507
11.7k
{
1508
11.7k
    if(mbMasterPagePaintCaching == bOn)
1509
0
        return;
1510
1511
11.7k
    mbMasterPagePaintCaching = bOn;
1512
1513
    // reset at all SdrPageWindows
1514
11.7k
    SdrPageView* pPageView = GetSdrPageView();
1515
1516
11.7k
    if(!pPageView)
1517
11.7k
        return;
1518
1519
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
1520
0
    {
1521
0
        SdrPageWindow* pPageWindow = pPageView->GetPageWindow(b);
1522
0
        assert(pPageWindow && "SdrView::SetMasterPagePaintCaching: Corrupt SdrPageWindow list (!)");
1523
1524
        // force deletion of ObjectContact, so at re-display all VOCs
1525
        // will be re-created with updated flag setting
1526
0
        pPageWindow->ResetObjectContact();
1527
0
    }
1528
1529
    // force redraw of this view
1530
0
    pPageView->InvalidateAllWin();
1531
0
}
1532
1533
// Default ObjectContact is ObjectContactOfPageView
1534
sdr::contact::ObjectContact* SdrView::createViewSpecificObjectContact(
1535
    SdrPageWindow& rPageWindow,
1536
    const char* pDebugName) const
1537
73.7k
{
1538
73.7k
    return new sdr::contact::ObjectContactOfPageView(rPageWindow, pDebugName);
1539
73.7k
}
1540
1541
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */