Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/func/fupoor.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 <fupoor.hxx>
21
22
#include <svx/svxids.hrc>
23
#include <svx/svdpagv.hxx>
24
#include <svx/svdoole2.hxx>
25
#include <svx/svdograf.hxx>
26
#include <vcl/seleng.hxx>
27
#include <sfx2/dispatch.hxx>
28
#include <sfx2/bindings.hxx>
29
#include <sfx2/request.hxx>
30
#include <svl/stritem.hxx>
31
32
#include <app.hrc>
33
#include <fusel.hxx>
34
#include <sdpage.hxx>
35
#include <DrawViewShell.hxx>
36
#include <Window.hxx>
37
#include <drawdoc.hxx>
38
#include <DrawDocShell.hxx>
39
#include <zoomlist.hxx>
40
#include <slideshow.hxx>
41
#include <LayerTabBar.hxx>
42
43
#include <com/sun/star/embed/EmbedVerbs.hpp>
44
45
#include <sfx2/viewfrm.hxx>
46
47
#include <svx/svditer.hxx>
48
49
#include <editeng/editeng.hxx>
50
51
using namespace ::com::sun::star;
52
53
namespace sd {
54
55
56
FuPoor::FuPoor (
57
    ViewShell& rViewSh,
58
    ::sd::Window* pWin,
59
    ::sd::View* pView,
60
    SdDrawDocument& rDrDoc,
61
    SfxRequest& rReq)
62
0
    : mpView(pView),
63
0
      mrViewShell(rViewSh),
64
0
      mpWindow(pWin),
65
0
      mpDocSh( rDrDoc.GetDocSh() ),
66
0
      mrDoc(rDrDoc),
67
0
      nSlotId( rReq.GetSlot() ),
68
0
      aScrollTimer("sd FuPoor aScrollTimer"),
69
0
      aDragTimer("sd FuPoor aDragTimer"),
70
0
      bIsInDragMode(false),
71
0
      bNoScrollUntilInside (true),
72
0
      aDelayToScrollTimer("sd FuPoor aDelayToScrollTimer"),
73
0
      bScrollable (false),
74
0
      bDelayActive (false),
75
0
      bFirstMouseMove (false),
76
      // remember MouseButton state
77
0
      mnCode(0)
78
0
{
79
0
    ReceiveRequest(rReq);
80
81
0
    aScrollTimer.SetInvokeHandler( LINK(this, FuPoor, ScrollHdl) );
82
0
    aScrollTimer.SetTimeout(SELENG_AUTOREPEAT_INTERVAL);
83
84
0
    aDragTimer.SetInvokeHandler( LINK(this, FuPoor, DragHdl) );
85
0
    aDragTimer.SetTimeout(SELENG_DRAGDROP_TIMEOUT);
86
87
0
    aDelayToScrollTimer.SetInvokeHandler( LINK(this, FuPoor, DelayHdl) );
88
0
    aDelayToScrollTimer.SetTimeout(2000);
89
0
}
90
91
FuPoor::~FuPoor()
92
0
{
93
0
    aDragTimer.Stop();
94
0
    aScrollTimer.Stop();
95
0
    aDelayToScrollTimer.Stop();
96
0
}
97
98
void FuPoor::Activate()
99
0
{
100
0
}
101
102
void FuPoor::Deactivate()
103
0
{
104
0
    aDragTimer.Stop();
105
0
    aScrollTimer.Stop();
106
0
    aDelayToScrollTimer.Stop ();
107
0
    bScrollable = bDelayActive = false;
108
109
0
    if (mpWindow && mpWindow->IsMouseCaptured())
110
0
        mpWindow->ReleaseMouse();
111
0
}
112
113
void FuPoor::SetWindow(::sd::Window* pWin)
114
0
{
115
0
    mpWindow = pWin;
116
0
}
117
118
/**
119
 * scroll when approached the border of the window; is called by MouseMove
120
 */
121
void FuPoor::ForceScroll(const Point& aPixPos)
122
0
{
123
0
    aScrollTimer.Stop();
124
125
0
    if ( mpView->IsDragHelpLine() || mpView->IsSetPageOrg() ||
126
0
         (SlideShow::IsRunning( mrViewShell.GetViewShellBase() )
127
0
            && !SlideShow::IsInteractiveSlideshow( mrViewShell.GetViewShellBase() )) ) // IASS
128
0
        return;
129
130
0
    Point aPos = mpWindow->OutputToScreenPixel(aPixPos);
131
0
    const ::tools::Rectangle& rRect = mrViewShell.GetAllWindowRect();
132
133
0
    if ( bNoScrollUntilInside )
134
0
    {
135
0
        if ( rRect.Contains(aPos) )
136
0
            bNoScrollUntilInside = false;
137
0
    }
138
0
    else
139
0
    {
140
0
        short dx = 0, dy = 0;
141
142
0
        if ( aPos.X() <= rRect.Left()   ) dx = -1;
143
0
        if ( aPos.X() >= rRect.Right()  ) dx =  1;
144
0
        if ( aPos.Y() <= rRect.Top()    ) dy = -1;
145
0
        if ( aPos.Y() >= rRect.Bottom() ) dy =  1;
146
147
0
        if ( dx != 0 || dy != 0 )
148
0
        {
149
0
            if (bScrollable)
150
0
            {
151
                // scroll action in derived class
152
0
                mrViewShell.ScrollLines(dx, dy);
153
0
                aScrollTimer.Start();
154
0
            }
155
0
            else if (! bDelayActive) StartDelayToScrollTimer ();
156
0
        }
157
0
    }
158
0
}
159
160
/**
161
 * timer handler for window scrolling
162
 */
163
IMPL_LINK_NOARG(FuPoor, ScrollHdl, Timer *, void)
164
0
{
165
0
    Point aPnt(mpWindow->GetPointerPosPixel());
166
167
    // use remembered MouseButton state to create correct
168
    // MouseEvents for this artificial MouseMove.
169
0
    MouseMove(MouseEvent(aPnt, 1, MouseEventModifiers::NONE, GetMouseButtonCode()));
170
0
}
171
172
/**
173
 * handle keyboard events
174
 * @returns sal_True if the event was handled, sal_False otherwise
175
 */
176
bool FuPoor::KeyInput(const KeyEvent& rKEvt)
177
0
{
178
0
    sal_uInt16          nCode = rKEvt.GetKeyCode().GetCode();
179
0
    bool            bReturn = false;
180
0
    bool bSlideShow = SlideShow::IsRunning( mrViewShell.GetViewShellBase() )
181
0
        && !SlideShow::IsInteractiveSlideshow( mrViewShell.GetViewShellBase() ); // IASS
182
183
0
    switch (nCode)
184
0
    {
185
0
        case KEY_RETURN:
186
0
        {
187
0
            if(rKEvt.GetKeyCode().IsMod1())
188
0
            {
189
0
                if( auto pDrawViewShell = dynamic_cast<DrawViewShell *>( &mrViewShell ))
190
0
                {
191
0
                    SdPage* pActualPage = pDrawViewShell->GetActualPage();
192
0
                    SdrTextObj* pCandidate = nullptr;
193
194
0
                    if(pActualPage)
195
0
                    {
196
0
                        SdrObjListIter aIter(pActualPage, SdrIterMode::DeepNoGroups);
197
198
0
                        while(aIter.IsMore() && !pCandidate)
199
0
                        {
200
0
                            SdrObject* pObj = aIter.Next();
201
202
0
                            if(auto pTextObj = DynCastSdrTextObj( pObj ))
203
0
                            {
204
0
                                SdrInventor nInv(pObj->GetObjInventor());
205
0
                                SdrObjKind nKnd(pObj->GetObjIdentifier());
206
207
0
                                if(SdrInventor::Default == nInv &&
208
0
                                    (SdrObjKind::TitleText == nKnd || SdrObjKind::OutlineText == nKnd || SdrObjKind::Text == nKnd))
209
0
                                {
210
0
                                    pCandidate = pTextObj;
211
0
                                }
212
0
                            }
213
0
                        }
214
0
                    }
215
216
0
                    if(pCandidate)
217
0
                    {
218
0
                        mpView->UnMarkAll();
219
0
                        mpView->MarkObj(pCandidate, mpView->GetSdrPageView());
220
221
0
                        mrViewShell.GetViewFrame()->GetDispatcher()->Execute(
222
0
                            SID_ATTR_CHAR, SfxCallMode::ASYNCHRON);
223
0
                    }
224
0
                    else
225
0
                    {
226
                        // insert a new page with the same page layout
227
0
                        mrViewShell.GetViewFrame()->GetDispatcher()->Execute(
228
0
                            SID_INSERTPAGE_QUICK, SfxCallMode::ASYNCHRON);
229
0
                    }
230
231
                    // consumed
232
0
                    bReturn = true;
233
0
                }
234
0
            }
235
0
            else if (!mpDocSh->IsReadOnly())
236
0
            {
237
                // activate OLE object on RETURN for selected object
238
                // activate text edit on RETURN for selected object
239
0
                const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
240
241
0
                if( !mpView->IsTextEdit() && 1 == rMarkList.GetMarkCount() )
242
0
                {
243
0
                    SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
244
245
0
                    if( dynamic_cast< const SdrOle2Obj* >( pObj ) && !mpDocSh->IsUIActive() )
246
0
                    {
247
                        //HMHmpView->HideMarkHdl();
248
0
                        mrViewShell.ActivateObject(static_cast<SdrOle2Obj*>(pObj), css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY);
249
0
                    }
250
0
                    else if( pObj && pObj->IsEmptyPresObj() && dynamic_cast< const SdrGrafObj *>( pObj ) !=  nullptr )
251
0
                    {
252
0
                        mrViewShell.GetViewFrame()->GetDispatcher()->Execute( SID_INSERT_GRAPHIC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
253
0
                    }
254
0
                    else
255
0
                    {
256
0
                        mrViewShell.GetViewFrame()->GetDispatcher()->Execute( SID_ATTR_CHAR, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
257
0
                    }
258
259
                    // consumed
260
0
                    bReturn = true;
261
0
                }
262
0
            }
263
0
        }
264
0
        break;
265
266
0
        case KEY_TAB:
267
0
        {
268
            // handle Mod1 and Mod2 to get travelling running on different systems
269
0
            if(rKEvt.GetKeyCode().IsMod1() || rKEvt.GetKeyCode().IsMod2())
270
0
            {
271
                // do something with a selected handle?
272
0
                const SdrHdlList& rHdlList = mpView->GetHdlList();
273
0
                bool bForward(!rKEvt.GetKeyCode().IsShift());
274
275
0
                const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
276
277
                // guarantee visibility of focused handle
278
0
                SdrHdl* pHdl = rHdlList.GetFocusHdl();
279
280
0
                if(pHdl)
281
0
                {
282
0
                    Point aHdlPosition(pHdl->GetPos());
283
0
                    ::tools::Rectangle aVisRect(aHdlPosition - Point(100, 100), Size(200, 200));
284
0
                    mpView->MakeVisible(aVisRect, *mpWindow);
285
0
                }
286
287
                // consumed
288
0
                bReturn = true;
289
0
            }
290
0
        }
291
0
        break;
292
293
0
        case KEY_ESCAPE:
294
0
        {
295
0
            bReturn = FuPoor::cancel();
296
0
        }
297
0
        break;
298
299
0
        case KEY_ADD:
300
0
        {
301
0
            if (!mpView->IsTextEdit() && !bSlideShow && !mpDocSh->IsUIActive())
302
0
            {
303
                // increase zoom
304
0
                mrViewShell.SetZoom(mpWindow->GetZoom() * 3 / 2);
305
306
0
                if( auto pViewShell = dynamic_cast<DrawViewShell *>( &mrViewShell ))
307
0
                    pViewShell->SetZoomOnPage(false);
308
309
0
                bReturn = true;
310
0
            }
311
0
        }
312
0
        break;
313
314
0
        case KEY_SUBTRACT:
315
0
        {
316
0
            if (!mpView->IsTextEdit() && !bSlideShow && !mpDocSh->IsUIActive())
317
0
            {
318
                // decrease zoom
319
0
                mrViewShell.SetZoom(mpWindow->GetZoom() * 2 / 3);
320
321
0
                if( auto pViewShell = dynamic_cast<DrawViewShell *>( &mrViewShell ))
322
0
                    pViewShell->SetZoomOnPage(false);
323
324
0
                bReturn = true;
325
0
            }
326
0
        }
327
0
        break;
328
329
0
        case KEY_MULTIPLY:
330
0
        {
331
0
            if (!mpView->IsTextEdit() && !bSlideShow)
332
0
            {
333
                // zoom to page
334
0
                mrViewShell.GetViewFrame()->GetDispatcher()->
335
0
                Execute(SID_SIZE_PAGE, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
336
0
                bReturn = true;
337
0
            }
338
0
        }
339
0
        break;
340
341
0
        case KEY_DIVIDE:
342
0
        {
343
0
            if (!mpView->IsTextEdit() && !bSlideShow)
344
0
            {
345
                // zoom to selected objects
346
0
                mrViewShell.GetViewFrame()->GetDispatcher()->
347
0
                Execute(SID_SIZE_OPTIMAL, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
348
0
                bReturn = true;
349
0
            }
350
0
        }
351
0
        break;
352
353
0
        case KEY_POINT:
354
0
        {
355
0
            ZoomList* pZoomList = mrViewShell.GetZoomList();
356
357
0
            if (!mpView->IsTextEdit() && pZoomList->IsNextPossible() && !bSlideShow && !mpDocSh->IsUIActive())
358
0
            {
359
                // use next ZoomRect
360
0
                mrViewShell.SetZoomRect(pZoomList->GetNextZoomRect());
361
0
                bReturn = true;
362
0
            }
363
0
        }
364
0
        break;
365
366
0
        case KEY_COMMA:
367
0
        {
368
0
            ZoomList* pZoomList = mrViewShell.GetZoomList();
369
370
0
            if (!mpView->IsTextEdit() && pZoomList->IsPreviousPossible() && !bSlideShow && !mpDocSh->IsUIActive())
371
0
            {
372
                // use previous ZoomRect
373
0
                mrViewShell.SetZoomRect(pZoomList->GetPreviousZoomRect());
374
0
                bReturn = true;
375
0
            }
376
0
        }
377
0
        break;
378
379
0
        case KEY_HOME:
380
0
        {
381
0
            if (!mpView->IsTextEdit() && !bSlideShow)
382
0
                if (auto pDrawViewShell = dynamic_cast<DrawViewShell *>( &mrViewShell ))
383
0
                {
384
                   // jump to first page
385
0
                   pDrawViewShell->SwitchPage(0);
386
0
                   bReturn = true;
387
0
                }
388
0
        }
389
0
        break;
390
391
0
        case KEY_END:
392
0
        {
393
0
            if (!mpView->IsTextEdit() && !bSlideShow)
394
0
                if (auto pDrawViewShell = dynamic_cast<DrawViewShell *>( &mrViewShell ))
395
0
                {
396
                    // jump to last page
397
0
                    SdPage* pPage = pDrawViewShell->GetActualPage();
398
0
                    pDrawViewShell->SwitchPage(mrDoc.GetSdPageCount(
399
0
                            pPage->GetPageKind()) - 1);
400
0
                    bReturn = true;
401
0
                }
402
0
        }
403
0
        break;
404
405
0
        case KEY_PAGEUP:
406
0
        {
407
0
            if( rKEvt.GetKeyCode().IsMod1() && rKEvt.GetKeyCode().IsMod2() )
408
0
                break;
409
0
            if( bSlideShow)
410
0
                break;
411
412
0
            if( auto pDrawViewShell = dynamic_cast<DrawViewShell *>( &mrViewShell ) )
413
0
            {
414
                // The page-up key switches layers or pages depending on the
415
                // modifier key.
416
0
                if ( ! rKEvt.GetKeyCode().GetModifier())
417
0
                {
418
                    // With no modifier pressed we move to the previous
419
                    // slide.
420
0
                    mpView->SdrEndTextEdit();
421
422
                    // Previous page.
423
0
                    bReturn = true;
424
0
                    SdPage* pPage = pDrawViewShell->GetActualPage();
425
0
                    sal_uInt16 nSdPage = (pPage->GetPageNum() - 1) / 2;
426
427
0
                    if (nSdPage > 0)
428
0
                    {
429
                        // Switch the page and send events regarding
430
                        // deactivation the old page and activating the new
431
                        // one.
432
0
                        TabControl& rPageTabControl =
433
0
                            pDrawViewShell->GetPageTabControl();
434
0
                        if (rPageTabControl.IsReallyShown())
435
0
                            rPageTabControl.SendDeactivatePageEvent ();
436
0
                        pDrawViewShell->SwitchPage(nSdPage - 1);
437
0
                        if (rPageTabControl.IsReallyShown())
438
0
                            rPageTabControl.SendActivatePageEvent ();
439
0
                    }
440
0
                }
441
0
                else if (rKEvt.GetKeyCode().IsMod1())
442
0
                {
443
                    // With the CONTROL modifier we switch layers.
444
0
                    if (pDrawViewShell->IsLayerModeActive())
445
0
                    {
446
                        // Moves to the previous layer.
447
0
                        SwitchLayer (-1);
448
0
                    }
449
0
                }
450
0
            }
451
0
        }
452
0
        break;
453
454
0
        case KEY_PAGEDOWN:
455
0
        {
456
0
            if( rKEvt.GetKeyCode().IsMod1() && rKEvt.GetKeyCode().IsMod2() )
457
0
                break;
458
0
            if(dynamic_cast< const DrawViewShell *>( &mrViewShell ) !=  nullptr && !bSlideShow)
459
0
            {
460
                // The page-down key switches layers or pages depending on the
461
                // modifier key.
462
0
                if ( ! rKEvt.GetKeyCode().GetModifier())
463
0
                {
464
                    // With no modifier pressed we move to the next slide.
465
0
                    mpView->SdrEndTextEdit();
466
467
                    // Next page.
468
0
                    bReturn = true;
469
0
                    SdPage* pPage = static_cast<DrawViewShell*>(&mrViewShell)->GetActualPage();
470
0
                    sal_uInt16 nSdPage = (pPage->GetPageNum() - 1) / 2;
471
472
0
                    if (nSdPage < mrDoc.GetSdPageCount(pPage->GetPageKind()) - 1)
473
0
                    {
474
                        // Switch the page and send events regarding
475
                        // deactivation the old page and activating the new
476
                        // one.
477
0
                        TabControl& rPageTabControl =
478
0
                            static_cast<DrawViewShell*>(&mrViewShell)->GetPageTabControl();
479
0
                        if (rPageTabControl.IsReallyShown())
480
0
                            rPageTabControl.SendDeactivatePageEvent ();
481
0
                        static_cast<DrawViewShell*>(&mrViewShell)->SwitchPage(nSdPage + 1);
482
0
                        if (rPageTabControl.IsReallyShown())
483
0
                            rPageTabControl.SendActivatePageEvent ();
484
0
                    }
485
0
                }
486
0
                else if (rKEvt.GetKeyCode().IsMod1())
487
0
                {
488
                    // With the CONTROL modifier we switch layers.
489
0
                    if (static_cast<DrawViewShell*>(&mrViewShell)->IsLayerModeActive())
490
0
                    {
491
                        // With the layer mode active pressing page-down
492
                        // moves to the next layer.
493
0
                        SwitchLayer (+1);
494
0
                    }
495
0
                }
496
0
            }
497
0
        }
498
0
        break;
499
500
        // change select state when focus is on poly point
501
0
        case KEY_SPACE:
502
0
        {
503
0
            const SdrHdlList& rHdlList = mpView->GetHdlList();
504
0
            SdrHdl* pHdl = rHdlList.GetFocusHdl();
505
506
0
            if(pHdl)
507
0
            {
508
0
                if(pHdl->GetKind() == SdrHdlKind::Poly)
509
0
                {
510
                    // rescue ID of point with focus
511
0
                    sal_uInt32 nPol(pHdl->GetPolyNum());
512
0
                    sal_uInt32 nPnt(pHdl->GetPointNum());
513
514
0
                    if(mpView->IsPointMarked(*pHdl))
515
0
                    {
516
0
                        if(rKEvt.GetKeyCode().IsShift())
517
0
                        {
518
0
                            mpView->UnmarkPoint(*pHdl);
519
0
                        }
520
0
                    }
521
0
                    else
522
0
                    {
523
0
                        if(!rKEvt.GetKeyCode().IsShift())
524
0
                        {
525
0
                            mpView->UnmarkAllPoints();
526
0
                        }
527
528
0
                        mpView->MarkPoint(*pHdl);
529
0
                    }
530
531
0
                    if(nullptr == rHdlList.GetFocusHdl())
532
0
                    {
533
                        // restore point with focus
534
0
                        SdrHdl* pNewOne = nullptr;
535
536
0
                        for(size_t a = 0; !pNewOne && a < rHdlList.GetHdlCount(); ++a)
537
0
                        {
538
0
                            SdrHdl* pAct = rHdlList.GetHdl(a);
539
540
0
                            if(pAct
541
0
                                && pAct->GetKind() == SdrHdlKind::Poly
542
0
                                && pAct->GetPolyNum() == nPol
543
0
                                && pAct->GetPointNum() == nPnt)
544
0
                            {
545
0
                                pNewOne = pAct;
546
0
                            }
547
0
                        }
548
549
0
                        if(pNewOne)
550
0
                        {
551
0
                            const_cast<SdrHdlList&>(rHdlList).SetFocusHdl(pNewOne);
552
0
                        }
553
0
                    }
554
555
0
                    bReturn = true;
556
0
                }
557
0
            }
558
0
        }
559
0
        break;
560
561
0
        case KEY_UP:
562
0
        case KEY_DOWN:
563
0
        case KEY_LEFT:
564
0
        case KEY_RIGHT:
565
0
        {
566
0
            if (!mpView->IsTextEdit() && !bSlideShow)
567
0
            {
568
0
                ::tools::Long nX = 0;
569
0
                ::tools::Long nY = 0;
570
571
0
                if (nCode == KEY_UP)
572
0
                {
573
                    // scroll up
574
0
                    nX = 0;
575
0
                    nY =-1;
576
0
                }
577
0
                else if (nCode == KEY_DOWN)
578
0
                {
579
                    // scroll down
580
0
                    nX = 0;
581
0
                    nY = 1;
582
0
                }
583
0
                else if (nCode == KEY_LEFT)
584
0
                {
585
                    // scroll left
586
0
                    nX =-1;
587
0
                    nY = 0;
588
0
                }
589
0
                else if (nCode == KEY_RIGHT)
590
0
                {
591
                    // scroll right
592
0
                    nX = 1;
593
0
                    nY = 0;
594
0
                }
595
596
0
                const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
597
0
                if (rMarkList.GetMarkCount() != 0 && !rKEvt.GetKeyCode().IsMod1() &&
598
0
                    !mpDocSh->IsReadOnly())
599
0
                {
600
0
                    const SdrHdlList& rHdlList = mpView->GetHdlList();
601
0
                    SdrHdl* pHdl = rHdlList.GetFocusHdl();
602
603
0
                    bool bIsMoveOfConnectedHandle(false);
604
0
                    bool bOldSuppress = false;
605
0
                    SdrEdgeObj* pEdgeObj = nullptr;
606
0
                    if(pHdl)
607
0
                        pEdgeObj = dynamic_cast<SdrEdgeObj *>( pHdl->GetObj() );
608
609
0
                    if(pEdgeObj && 0 == pHdl->GetPolyNum())
610
0
                    {
611
0
                        if(0 == pHdl->GetPointNum())
612
0
                        {
613
0
                            if(pEdgeObj->GetConnection(true).GetSdrObject())
614
0
                            {
615
0
                                bIsMoveOfConnectedHandle = true;
616
0
                            }
617
0
                        }
618
0
                        if(1 == pHdl->GetPointNum())
619
0
                        {
620
0
                            if(pEdgeObj->GetConnection(false).GetSdrObject())
621
0
                            {
622
0
                                bIsMoveOfConnectedHandle = true;
623
0
                            }
624
0
                        }
625
0
                    }
626
627
0
                    if(pEdgeObj)
628
0
                    {
629
                        // Suppress default connects to inside object and object center
630
0
                        bOldSuppress = pEdgeObj->GetSuppressDefaultConnect();
631
0
                        pEdgeObj->SetSuppressDefaultConnect(true);
632
0
                    }
633
634
0
                    if(bIsMoveOfConnectedHandle)
635
0
                    {
636
0
                        sal_uInt16 nMarkHdSiz(mpView->GetMarkHdlSizePixel());
637
0
                        Size aHalfConSiz(nMarkHdSiz + 1, nMarkHdSiz + 1);
638
0
                        aHalfConSiz = mpWindow->PixelToLogic(aHalfConSiz);
639
640
0
                        if(100 < aHalfConSiz.Width())
641
0
                            nX *= aHalfConSiz.Width();
642
0
                        else
643
0
                            nX *= 100;
644
645
0
                        if(100 < aHalfConSiz.Height())
646
0
                            nY *= aHalfConSiz.Height();
647
0
                        else
648
0
                            nY *= 100;
649
0
                    }
650
0
                    else if(rKEvt.GetKeyCode().IsMod2())
651
0
                    {
652
                        // move in 1 pixel distance
653
0
                        Size aLogicSizeOnePixel = mpWindow->PixelToLogic(Size(1,1));
654
0
                        nX *= aLogicSizeOnePixel.Width();
655
0
                        nY *= aLogicSizeOnePixel.Height();
656
0
                    }
657
0
                    else if(rKEvt.GetKeyCode().IsShift())
658
0
                    {
659
0
                        nX *= 1000;
660
0
                        nY *= 1000;
661
0
                    }
662
0
                    else
663
0
                    {
664
                        // old, fixed move distance
665
0
                        nX *= 100;
666
0
                        nY *= 100;
667
0
                    }
668
669
0
                    if(nullptr == pHdl)
670
0
                    {
671
                        // only take action when move is allowed
672
0
                        if(mpView->IsMoveAllowed())
673
0
                        {
674
                            // restrict movement to WorkArea
675
0
                            const ::tools::Rectangle& rWorkArea = mpView->GetWorkArea();
676
677
0
                            if(!rWorkArea.IsEmpty())
678
0
                            {
679
0
                                ::tools::Rectangle aMarkRect(mpView->GetMarkedObjRect());
680
0
                                aMarkRect.Move(nX, nY);
681
682
0
                                if(!aMarkRect.Contains(rWorkArea))
683
0
                                {
684
0
                                    if(aMarkRect.Left() < rWorkArea.Left())
685
0
                                    {
686
0
                                        nX += rWorkArea.Left() - aMarkRect.Left();
687
0
                                    }
688
689
0
                                    if(aMarkRect.Right() > rWorkArea.Right())
690
0
                                    {
691
0
                                        nX -= aMarkRect.Right() - rWorkArea.Right();
692
0
                                    }
693
694
0
                                    if(aMarkRect.Top() < rWorkArea.Top())
695
0
                                    {
696
0
                                        nY += rWorkArea.Top() - aMarkRect.Top();
697
0
                                    }
698
699
0
                                    if(aMarkRect.Bottom() > rWorkArea.Bottom())
700
0
                                    {
701
0
                                        nY -= aMarkRect.Bottom() - rWorkArea.Bottom();
702
0
                                    }
703
0
                                }
704
0
                            }
705
706
                            // no handle selected
707
0
                            if(0 != nX || 0 != nY)
708
0
                            {
709
0
                                mpView->MoveAllMarked(Size(nX, nY));
710
711
0
                                mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
712
0
                            }
713
0
                        }
714
0
                    }
715
0
                    else
716
0
                    {
717
                        // move handle with index nHandleIndex
718
0
                        if (nX || nY)
719
0
                        {
720
                            // now move the Handle (nX, nY)
721
0
                            Point aStartPoint(pHdl->GetPos());
722
0
                            Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
723
0
                            const SdrDragStat& rDragStat = mpView->GetDragStat();
724
725
                            // start dragging
726
0
                            mpView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
727
728
0
                            if(mpView->IsDragObj())
729
0
                            {
730
0
                                bool bWasNoSnap = rDragStat.IsNoSnap();
731
0
                                bool bWasSnapEnabled = mpView->IsSnapEnabled();
732
733
                                // switch snapping off
734
0
                                if(!bWasNoSnap)
735
0
                                    const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
736
0
                                if(bWasSnapEnabled)
737
0
                                    mpView->SetSnapEnabled(false);
738
739
0
                                mpView->MovAction(aEndPoint);
740
0
                                mpView->EndDragObj();
741
742
                                // restore snap
743
0
                                if(!bWasNoSnap)
744
0
                                    const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
745
0
                                if(bWasSnapEnabled)
746
0
                                    mpView->SetSnapEnabled(bWasSnapEnabled);
747
0
                            }
748
749
                            // make moved handle visible
750
0
                            ::tools::Rectangle aVisRect(aEndPoint - Point(100, 100), Size(200, 200));
751
0
                            mpView->MakeVisible(aVisRect, *mpWindow);
752
0
                        }
753
0
                    }
754
755
0
                    if(pEdgeObj)
756
0
                    {
757
                        // Restore original suppress value
758
0
                        pEdgeObj->SetSuppressDefaultConnect(bOldSuppress);
759
0
                    }
760
0
                }
761
0
                else
762
0
                {
763
                    // scroll page
764
0
                    mrViewShell.ScrollLines(nX, nY);
765
0
                }
766
767
0
                bReturn = true;
768
0
            }
769
0
        }
770
0
        break;
771
0
    }
772
773
0
    if (bReturn)
774
0
    {
775
0
        mpWindow->ReleaseMouse();
776
0
    }
777
778
    // when a text-editable object is selected and the
779
    // input character is printable, activate text edit on that object
780
    // and feed character to object
781
0
    if(!bReturn && !mpDocSh->IsReadOnly())
782
0
    {
783
0
        if (!mpView->IsTextEdit())
784
0
        {
785
0
            const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
786
787
0
            if(1 == rMarkList.GetMarkCount())
788
0
            {
789
0
                SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
790
791
                // #i118485# allow TextInput for OLEs, too
792
0
                if( DynCastSdrTextObj( pObj ) !=  nullptr && pObj->HasTextEdit())
793
0
                {
794
                    // use common IsSimpleCharInput from the EditEngine.
795
0
                    bool bPrintable(EditEngine::IsSimpleCharInput(rKEvt));
796
797
0
                    if(bPrintable)
798
0
                    {
799
                        // try to activate textedit mode for the selected object
800
0
                        SfxStringItem aInputString(SID_ATTR_CHAR, OUString(rKEvt.GetCharCode()));
801
802
0
                        mrViewShell.GetViewFrame()->GetDispatcher()->ExecuteList(
803
0
                            SID_ATTR_CHAR,
804
0
                            SfxCallMode::ASYNCHRON,
805
0
                            { &aInputString });
806
807
                        // consumed
808
0
                        bReturn = true;
809
0
                    }
810
0
                }
811
0
            }
812
0
            else
813
0
            {
814
                // test if there is a title object there. If yes, try to
815
                // set it to edit mode and start typing...
816
0
                DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(&mrViewShell);
817
0
                if (pDrawViewShell && EditEngine::IsSimpleCharInput(rKEvt))
818
0
                {
819
0
                    SdPage* pActualPage = pDrawViewShell->GetActualPage();
820
0
                    SdrTextObj* pCandidate = nullptr;
821
822
0
                    if(pActualPage)
823
0
                    {
824
0
                        SdrObjListIter aIter(pActualPage, SdrIterMode::DeepNoGroups);
825
826
0
                        while(aIter.IsMore() && !pCandidate)
827
0
                        {
828
0
                            SdrObject* pObj = aIter.Next();
829
830
0
                            if(auto pTextObj = DynCastSdrTextObj( pObj ))
831
0
                            {
832
0
                                SdrInventor nInv(pObj->GetObjInventor());
833
0
                                SdrObjKind nKnd(pObj->GetObjIdentifier());
834
835
0
                                if(SdrInventor::Default == nInv && SdrObjKind::TitleText == nKnd)
836
0
                                {
837
0
                                    pCandidate = pTextObj;
838
0
                                }
839
0
                            }
840
0
                        }
841
0
                    }
842
843
                    // when candidate found and candidate is untouched, start editing text...
844
0
                    if(pCandidate && pCandidate->IsEmptyPresObj())
845
0
                    {
846
0
                        mpView->UnMarkAll();
847
0
                        mpView->MarkObj(pCandidate, mpView->GetSdrPageView());
848
0
                        SfxStringItem aInputString(SID_ATTR_CHAR, OUString(rKEvt.GetCharCode()));
849
850
0
                        mrViewShell.GetViewFrame()->GetDispatcher()->ExecuteList(
851
0
                            SID_ATTR_CHAR,
852
0
                            SfxCallMode::ASYNCHRON,
853
0
                            { &aInputString });
854
855
                        // consumed
856
0
                        bReturn = true;
857
0
                    }
858
0
                }
859
0
            }
860
0
        }
861
0
    }
862
863
0
    return bReturn;
864
0
}
865
866
bool FuPoor::MouseMove(const MouseEvent& )
867
0
{
868
0
    return false;
869
0
}
870
871
void FuPoor::SelectionHasChanged()
872
0
{
873
0
    const SdrHdlList& rHdlList = mpView->GetHdlList();
874
0
    const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl();
875
0
}
876
877
/**
878
 * Cut object to clipboard
879
 */
880
void FuPoor::DoCut()
881
0
{
882
0
    if (mpView)
883
0
    {
884
0
        mpView->DoCut();
885
0
    }
886
0
}
887
888
/**
889
 * Copy object to clipboard
890
 */
891
void FuPoor::DoCopy(bool bMergeMasterPagesOnly )
892
0
{
893
0
    if (mpView)
894
0
    {
895
0
        mpView->DoCopy(bMergeMasterPagesOnly);
896
0
    }
897
0
}
898
899
/**
900
 * Paste object from clipboard
901
 */
902
void FuPoor::DoPaste(bool bMergeMasterPagesOnly )
903
0
{
904
0
    if (mpView)
905
0
    {
906
0
        mpView->DoPaste(mpWindow, bMergeMasterPagesOnly);
907
0
    }
908
0
}
909
910
/**
911
 * Paste unformatted text from clipboard
912
 */
913
void FuPoor::DoPasteUnformatted()
914
0
{
915
0
    if (mpView)
916
0
    {
917
0
        TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mrViewShell.GetActiveWindow() ) );
918
0
        if (aDataHelper.GetTransferable().is())
919
0
        {
920
0
            sal_Int8 nAction = DND_ACTION_COPY;
921
0
            mpView->InsertData( aDataHelper,
922
0
                                mpWindow->PixelToLogic( ::tools::Rectangle( Point(), mpWindow->GetOutputSizePixel() ).Center() ),
923
0
                                nAction, false, SotClipboardFormatId::STRING);
924
0
        }
925
0
    }
926
0
}
927
928
/**
929
 * Timer handler for Drag&Drop
930
 */
931
IMPL_LINK_NOARG(FuPoor, DragHdl, Timer *, void)
932
0
{
933
0
    if( !mpView )
934
0
        return;
935
936
0
    sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
937
0
    SdrHdl* pHdl = mpView->PickHandle(aMDPos);
938
939
0
    if ( pHdl==nullptr && mpView->IsMarkedHit(aMDPos, nHitLog)
940
0
         && !mpView->IsPresObjSelected(false) )
941
0
    {
942
0
        mpWindow->ReleaseMouse();
943
0
        bIsInDragMode = true;
944
0
        mpView->StartDrag( aMDPos, mpWindow );
945
0
    }
946
0
}
947
948
bool FuPoor::Command(const CommandEvent& rCEvt)
949
0
{
950
0
    return mpView->Command(rCEvt,mpWindow);
951
0
}
952
953
/**
954
 * Timer handler for window scrolling
955
 */
956
IMPL_LINK_NOARG(FuPoor, DelayHdl, Timer *, void)
957
0
{
958
0
    aDelayToScrollTimer.Stop ();
959
0
    bScrollable = true;
960
961
0
    Point aPnt(mpWindow->GetPointerPosPixel());
962
963
    // use remembered MouseButton state to create correct
964
    // MouseEvents for this artificial MouseMove.
965
0
    MouseMove(MouseEvent(aPnt, 1, MouseEventModifiers::NONE, GetMouseButtonCode()));
966
0
}
967
968
bool FuPoor::MouseButtonUp (const MouseEvent& rMEvt)
969
0
{
970
    // remember button state for creation of own MouseEvents
971
0
    SetMouseButtonCode(rMEvt.GetButtons());
972
973
0
    aDelayToScrollTimer.Stop ();
974
0
    bScrollable = bDelayActive = false;
975
0
    return bScrollable;
976
0
}
977
978
bool FuPoor::MouseButtonDown(const MouseEvent& rMEvt)
979
0
{
980
    // remember button state for creation of own MouseEvents
981
0
    SetMouseButtonCode(rMEvt.GetButtons());
982
983
0
    return false;
984
0
}
985
986
void FuPoor::StartDelayToScrollTimer ()
987
0
{
988
0
    bDelayActive = true;
989
0
    aDelayToScrollTimer.Start ();
990
0
}
991
992
bool FuPoor::RequestHelp(const HelpEvent& rHEvt)
993
0
{
994
0
    bool bReturn = false;
995
996
0
    SdrPageView* pPV = mpView->GetSdrPageView();
997
998
0
    if (pPV)
999
0
    {
1000
0
        SdPage* pPage = static_cast<SdPage*>( pPV->GetPage() );
1001
1002
0
        if (pPage)
1003
0
        {
1004
0
            bReturn = FmFormPage::RequestHelp(mpWindow, mpView, rHEvt);
1005
0
        }
1006
0
    }
1007
1008
0
    return bReturn;
1009
0
}
1010
1011
void FuPoor::ReceiveRequest(SfxRequest& /*rReq*/)
1012
0
{
1013
0
}
1014
1015
rtl::Reference<SdrObject> FuPoor::CreateDefaultObject(const sal_uInt16, const ::tools::Rectangle& )
1016
0
{
1017
    // empty base implementation
1018
0
    return nullptr;
1019
0
}
1020
1021
void FuPoor::ImpForceQuadratic(::tools::Rectangle& rRect)
1022
0
{
1023
0
    if(rRect.GetWidth() > rRect.GetHeight())
1024
0
    {
1025
0
        rRect = ::tools::Rectangle(
1026
0
            Point(rRect.Left() + ((rRect.GetWidth() - rRect.GetHeight()) / 2), rRect.Top()),
1027
0
            Size(rRect.GetHeight(), rRect.GetHeight()));
1028
0
    }
1029
0
    else
1030
0
    {
1031
0
        rRect = ::tools::Rectangle(
1032
0
            Point(rRect.Left(), rRect.Top() + ((rRect.GetHeight() - rRect.GetWidth()) / 2)),
1033
0
            Size(rRect.GetWidth(), rRect.GetWidth()));
1034
0
    }
1035
0
}
1036
1037
void FuPoor::SwitchLayer (sal_Int32 nOffset)
1038
0
{
1039
0
    auto pDrawViewShell = dynamic_cast<DrawViewShell *>( &mrViewShell );
1040
0
    if(!pDrawViewShell)
1041
0
        return;
1042
1043
    // Calculate the new index.
1044
0
    sal_Int32 nIndex = pDrawViewShell->GetActiveTabLayerIndex() + nOffset;
1045
1046
    // Make sure the new index lies inside the range of valid indices.
1047
0
    if (nIndex < 0)
1048
0
        nIndex = 0;
1049
0
    else if (nIndex >= pDrawViewShell->GetTabLayerCount ())
1050
0
        nIndex = pDrawViewShell->GetTabLayerCount() - 1;
1051
1052
    // Set the new active layer.
1053
0
    if (nIndex != pDrawViewShell->GetActiveTabLayerIndex ())
1054
0
    {
1055
0
        LayerTabBar* pLayerTabControl =
1056
0
            static_cast<DrawViewShell*>(&mrViewShell)->GetLayerTabControl();
1057
0
        if (pLayerTabControl != nullptr)
1058
0
            pLayerTabControl->SendDeactivatePageEvent ();
1059
1060
0
        pDrawViewShell->SetActiveTabLayerIndex (nIndex);
1061
1062
0
        if (pLayerTabControl != nullptr)
1063
0
            pLayerTabControl->SendActivatePageEvent ();
1064
0
    }
1065
0
}
1066
1067
/** is called when the current function should be aborted. <p>
1068
    This is used when a function gets a KEY_ESCAPE but can also
1069
    be called directly.
1070
1071
    @returns true if an active function was aborted
1072
*/
1073
bool FuPoor::cancel()
1074
0
{
1075
0
    if ( dynamic_cast< const FuSelection *>( this ) ==  nullptr )
1076
0
    {
1077
0
        mrViewShell.GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON);
1078
0
        return true;
1079
0
    }
1080
1081
0
    return false;
1082
0
}
1083
1084
// #i33136#
1085
bool FuPoor::doConstructOrthogonal() const
1086
0
{
1087
    // Check whether a media object is selected
1088
0
    bool bResizeKeepRatio = false;
1089
0
    const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
1090
    // tdf#89758 Avoid interactive crop preview from being proportionally scaled by default.
1091
0
    if (rMarkList.GetMarkCount() != 0 && mpView->GetDragMode() != SdrDragMode::Crop)
1092
0
    {
1093
0
        if (rMarkList.GetMarkCount() == 1)
1094
0
        {
1095
0
            SdrObjKind aObjIdentifier = rMarkList.GetMark(0)->GetMarkedSdrObj()->GetObjIdentifier();
1096
0
            bResizeKeepRatio = aObjIdentifier == SdrObjKind::Graphic ||
1097
0
                               aObjIdentifier == SdrObjKind::Media ||
1098
0
                               aObjIdentifier == SdrObjKind::OLE2;
1099
0
        }
1100
0
    }
1101
0
    SdrHdl* pHdl = mpView->PickHandle(aMDPos);
1102
    // Resize proportionally when media is selected and the user drags on a corner
1103
0
    if (pHdl)
1104
0
        bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl();
1105
1106
0
    return (
1107
0
        bResizeKeepRatio ||
1108
0
        SID_DRAW_XLINE == nSlotId ||
1109
0
        SID_DRAW_CIRCLEARC == nSlotId ||
1110
0
        SID_DRAW_SQUARE == nSlotId ||
1111
0
        SID_DRAW_SQUARE_NOFILL == nSlotId ||
1112
0
        SID_DRAW_SQUARE_ROUND == nSlotId ||
1113
0
        SID_DRAW_SQUARE_ROUND_NOFILL == nSlotId ||
1114
0
        SID_DRAW_CIRCLE == nSlotId ||
1115
0
        SID_DRAW_CIRCLE_NOFILL == nSlotId ||
1116
0
        SID_DRAW_CIRCLEPIE == nSlotId ||
1117
0
        SID_DRAW_CIRCLEPIE_NOFILL == nSlotId ||
1118
0
        SID_DRAW_CIRCLECUT == nSlotId ||
1119
0
        SID_DRAW_CIRCLECUT_NOFILL == nSlotId ||
1120
0
        SID_DRAW_XPOLYGON == nSlotId ||
1121
0
        SID_DRAW_XPOLYGON_NOFILL == nSlotId ||
1122
0
        SID_3D_CUBE == nSlotId ||
1123
0
        SID_3D_SPHERE == nSlotId ||
1124
0
        SID_3D_SHELL == nSlotId ||
1125
0
        SID_3D_HALF_SPHERE == nSlotId ||
1126
0
        SID_3D_TORUS == nSlotId ||
1127
0
        SID_3D_CYLINDER == nSlotId ||
1128
0
        SID_3D_CONE == nSlotId ||
1129
0
        SID_3D_PYRAMID == nSlotId);
1130
0
}
1131
1132
void FuPoor::DoExecute( SfxRequest& )
1133
0
{
1134
0
}
1135
1136
} // end of namespace sd
1137
1138
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */