Coverage Report

Created: 2025-11-16 09:57

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