Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/func/fudraw.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 <sal/config.h>
21
22
#include <vcl/svapp.hxx>
23
#include <vcl/ptrstyle.hxx>
24
#include <editeng/flditem.hxx>
25
#include <svx/svdogrp.hxx>
26
#include <tools/urlobj.hxx>
27
#include <vcl/help.hxx>
28
#include <svx/bmpmask.hxx>
29
#include <svx/svdotext.hxx>
30
#include <svx/ImageMapInfo.hxx>
31
#include <sfx2/dispatch.hxx>
32
#include <sfx2/bindings.hxx>
33
#include <sfx2/sfxhelp.hxx>
34
#include <svx/svdpagv.hxx>
35
#include <vcl/imapobj.hxx>
36
#include <svx/svxids.hrc>
37
#include <svx/obj3d.hxx>
38
#include <svx/scene3d.hxx>
39
#include <sfx2/viewfrm.hxx>
40
41
#include <strings.hrc>
42
43
44
#include <sdmod.hxx>
45
#include <fudraw.hxx>
46
#include <ViewShell.hxx>
47
#include <FrameView.hxx>
48
#include <View.hxx>
49
#include <Window.hxx>
50
#include <drawdoc.hxx>
51
#include <DrawDocShell.hxx>
52
#include <sdresid.hxx>
53
#include <fusel.hxx>
54
#include <vcl/weld/MessageDialog.hxx>
55
#include <vcl/weld/WaitObject.hxx>
56
#include <svx/sdrhittesthelper.hxx>
57
58
using namespace ::com::sun::star;
59
60
namespace sd {
61
62
63
/**
64
 * Base-class for all drawmodul-specific functions
65
 */
66
FuDraw::FuDraw(ViewShell& rViewSh, ::sd::Window* pWin, ::sd::View* pView,
67
               SdDrawDocument& rDoc, SfxRequest& rReq)
68
0
    : FuPoor(rViewSh, pWin, pView, rDoc, rReq)
69
0
    , aNewPointer(PointerStyle::Arrow)
70
0
    , aOldPointer(PointerStyle::Arrow)
71
0
    , bMBDown(false)
72
0
    , bDragHelpLine(false)
73
0
    , nHelpLine(0)
74
0
    , bPermanent(false)
75
0
{
76
0
}
77
78
FuDraw::~FuDraw()
79
0
{
80
0
    mpView->BrkAction();
81
0
}
82
83
84
/**
85
 * Code shared by MouseButtonDown and MouseMove
86
 */
87
void FuDraw::DoModifiers(const MouseEvent& rMEvt, bool bSnapModPressed)
88
0
{
89
0
    FrameView* pFrameView = mrViewShell.GetFrameView();
90
0
    bool bGridSnap = pFrameView->IsGridSnap();
91
0
    bGridSnap = (bSnapModPressed != bGridSnap);
92
93
0
    if (mpView->IsGridSnap() != bGridSnap)
94
0
        mpView->SetGridSnap(bGridSnap);
95
96
0
    bool bBordSnap = pFrameView->IsBordSnap();
97
0
    bBordSnap = (bSnapModPressed != bBordSnap);
98
99
0
    if (mpView->IsBordSnap() != bBordSnap)
100
0
        mpView->SetBordSnap(bBordSnap);
101
102
0
    bool bHlplSnap = pFrameView->IsHlplSnap();
103
0
    bHlplSnap = (bSnapModPressed != bHlplSnap);
104
105
0
    if (mpView->IsHlplSnap() != bHlplSnap)
106
0
        mpView->SetHlplSnap(bHlplSnap);
107
108
0
    bool bOFrmSnap = pFrameView->IsOFrmSnap();
109
0
    bOFrmSnap = (bSnapModPressed != bOFrmSnap);
110
111
0
    if (mpView->IsOFrmSnap() != bOFrmSnap)
112
0
        mpView->SetOFrmSnap(bOFrmSnap);
113
114
0
    bool bOPntSnap = pFrameView->IsOPntSnap();
115
0
    bOPntSnap = (bSnapModPressed != bOPntSnap);
116
117
0
    if (mpView->IsOPntSnap() != bOPntSnap)
118
0
        mpView->SetOPntSnap(bOPntSnap);
119
120
0
    bool bOConSnap = pFrameView->IsOConSnap();
121
0
    bOConSnap = (bSnapModPressed != bOConSnap);
122
123
0
    if (mpView->IsOConSnap() != bOConSnap)
124
0
        mpView->SetOConSnap(bOConSnap);
125
126
0
    bool bAngleSnap = rMEvt.IsShift() == !pFrameView->IsAngleSnapEnabled();
127
128
0
    if (mpView->IsAngleSnapEnabled() != bAngleSnap)
129
0
        mpView->SetAngleSnapEnabled(bAngleSnap);
130
131
0
    bool bCenter = rMEvt.IsMod2();
132
133
0
    if ( mpView->IsCreate1stPointAsCenter() != bCenter ||
134
0
         mpView->IsResizeAtCenter() != bCenter )
135
0
    {
136
0
        mpView->SetCreate1stPointAsCenter(bCenter);
137
0
        mpView->SetResizeAtCenter(bCenter);
138
0
    }
139
0
}
140
141
142
bool FuDraw::MouseButtonDown(const MouseEvent& rMEvt)
143
0
{
144
    // remember button state for creation of own MouseEvents
145
0
    SetMouseButtonCode(rMEvt.GetButtons());
146
147
0
    bool bReturn = false;
148
0
    bDragHelpLine = false;
149
0
    aMDPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() );
150
151
0
    if ( rMEvt.IsLeft() )
152
0
    {
153
0
        FrameView* pFrameView = mrViewShell.GetFrameView();
154
155
0
        bool bOrtho = false;
156
157
0
        bool bRestricted = true;
158
159
0
        if (mpView->IsDragObj())
160
0
        {
161
            // object is dragged (move, resize,...)
162
0
            const SdrHdl* pHdl = mpView->GetDragStat().GetHdl();
163
164
0
            if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl()))
165
0
            {
166
                // Move
167
0
                bRestricted = false;
168
0
            }
169
0
        }
170
171
        // #i33136#
172
0
        if(bRestricted && doConstructOrthogonal())
173
0
        {
174
            // Restrict movement:
175
            // rectangle->square, ellipse->circle, etc.
176
0
            bOrtho = !rMEvt.IsShift();
177
0
        }
178
0
        else
179
0
        {
180
0
            bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho();
181
0
        }
182
0
        if (!mpView->IsSnapEnabled())
183
0
            mpView->SetSnapEnabled(true);
184
185
0
        bool bSnapModPressed = rMEvt.IsMod1();
186
0
        if (mpView->IsOrtho() != bOrtho)
187
0
            mpView->SetOrtho(bOrtho);
188
189
0
        DoModifiers(rMEvt, bSnapModPressed);
190
191
0
        SdrPageView* pPV = nullptr;
192
0
        sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
193
194
        // look only for HelpLines when they are visible (!)
195
0
        bool bHelpLine(false);
196
0
        if(mpView->IsHlplVisible())
197
0
            bHelpLine = mpView->PickHelpLine(aMDPos, nHitLog, *mpWindow->GetOutDev(), nHelpLine, pPV);
198
0
        bool bHitHdl = (mpView->PickHandle(aMDPos) != nullptr);
199
200
0
        if ( bHelpLine
201
0
            && !mpView->IsCreateObj()
202
0
            && ((mpView->GetEditMode() == SdrViewEditMode::Edit && !bHitHdl) || (rMEvt.IsShift() && bSnapModPressed)) )
203
0
        {
204
0
            mpWindow->CaptureMouse();
205
0
            mpView->BegDragHelpLine(nHelpLine, pPV);
206
0
            bDragHelpLine = mpView->IsDragHelpLine();
207
0
            bReturn = true;
208
0
        }
209
0
    }
210
0
    ForcePointer(&rMEvt);
211
212
0
    return bReturn;
213
0
}
214
215
bool FuDraw::MouseMove(const MouseEvent& rMEvt)
216
0
{
217
0
    FrameView* pFrameView = mrViewShell.GetFrameView();
218
0
    Point aPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() );
219
220
0
    bool bOrtho = false;
221
0
    bool bRestricted = true;
222
223
0
    if (mpView->IsDragObj())
224
0
    {
225
        // object is dragged (move, resize, ...)
226
0
        const SdrHdl* pHdl = mpView->GetDragStat().GetHdl();
227
228
0
        if (!pHdl || (!pHdl->IsCornerHdl() && !pHdl->IsVertexHdl()))
229
0
        {
230
            // Move
231
0
            bRestricted = false;
232
0
        }
233
0
    }
234
235
0
    if (mpView->IsAction())
236
0
    {
237
        // #i33136# and fdo#88339
238
0
        if(bRestricted && doConstructOrthogonal())
239
0
        {
240
            // Scale proportionally by default:
241
            // rectangle->square, ellipse->circle, images, etc.
242
0
            bOrtho = !rMEvt.IsShift();
243
0
        }
244
0
        else
245
0
        {
246
0
            bOrtho = rMEvt.IsShift() != pFrameView->IsOrtho();
247
0
        }
248
249
0
        bool bSnapModPressed = rMEvt.IsMod2();
250
0
        mpView->SetDragWithCopy(rMEvt.IsMod1() && pFrameView->IsDragWithCopy());
251
252
0
        if (mpView->IsOrtho() != bOrtho)
253
0
            mpView->SetOrtho(bOrtho);
254
0
        DoModifiers(rMEvt, bSnapModPressed);
255
256
257
0
        if ( mpView->IsDragHelpLine() )
258
0
            mpView->MovDragHelpLine(aPos);
259
0
    }
260
261
0
    bool bReturn = mpView->MouseMove(rMEvt, mpWindow->GetOutDev());
262
263
0
    if (mpView->IsAction())
264
0
    {
265
        // Because the flag set back if necessary in MouseMove
266
0
        if (mpView->IsOrtho() != bOrtho)
267
0
            mpView->SetOrtho(bOrtho);
268
0
    }
269
270
0
    ForcePointer(&rMEvt);
271
272
0
    return bReturn;
273
0
}
274
275
bool FuDraw::MouseButtonUp(const MouseEvent& rMEvt)
276
0
{
277
0
    if (mpView && mpView->IsDragHelpLine())
278
0
        mpView->EndDragHelpLine();
279
280
0
    if ( bDragHelpLine )
281
0
    {
282
0
        ::tools::Rectangle aOutputArea(Point(0,0), mpWindow->GetOutputSizePixel());
283
284
0
        if (mpView && !aOutputArea.Contains(rMEvt.GetPosPixel()))
285
0
            mpView->GetSdrPageView()->DeleteHelpLine(nHelpLine);
286
287
0
        mpWindow->ReleaseMouse();
288
0
    }
289
290
0
    if (mpView)
291
0
    {
292
0
        FrameView* pFrameView = mrViewShell.GetFrameView();
293
0
        mpView->SetOrtho( pFrameView->IsOrtho() );
294
0
        mpView->SetAngleSnapEnabled( pFrameView->IsAngleSnapEnabled() );
295
0
        mpView->SetSnapEnabled(true);
296
0
        mpView->SetCreate1stPointAsCenter(false);
297
0
        mpView->SetResizeAtCenter(false);
298
0
        mpView->SetDragWithCopy(pFrameView->IsDragWithCopy());
299
0
        mpView->SetGridSnap(pFrameView->IsGridSnap());
300
0
        mpView->SetBordSnap(pFrameView->IsBordSnap());
301
0
        mpView->SetHlplSnap(pFrameView->IsHlplSnap());
302
0
        mpView->SetOFrmSnap(pFrameView->IsOFrmSnap());
303
0
        mpView->SetOPntSnap(pFrameView->IsOPntSnap());
304
0
        mpView->SetOConSnap(pFrameView->IsOConSnap());
305
0
    }
306
307
0
    bIsInDragMode = false;
308
0
    ForcePointer(&rMEvt);
309
0
    FuPoor::MouseButtonUp(rMEvt);
310
311
0
    return false;
312
0
}
313
314
/**
315
 * Process keyboard input
316
 * @returns sal_True if a KeyEvent is being processed, sal_False otherwise
317
 */
318
bool FuDraw::KeyInput(const KeyEvent& rKEvt)
319
0
{
320
0
    bool bReturn = false;
321
0
    const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
322
323
0
    switch ( rKEvt.GetKeyCode().GetCode() )
324
0
    {
325
0
        case KEY_ESCAPE:
326
0
        {
327
0
            bReturn = FuDraw::cancel();
328
0
        }
329
0
        break;
330
331
0
        case KEY_DELETE:
332
0
        case KEY_BACKSPACE:
333
0
        {
334
0
            if (!mpDocSh->IsReadOnly())
335
0
            {
336
0
                if (mpView->IsPresObjSelected(false, true, false, true))
337
0
                {
338
0
                    std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(mpWindow->GetFrameWeld(),
339
0
                                                                  VclMessageType::Info, VclButtonsType::Ok,
340
0
                                                                  SdResId(STR_ACTION_NOTPOSSIBLE)));
341
0
                    xInfoBox->run();
342
0
                }
343
0
                else
344
0
                {
345
                    // wait-mousepointer while deleting object
346
0
                    weld::WaitObject aWait(mrViewShell.GetFrameWeld());
347
                    // delete object
348
0
                    mpView->DeleteMarked();
349
0
                }
350
0
            }
351
0
            bReturn = true;
352
0
        }
353
0
        break;
354
355
0
        case KEY_TAB:
356
0
        {
357
0
            vcl::KeyCode aCode = rKEvt.GetKeyCode();
358
359
0
            if ( !aCode.IsMod1() && !aCode.IsMod2() )
360
0
            {
361
                // Moved next line which was a bugfix itself into
362
                // the scope which really does the object selection travel
363
                // and thus is allowed to call SelectionHasChanged().
364
365
                // Switch to FuSelect.
366
0
                mrViewShell.GetViewFrame()->GetDispatcher()->Execute(
367
0
                    SID_OBJECT_SELECT,
368
0
                    SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
369
370
                // changeover to the next object
371
0
                if(!mpView->MarkNextObj( !aCode.IsShift() ))
372
0
                {
373
                    //If there is only one object, don't do the UnmarkAllObj() & MarkNextObj().
374
0
                    if ( mpView->HasMultipleMarkableObjects() && rMarkList.GetMarkCount() != 0 )
375
0
                    {
376
                        // No next object: go over open end and get first from
377
                        // the other side
378
0
                        mpView->UnmarkAllObj();
379
0
                        mpView->MarkNextObj(!aCode.IsShift());
380
0
                    }
381
0
                }
382
383
0
                if(rMarkList.GetMarkCount() != 0)
384
0
                    mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
385
386
0
                bReturn = true;
387
0
            }
388
0
        }
389
0
        break;
390
391
0
        case KEY_END:
392
0
        {
393
0
            vcl::KeyCode aCode = rKEvt.GetKeyCode();
394
395
0
            if ( aCode.IsMod1() )
396
0
            {
397
                // mark last object
398
0
                mpView->UnmarkAllObj();
399
0
                mpView->MarkNextObj();
400
401
0
                if(rMarkList.GetMarkCount() != 0)
402
0
                    mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
403
404
0
                bReturn = true;
405
0
            }
406
0
        }
407
0
        break;
408
409
0
        case KEY_HOME:
410
0
        {
411
0
            vcl::KeyCode aCode = rKEvt.GetKeyCode();
412
413
0
            if ( aCode.IsMod1() )
414
0
            {
415
                // mark first object
416
0
                mpView->UnmarkAllObj();
417
0
                mpView->MarkNextObj(true);
418
419
0
                if(rMarkList.GetMarkCount() != 0)
420
0
                    mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
421
422
0
                bReturn = true;
423
0
            }
424
0
        }
425
0
        break;
426
427
0
        default:
428
0
        break;
429
0
    }
430
431
0
    if (!bReturn)
432
0
    {
433
0
        bReturn = FuPoor::KeyInput(rKEvt);
434
0
    }
435
0
    else
436
0
    {
437
0
        mpWindow->ReleaseMouse();
438
0
    }
439
440
0
    return bReturn;
441
0
}
442
443
void FuDraw::Activate()
444
0
{
445
0
    FuPoor::Activate();
446
0
    ForcePointer();
447
0
}
448
449
/**
450
 * Toggle mouse-pointer
451
 */
452
void FuDraw::ForcePointer(const MouseEvent* pMEvt)
453
0
{
454
0
    Point aPnt;
455
0
    sal_uInt16 nModifier = 0;
456
0
    bool bLeftDown = false;
457
0
    bool bDefPointer = true;
458
459
0
    if (pMEvt)
460
0
    {
461
0
        aPnt = mpWindow->PixelToLogic(pMEvt->GetPosPixel());
462
0
        nModifier = pMEvt->GetModifier();
463
0
        bLeftDown = pMEvt->IsLeft();
464
0
    }
465
0
    else
466
0
    {
467
0
        aPnt = mpWindow->PixelToLogic(mpWindow->GetPointerPosPixel());
468
0
    }
469
470
0
    if (mpView->IsDragObj())
471
0
    {
472
0
        if (SdModule::get()->GetWaterCan() && !mpView->PickHandle(aPnt))
473
0
        {
474
            // water can mode
475
0
            bDefPointer = false;
476
0
            mpWindow->SetPointer(PointerStyle::Fill);
477
0
        }
478
0
    }
479
0
    else
480
0
    {
481
0
        SdrHdl* pHdl = mpView->PickHandle(aPnt);
482
483
0
        if (SdModule::get()->GetWaterCan() && !pHdl)
484
0
        {
485
            // water can mode
486
0
            bDefPointer = false;
487
0
            mpWindow->SetPointer(PointerStyle::Fill);
488
0
        }
489
0
        else if (!pHdl &&
490
0
                 mrViewShell.GetViewFrame()->HasChildWindow(SvxBmpMaskChildWindow::GetChildWindowId()))
491
0
        {
492
            // pipette mode
493
0
            SfxChildWindow* pWnd = mrViewShell.GetViewFrame()->GetChildWindow(SvxBmpMaskChildWindow::GetChildWindowId());
494
0
            SvxBmpMask* pMask = pWnd ? static_cast<SvxBmpMask*>(pWnd->GetWindow()) : nullptr;
495
0
            if (pMask && pMask->IsEyedropping())
496
0
            {
497
0
                bDefPointer = false;
498
0
                mpWindow->SetPointer(PointerStyle::RefHand);
499
0
            }
500
0
        }
501
0
        else if (!mpView->IsAction())
502
0
        {
503
0
            SdrObject* pObj = nullptr;
504
0
            SdrPageView* pPV = nullptr;
505
0
            SdrViewEvent aVEvt;
506
0
            SdrHitKind eHit = SdrHitKind::NONE;
507
0
            SdrDragMode eDragMode = mpView->GetDragMode();
508
509
0
            if (pMEvt)
510
0
            {
511
0
                eHit = mpView->PickAnything(*pMEvt, SdrMouseEventKind::MOVE, aVEvt);
512
0
            }
513
514
0
            if ((eDragMode == SdrDragMode::Rotate) && (eHit == SdrHitKind::MarkedObject))
515
0
            {
516
                // The goal of this request is show always the rotation arrow for 3D-objects at rotation mode
517
                // Independent of the settings at Tools->Options->Draw "Objects always moveable"
518
                // 2D-objects acquit in another way. Otherwise, the rotation of 3d-objects around any axes
519
                // wouldn't be possible per default.
520
0
                const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
521
0
                SdrObject* pObject = rMarkList.GetMark(0)->GetMarkedSdrObj();
522
0
                if (DynCastE3dObject(pObject) && (rMarkList.GetMarkCount() == 1))
523
0
                {
524
0
                    mpWindow->SetPointer(PointerStyle::Rotate);
525
0
                    bDefPointer = false;     // Otherwise it'll be called Joe's routine and the mousepointer will reconfigurate again
526
0
                }
527
0
            }
528
529
0
            if (eHit == SdrHitKind::NONE)
530
0
            {
531
                // found nothing -> look after at the masterpage
532
0
                pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER);
533
0
            }
534
0
            else if (eHit == SdrHitKind::UnmarkedObject)
535
0
            {
536
0
                pObj = aVEvt.mpObj;
537
0
            }
538
0
            else if (eHit == SdrHitKind::TextEditObj && dynamic_cast< const FuSelection *>( this ) !=  nullptr)
539
0
            {
540
0
                SdrObjKind nSdrObjKind = aVEvt.mpObj->GetObjIdentifier();
541
542
0
                if ( nSdrObjKind != SdrObjKind::Text        &&
543
0
                     nSdrObjKind != SdrObjKind::TitleText   &&
544
0
                     nSdrObjKind != SdrObjKind::OutlineText &&
545
0
                     aVEvt.mpObj->IsEmptyPresObj() )
546
0
                {
547
0
                    pObj = nullptr;
548
0
                    bDefPointer = false;
549
0
                    mpWindow->SetPointer(PointerStyle::Arrow);
550
0
                }
551
0
            }
552
553
0
            if (pObj && pMEvt && !pMEvt->IsMod2()
554
0
                && dynamic_cast<const FuSelection*>(this) != nullptr)
555
0
            {
556
                // test for ImageMap
557
0
                bDefPointer = !SetPointer(pObj, aPnt);
558
559
0
                if (bDefPointer
560
0
                    && (dynamic_cast<const SdrObjGroup*>(pObj) != nullptr
561
0
                        || DynCastE3dScene(pObj)))
562
0
                {
563
                    // take a glance into the group
564
0
                    pObj = mpView->PickObj(aPnt, mpView->getHitTolLog(), pPV,
565
0
                                           SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP);
566
0
                    if (pObj)
567
0
                        bDefPointer = !SetPointer(pObj, aPnt);
568
0
                }
569
0
            }
570
0
        }
571
0
    }
572
573
0
    if (bDefPointer)
574
0
    {
575
0
        mpWindow->SetPointer(mpView->GetPreferredPointer(
576
0
                            aPnt, mpWindow->GetOutDev(), nModifier, bLeftDown));
577
0
    }
578
0
}
579
580
/**
581
 * Set cursor to pointer when in clickable area of an ImageMap
582
 *
583
 * @return True when pointer was set
584
 */
585
bool FuDraw::SetPointer(const SdrObject* pObj, const Point& rPos)
586
0
{
587
0
    bool bImageMapInfo = SvxIMapInfo::GetIMapInfo(pObj) != nullptr;
588
589
0
    if (!bImageMapInfo)
590
0
        return false;
591
592
0
    const SdrLayerIDSet* pVisiLayer = &mpView->GetSdrPageView()->GetVisibleLayers();
593
0
    double fHitLog(mpWindow->PixelToLogic(Size(HITPIX, 0)).Width());
594
0
    ::tools::Long n2HitLog(fHitLog * 2);
595
0
    Point aHitPosR(rPos);
596
0
    Point aHitPosL(rPos);
597
0
    Point aHitPosT(rPos);
598
0
    Point aHitPosB(rPos);
599
600
0
    aHitPosR.AdjustX(n2HitLog);
601
0
    aHitPosL.AdjustX(-n2HitLog);
602
0
    aHitPosT.AdjustY(n2HitLog);
603
0
    aHitPosB.AdjustY(-n2HitLog);
604
605
0
    if (!pObj->IsClosedObj()
606
0
        || (SdrObjectPrimitiveHit(*pObj, aHitPosR, {fHitLog, fHitLog}, *mpView->GetSdrPageView(), pVisiLayer,
607
0
                                  false)
608
0
            && SdrObjectPrimitiveHit(*pObj, aHitPosL, {fHitLog, fHitLog}, *mpView->GetSdrPageView(),
609
0
                                     pVisiLayer, false)
610
0
            && SdrObjectPrimitiveHit(*pObj, aHitPosT, {fHitLog, fHitLog}, *mpView->GetSdrPageView(),
611
0
                                     pVisiLayer, false)
612
0
            && SdrObjectPrimitiveHit(*pObj, aHitPosB, {fHitLog, fHitLog}, *mpView->GetSdrPageView(),
613
0
                                     pVisiLayer, false)))
614
0
    {
615
        // hit inside the object (without margin) or open object
616
0
        if (SvxIMapInfo::GetHitIMapObject(pObj, rPos))
617
0
        {
618
0
            mpWindow->SetPointer(PointerStyle::RefHand);
619
0
            return true;
620
0
        }
621
0
    }
622
623
0
    return false;
624
0
}
625
626
/**
627
 * Response of doubleclick
628
 */
629
void FuDraw::DoubleClick(const MouseEvent& rMEvt)
630
0
{
631
0
    sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
632
633
0
    const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
634
0
    if ( rMarkList.GetMarkCount() != 0 )
635
0
    {
636
0
        if (rMarkList.GetMarkCount() == 1)
637
0
        {
638
0
            SdrMark* pMark = rMarkList.GetMark(0);
639
0
            SdrObject* pObj = pMark->GetMarkedSdrObj();
640
641
0
            SdrInventor nInv = pObj->GetObjInventor();
642
0
            SdrObjKind  nSdrObjKind = pObj->GetObjIdentifier();
643
644
0
            bool bReadOnly = mpDocSh->IsReadOnly();
645
0
            if (!bReadOnly)
646
0
            {
647
0
                SfxViewShell* pViewShell = mrViewShell.GetViewShell();
648
0
                if (pViewShell)
649
0
                {
650
0
                    bReadOnly = pViewShell->IsLokReadOnlyView();
651
0
                }
652
0
            }
653
654
0
            if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::OLE2
655
0
                && !bReadOnly)
656
0
            {
657
                // activate OLE-object
658
0
                SfxInt16Item aItem(SID_OBJECT, 0);
659
0
                mrViewShell.GetViewFrame()->
660
0
                    GetDispatcher()->ExecuteList(SID_OBJECT,
661
0
                                                 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
662
0
                                                 { &aItem });
663
0
            }
664
0
            else if (nInv == SdrInventor::Default && nSdrObjKind == SdrObjKind::Graphic
665
0
                     && pObj->IsEmptyPresObj() && !bReadOnly)
666
0
            {
667
0
                mrViewShell.GetViewFrame()->
668
0
                    GetDispatcher()->Execute( SID_INSERT_GRAPHIC,
669
0
                                              SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
670
0
            }
671
0
            else if ( ( DynCastSdrTextObj( pObj ) != nullptr || dynamic_cast< const SdrObjGroup *>( pObj ) !=  nullptr ) &&
672
0
                      !SdModule::get()->GetWaterCan() &&
673
0
                      mrViewShell.GetFrameView()->IsDoubleClickTextEdit() &&
674
0
                      !bReadOnly)
675
0
            {
676
0
                SfxUInt16Item aItem(SID_TEXTEDIT, 2);
677
0
                mrViewShell.GetViewFrame()->GetDispatcher()->ExecuteList(
678
0
                        SID_TEXTEDIT,
679
0
                        SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
680
0
                        { &aItem });
681
0
            }
682
0
            else if (nInv == SdrInventor::Default &&  nSdrObjKind == SdrObjKind::Group)
683
0
            {
684
                // hit group -> select subobject
685
0
                mpView->UnMarkAll();
686
0
                mpView->MarkObj(aMDPos, nHitLog, rMEvt.IsShift(), true);
687
0
            }
688
0
        }
689
0
    }
690
0
    else
691
0
        mrViewShell.GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
692
0
}
693
694
bool FuDraw::RequestHelp(const HelpEvent& rHEvt)
695
0
{
696
0
    bool bReturn = false;
697
698
0
    if (Help::IsBalloonHelpEnabled() || Help::IsQuickHelpEnabled())
699
0
    {
700
0
        SdrViewEvent aVEvt;
701
702
0
        MouseEvent aMEvt(mpWindow->GetPointerPosPixel(), 1, MouseEventModifiers::NONE, MOUSE_LEFT);
703
704
0
        SdrHitKind eHit = mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
705
706
0
        SdrObject* pObj = aVEvt.mpObj;
707
708
0
        if (eHit != SdrHitKind::NONE && pObj != nullptr)
709
0
        {
710
0
            Point aPosPixel = rHEvt.GetMousePosPixel();
711
712
0
            bReturn = SetHelpText(pObj, aPosPixel, aVEvt);
713
714
0
            if (!bReturn && (dynamic_cast< const SdrObjGroup *>( pObj ) != nullptr || DynCastE3dScene(pObj)))
715
0
            {
716
                // take a glance into the group
717
0
                SdrPageView* pPV = nullptr;
718
719
0
                Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(aPosPixel)));
720
721
0
                pObj = mpView->PickObj(aPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP);
722
0
                if (pObj)
723
0
                    bReturn = SetHelpText(pObj, aPosPixel, aVEvt);
724
0
            }
725
0
        }
726
0
    }
727
728
0
    if (!bReturn)
729
0
    {
730
0
        bReturn = FuPoor::RequestHelp(rHEvt);
731
0
    }
732
733
0
    if (!bReturn)
734
0
       bReturn = mpView->RequestHelp(rHEvt);
735
736
0
    return bReturn;
737
0
}
738
739
bool FuDraw::SetHelpText(const SdrObject* pObj, const Point& rPosPixel, const SdrViewEvent& rVEvt)
740
0
{
741
0
    OUString aHelpText;
742
0
    Point aPos(mpWindow->PixelToLogic(mpWindow->ScreenToOutputPixel(rPosPixel)));
743
0
    IMapObject* pIMapObj = SvxIMapInfo::GetHitIMapObject(pObj, aPos);
744
745
0
    if (!rVEvt.mpURLField && !pIMapObj)
746
0
        return false;
747
748
0
    OUString aURL;
749
0
    if (rVEvt.mpURLField)
750
0
        aURL = INetURLObject::decode(rVEvt.mpURLField->GetURL(),
751
0
                                     INetURLObject::DecodeMechanism::WithCharset);
752
0
    else if (pIMapObj)
753
0
    {
754
0
        aURL = pIMapObj->GetAltText() +
755
0
            " (" +
756
0
            INetURLObject::decode(pIMapObj->GetURL(),
757
0
                                        INetURLObject::DecodeMechanism::WithCharset) +
758
0
            ")";
759
0
    }
760
0
    else
761
0
        return false;
762
763
0
    aHelpText = SfxHelp::GetURLHelpText(aURL);
764
765
0
    if (aHelpText.isEmpty())
766
0
        return false;
767
768
0
    ::tools::Rectangle aLogicPix = mpWindow->LogicToPixel(pObj->GetLogicRect());
769
0
    ::tools::Rectangle aScreenRect(mpWindow->OutputToScreenPixel(aLogicPix.TopLeft()),
770
0
                            mpWindow->OutputToScreenPixel(aLogicPix.BottomRight()));
771
772
0
    if (Help::IsBalloonHelpEnabled())
773
0
        Help::ShowBalloon( static_cast<vcl::Window*>(mpWindow), rPosPixel, aScreenRect, aHelpText);
774
0
    else if (Help::IsQuickHelpEnabled())
775
0
        Help::ShowQuickHelp( static_cast<vcl::Window*>(mpWindow), aScreenRect, aHelpText);
776
777
0
    return true;
778
0
}
779
780
/** is called when the current function should be aborted. <p>
781
    This is used when a function gets a KEY_ESCAPE but can also
782
    be called directly.
783
784
    @returns true if an active function was aborted
785
*/
786
bool FuDraw::cancel()
787
0
{
788
0
    bool bReturn = false;
789
0
    const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
790
791
0
    if ( mpView->IsAction() )
792
0
    {
793
0
        mpView->BrkAction();
794
0
        bReturn = true;
795
0
    }
796
0
    else if ( mpView->IsTextEdit() )
797
0
    {
798
0
        mpView->SdrEndTextEdit();
799
0
        bReturn = true;
800
801
0
        SfxBindings& rBindings = mrViewShell.GetViewFrame()->GetBindings();
802
0
        rBindings.Invalidate( SID_DEC_INDENT );
803
0
        rBindings.Invalidate( SID_INC_INDENT );
804
0
        rBindings.Invalidate( SID_PARASPACE_INCREASE );
805
0
        rBindings.Invalidate( SID_PARASPACE_DECREASE );
806
0
    }
807
0
    else if ( rMarkList.GetMarkCount() != 0 )
808
0
    {
809
0
        const SdrHdlList& rHdlList = mpView->GetHdlList();
810
0
        SdrHdl* pHdl = rHdlList.GetFocusHdl();
811
812
0
        if(pHdl)
813
0
        {
814
0
            const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl();
815
0
        }
816
0
        else
817
0
        {
818
0
            mpView->UnmarkAll();
819
0
        }
820
821
        // Switch to FuSelect.
822
0
        mrViewShell.GetViewFrame()->GetDispatcher()->Execute(
823
0
            SID_OBJECT_SELECT,
824
0
            SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
825
826
0
        bReturn = true;
827
0
    }
828
829
0
    return bReturn;
830
0
}
831
832
} // end of namespace sd
833
834
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */