Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/drawfunc/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 <editeng/editeng.hxx>
21
#include <vcl/ptrstyle.hxx>
22
#include <editeng/outlobj.hxx>
23
#include <svx/svdobj.hxx>
24
#include <svx/svdoole2.hxx>
25
#include <svx/svdouno.hxx>
26
#include <svx/ImageMapInfo.hxx>
27
#include <sfx2/dispatch.hxx>
28
#include <sfx2/viewfrm.hxx>
29
#include <vcl/uitest/logger.hxx>
30
#include <vcl/uitest/eventdescription.hxx>
31
32
#include <sc.hrc>
33
#include <fudraw.hxx>
34
#include <futext.hxx>
35
#include <tabvwsh.hxx>
36
#include <drwlayer.hxx>
37
#include <userdat.hxx>
38
#include <docsh.hxx>
39
#include <drawview.hxx>
40
#include <comphelper/lok.hxx>
41
#include <com/sun/star/embed/EmbedVerbs.hpp>
42
43
namespace
44
{
45
46
void collectUIInformation( const OUString& aevent )
47
0
{
48
0
    EventDescription aDescription;
49
0
    aDescription.aID =  "grid_window";
50
0
    aDescription.aParameters = {{ aevent ,  ""}};
51
0
    aDescription.aAction = "COMMENT";
52
0
    aDescription.aParent = "MainWindow";
53
0
    aDescription.aKeyWord = "ScGridWinUIObject";
54
0
    UITestLogger::getInstance().logEvent(aDescription);
55
0
}
56
57
}
58
59
// base class for draw module specific functions
60
FuDraw::FuDraw(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
61
               SdrModel& rDoc, const SfxRequest& rReq)
62
0
    : FuPoor(rViewSh, pWin, pViewP, rDoc, rReq)
63
0
    , aNewPointer(PointerStyle::Arrow)
64
0
    , aOldPointer(PointerStyle::Arrow)
65
0
{
66
0
}
67
68
FuDraw::~FuDraw()
69
0
{
70
0
}
71
72
void FuDraw::DoModifiers(const MouseEvent& rMEvt)
73
0
{
74
    //  Shift   = Ortho and AngleSnap
75
    //  Control = Snap (Toggle)
76
    //  Alt     = centric
77
78
0
    bool bShift = rMEvt.IsShift();
79
0
    bool bAlt   = rMEvt.IsMod2();
80
81
0
    bool bOrtho     = bShift;
82
0
    bool bAngleSnap = bShift;
83
0
    bool bCenter    = bAlt;
84
85
    // #i33136#
86
0
    if(doConstructOrthogonal())
87
0
    {
88
0
        bOrtho = !bShift;
89
0
    }
90
91
0
    if (pView->IsOrtho() != bOrtho)
92
0
        pView->SetOrtho(bOrtho);
93
0
    if (pView->IsAngleSnapEnabled() != bAngleSnap)
94
0
        pView->SetAngleSnapEnabled(bAngleSnap);
95
96
0
    if (pView->IsCreate1stPointAsCenter() != bCenter)
97
0
        pView->SetCreate1stPointAsCenter(bCenter);
98
0
    if (pView->IsResizeAtCenter() != bCenter)
99
0
        pView->SetResizeAtCenter(bCenter);
100
101
0
}
102
103
void FuDraw::ResetModifiers()
104
0
{
105
0
    if (!pView)
106
0
        return;
107
108
0
    ScViewData& rViewData = rViewShell.GetViewData();
109
0
    const ScViewOptions& rOpt = rViewData.GetOptions();
110
0
    const ScGridOptions& rGrid = rOpt.GetGridOptions();
111
0
    bool bGridOpt = rGrid.GetUseGridSnap();
112
113
0
    if (pView->IsOrtho())
114
0
        pView->SetOrtho(false);
115
0
    if (pView->IsAngleSnapEnabled())
116
0
        pView->SetAngleSnapEnabled(false);
117
118
0
    if (pView->IsGridSnap() != bGridOpt)
119
0
        pView->SetGridSnap(bGridOpt);
120
0
    if (pView->IsSnapEnabled() != bGridOpt)
121
0
        pView->SetSnapEnabled(bGridOpt);
122
123
0
    if (pView->IsCreate1stPointAsCenter())
124
0
        pView->SetCreate1stPointAsCenter(false);
125
0
    if (pView->IsResizeAtCenter())
126
0
        pView->SetResizeAtCenter(false);
127
0
}
128
129
bool FuDraw::MouseButtonDown(const MouseEvent& rMEvt)
130
0
{
131
    // remember button state for creation of own MouseEvents
132
0
    SetMouseButtonCode(rMEvt.GetButtons());
133
134
0
    DoModifiers( rMEvt );
135
0
    return false;
136
0
}
137
138
bool FuDraw::MouseMove(const MouseEvent& rMEvt)
139
0
{
140
0
    if (SfxViewShell* pSfxViewShell = pView->GetSfxViewShell())
141
0
    {
142
0
        pSfxViewShell->GetDrawView()->MouseMove(rMEvt, pWindow->GetOutDev());
143
        //  evaluate modifiers only if in a drawing layer action
144
        //  (don't interfere with keyboard shortcut handling)
145
0
        if (pView->IsAction())
146
0
            DoModifiers( rMEvt );
147
0
    }
148
149
0
    return false;
150
0
}
151
152
bool FuDraw::MouseButtonUp(const MouseEvent& rMEvt)
153
0
{
154
    // remember button state for creation of own MouseEvents
155
0
    SetMouseButtonCode(rMEvt.GetButtons());
156
157
0
    ResetModifiers();
158
0
    return false;
159
0
}
160
161
// Process Keyboard events. Return true if an event is being handled
162
static bool lcl_KeyEditMode( SdrObject* pObj, ScTabViewShell& rViewShell, const KeyEvent* pInitialKey )
163
0
{
164
0
    bool bReturn = false;
165
0
    if ( DynCastSdrTextObj( pObj) != nullptr && dynamic_cast<const SdrUnoObj*>( pObj) ==  nullptr )
166
0
    {
167
0
        assert(pObj);
168
        // start text edit - like FuSelection::MouseButtonUp,
169
        // but with bCursorToEnd instead of mouse position
170
171
0
        OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
172
0
        bool bVertical = ( pOPO && pOPO->IsEffectivelyVertical() );
173
0
        sal_uInt16 nTextSlotId = bVertical ? SID_DRAW_TEXT_VERTICAL : SID_DRAW_TEXT;
174
175
        // don't switch shells if text shell is already active
176
0
        FuPoor* pPoor = rViewShell.GetViewData().GetView()->GetDrawFuncPtr();
177
0
        if ( !pPoor || pPoor->GetSlotID() != nTextSlotId )
178
0
        {
179
0
            rViewShell.GetViewData().GetDispatcher().
180
0
                Execute(nTextSlotId, SfxCallMode::SYNCHRON | SfxCallMode::RECORD);
181
0
        }
182
183
        // get the resulting FuText and set in edit mode
184
0
        pPoor = rViewShell.GetViewData().GetView()->GetDrawFuncPtr();
185
0
        if ( pPoor && pPoor->GetSlotID() == nTextSlotId )    // no RTTI
186
0
        {
187
0
            FuText* pText = static_cast<FuText*>(pPoor);
188
0
            pText->SetInEditMode( pObj, nullptr, true, pInitialKey );
189
            //! set cursor to end of text
190
0
        }
191
0
        bReturn = true;
192
0
    }
193
0
    return bReturn;
194
0
}
195
196
bool FuDraw::KeyInput(const KeyEvent& rKEvt)
197
0
{
198
0
    bool bReturn = false;
199
0
    ScViewData& rViewData = rViewShell.GetViewData();
200
201
0
    const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
202
0
    switch ( rKEvt.GetKeyCode().GetCode() )
203
0
    {
204
0
        case KEY_ESCAPE:
205
0
            if ( rViewShell.IsDrawTextShell() || aSfxRequest.GetSlot() == SID_DRAW_NOTEEDIT )
206
0
            {
207
0
                collectUIInformation(u"CLOSE"_ustr);
208
                // if object selected -> normal draw-shell, else turn off drawing
209
0
                rViewData.GetDispatcher().Execute(aSfxRequest.GetSlot(), SfxCallMode::SLOT | SfxCallMode::RECORD);
210
0
                bReturn = true;
211
0
            }
212
0
            else if ( rViewShell.IsDrawSelMode() )
213
0
            {
214
0
                pView->UnmarkAll();
215
0
                rViewData.GetDispatcher().Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD);
216
0
                bReturn = true;
217
0
            }
218
0
            else if ( rMarkList.GetMarkCount() != 0 )
219
0
            {
220
                // III
221
0
                SdrHdlList& rHdlList = const_cast< SdrHdlList& >( pView->GetHdlList() );
222
0
                if( rHdlList.GetFocusHdl() )
223
0
                    rHdlList.ResetFocusHdl();
224
0
                else
225
0
                    pView->UnmarkAll();
226
227
                //  while bezier editing, object is selected
228
0
                if (rMarkList.GetMarkCount() == 0)
229
0
                    rViewShell.SetDrawShell( false );
230
231
0
                bReturn = true;
232
0
            }
233
0
            break;
234
235
0
        case KEY_DELETE:                    //! via accelerator
236
0
            pView->DeleteMarked();
237
0
            bReturn = true;
238
0
        break;
239
240
0
        case KEY_RETURN:
241
0
        {
242
0
            if( rKEvt.GetKeyCode().GetModifier() == 0 )
243
0
            {
244
                // activate OLE object on RETURN for selected object
245
                // put selected text object in edit mode
246
0
                if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() )
247
0
                {
248
0
                    bool bOle = rViewShell.GetViewFrame().GetFrame().IsInPlace();
249
0
                    SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
250
0
                    auto pOleObj = dynamic_cast<SdrOle2Obj*>(pObj);
251
0
                    if( pOleObj && !bOle )
252
0
                    {
253
0
                        rViewShell.ActivateObject(pOleObj, css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY);
254
255
                        // consumed
256
0
                        bReturn = true;
257
0
                    }
258
0
                    else if ( lcl_KeyEditMode( pObj, rViewShell, nullptr ) )       // start text edit for suitable object
259
0
                        bReturn = true;
260
0
                }
261
0
            }
262
0
        }
263
0
        break;
264
265
0
        case KEY_F2:
266
0
        {
267
0
            if( rKEvt.GetKeyCode().GetModifier() == 0 )
268
0
            {
269
                // put selected text object in edit mode
270
                // (this is not SID_SETINPUTMODE, but F2 hardcoded, like in Writer)
271
0
                if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() )
272
0
                {
273
0
                    SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
274
0
                    if ( lcl_KeyEditMode( pObj, rViewShell, nullptr ) )            // start text edit for suitable object
275
0
                        bReturn = true;
276
0
                }
277
0
            }
278
0
        }
279
0
        break;
280
281
0
        case KEY_TAB:
282
0
        {
283
            // in calc do NOT start draw object selection using TAB/SHIFT-TAB when
284
            // there is not yet an object selected
285
0
            if(rMarkList.GetMarkCount() != 0)
286
0
            {
287
0
                vcl::KeyCode aCode = rKEvt.GetKeyCode();
288
289
0
                if ( !aCode.IsMod1() && !aCode.IsMod2() )
290
0
                {
291
                    // changeover to the next object
292
0
                    if(!pView->MarkNextObj( !aCode.IsShift() ))
293
0
                    {
294
                        //If there is only one object, don't do the UnmarkAllObj() & MarkNextObj().
295
0
                        if ( pView->HasMultipleMarkableObjects() && pView->HasMarkableObj() )
296
0
                        {
297
                            // No next object: go over open end and
298
                            // get first from the other side
299
0
                            pView->UnmarkAllObj();
300
0
                            pView->MarkNextObj(!aCode.IsShift());
301
0
                        }
302
0
                    }
303
304
                    // II
305
0
                    if(rMarkList.GetMarkCount() != 0)
306
0
                        pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
307
308
0
                    bReturn = true;
309
0
                }
310
311
                // handle Mod1 and Mod2 to get travelling running on different systems
312
0
                if(rKEvt.GetKeyCode().IsMod1() || rKEvt.GetKeyCode().IsMod2())
313
0
                {
314
                    // II do something with a selected handle?
315
0
                    const SdrHdlList& rHdlList = pView->GetHdlList();
316
0
                    bool bForward(!rKEvt.GetKeyCode().IsShift());
317
318
0
                    const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
319
320
                    // guarantee visibility of focused handle
321
0
                    SdrHdl* pHdl = rHdlList.GetFocusHdl();
322
323
0
                    if(pHdl)
324
0
                    {
325
0
                        Point aHdlPosition(pHdl->GetPos());
326
0
                        tools::Rectangle aVisRect(aHdlPosition - Point(100, 100), Size(200, 200));
327
0
                        pView->MakeVisible(aVisRect, *pWindow);
328
0
                    }
329
330
                    // consumed
331
0
                    bReturn = true;
332
0
                }
333
0
            }
334
0
        }
335
0
        break;
336
337
0
        case KEY_END:
338
0
        {
339
            // in calc do NOT select the last draw object when
340
            // there is not yet an object selected
341
0
            if(rMarkList.GetMarkCount() != 0)
342
0
            {
343
0
                vcl::KeyCode aCode = rKEvt.GetKeyCode();
344
345
0
                if ( aCode.IsMod1() )
346
0
                {
347
                    // mark last object
348
0
                    pView->UnmarkAllObj();
349
0
                    pView->MarkNextObj();
350
351
                    // II
352
0
                    if(rMarkList.GetMarkCount() != 0)
353
0
                        pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
354
355
0
                    bReturn = true;
356
0
                }
357
0
            }
358
0
        }
359
0
        break;
360
361
0
        case KEY_HOME:
362
0
        {
363
            // in calc do NOT select the first draw object when
364
            // there is not yet an object selected
365
0
            if(rMarkList.GetMarkCount() != 0)
366
0
            {
367
0
                vcl::KeyCode aCode = rKEvt.GetKeyCode();
368
369
0
                if ( aCode.IsMod1() )
370
0
                {
371
                    // mark first object
372
0
                    pView->UnmarkAllObj();
373
0
                    pView->MarkNextObj(true);
374
375
                    // II
376
0
                    if(rMarkList.GetMarkCount() != 0)
377
0
                        pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
378
379
0
                    bReturn = true;
380
0
                }
381
0
            }
382
0
        }
383
0
        break;
384
385
0
        case KEY_UP:
386
0
        case KEY_DOWN:
387
0
        case KEY_LEFT:
388
0
        case KEY_RIGHT:
389
0
        {
390
            // in calc do cursor travelling of draw objects only when
391
            // there is an object selected yet
392
0
            if(rMarkList.GetMarkCount() != 0)
393
0
            {
394
395
0
                if(rMarkList.GetMarkCount() == 1)
396
0
                {
397
                    // disable cursor travelling on note objects as the tail connector position
398
                    // must not move.
399
0
                    SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
400
0
                    if( ScDrawLayer::IsNoteCaption( pObj ) )
401
0
                        break;
402
0
                }
403
404
0
                tools::Long nX = 0;
405
0
                tools::Long nY = 0;
406
0
                sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
407
408
0
                if (nCode == KEY_UP)
409
0
                {
410
                    // scroll up
411
0
                    nX = 0;
412
0
                    nY =-1;
413
0
                }
414
0
                else if (nCode == KEY_DOWN)
415
0
                {
416
                    // scroll down
417
0
                    nX = 0;
418
0
                    nY = 1;
419
0
                }
420
0
                else if (nCode == KEY_LEFT)
421
0
                {
422
                    // scroll left
423
0
                    nX =-1;
424
0
                    nY = 0;
425
0
                }
426
0
                else if (nCode == KEY_RIGHT)
427
0
                {
428
                    // scroll right
429
0
                    nX = 1;
430
0
                    nY = 0;
431
0
                }
432
433
0
                bool bReadOnly = rViewData.GetDocShell()->IsReadOnly();
434
435
0
                if(!rKEvt.GetKeyCode().IsMod1() && !bReadOnly)
436
0
                {
437
0
                    if(rKEvt.GetKeyCode().IsMod2())
438
0
                    {
439
                        // move in 1 pixel distance
440
0
                        Size aLogicSizeOnePixel = pWindow ? pWindow->PixelToLogic(Size(1,1)) : Size(100, 100);
441
0
                        nX *= aLogicSizeOnePixel.Width();
442
0
                        nY *= aLogicSizeOnePixel.Height();
443
0
                    }
444
0
                    else if(rKEvt.GetKeyCode().IsShift()) // #i121236# Support for shift key in calc
445
0
                    {
446
0
                        nX *= 1000;
447
0
                        nY *= 1000;
448
0
                    }
449
0
                    else
450
0
                    {
451
                        // old, fixed move distance
452
0
                        nX *= 100;
453
0
                        nY *= 100;
454
0
                    }
455
456
                    // is there a movement to do?
457
0
                    if(0 != nX || 0 != nY)
458
0
                    {
459
                        // II
460
0
                        const SdrHdlList& rHdlList = pView->GetHdlList();
461
0
                        SdrHdl* pHdl = rHdlList.GetFocusHdl();
462
463
0
                        if(nullptr == pHdl)
464
0
                        {
465
                            // only take action when move is allowed
466
0
                            if(pView->IsMoveAllowed())
467
0
                            {
468
                                // restrict movement to WorkArea
469
0
                                const tools::Rectangle& rWorkArea = pView->GetWorkArea();
470
471
0
                                if(!rWorkArea.IsEmpty())
472
0
                                {
473
0
                                    tools::Rectangle aMarkRect(pView->GetMarkedObjRect());
474
0
                                    aMarkRect.Move(nX, nY);
475
476
0
                                    if(!aMarkRect.Contains(rWorkArea))
477
0
                                    {
478
0
                                        if(aMarkRect.Left() < rWorkArea.Left())
479
0
                                        {
480
0
                                            nX += rWorkArea.Left() - aMarkRect.Left();
481
0
                                        }
482
483
0
                                        if(aMarkRect.Right() > rWorkArea.Right())
484
0
                                        {
485
0
                                            nX -= aMarkRect.Right() - rWorkArea.Right();
486
0
                                        }
487
488
0
                                        if(aMarkRect.Top() < rWorkArea.Top())
489
0
                                        {
490
0
                                            nY += rWorkArea.Top() - aMarkRect.Top();
491
0
                                        }
492
493
0
                                        if(aMarkRect.Bottom() > rWorkArea.Bottom())
494
0
                                        {
495
0
                                            nY -= aMarkRect.Bottom() - rWorkArea.Bottom();
496
0
                                        }
497
0
                                    }
498
0
                                }
499
500
                                // now move the selected draw objects
501
0
                                pView->MoveAllMarked(Size(nX, nY));
502
503
                                // II
504
0
                                pView->MakeVisible(pView->GetAllMarkedRect(), *pWindow);
505
506
0
                                bReturn = true;
507
0
                            }
508
0
                        }
509
0
                        else
510
0
                        {
511
                            // move handle with index nHandleIndex
512
0
                            if (nX || nY)
513
0
                            {
514
                                // now move the Handle (nX, nY)
515
0
                                Point aStartPoint(pHdl->GetPos());
516
0
                                Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
517
0
                                const SdrDragStat& rDragStat = pView->GetDragStat();
518
519
                                // start dragging
520
0
                                pView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
521
522
0
                                if(pView->IsDragObj())
523
0
                                {
524
0
                                    bool bWasNoSnap = rDragStat.IsNoSnap();
525
0
                                    bool bWasSnapEnabled = pView->IsSnapEnabled();
526
527
                                    // switch snapping off
528
0
                                    if(!bWasNoSnap)
529
0
                                        const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
530
0
                                    if(bWasSnapEnabled)
531
0
                                        pView->SetSnapEnabled(false);
532
533
0
                                    pView->MovAction(aEndPoint);
534
0
                                    pView->EndDragObj();
535
536
                                    // restore snap
537
0
                                    if(!bWasNoSnap)
538
0
                                        const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
539
0
                                    if(bWasSnapEnabled)
540
0
                                        pView->SetSnapEnabled(bWasSnapEnabled);
541
0
                                }
542
543
                                // make moved handle visible
544
0
                                tools::Rectangle aVisRect(aEndPoint - Point(100, 100), Size(200, 200));
545
0
                                pView->MakeVisible(aVisRect, *pWindow);
546
547
0
                                bReturn = true;
548
0
                            }
549
0
                        }
550
0
                    }
551
0
                }
552
0
            }
553
0
        }
554
0
        break;
555
556
0
        case KEY_SPACE:
557
0
        {
558
            // in calc do only something when draw objects are selected
559
0
            if(rMarkList.GetMarkCount() != 0)
560
0
            {
561
0
                const SdrHdlList& rHdlList = pView->GetHdlList();
562
0
                SdrHdl* pHdl = rHdlList.GetFocusHdl();
563
564
0
                if(pHdl)
565
0
                {
566
0
                    if(pHdl->GetKind() == SdrHdlKind::Poly)
567
0
                    {
568
                        // rescue ID of point with focus
569
0
                        sal_uInt32 nPol(pHdl->GetPolyNum());
570
0
                        sal_uInt32 nPnt(pHdl->GetPointNum());
571
572
0
                        if(pView->IsPointMarked(*pHdl))
573
0
                        {
574
0
                            if(rKEvt.GetKeyCode().IsShift())
575
0
                            {
576
0
                                pView->UnmarkPoint(*pHdl);
577
0
                            }
578
0
                        }
579
0
                        else
580
0
                        {
581
0
                            if(!rKEvt.GetKeyCode().IsShift())
582
0
                            {
583
0
                                pView->UnmarkAllPoints();
584
0
                            }
585
586
0
                            pView->MarkPoint(*pHdl);
587
0
                        }
588
589
0
                        if(nullptr == rHdlList.GetFocusHdl())
590
0
                        {
591
                            // restore point with focus
592
0
                            SdrHdl* pNewOne = nullptr;
593
594
0
                            for(size_t a = 0; !pNewOne && a < rHdlList.GetHdlCount(); ++a)
595
0
                            {
596
0
                                SdrHdl* pAct = rHdlList.GetHdl(a);
597
598
0
                                if(pAct
599
0
                                    && pAct->GetKind() == SdrHdlKind::Poly
600
0
                                    && pAct->GetPolyNum() == nPol
601
0
                                    && pAct->GetPointNum() == nPnt)
602
0
                                {
603
0
                                    pNewOne = pAct;
604
0
                                }
605
0
                            }
606
607
0
                            if(pNewOne)
608
0
                            {
609
0
                                const_cast<SdrHdlList&>(rHdlList).SetFocusHdl(pNewOne);
610
0
                            }
611
0
                        }
612
613
0
                        bReturn = true;
614
0
                    }
615
0
                }
616
0
            }
617
0
        }
618
0
        break;
619
0
    }
620
621
0
    if (!bReturn)
622
0
    {
623
0
        bReturn = FuPoor::KeyInput(rKEvt);
624
0
    }
625
626
0
    if (!bReturn)
627
0
    {
628
        // allow direct typing into a selected text object
629
630
0
        if( !pView->IsTextEdit() && 1 == rMarkList.GetMarkCount() && EditEngine::IsSimpleCharInput(rKEvt) )
631
0
        {
632
0
            SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
633
634
0
            if (nullptr != pObj && pObj->isDiagram())
635
0
            {
636
0
                SdrObject* pSubSelection(pObj->getDiagramSubSelection());
637
0
                if (nullptr != pSubSelection && pSubSelection->isDiagramTextNode())
638
0
                    pObj = pSubSelection;
639
0
            }
640
641
            // start text edit for suitable object, pass key event to OutlinerView
642
0
            if ( lcl_KeyEditMode( pObj, rViewShell, &rKEvt ) )
643
0
                bReturn = true;
644
0
        }
645
0
    }
646
647
0
    return bReturn;
648
0
}
649
650
// toggle mouse-pointer
651
static bool lcl_UrlHit( const SdrView* pView, const Point& rPosPixel, const vcl::Window* pWindow )
652
0
{
653
0
    SdrViewEvent aVEvt;
654
0
    MouseEvent aMEvt( rPosPixel, 1, MouseEventModifiers::NONE, MOUSE_LEFT );
655
0
    SdrHitKind eHit = pView->PickAnything( aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt );
656
657
0
    if (eHit != SdrHitKind::NONE && aVEvt.mpObj != nullptr)
658
0
    {
659
0
        if ( SvxIMapInfo::GetIMapInfo(aVEvt.mpObj) && SvxIMapInfo::GetHitIMapObject(
660
0
                                aVEvt.mpObj, pWindow->PixelToLogic(rPosPixel), pWindow->GetOutDev() ) )
661
0
            return true;
662
663
0
        if (aVEvt.meEvent == SdrEventKind::ExecuteUrl)
664
0
            return true;
665
0
    }
666
667
0
    return false;
668
0
}
669
670
void FuDraw::ForcePointer(const MouseEvent* pMEvt)
671
0
{
672
0
    if ( pView->IsAction() )
673
0
        return;
674
675
0
    Point aPosPixel = pWindow->GetPointerPosPixel();
676
0
    bool bAlt       = pMEvt && pMEvt->IsMod2();
677
0
    Point aPnt      = pWindow->PixelToLogic( aPosPixel );
678
0
    SdrHdl* pHdl    = pView->PickHandle(aPnt);
679
0
    SdrPageView* pPV;
680
0
    SdrObject* pMacroPickObj;
681
682
0
    ScMacroInfo* pInfo = nullptr;
683
0
    SdrObject* pObj = pView->PickObj(aPnt, pView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER);
684
0
    if (pObj)
685
0
    {
686
0
        if ( pObj->IsGroupObject() )
687
0
        {
688
0
            SdrObject* pHit = pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::DEEP);
689
0
            if (pHit)
690
0
                pObj = pHit;
691
0
        }
692
0
        pInfo = ScDrawLayer::GetMacroInfo( pObj );
693
0
    }
694
695
0
    if ( pView->IsTextEdit() )
696
0
    {
697
0
        rViewShell.SetActivePointer(PointerStyle::Text);        // can't be ?
698
0
    }
699
0
    else if ( pHdl )
700
0
    {
701
0
        rViewShell.SetActivePointer(
702
0
            pView->GetPreferredPointer( aPnt, pWindow->GetOutDev() ) );
703
0
    }
704
0
    else if ( pView->IsMarkedHit(aPnt) )
705
0
    {
706
0
        rViewShell.SetActivePointer( PointerStyle::Move );
707
0
    }
708
0
    else if ( !bAlt && ( !pMEvt || !pMEvt->GetButtons() )
709
0
                    && lcl_UrlHit( pView, aPosPixel, pWindow ) )
710
0
    {
711
        //  could be suppressed with ALT
712
0
        pWindow->SetPointer( PointerStyle::RefHand );          // Text-URL / ImageMap
713
0
    }
714
0
    else if ( !bAlt && (pMacroPickObj = pView->PickObj(aPnt, pView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO)) )
715
0
    {
716
        //  could be suppressed with ALT
717
0
        SdrObjMacroHitRec aHitRec;  //! something missing ????
718
0
        rViewShell.SetActivePointer(pMacroPickObj->GetMacroPointer(aHitRec));
719
0
    }
720
0
    else if ( !bAlt && pInfo && (!pInfo->GetMacro().isEmpty() || !pObj->getHyperlink().isEmpty()) )
721
0
        pWindow->SetPointer( PointerStyle::RefHand );
722
0
    else if ( IsDetectiveHit( aPnt ) )
723
0
        rViewShell.SetActivePointer( PointerStyle::Detective );
724
0
    else
725
0
    {
726
0
        const bool bIsThemed = rViewShell.GetViewData().IsThemedCursor();
727
0
        rViewShell.SetActivePointer( bIsThemed ? PointerStyle::FatCross : PointerStyle::Arrow ); //! in Gridwin?
728
0
    }
729
0
}
730
731
bool FuDraw::IsEditingANote() const
732
0
{
733
0
    const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
734
0
    const size_t backval=rMarkList.GetMarkCount();
735
0
    for (size_t nlv1=0; nlv1<backval; ++nlv1)
736
0
    {
737
0
        SdrObject* pObj = rMarkList.GetMark( nlv1 )->GetMarkedSdrObj();
738
0
        if ( ScDrawLayer::IsNoteCaption( pObj ) )
739
0
        {
740
0
            return true;
741
0
        }
742
0
    }
743
0
    return false;
744
0
}
745
746
bool FuDraw::IsSizingOrMovingNote( const MouseEvent& rMEvt ) const
747
0
{
748
0
    bool bIsSizingOrMoving = false;
749
0
    if ( rMEvt.IsLeft() )
750
0
    {
751
0
        const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
752
0
        if(rMarkList.GetMarkCount() == 1)
753
0
        {
754
0
            SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
755
0
            if ( ScDrawLayer::IsNoteCaption( pObj ) )
756
0
            {
757
0
                Point aMPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() );
758
0
                bIsSizingOrMoving =
759
0
                    pView->PickHandle( aMPos ) ||      // handles to resize the note
760
0
                    pView->IsTextEditFrameHit( aMPos );         // frame for moving the note
761
0
            }
762
0
        }
763
0
    }
764
0
    return bIsSizingOrMoving;
765
0
}
766
767
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */