Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/dialog/graphctl.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 <config_wasm_strip.h>
21
22
#include <svl/itempool.hxx>
23
#include <vcl/settings.hxx>
24
#include <vcl/ptrstyle.hxx>
25
#include <vcl/svapp.hxx>
26
#include <vcl/weld/Dialog.hxx>
27
28
#include <svx/graphctl.hxx>
29
#include <svx/sdr/overlay/overlaymanager.hxx>
30
#include <GraphCtlAccessibleContext.hxx>
31
#include <svx/svxids.hrc>
32
#include <svx/svdpage.hxx>
33
#include <svx/sdrpaintwindow.hxx>
34
35
void GraphCtrlUserCall::Changed( const SdrObject& rObj, SdrUserCallType eType, const tools::Rectangle& /*rOldBoundRect*/ )
36
0
{
37
0
    switch( eType )
38
0
    {
39
0
        case SdrUserCallType::MoveOnly:
40
0
        case SdrUserCallType::Resize:
41
0
            m_rWin.SdrObjChanged( rObj );
42
0
        break;
43
44
0
        case SdrUserCallType::Inserted:
45
0
            m_rWin.SdrObjCreated( rObj );
46
0
        break;
47
48
0
        default:
49
0
        break;
50
0
    }
51
0
    m_rWin.QueueIdleUpdate();
52
0
}
53
54
GraphCtrl::GraphCtrl(weld::Dialog* pDialog)
55
0
    : maUpdateIdle("svx GraphCtrl Update")
56
0
    , maMap100(MapUnit::Map100thMM)
57
0
    , meObjKind(SdrObjKind::NONE)
58
0
    , mnPolyEdit(0)
59
0
    , mbEditMode(false)
60
0
    , mbSdrMode(false)
61
0
    , mbInIdleUpdate(false)
62
0
    , mpDialog(pDialog)
63
0
{
64
0
    mpUserCall.reset(new GraphCtrlUserCall( *this ));
65
0
    maUpdateIdle.SetPriority( TaskPriority::LOWEST );
66
0
    maUpdateIdle.SetInvokeHandler( LINK( this, GraphCtrl, UpdateHdl ) );
67
0
    maUpdateIdle.Start();
68
0
}
69
70
void GraphCtrl::SetDrawingArea(weld::DrawingArea* pDrawingArea)
71
0
{
72
0
    weld::CustomWidgetController::SetDrawingArea(pDrawingArea);
73
0
    EnableRTL(false);
74
0
}
75
76
GraphCtrl::~GraphCtrl()
77
0
{
78
0
    maUpdateIdle.Stop();
79
80
0
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
81
0
    if( mpAccContext.is() )
82
0
    {
83
0
        mpAccContext->disposing();
84
0
        mpAccContext.clear();
85
0
    }
86
0
#endif
87
88
0
    mpView.reset();
89
0
    mpModel.reset();
90
0
    mpUserCall.reset();
91
0
}
92
93
void GraphCtrl::SetSdrMode(bool bSdrMode)
94
0
{
95
0
    mbSdrMode = bSdrMode;
96
97
0
    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
98
0
    OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
99
0
    rDevice.SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
100
0
    mxVD->SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
101
0
    rDevice.SetMapMode( maMap100 );
102
0
    mxVD->SetMapMode( maMap100 );
103
104
0
    mpView.reset();
105
0
    mpModel.reset();
106
107
0
    if ( mbSdrMode )
108
0
        InitSdrModel();
109
110
0
    QueueIdleUpdate();
111
0
}
112
113
void GraphCtrl::InitSdrModel()
114
0
{
115
0
    SolarMutexGuard aGuard;
116
117
0
    rtl::Reference<SdrPage> pPage;
118
119
    // destroy old junk
120
0
    mpView.reset();
121
0
    mpModel.reset();
122
123
    // Creating a Model
124
0
    mpModel.reset(new SdrModel(nullptr, nullptr, true));
125
0
    mpModel->SetScaleUnit(maMap100.GetMapUnit());
126
0
    mpModel->SetDefaultFontHeight( 500 );
127
128
0
    pPage = new SdrPage( *mpModel );
129
130
0
    pPage->SetSize( maGraphSize );
131
0
    pPage->SetBorder( 0, 0, 0, 0 );
132
0
    mpModel->InsertPage( pPage.get() );
133
0
    mpModel->SetChanged( false );
134
135
    // Creating a View
136
0
    mpView.reset(new GraphCtrlView(*mpModel, this));
137
0
    mpView->SetWorkArea( tools::Rectangle( Point(), maGraphSize ) );
138
0
    mpView->EnableExtendedMouseEventDispatcher( true );
139
0
    mpView->ShowSdrPage(mpView->GetModel().GetPage(0));
140
0
    mpView->SetFrameDragSingles();
141
0
    mpView->SetMarkedPointsSmooth( SdrPathSmoothKind::Symmetric );
142
0
    mpView->SetEditMode();
143
144
    // #i72889# set needed flags
145
0
    mpView->SetPageDecorationAllowed(false);
146
0
    mpView->SetMasterPageVisualizationAllowed(false);
147
0
    mpView->SetBufferedOutputAllowed(true);
148
0
    mpView->SetBufferedOverlayAllowed(true);
149
150
0
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
151
    // Tell the accessibility object about the changes.
152
0
    if (mpAccContext.is())
153
0
        mpAccContext->setModelAndView (mpModel.get(), mpView.get());
154
0
#endif
155
0
}
156
157
void GraphCtrl::SetGraphic( const Graphic& rGraphic, bool bNewModel )
158
0
{
159
0
    maGraphic = rGraphic;
160
0
    mxVD->SetOutputSizePixel(Size(0, 0)); //force redraw
161
162
0
    if ( maGraphic.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel )
163
0
        maGraphSize = Application::GetDefaultDevice()->PixelToLogic( maGraphic.GetPrefSize(), maMap100 );
164
0
    else
165
0
        maGraphSize = OutputDevice::LogicToLogic( maGraphic.GetPrefSize(), maGraphic.GetPrefMapMode(), maMap100 );
166
167
0
    if ( mbSdrMode && bNewModel )
168
0
        InitSdrModel();
169
170
0
    maGraphSizeLink.Call( this );
171
172
0
    Resize();
173
174
0
    Invalidate();
175
0
    QueueIdleUpdate();
176
0
}
177
178
void GraphCtrl::GraphicToVD()
179
0
{
180
0
    OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
181
0
    mxVD->SetOutputSizePixel(GetOutputSizePixel());
182
0
    mxVD->SetBackground(rDevice.GetBackground());
183
0
    mxVD->Erase();
184
0
    const bool bGraphicValid(GraphicType::NONE != maGraphic.GetType());
185
0
    if (bGraphicValid)
186
0
        maGraphic.Draw(*mxVD, Point(), maGraphSize);
187
0
}
188
189
void GraphCtrl::Resize()
190
0
{
191
0
    weld::CustomWidgetController::Resize();
192
193
0
    if (maGraphSize.Width() && maGraphSize.Height())
194
0
    {
195
0
        MapMode         aDisplayMap( maMap100 );
196
0
        Point           aNewPos;
197
0
        Size            aNewSize;
198
0
        OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
199
0
        const Size      aWinSize = rDevice.PixelToLogic( GetOutputSizePixel(), aDisplayMap );
200
0
        const tools::Long      nWidth = aWinSize.Width();
201
0
        const tools::Long      nHeight = aWinSize.Height();
202
0
        double          fGrfWH = static_cast<double>(maGraphSize.Width()) / maGraphSize.Height();
203
0
        double          fWinWH = static_cast<double>(nWidth) / nHeight;
204
205
        // Adapt Bitmap to Thumb size
206
0
        if ( fGrfWH < fWinWH)
207
0
        {
208
0
            aNewSize.setWidth( static_cast<tools::Long>( static_cast<double>(nHeight) * fGrfWH ) );
209
0
            aNewSize.setHeight( nHeight );
210
0
        }
211
0
        else
212
0
        {
213
0
            aNewSize.setWidth( nWidth );
214
0
            aNewSize.setHeight( static_cast<tools::Long>( static_cast<double>(nWidth) / fGrfWH ) );
215
0
        }
216
217
0
        aNewPos.setX( ( nWidth - aNewSize.Width() )  >> 1 );
218
0
        aNewPos.setY( ( nHeight - aNewSize.Height() ) >> 1 );
219
220
        // Implementing MapMode for Engine
221
0
        aDisplayMap.SetScaleX( double(aNewSize.Width()) / maGraphSize.Width() );
222
0
        aDisplayMap.SetScaleY( double(aNewSize.Height()) / maGraphSize.Height() );
223
224
0
        aDisplayMap.SetOrigin( OutputDevice::LogicToLogic( aNewPos, maMap100, aDisplayMap ) );
225
0
        rDevice.SetMapMode( aDisplayMap );
226
0
        mxVD->SetMapMode( aDisplayMap );
227
0
    }
228
229
0
    Invalidate();
230
0
}
231
232
void GraphCtrl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
233
0
{
234
    // #i72889# used split repaint to be able to paint an own background
235
    // even to the buffered view
236
0
    const bool bGraphicValid(GraphicType::NONE != maGraphic.GetType());
237
238
0
    if (GetOutputSizePixel() != mxVD->GetOutputSizePixel())
239
0
        GraphicToVD();
240
241
0
    if (mbSdrMode)
242
0
    {
243
0
        SdrPaintWindow* pPaintWindow = mpView->BeginCompleteRedraw(&rRenderContext);
244
0
        pPaintWindow->SetOutputToWindow(true);
245
246
0
        if (bGraphicValid)
247
0
        {
248
0
            vcl::RenderContext& rTarget = pPaintWindow->GetTargetOutputDevice();
249
250
0
            OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
251
0
            rTarget.SetBackground(rDevice.GetBackground());
252
0
            rTarget.Erase();
253
254
0
            rTarget.DrawOutDev(Point(), mxVD->GetOutputSize(), Point(), mxVD->GetOutputSize(), *mxVD);
255
0
        }
256
257
0
        const vcl::Region aRepaintRegion(rRect);
258
0
        mpView->DoCompleteRedraw(*pPaintWindow, aRepaintRegion);
259
0
        mpView->EndCompleteRedraw(*pPaintWindow, true);
260
0
    }
261
0
    else
262
0
    {
263
        // #i73381# in non-SdrMode, paint to local directly
264
0
        rRenderContext.DrawOutDev(rRect.TopLeft(), rRect.GetSize(),
265
0
                                  rRect.TopLeft(), rRect.GetSize(),
266
0
                                  *mxVD);
267
0
    }
268
0
}
269
270
void GraphCtrl::SdrObjChanged( const SdrObject&  )
271
0
{
272
0
    QueueIdleUpdate();
273
0
}
274
275
void GraphCtrl::SdrObjCreated( const SdrObject& )
276
0
{
277
0
    QueueIdleUpdate();
278
0
}
279
280
void GraphCtrl::MarkListHasChanged()
281
0
{
282
0
    QueueIdleUpdate();
283
0
}
284
285
bool GraphCtrl::KeyInput( const KeyEvent& rKEvt )
286
0
{
287
0
    vcl::KeyCode aCode( rKEvt.GetKeyCode() );
288
0
    bool    bProc = false;
289
290
0
    OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
291
292
0
    switch ( aCode.GetCode() )
293
0
    {
294
0
        case KEY_DELETE:
295
0
        case KEY_BACKSPACE:
296
0
        {
297
0
            if ( mbSdrMode )
298
0
            {
299
0
                mpView->DeleteMarked();
300
0
                bProc = true;
301
0
            }
302
0
        }
303
0
        break;
304
305
0
        case KEY_ESCAPE:
306
0
        {
307
0
            if ( mbSdrMode )
308
0
            {
309
0
                const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
310
0
                if ( mpView->IsAction() )
311
0
                {
312
0
                    mpView->BrkAction();
313
0
                    bProc = true;
314
0
                }
315
0
                else if ( rMarkList.GetMarkCount() != 0 )
316
0
                {
317
0
                    mpView->UnmarkAllObj();
318
0
                    bProc = true;
319
0
                }
320
0
            }
321
0
        }
322
0
        break;
323
324
0
        case KEY_F11:
325
0
        case KEY_TAB:
326
0
        {
327
0
            if( mbSdrMode )
328
0
            {
329
0
                if( !aCode.IsMod1() && !aCode.IsMod2() )
330
0
                {
331
0
                    bool bForward = !aCode.IsShift();
332
                    // select next object
333
0
                    if ( ! mpView->MarkNextObj( bForward ))
334
0
                    {
335
                        // At first or last object.  Cycle to the other end
336
                        // of the list.
337
0
                        mpView->UnmarkAllObj();
338
0
                        mpView->MarkNextObj (bForward);
339
0
                    }
340
0
                    bProc = true;
341
0
                }
342
0
                else if(aCode.IsMod1())
343
0
                {
344
                    // select next handle
345
0
                    const SdrHdlList& rHdlList = mpView->GetHdlList();
346
0
                    bool bForward(!aCode.IsShift());
347
348
0
                    const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
349
350
0
                    bProc = true;
351
0
                }
352
0
            }
353
0
        }
354
0
        break;
355
356
0
        case KEY_END:
357
0
        {
358
359
0
            if ( aCode.IsMod1() )
360
0
            {
361
                // mark last object
362
0
                mpView->UnmarkAllObj();
363
0
                mpView->MarkNextObj();
364
365
0
                bProc = true;
366
0
            }
367
0
        }
368
0
        break;
369
370
0
        case KEY_HOME:
371
0
        {
372
0
            if ( aCode.IsMod1() )
373
0
            {
374
0
                mpView->UnmarkAllObj();
375
0
                mpView->MarkNextObj(true);
376
377
0
                bProc = true;
378
0
            }
379
0
        }
380
0
        break;
381
382
0
        case KEY_UP:
383
0
        case KEY_DOWN:
384
0
        case KEY_LEFT:
385
0
        case KEY_RIGHT:
386
0
        {
387
0
            tools::Long nX = 0;
388
0
            tools::Long nY = 0;
389
390
0
            if (aCode.GetCode() == KEY_UP)
391
0
            {
392
                // Scroll up
393
0
                nX = 0;
394
0
                nY =-1;
395
0
            }
396
0
            else if (aCode.GetCode() == KEY_DOWN)
397
0
            {
398
                // Scroll down
399
0
                nX = 0;
400
0
                nY = 1;
401
0
            }
402
0
            else if (aCode.GetCode() == KEY_LEFT)
403
0
            {
404
                // Scroll left
405
0
                nX =-1;
406
0
                nY = 0;
407
0
            }
408
0
            else if (aCode.GetCode() == KEY_RIGHT)
409
0
            {
410
                // Scroll right
411
0
                nX = 1;
412
0
                nY = 0;
413
0
            }
414
415
0
            const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
416
0
            if (rMarkList.GetMarkCount() != 0 && !aCode.IsMod1() )
417
0
            {
418
0
                if(aCode.IsMod2())
419
0
                {
420
                    // move in 1 pixel distance
421
0
                    Size aLogicSizeOnePixel = rDevice.PixelToLogic(Size(1,1));
422
0
                    nX *= aLogicSizeOnePixel.Width();
423
0
                    nY *= aLogicSizeOnePixel.Height();
424
0
                }
425
0
                else
426
0
                {
427
                    // old, fixed move distance
428
0
                    nX *= 100;
429
0
                    nY *= 100;
430
0
                }
431
432
                // II
433
0
                const SdrHdlList& rHdlList = mpView->GetHdlList();
434
0
                SdrHdl* pHdl = rHdlList.GetFocusHdl();
435
436
0
                if(nullptr == pHdl)
437
0
                {
438
                    // restrict movement to WorkArea
439
0
                    const tools::Rectangle& rWorkArea = mpView->GetWorkArea();
440
441
0
                    if(!rWorkArea.IsEmpty())
442
0
                    {
443
0
                        tools::Rectangle aMarkRect(mpView->GetMarkedObjRect());
444
0
                        aMarkRect.Move(nX, nY);
445
446
0
                        if(!aMarkRect.Contains(rWorkArea))
447
0
                        {
448
0
                            if(aMarkRect.Left() < rWorkArea.Left())
449
0
                            {
450
0
                                nX += rWorkArea.Left() - aMarkRect.Left();
451
0
                            }
452
453
0
                            if(aMarkRect.Right() > rWorkArea.Right())
454
0
                            {
455
0
                                nX -= aMarkRect.Right() - rWorkArea.Right();
456
0
                            }
457
458
0
                            if(aMarkRect.Top() < rWorkArea.Top())
459
0
                            {
460
0
                                nY += rWorkArea.Top() - aMarkRect.Top();
461
0
                            }
462
463
0
                            if(aMarkRect.Bottom() > rWorkArea.Bottom())
464
0
                            {
465
0
                                nY -= aMarkRect.Bottom() - rWorkArea.Bottom();
466
0
                            }
467
0
                        }
468
0
                    }
469
470
                    // no handle selected
471
0
                    if(0 != nX || 0 != nY)
472
0
                    {
473
0
                        mpView->MoveAllMarked(Size(nX, nY));
474
0
                    }
475
0
                }
476
0
                else
477
0
                {
478
                    // move handle with index nHandleIndex
479
0
                    if (nX || nY)
480
0
                    {
481
                        // now move the Handle (nX, nY)
482
0
                        Point aStartPoint(pHdl->GetPos());
483
0
                        Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
484
0
                        const SdrDragStat& rDragStat = mpView->GetDragStat();
485
486
                        // start dragging
487
0
                        mpView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
488
489
0
                        if(mpView->IsDragObj())
490
0
                        {
491
0
                            bool bWasNoSnap = rDragStat.IsNoSnap();
492
0
                            bool bWasSnapEnabled = mpView->IsSnapEnabled();
493
494
                            // switch snapping off
495
0
                            if(!bWasNoSnap)
496
0
                                const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
497
0
                            if(bWasSnapEnabled)
498
0
                                mpView->SetSnapEnabled(false);
499
500
0
                            mpView->MovAction(aEndPoint);
501
0
                            mpView->EndDragObj();
502
503
                            // restore snap
504
0
                            if(!bWasNoSnap)
505
0
                                const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
506
0
                            if(bWasSnapEnabled)
507
0
                                mpView->SetSnapEnabled(bWasSnapEnabled);
508
0
                        }
509
0
                    }
510
0
                }
511
512
0
                bProc = true;
513
0
            }
514
0
        }
515
0
        break;
516
517
0
        case KEY_SPACE:
518
0
        {
519
0
            const SdrHdlList& rHdlList = mpView->GetHdlList();
520
0
            SdrHdl* pHdl = rHdlList.GetFocusHdl();
521
522
0
            if(pHdl)
523
0
            {
524
0
                if(pHdl->GetKind() == SdrHdlKind::Poly)
525
0
                {
526
                    // rescue ID of point with focus
527
0
                    sal_uInt32 nPol(pHdl->GetPolyNum());
528
0
                    sal_uInt32 nPnt(pHdl->GetPointNum());
529
530
0
                    if(mpView->IsPointMarked(*pHdl))
531
0
                    {
532
0
                        if(rKEvt.GetKeyCode().IsShift())
533
0
                        {
534
0
                            mpView->UnmarkPoint(*pHdl);
535
0
                        }
536
0
                    }
537
0
                    else
538
0
                    {
539
0
                        if(!rKEvt.GetKeyCode().IsShift())
540
0
                        {
541
0
                            mpView->UnmarkAllPoints();
542
0
                        }
543
544
0
                        mpView->MarkPoint(*pHdl);
545
0
                    }
546
547
0
                    if(nullptr == rHdlList.GetFocusHdl())
548
0
                    {
549
                        // restore point with focus
550
0
                        SdrHdl* pNewOne = nullptr;
551
552
0
                        for(size_t a = 0; !pNewOne && a < rHdlList.GetHdlCount(); ++a)
553
0
                        {
554
0
                            SdrHdl* pAct = rHdlList.GetHdl(a);
555
556
0
                            if(pAct
557
0
                                && pAct->GetKind() == SdrHdlKind::Poly
558
0
                                && pAct->GetPolyNum() == nPol
559
0
                                && pAct->GetPointNum() == nPnt)
560
0
                            {
561
0
                                pNewOne = pAct;
562
0
                            }
563
0
                        }
564
565
0
                        if(pNewOne)
566
0
                        {
567
0
                            const_cast<SdrHdlList&>(rHdlList).SetFocusHdl(pNewOne);
568
0
                        }
569
0
                    }
570
571
0
                    bProc = true;
572
0
                }
573
0
            }
574
0
        }
575
0
        break;
576
577
0
        default:
578
0
        break;
579
0
    }
580
581
0
    if (bProc)
582
0
        ReleaseMouse();
583
584
0
    QueueIdleUpdate();
585
586
0
    return bProc;
587
0
}
588
589
bool GraphCtrl::MouseButtonDown( const MouseEvent& rMEvt )
590
0
{
591
0
    if ( mbSdrMode && ( rMEvt.GetClicks() < 2 ) )
592
0
    {
593
0
        OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
594
595
0
        const Point aLogPt( rDevice.PixelToLogic( rMEvt.GetPosPixel() ) );
596
597
0
        if ( !tools::Rectangle( Point(), maGraphSize ).Contains( aLogPt ) && !mpView->IsEditMode() )
598
0
            weld::CustomWidgetController::MouseButtonDown( rMEvt );
599
0
        else
600
0
        {
601
            // Get Focus for key inputs
602
0
            GrabFocus();
603
604
0
            if ( mnPolyEdit )
605
0
            {
606
0
                SdrViewEvent    aVEvt;
607
0
                SdrHitKind      eHit = mpView->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt );
608
609
0
                if ( mnPolyEdit == SID_BEZIER_INSERT && eHit == SdrHitKind::MarkedObject )
610
0
                    mpView->BegInsObjPoint( aLogPt, rMEvt.IsMod1());
611
0
                else
612
0
                    mpView->MouseButtonDown( rMEvt, &rDevice );
613
0
            }
614
0
            else
615
0
                mpView->MouseButtonDown( rMEvt, &rDevice );
616
0
        }
617
618
0
        SdrObject* pCreateObj = mpView->GetCreateObj();
619
620
        // We want to realize the insert
621
0
        if ( pCreateObj && !pCreateObj->GetUserCall() )
622
0
            pCreateObj->SetUserCall( mpUserCall.get() );
623
624
0
        SetPointer( mpView->GetPreferredPointer( aLogPt, &rDevice ) );
625
0
    }
626
0
    else
627
0
        weld::CustomWidgetController::MouseButtonDown( rMEvt );
628
629
0
    QueueIdleUpdate();
630
631
0
    return false;
632
0
}
633
634
bool GraphCtrl::MouseMove(const MouseEvent& rMEvt)
635
0
{
636
0
    OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
637
0
    const Point aLogPos( rDevice.PixelToLogic( rMEvt.GetPosPixel() ) );
638
639
0
    if ( mbSdrMode )
640
0
    {
641
0
        mpView->MouseMove( rMEvt, &rDevice );
642
643
0
        if( ( SID_BEZIER_INSERT == mnPolyEdit ) &&
644
0
            !mpView->PickHandle( aLogPos ) &&
645
0
            !mpView->IsInsObjPoint() )
646
0
        {
647
0
            SetPointer( PointerStyle::Cross );
648
0
        }
649
0
        else
650
0
            SetPointer( mpView->GetPreferredPointer( aLogPos, &rDevice ) );
651
0
    }
652
0
    else
653
0
        weld::CustomWidgetController::MouseButtonUp( rMEvt );
654
655
0
    if ( maMousePosLink.IsSet() )
656
0
    {
657
0
        if ( tools::Rectangle( Point(), maGraphSize ).Contains( aLogPos ) )
658
0
            maMousePos = aLogPos;
659
0
        else
660
0
            maMousePos = Point();
661
662
0
        maMousePosLink.Call( this );
663
0
    }
664
665
0
    QueueIdleUpdate();
666
667
0
    return false;
668
0
}
669
670
bool GraphCtrl::MouseButtonUp(const MouseEvent& rMEvt)
671
0
{
672
0
    if ( mbSdrMode )
673
0
    {
674
0
        OutputDevice& rDevice = GetDrawingArea()->get_ref_device();
675
676
0
        if ( mpView->IsInsObjPoint() )
677
0
            mpView->EndInsObjPoint( SdrCreateCmd::ForceEnd );
678
0
        else
679
0
            mpView->MouseButtonUp( rMEvt, &rDevice );
680
681
0
        ReleaseMouse();
682
0
        SetPointer( mpView->GetPreferredPointer( rDevice.PixelToLogic( rMEvt.GetPosPixel() ), &rDevice ) );
683
0
    }
684
0
    else
685
0
        weld::CustomWidgetController::MouseButtonUp( rMEvt );
686
687
0
    QueueIdleUpdate();
688
689
0
    return false;
690
0
}
691
692
SdrObject* GraphCtrl::GetSelectedSdrObject() const
693
0
{
694
0
    SdrObject* pSdrObj = nullptr;
695
696
0
    if ( mbSdrMode )
697
0
    {
698
0
        const SdrMarkList&  rMarkList = mpView->GetMarkedObjectList();
699
700
0
        if ( rMarkList.GetMarkCount() == 1 )
701
0
            pSdrObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
702
0
    }
703
704
0
    return pSdrObj;
705
0
}
706
707
void GraphCtrl::SetEditMode( const bool _bEditMode )
708
0
{
709
0
    if ( mbSdrMode )
710
0
    {
711
0
        mbEditMode = _bEditMode;
712
0
        mpView->SetEditMode( mbEditMode );
713
0
        meObjKind = SdrObjKind::NONE;
714
0
        mpView->SetCurrentObj(meObjKind);
715
0
    }
716
0
    else
717
0
        mbEditMode = false;
718
719
0
    QueueIdleUpdate();
720
0
}
721
722
void GraphCtrl::SetPolyEditMode( const sal_uInt16 _nPolyEdit )
723
0
{
724
0
    if ( mbSdrMode && ( _nPolyEdit != mnPolyEdit ) )
725
0
    {
726
0
        mnPolyEdit = _nPolyEdit;
727
0
        mpView->SetFrameDragSingles( mnPolyEdit == 0 );
728
0
    }
729
0
    else
730
0
        mnPolyEdit = 0;
731
732
0
    QueueIdleUpdate();
733
0
}
734
735
void GraphCtrl::SetObjKind( const SdrObjKind _eObjKind )
736
0
{
737
0
    if ( mbSdrMode )
738
0
    {
739
0
        mbEditMode = false;
740
0
        mpView->SetEditMode( mbEditMode );
741
0
        meObjKind = _eObjKind;
742
0
        mpView->SetCurrentObj(meObjKind);
743
0
    }
744
0
    else
745
0
        meObjKind = SdrObjKind::NONE;
746
747
0
    QueueIdleUpdate();
748
0
}
749
750
IMPL_LINK_NOARG(GraphCtrl, UpdateHdl, Timer *, void)
751
0
{
752
0
    mbInIdleUpdate = true;
753
0
    maUpdateLink.Call( this );
754
0
    mbInIdleUpdate = false;
755
0
}
756
757
void GraphCtrl::QueueIdleUpdate()
758
0
{
759
0
    if (!mbInIdleUpdate)
760
0
        maUpdateIdle.Start();
761
0
}
762
763
namespace
764
{
765
    class WeldOverlayManager final : public sdr::overlay::OverlayManager
766
    {
767
        weld::CustomWidgetController& m_rGraphCtrl;
768
769
    public:
770
        WeldOverlayManager(weld::CustomWidgetController& rGraphCtrl, OutputDevice& rDevice)
771
0
            : OverlayManager(rDevice)
772
0
            , m_rGraphCtrl(rGraphCtrl)
773
0
        {
774
0
        }
775
776
        // invalidate the given range at local OutputDevice
777
        virtual void invalidateRange(const basegfx::B2DRange& rRange) override
778
0
        {
779
0
            tools::Rectangle aInvalidateRectangle(RangeToInvalidateRectangle(rRange));
780
0
            m_rGraphCtrl.Invalidate(aInvalidateRectangle);
781
0
        }
782
    };
783
}
784
785
rtl::Reference<sdr::overlay::OverlayManager> GraphCtrlView::CreateOverlayManager(OutputDevice& rDevice) const
786
0
{
787
0
    assert(&rDevice == &m_rGraphCtrl.GetDrawingArea()->get_ref_device());
788
0
    if (rDevice.GetOutDevType() == OUTDEV_VIRDEV)
789
0
    {
790
0
        rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager(new WeldOverlayManager(m_rGraphCtrl, rDevice));
791
0
        InitOverlayManager(xOverlayManager);
792
0
        return xOverlayManager;
793
0
    }
794
0
    return SdrView::CreateOverlayManager(rDevice);
795
0
}
796
797
void GraphCtrlView::InvalidateOneWin(OutputDevice& rDevice)
798
0
{
799
0
    assert(&rDevice == &m_rGraphCtrl.GetDrawingArea()->get_ref_device());
800
0
    if (rDevice.GetOutDevType() == OUTDEV_VIRDEV)
801
0
    {
802
0
        m_rGraphCtrl.Invalidate();
803
0
        return;
804
0
    }
805
0
    SdrView::InvalidateOneWin(rDevice);
806
0
}
807
808
void GraphCtrlView::InvalidateOneWin(OutputDevice& rDevice, const tools::Rectangle& rArea)
809
0
{
810
0
    assert(&rDevice == &m_rGraphCtrl.GetDrawingArea()->get_ref_device());
811
0
    if (rDevice.GetOutDevType() == OUTDEV_VIRDEV)
812
0
    {
813
0
        m_rGraphCtrl.Invalidate(rArea);
814
0
        return;
815
0
    }
816
0
    SdrView::InvalidateOneWin(rDevice, rArea);
817
0
}
818
819
GraphCtrlView::~GraphCtrlView()
820
0
{
821
    // turn SetOutputToWindow back off again before
822
    // turning back into our baseclass during dtoring
823
0
    const sal_uInt32 nWindowCount(PaintWindowCount());
824
0
    for (sal_uInt32 nWinNum(0); nWinNum < nWindowCount; nWinNum++)
825
0
    {
826
0
        SdrPaintWindow* pPaintWindow = GetPaintWindow(nWinNum);
827
0
        pPaintWindow->SetOutputToWindow(false);
828
0
    }
829
0
}
830
831
Point GraphCtrl::GetPositionInDialog() const
832
0
{
833
0
    int x, y, width, height;
834
0
    if (GetDrawingArea()->get_extents_relative_to(*mpDialog, x, y, width, height))
835
0
        return Point(x, y);
836
0
    return Point();
837
0
}
838
839
rtl::Reference<comphelper::OAccessible> GraphCtrl::CreateAccessible()
840
0
{
841
0
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
842
0
    if(mpAccContext == nullptr )
843
0
    {
844
0
        mpAccContext = new SvxGraphCtrlAccessibleContext(*this);
845
0
    }
846
0
#endif
847
0
    return mpAccContext;
848
0
}
849
850
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */