Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/controller/main/ChartController_Window.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <sal/config.h>
21
22
#include <string_view>
23
24
#include <ChartController.hxx>
25
#include <ChartView.hxx>
26
#include <PositionAndSizeHelper.hxx>
27
#include <ObjectIdentifier.hxx>
28
#include <ChartWindow.hxx>
29
#include <ResId.hxx>
30
#include <ChartModel.hxx>
31
#include <ChartType.hxx>
32
#include <DiagramHelper.hxx>
33
#include <Diagram.hxx>
34
#include <TitleHelper.hxx>
35
#include "UndoGuard.hxx"
36
#include <ControllerLockGuard.hxx>
37
#include <ObjectNameProvider.hxx>
38
#include <strings.hrc>
39
#include "DragMethod_PieSegment.hxx"
40
#include "DragMethod_RotateDiagram.hxx"
41
#include <ObjectHierarchy.hxx>
42
#include <RelativePositionHelper.hxx>
43
#include <chartview/DrawModelWrapper.hxx>
44
#include <RegressionCurveHelper.hxx>
45
#include <RegressionCurveModel.hxx>
46
#include <StatisticsHelper.hxx>
47
#include <DataSeries.hxx>
48
#include <DataSeriesProperties.hxx>
49
#include <Axis.hxx>
50
#include <AxisHelper.hxx>
51
#include <LegendHelper.hxx>
52
#include <servicenames_charttypes.hxx>
53
#include "DrawCommandDispatch.hxx"
54
#include <PopupRequest.hxx>
55
#include <ControllerCommandDispatch.hxx>
56
57
#include <com/sun/star/chart2/RelativePosition.hpp>
58
#include <com/sun/star/chart2/RelativeSize.hpp>
59
60
#include <com/sun/star/awt/PopupMenuDirection.hpp>
61
#include <com/sun/star/frame/DispatchHelper.hpp>
62
#include <com/sun/star/frame/FrameSearchFlag.hpp>
63
#include <com/sun/star/frame/XPopupMenuController.hpp>
64
#include <com/sun/star/awt/Rectangle.hpp>
65
66
#include <chart2/AbstractPivotTableDataProvider.hxx>
67
#include <comphelper/lok.hxx>
68
#include <comphelper/propertysequence.hxx>
69
#include <comphelper/propertyvalue.hxx>
70
71
#include <sfx2/viewsh.hxx>
72
#include <svx/ActionDescriptionProvider.hxx>
73
#include <svx/obj3d.hxx>
74
#include <svx/scene3d.hxx>
75
#include <svx/svddrgmt.hxx>
76
#include <vcl/commandevent.hxx>
77
#include <vcl/event.hxx>
78
#include <vcl/svapp.hxx>
79
#include <vcl/settings.hxx>
80
#include <vcl/weld/MessageDialog.hxx>
81
#include <vcl/weld/weld.hxx>
82
#include <vcl/ptrstyle.hxx>
83
#include <svtools/acceleratorexecute.hxx>
84
#include <comphelper/diagnose_ex.hxx>
85
#include <toolkit/awt/vclxmenu.hxx>
86
#include <sal/log.hxx>
87
#include <o3tl/string_view.hxx>
88
89
#include <boost/property_tree/json_parser.hpp>
90
#include <sfx2/dispatch.hxx>
91
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
92
93
0
#define DRGPIX    2     // Drag MinMove in Pixel
94
95
using namespace ::com::sun::star;
96
using namespace ::com::sun::star::chart2;
97
using namespace ::chart::DataSeriesProperties;
98
using ::com::sun::star::uno::Reference;
99
100
namespace chart
101
{
102
103
namespace
104
{
105
bool lcl_GrowAndShiftLogic(
106
    RelativePosition &  rInOutRelPos,
107
    RelativeSize &      rInOutRelSize,
108
    const awt::Size &   rRefSize,
109
    double              fGrowLogicX,
110
    double              fGrowLogicY )
111
0
{
112
0
    if( rRefSize.Width == 0 ||
113
0
        rRefSize.Height == 0 )
114
0
        return false;
115
116
0
    double fRelativeGrowX = fGrowLogicX / rRefSize.Width;
117
0
    double fRelativeGrowY = fGrowLogicY / rRefSize.Height;
118
119
0
    return ::chart::RelativePositionHelper::centerGrow(
120
0
        rInOutRelPos, rInOutRelSize,
121
0
        fRelativeGrowX, fRelativeGrowY );
122
0
}
123
124
bool lcl_MoveObjectLogic(
125
    RelativePosition &  rInOutRelPos,
126
    RelativeSize const & rObjectSize,
127
    const awt::Size &   rRefSize,
128
    double              fShiftLogicX,
129
    double              fShiftLogicY )
130
0
{
131
0
    if( rRefSize.Width == 0 ||
132
0
        rRefSize.Height == 0 )
133
0
        return false;
134
135
0
    double fRelativeShiftX = fShiftLogicX / rRefSize.Width;
136
0
    double fRelativeShiftY = fShiftLogicY / rRefSize.Height;
137
138
0
    return ::chart::RelativePositionHelper::moveObject(
139
0
        rInOutRelPos, rObjectSize,
140
0
        fRelativeShiftX, fRelativeShiftY );
141
0
}
142
143
void lcl_insertMenuCommand(
144
    const uno::Reference< awt::XPopupMenu > & xMenu,
145
    sal_Int16 nId, const OUString & rCommand )
146
0
{
147
0
    xMenu->insertItem( nId, u""_ustr, 0, -1 );
148
0
    xMenu->setCommand( nId, rCommand );
149
0
}
150
151
OUString lcl_getFormatCommandForObjectCID( std::u16string_view rCID )
152
0
{
153
0
    OUString aDispatchCommand( u".uno:FormatSelection"_ustr );
154
155
0
    ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID );
156
157
0
    switch(eObjectType)
158
0
    {
159
0
        case OBJECTTYPE_DIAGRAM:
160
0
        case OBJECTTYPE_DIAGRAM_WALL:
161
0
            aDispatchCommand = ".uno:FormatWall";
162
0
            break;
163
0
        case OBJECTTYPE_DIAGRAM_FLOOR:
164
0
            aDispatchCommand = ".uno:FormatFloor";
165
0
            break;
166
0
        case OBJECTTYPE_PAGE:
167
0
            aDispatchCommand = ".uno:FormatChartArea";
168
0
            break;
169
0
        case OBJECTTYPE_LEGEND:
170
0
            aDispatchCommand = ".uno:FormatLegend";
171
0
            break;
172
0
        case OBJECTTYPE_TITLE:
173
0
            aDispatchCommand = ".uno:FormatTitle";
174
0
            break;
175
0
        case OBJECTTYPE_LEGEND_ENTRY:
176
0
        case OBJECTTYPE_DATA_SERIES:
177
0
            aDispatchCommand = ".uno:FormatDataSeries";
178
0
            break;
179
0
        case OBJECTTYPE_AXIS:
180
0
        case OBJECTTYPE_AXIS_UNITLABEL:
181
0
            aDispatchCommand = ".uno:FormatAxis";
182
0
            break;
183
0
        case OBJECTTYPE_GRID:
184
0
            aDispatchCommand = ".uno:FormatMajorGrid";
185
0
            break;
186
0
        case OBJECTTYPE_SUBGRID:
187
0
            aDispatchCommand = ".uno:FormatMinorGrid";
188
0
            break;
189
0
        case OBJECTTYPE_DATA_LABELS:
190
0
            aDispatchCommand = ".uno:FormatDataLabels";
191
0
            break;
192
0
        case OBJECTTYPE_DATA_LABEL:
193
0
            aDispatchCommand = ".uno:FormatDataLabel";
194
0
            break;
195
0
        case OBJECTTYPE_DATA_POINT:
196
0
            aDispatchCommand = ".uno:FormatDataPoint";
197
0
            break;
198
0
        case OBJECTTYPE_DATA_AVERAGE_LINE:
199
0
            aDispatchCommand = ".uno:FormatMeanValue";
200
0
            break;
201
0
        case OBJECTTYPE_DATA_ERRORS_X:
202
0
            aDispatchCommand = ".uno:FormatXErrorBars";
203
0
            break;
204
0
        case OBJECTTYPE_DATA_ERRORS_Y:
205
0
            aDispatchCommand = ".uno:FormatYErrorBars";
206
0
            break;
207
0
        case OBJECTTYPE_DATA_ERRORS_Z:
208
0
            aDispatchCommand = ".uno:FormatZErrorBars";
209
0
            break;
210
0
        case OBJECTTYPE_DATA_CURVE:
211
0
            aDispatchCommand = ".uno:FormatTrendline";
212
0
            break;
213
0
        case OBJECTTYPE_DATA_CURVE_EQUATION:
214
0
            aDispatchCommand = ".uno:FormatTrendlineEquation";
215
0
            break;
216
0
        case OBJECTTYPE_DATA_STOCK_RANGE:
217
0
            aDispatchCommand = ".uno:FormatSelection";
218
0
            break;
219
0
        case OBJECTTYPE_DATA_STOCK_LOSS:
220
0
            aDispatchCommand = ".uno:FormatStockLoss";
221
0
            break;
222
0
        case OBJECTTYPE_DATA_STOCK_GAIN:
223
0
            aDispatchCommand = ".uno:FormatStockGain";
224
0
            break;
225
0
        default: //OBJECTTYPE_UNKNOWN
226
0
            break;
227
0
    }
228
0
    return aDispatchCommand;
229
0
}
230
231
} // anonymous namespace
232
233
// awt::XWindow
234
void SAL_CALL ChartController::setPosSize(
235
    sal_Int32 X,
236
    sal_Int32 Y,
237
    sal_Int32 Width,
238
    sal_Int32 Height,
239
    sal_Int16 Flags )
240
0
{
241
0
    SolarMutexGuard aGuard;
242
0
    auto pChartWindow(GetChartWindow());
243
244
0
    if(!(m_xViewWindow.is() && pChartWindow))
245
0
        return;
246
247
0
    Size aLogicSize = pChartWindow->PixelToLogic( Size( Width, Height ), MapMode( MapUnit::Map100thMM )  );
248
249
    //todo: for standalone chart: detect whether we are standalone
250
    //change map mode to fit new size
251
0
    awt::Size aModelPageSize = getChartModel()->getPageSize();
252
0
    double fScaleX = double(aLogicSize.Width()) / aModelPageSize.Width;
253
0
    double fScaleY = double(aLogicSize.Height()) / aModelPageSize.Height;
254
0
    MapMode aNewMapMode(
255
0
                MapUnit::Map100thMM,
256
0
                Point(0,0),
257
0
                fScaleX,
258
0
                fScaleY );
259
0
    pChartWindow->SetMapMode(aNewMapMode);
260
0
    pChartWindow->setPosSizePixel( X, Y, Width, Height, static_cast<PosSizeFlags>(Flags) );
261
262
    //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
263
0
    if( m_xChartView.is() )
264
0
    {
265
0
        Fraction aScaleXFrac(fScaleX);
266
0
        Fraction aScaleYFrac(fScaleY);
267
0
        auto aZoomFactors(::comphelper::InitPropertySequence({
268
0
            { "ScaleXNumerator", uno::Any( aScaleXFrac.GetNumerator() ) },
269
0
            { "ScaleXDenominator", uno::Any( aScaleXFrac.GetDenominator() ) },
270
0
            { "ScaleYNumerator", uno::Any( aScaleYFrac.GetNumerator() ) },
271
0
            { "ScaleYDenominator", uno::Any( aScaleYFrac.GetDenominator() ) }
272
0
        }));
273
0
        m_xChartView->setPropertyValue( u"ZoomFactors"_ustr, uno::Any( aZoomFactors ));
274
0
    }
275
276
    //a correct work area is at least necessary for correct values in the position and  size dialog and for dragging area
277
0
    if(m_pDrawViewWrapper)
278
0
    {
279
0
        tools::Rectangle aRect(Point(0,0), pChartWindow->GetOutDev()->GetOutputSize());
280
0
        m_pDrawViewWrapper->SetWorkArea( aRect );
281
0
    }
282
0
    pChartWindow->Invalidate();
283
0
}
284
285
awt::Rectangle SAL_CALL ChartController::getPosSize()
286
0
{
287
0
    awt::Rectangle aRet(0, 0, 0, 0);
288
289
0
    if (m_xViewWindow.is())
290
0
        aRet = m_xViewWindow->getPosSize();
291
292
0
    return aRet;
293
0
}
294
295
void SAL_CALL ChartController::setVisible( sal_Bool Visible )
296
0
{
297
0
    if (m_xViewWindow.is())
298
0
        m_xViewWindow->setVisible(Visible);
299
0
}
300
301
void SAL_CALL ChartController::setEnable( sal_Bool Enable )
302
0
{
303
0
    if (m_xViewWindow.is())
304
0
        m_xViewWindow->setEnable(Enable);
305
0
}
306
307
void SAL_CALL ChartController::setFocus()
308
0
{
309
0
    if (m_xViewWindow.is())
310
0
        m_xViewWindow->setFocus();
311
0
}
312
313
void SAL_CALL ChartController::addWindowListener(
314
    const uno::Reference< awt::XWindowListener >& xListener )
315
0
{
316
0
    if (m_xViewWindow.is())
317
0
        m_xViewWindow->addWindowListener(xListener);
318
0
}
319
320
void SAL_CALL ChartController::removeWindowListener(
321
    const uno::Reference< awt::XWindowListener >& xListener )
322
0
{
323
0
    if (m_xViewWindow.is())
324
0
        m_xViewWindow->removeWindowListener(xListener);
325
0
}
326
327
void SAL_CALL ChartController::addFocusListener(
328
    const uno::Reference< awt::XFocusListener >& xListener )
329
0
{
330
0
    if (m_xViewWindow.is())
331
0
        m_xViewWindow->addFocusListener(xListener);
332
0
}
333
334
void SAL_CALL ChartController::removeFocusListener(
335
    const uno::Reference< awt::XFocusListener >& xListener )
336
0
{
337
0
    if (m_xViewWindow.is())
338
0
        m_xViewWindow->removeFocusListener(xListener);
339
0
}
340
341
void SAL_CALL ChartController::addKeyListener(
342
    const uno::Reference< awt::XKeyListener >& xListener )
343
0
{
344
0
    if (m_xViewWindow.is())
345
0
        m_xViewWindow->addKeyListener(xListener);
346
0
}
347
348
void SAL_CALL ChartController::removeKeyListener(
349
    const uno::Reference< awt::XKeyListener >& xListener )
350
0
{
351
0
    if (m_xViewWindow.is())
352
0
        m_xViewWindow->removeKeyListener(xListener);
353
0
}
354
355
void SAL_CALL ChartController::addMouseListener(
356
    const uno::Reference< awt::XMouseListener >& xListener )
357
0
{
358
0
    if (m_xViewWindow.is())
359
0
        m_xViewWindow->addMouseListener(xListener);
360
0
}
361
362
void SAL_CALL ChartController::removeMouseListener(
363
    const uno::Reference< awt::XMouseListener >& xListener )
364
0
{
365
0
    if (m_xViewWindow.is())
366
0
        m_xViewWindow->removeMouseListener(xListener);
367
0
}
368
369
void SAL_CALL ChartController::addMouseMotionListener(
370
    const uno::Reference< awt::XMouseMotionListener >& xListener )
371
0
{
372
0
    if (m_xViewWindow.is())
373
0
        m_xViewWindow->addMouseMotionListener(xListener);
374
0
}
375
376
void SAL_CALL ChartController::removeMouseMotionListener(
377
    const uno::Reference< awt::XMouseMotionListener >& xListener )
378
0
{
379
0
    if (m_xViewWindow.is())
380
0
        m_xViewWindow->removeMouseMotionListener(xListener);
381
0
}
382
383
void SAL_CALL ChartController::addPaintListener(
384
    const uno::Reference< awt::XPaintListener >& xListener )
385
0
{
386
0
    if (m_xViewWindow.is())
387
0
        m_xViewWindow->addPaintListener(xListener);
388
0
}
389
390
void SAL_CALL ChartController::removePaintListener(
391
    const uno::Reference< awt::XPaintListener >& xListener )
392
0
{
393
0
    if (m_xViewWindow.is())
394
0
        m_xViewWindow->removePaintListener(xListener);
395
0
}
396
397
// impl vcl window controller methods
398
void ChartController::PrePaint()
399
0
{
400
    // forward VCLs PrePaint window event to DrawingLayer
401
0
    DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
402
403
0
    if (pDrawViewWrapper)
404
0
    {
405
0
        pDrawViewWrapper->PrePaint();
406
0
    }
407
0
}
408
409
void ChartController::execute_Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
410
0
{
411
0
    try
412
0
    {
413
0
        rtl::Reference<ChartModel> xModel(getChartModel());
414
        //OSL_ENSURE( xModel.is(), "ChartController::execute_Paint: have no model to paint");
415
0
        if (!xModel.is())
416
0
            return;
417
418
        //better performance for big data
419
0
        if (m_xChartView.is())
420
0
        {
421
0
            awt::Size aResolution(1000, 1000);
422
0
            {
423
0
                SolarMutexGuard aGuard;
424
0
                auto pChartWindow(GetChartWindow());
425
0
                if (pChartWindow)
426
0
                {
427
0
                    aResolution.Width = pChartWindow->GetSizePixel().Width();
428
0
                    aResolution.Height = pChartWindow->GetSizePixel().Height();
429
0
                }
430
0
            }
431
0
            m_xChartView->setPropertyValue( u"Resolution"_ustr, uno::Any( aResolution ));
432
0
        }
433
434
0
        if (m_xChartView.is())
435
0
            m_xChartView->update();
436
437
0
        {
438
0
            SolarMutexGuard aGuard;
439
0
            DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
440
0
            if (pDrawViewWrapper)
441
0
                pDrawViewWrapper->CompleteRedraw(&rRenderContext, vcl::Region(rRect));
442
0
        }
443
0
    }
444
0
    catch( const uno::Exception & )
445
0
    {
446
0
        DBG_UNHANDLED_EXCEPTION("chart2");
447
0
    }
448
0
    catch( ... )
449
0
    {
450
0
    }
451
0
}
452
453
static bool isDoubleClick( const MouseEvent& rMEvt )
454
0
{
455
0
    return rMEvt.GetClicks() == 2 && rMEvt.IsLeft() &&
456
0
        !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsShift();
457
0
}
458
459
void ChartController::startDoubleClickWaiting()
460
0
{
461
0
    SolarMutexGuard aGuard;
462
463
0
    m_bWaitingForDoubleClick = true;
464
465
0
    sal_uInt64 nDblClkTime = 500;
466
0
    auto pChartWindow(GetChartWindow());
467
0
    if( pChartWindow )
468
0
    {
469
0
        const MouseSettings& rMSettings = pChartWindow->GetSettings().GetMouseSettings();
470
0
        nDblClkTime = rMSettings.GetDoubleClickTime();
471
0
    }
472
0
    m_aDoubleClickTimer.SetTimeout( nDblClkTime );
473
0
    m_aDoubleClickTimer.Start();
474
0
}
475
476
void ChartController::stopDoubleClickWaiting()
477
0
{
478
0
    m_aDoubleClickTimer.Stop();
479
0
    m_bWaitingForDoubleClick = false;
480
0
}
481
482
IMPL_LINK_NOARG(ChartController, DoubleClickWaitingHdl, Timer *, void)
483
0
{
484
0
    m_bWaitingForDoubleClick = false;
485
486
0
    if( m_bWaitingForMouseUp || !m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() )
487
0
        return;
488
489
0
    impl_selectObjectAndNotiy();
490
0
    SolarMutexGuard aGuard;
491
0
    auto pChartWindow(GetChartWindow());
492
0
    if( pChartWindow )
493
0
    {
494
0
        vcl::Window::PointerState aPointerState( pChartWindow->GetPointerState() );
495
0
        MouseEvent aMouseEvent(
496
0
                        aPointerState.maPos,
497
0
                        1/*nClicks*/,
498
0
                        MouseEventModifiers::NONE,
499
0
                        static_cast< sal_uInt16 >( aPointerState.mnState )/*nButtons*/,
500
0
                        0/*nModifier*/ );
501
0
        impl_SetMousePointer( aMouseEvent );
502
0
    }
503
0
}
504
505
void ChartController::execute_MouseButtonDown( const MouseEvent& rMEvt )
506
0
{
507
0
    SolarMutexGuard aGuard;
508
509
0
    m_bWaitingForMouseUp = true;
510
0
    m_bFieldButtonDown = false;
511
512
0
    if( isDoubleClick(rMEvt) )
513
0
        stopDoubleClickWaiting();
514
0
    else
515
0
        startDoubleClickWaiting();
516
517
0
    m_aSelection.remindSelectionBeforeMouseDown();
518
519
0
    DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
520
0
    auto pChartWindow(GetChartWindow());
521
0
    if(!pChartWindow || !pDrawViewWrapper )
522
0
        return;
523
524
0
    Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel());
525
526
    // Check if button was clicked
527
0
    SdrObject* pObject = pDrawViewWrapper->getHitObject(aMPos);
528
0
    if (pObject)
529
0
    {
530
0
        OUString aCID = pObject->GetName();
531
0
        if (aCID.startsWith("FieldButton"))
532
0
        {
533
0
            m_bFieldButtonDown = true;
534
0
            return; // Don't take any action if button was clicked
535
0
        }
536
0
    }
537
538
0
    if ( rMEvt.GetButtons() == MOUSE_LEFT )
539
0
    {
540
0
        pChartWindow->GrabFocus();
541
0
        pChartWindow->CaptureMouse();
542
0
    }
543
544
0
    if( pDrawViewWrapper->IsTextEdit() )
545
0
    {
546
0
        SdrViewEvent aVEvt;
547
0
        if ( pDrawViewWrapper->IsTextEditHit( aMPos ) ||
548
             // #i12587# support for shapes in chart
549
0
             ( rMEvt.IsRight() && pDrawViewWrapper->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt ) == SdrHitKind::MarkedObject ) )
550
0
        {
551
0
            pDrawViewWrapper->MouseButtonDown(rMEvt, pChartWindow->GetOutDev());
552
0
            return;
553
0
        }
554
0
        else
555
0
        {
556
0
            EndTextEdit();
557
0
        }
558
0
    }
559
560
    //abort running action
561
0
    if( pDrawViewWrapper->IsAction() )
562
0
    {
563
0
        if( rMEvt.IsRight() )
564
0
            pDrawViewWrapper->BckAction();
565
0
        return;
566
0
    }
567
568
0
    if( isDoubleClick(rMEvt) ) //do not change selection if double click
569
0
        return;//double click is handled further in mousebutton up
570
571
0
    SdrHdl* pHitSelectionHdl = nullptr;
572
    //switch from move to resize if handle is hit on a resizable object
573
0
    if( m_aSelection.isResizeableObjectSelected() )
574
0
        pHitSelectionHdl = pDrawViewWrapper->PickHandle( aMPos );
575
    //only change selection if no selection handles are hit
576
0
    if( !pHitSelectionHdl )
577
0
    {
578
        // #i12587# support for shapes in chart
579
0
        if ( m_eDrawMode == CHARTDRAW_INSERT &&
580
0
             ( !pDrawViewWrapper->IsMarkedHit( aMPos ) || !m_aSelection.isDragableObjectSelected() ) )
581
0
        {
582
0
            if ( m_aSelection.hasSelection() )
583
0
            {
584
0
                m_aSelection.clearSelection();
585
0
            }
586
0
            if ( !pDrawViewWrapper->IsAction() )
587
0
            {
588
0
                if ( pDrawViewWrapper->GetCurrentObjIdentifier() == SdrObjKind::Caption )
589
0
                {
590
0
                    Size aCaptionSize( 2268, 1134 );
591
0
                    pDrawViewWrapper->BegCreateCaptionObj( aMPos, aCaptionSize );
592
0
                }
593
0
                else
594
0
                {
595
0
                    pDrawViewWrapper->BegCreateObj( aMPos);
596
0
                }
597
0
                SdrObject* pObj = pDrawViewWrapper->GetCreateObj();
598
0
                DrawCommandDispatch* pDrawCommandDispatch = m_aDispatchContainer.getDrawCommandDispatch();
599
0
                if ( pObj && m_pDrawModelWrapper && pDrawCommandDispatch )
600
0
                {
601
0
                    SfxItemSet aSet( m_pDrawModelWrapper->GetItemPool() );
602
0
                    pDrawCommandDispatch->setAttributes( pObj );
603
0
                    pDrawCommandDispatch->setLineEnds( aSet );
604
0
                    pObj->SetMergedItemSet( aSet );
605
0
                }
606
0
            }
607
0
            impl_SetMousePointer( rMEvt );
608
0
            return;
609
0
        }
610
611
0
        m_aSelection.adaptSelectionToNewPos(
612
0
                        aMPos,
613
0
                        pDrawViewWrapper,
614
0
                        rMEvt.IsRight(),
615
0
                        m_bWaitingForDoubleClick );
616
617
0
        if( !m_aSelection.isRotateableObjectSelected( getChartModel() ) )
618
0
        {
619
0
                m_eDragMode = SdrDragMode::Move;
620
0
                pDrawViewWrapper->SetDragMode(m_eDragMode);
621
0
        }
622
623
0
        m_aSelection.applySelection(pDrawViewWrapper);
624
0
    }
625
0
    if( m_aSelection.isDragableObjectSelected()
626
0
        && !rMEvt.IsRight() )
627
0
    {
628
        //start drag
629
0
        sal_uInt16  nDrgLog = static_cast<sal_uInt16>(pChartWindow->PixelToLogic(Size(DRGPIX,0)).Width());
630
0
        SdrDragMethod* pDragMethod = nullptr;
631
632
        //change selection to 3D scene if rotate mode
633
0
        SdrDragMode eDragMode = pDrawViewWrapper->GetDragMode();
634
0
        if( eDragMode==SdrDragMode::Rotate )
635
0
        {
636
0
            E3dScene* pScene = SelectionHelper::getSceneToRotate( pDrawViewWrapper->getNamedSdrObject( m_aSelection.getSelectedCID() ) );
637
0
            if( pScene )
638
0
            {
639
0
                DragMethod_RotateDiagram::RotationDirection eRotationDirection(DragMethod_RotateDiagram::ROTATIONDIRECTION_FREE);
640
0
                if(pHitSelectionHdl)
641
0
                {
642
0
                    SdrHdlKind eKind = pHitSelectionHdl->GetKind();
643
0
                    if( eKind==SdrHdlKind::Upper || eKind==SdrHdlKind::Lower )
644
0
                        eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_X;
645
0
                    else if( eKind==SdrHdlKind::Left || eKind==SdrHdlKind::Right )
646
0
                        eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Y;
647
0
                    else if( eKind==SdrHdlKind::UpperLeft || eKind==SdrHdlKind::UpperRight || eKind==SdrHdlKind::LowerLeft || eKind==SdrHdlKind::LowerRight )
648
0
                        eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Z;
649
0
                }
650
0
                pDragMethod = new DragMethod_RotateDiagram( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getChartModel(), eRotationDirection );
651
0
            }
652
0
        }
653
0
        else
654
0
        {
655
0
            std::u16string_view aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) );
656
0
            if( aDragMethodServiceName == ObjectIdentifier::getPieSegmentDragMethodServiceName() )
657
0
                pDragMethod = new DragMethod_PieSegment( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getChartModel() );
658
0
        }
659
0
        pDrawViewWrapper->SdrView::BegDragObj(aMPos, nullptr, pHitSelectionHdl, nDrgLog, pDragMethod);
660
0
    }
661
662
0
    impl_SetMousePointer( rMEvt );
663
0
}
664
665
void ChartController::execute_MouseMove( const MouseEvent& rMEvt )
666
0
{
667
0
    SolarMutexGuard aGuard;
668
669
0
    DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
670
0
    auto pChartWindow(GetChartWindow());
671
0
    if(!pChartWindow || !pDrawViewWrapper)
672
0
        return;
673
674
0
    if( m_pDrawViewWrapper->IsTextEdit() )
675
0
    {
676
0
        if( m_pDrawViewWrapper->MouseMove(rMEvt,pChartWindow->GetOutDev()) )
677
0
            return;
678
0
    }
679
680
0
    if(pDrawViewWrapper->IsAction())
681
0
    {
682
0
        pDrawViewWrapper->MovAction( pChartWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
683
0
    }
684
685
0
    impl_SetMousePointer( rMEvt );
686
0
}
687
688
void ChartController::execute_MouseButtonUp( const MouseEvent& rMEvt )
689
0
{
690
0
    ControllerLockGuardUNO aCLGuard( getChartModel() );
691
0
    bool bMouseUpWithoutMouseDown = !m_bWaitingForMouseUp;
692
0
    m_bWaitingForMouseUp = false;
693
0
    bool bNotifySelectionChange = false;
694
0
    bool bEditText = false;
695
0
    {
696
0
        SolarMutexGuard aGuard;
697
698
0
        DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
699
0
        auto pChartWindow(GetChartWindow());
700
0
        if(!pChartWindow || !pDrawViewWrapper)
701
0
            return;
702
703
0
        Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel());
704
705
        // Check if button was clicked
706
0
        if (m_bFieldButtonDown)
707
0
        {
708
0
            m_bFieldButtonDown = false;
709
0
            SdrObject* pObject = pDrawViewWrapper->getHitObject(aMPos);
710
0
            if (pObject)
711
0
            {
712
0
                OUString aCID = pObject->GetName();
713
0
                if (aCID.startsWith("FieldButton"))
714
0
                {
715
0
                    sendPopupRequest(aCID, pObject->GetCurrentBoundRect());
716
0
                    return;
717
0
                }
718
0
            }
719
0
        }
720
721
0
        if(pDrawViewWrapper->IsTextEdit())
722
0
        {
723
0
            if( pDrawViewWrapper->MouseButtonUp(rMEvt,pChartWindow->GetOutDev()) )
724
0
                return;
725
0
        }
726
727
        // #i12587# support for shapes in chart
728
0
        if ( m_eDrawMode == CHARTDRAW_INSERT && pDrawViewWrapper->IsCreateObj() )
729
0
        {
730
0
            pDrawViewWrapper->EndCreateObj( SdrCreateCmd::ForceEnd );
731
0
            {
732
0
                HiddenUndoContext aUndoContext( m_xUndoManager );
733
                    // don't want the positioning Undo action to appear in the UI
734
0
                impl_switchDiagramPositioningToExcludingPositioning();
735
0
            }
736
0
            if ( pDrawViewWrapper->GetMarkedObjectList().GetMarkCount() != 0 )
737
0
            {
738
0
                if ( pDrawViewWrapper->GetCurrentObjIdentifier() == SdrObjKind::Text )
739
0
                {
740
0
                    executeDispatch_EditText();
741
0
                }
742
0
                else
743
0
                {
744
0
                    SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
745
0
                    if ( pObj )
746
0
                    {
747
0
                        uno::Reference< drawing::XShape > xShape( pObj->getUnoShape(), uno::UNO_QUERY );
748
0
                        if ( xShape.is() )
749
0
                        {
750
0
                            m_aSelection.setSelection( xShape );
751
0
                            m_aSelection.applySelection( pDrawViewWrapper );
752
0
                        }
753
0
                    }
754
0
                }
755
0
            }
756
0
            else
757
0
            {
758
0
                m_aSelection.adaptSelectionToNewPos( aMPos, pDrawViewWrapper, rMEvt.IsRight(), m_bWaitingForDoubleClick );
759
0
                m_aSelection.applySelection( pDrawViewWrapper );
760
0
                setDrawMode( CHARTDRAW_SELECT );
761
0
            }
762
0
        }
763
0
        else if ( pDrawViewWrapper->IsDragObj() )
764
0
        {
765
0
            bool bDraggingDone = false;
766
0
            SdrDragMethod* pDragMethod = pDrawViewWrapper->SdrView::GetDragMethod();
767
0
            bool bIsMoveOnly = pDragMethod && pDragMethod->getMoveOnly();
768
0
            DragMethod_Base* pChartDragMethod = dynamic_cast< DragMethod_Base* >(pDragMethod);
769
0
            if( pChartDragMethod )
770
0
            {
771
0
                UndoGuard aUndoGuard( pChartDragMethod->getUndoDescription(),
772
0
                        m_xUndoManager );
773
774
0
                if( pDrawViewWrapper->EndDragObj() )
775
0
                {
776
0
                    bDraggingDone = true;
777
0
                    aUndoGuard.commit();
778
0
                }
779
0
            }
780
781
0
            if( !bDraggingDone && pDrawViewWrapper->EndDragObj() )
782
0
            {
783
0
                try
784
0
                {
785
                    //end move or size
786
0
                    SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
787
0
                    if( pObj )
788
0
                    {
789
0
                        tools::Rectangle aObjectRect = pObj->GetSnapRect();
790
0
                        tools::Rectangle aOldObjectRect = pObj->GetLastBoundRect();
791
0
                        awt::Size aPageSize( getChartModel()->getPageSize() );
792
0
                        tools::Rectangle aPageRect( 0,0,aPageSize.Width,aPageSize.Height );
793
794
0
                        const E3dObject* pE3dObject(DynCastE3dObject(pObj));
795
0
                        if(nullptr != pE3dObject)
796
0
                        {
797
0
                            E3dScene* pScene(pE3dObject->getRootE3dSceneFromE3dObject());
798
0
                            if(nullptr != pScene)
799
0
                            {
800
0
                                aObjectRect = pScene->GetSnapRect();
801
0
                            }
802
0
                        }
803
804
0
                        ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::ActionType::Move);
805
0
                        if( !bIsMoveOnly && m_aSelection.isResizeableObjectSelected() )
806
0
                            eActionType = ActionDescriptionProvider::ActionType::Resize;
807
808
0
                        ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
809
810
0
                        UndoGuard aUndoGuard(
811
0
                            ActionDescriptionProvider::createDescription( eActionType, ObjectNameProvider::getName( eObjectType)),
812
0
                            m_xUndoManager );
813
814
0
                        bool bChanged = false;
815
0
                        rtl::Reference< ChartModel > xModel = getChartModel();
816
0
                        if ( eObjectType == OBJECTTYPE_LEGEND )
817
0
                            bChanged = DiagramHelper::switchDiagramPositioningToExcludingPositioning( *xModel, false , true );
818
819
0
                        bool bMoved = PositionAndSizeHelper::moveObject( m_aSelection.getSelectedCID()
820
0
                                        , xModel
821
0
                                        , awt::Rectangle(aObjectRect.Left(),aObjectRect.Top(),aObjectRect.getOpenWidth(),aObjectRect.getOpenHeight())
822
0
                                        , awt::Rectangle(aOldObjectRect.Left(), aOldObjectRect.Top(), 0, 0)
823
0
                                        , awt::Rectangle(aPageRect.Left(),aPageRect.Top(),aPageRect.getOpenWidth(),aPageRect.getOpenHeight()) );
824
825
0
                        if( bMoved || bChanged )
826
0
                        {
827
0
                            bDraggingDone = true;
828
0
                            aUndoGuard.commit();
829
0
                        }
830
0
                    }
831
0
                }
832
0
                catch( const uno::Exception & )
833
0
                {
834
0
                    DBG_UNHANDLED_EXCEPTION("chart2");
835
0
                }
836
                //all wanted model changes will take effect
837
                //and all unwanted view modifications are cleaned
838
0
            }
839
840
0
            if( !bDraggingDone ) //mouse wasn't moved while dragging
841
0
            {
842
0
                bool bClickedTwiceOnDragableObject = SelectionHelper::isDragableObjectHitTwice( aMPos, m_aSelection.getSelectedCID(), *pDrawViewWrapper );
843
0
                bool bIsRotateable = m_aSelection.isRotateableObjectSelected( getChartModel() );
844
845
                //toggle between move and rotate
846
0
                if( bIsRotateable && bClickedTwiceOnDragableObject && m_eDragMode==SdrDragMode::Move )
847
0
                    m_eDragMode=SdrDragMode::Rotate;
848
0
                else
849
0
                    m_eDragMode=SdrDragMode::Move;
850
851
0
                pDrawViewWrapper->SetDragMode(m_eDragMode);
852
853
0
                if( !m_bWaitingForDoubleClick && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() )
854
0
                {
855
0
                    impl_selectObjectAndNotiy();
856
0
                }
857
0
            }
858
0
            else
859
0
                m_aSelection.resetPossibleSelectionAfterSingleClickWasEnsured();
860
0
        }
861
862
        //@todo ForcePointer(&rMEvt);
863
0
        pChartWindow->ReleaseMouse();
864
865
        // In tiled rendering drag mode could be not yet over on the call
866
        // that should handle the double-click, so better to perform this check
867
        // always.
868
0
        if( isDoubleClick(rMEvt) && !bMouseUpWithoutMouseDown /*#i106966#*/ )
869
0
        {
870
0
            Point aMousePixel = rMEvt.GetPosPixel();
871
0
            execute_DoubleClick( &aMousePixel, bEditText );
872
0
        }
873
874
0
        if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() )
875
0
            bNotifySelectionChange = true;
876
0
    }
877
878
0
    impl_SetMousePointer( rMEvt );
879
880
0
    if(bNotifySelectionChange || bEditText)
881
0
        impl_notifySelectionChangeListeners();
882
0
}
883
884
void ChartController::execute_DoubleClick( const Point* pMousePixel, bool &bEditText )
885
0
{
886
0
    const SfxViewShell* pViewShell = SfxViewShell::Current();
887
0
    bool notAllowed = pViewShell && (pViewShell->isLOKMobilePhone() || pViewShell->IsLokReadOnlyView());
888
0
    if (notAllowed)
889
0
        return;
890
891
0
    if ( m_aSelection.hasSelection() )
892
0
    {
893
0
        OUString aCID( m_aSelection.getSelectedCID() );
894
0
        if ( !aCID.isEmpty() )
895
0
        {
896
0
            ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID );
897
0
            if ( eObjectType == OBJECTTYPE_TITLE )
898
0
            {
899
0
                bEditText = true;
900
0
            }
901
0
        }
902
0
        else
903
0
        {
904
            // #i12587# support for shapes in chart
905
0
            SdrObject* pObj = DrawViewWrapper::getSdrObject( m_aSelection.getSelectedAdditionalShape() );
906
0
            if ( DynCastSdrTextObj(pObj) !=  nullptr )
907
0
            {
908
0
                bEditText = true;
909
0
            }
910
0
        }
911
0
    }
912
913
0
    if ( bEditText )
914
0
    {
915
0
        executeDispatch_EditText( pMousePixel );
916
0
    }
917
0
    else
918
0
    {
919
0
        executeDispatch_ObjectProperties();
920
0
    }
921
0
}
922
923
void ChartController::execute_Resize()
924
0
{
925
0
    SolarMutexGuard aGuard;
926
0
    auto pChartWindow(GetChartWindow());
927
0
    if(pChartWindow)
928
0
        pChartWindow->Invalidate();
929
0
}
930
931
void ChartController::execute_Command( const CommandEvent& rCEvt )
932
0
{
933
0
    SolarMutexGuard aGuard;
934
0
    auto pChartWindow(GetChartWindow());
935
0
    DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
936
0
    if(!pChartWindow || !pDrawViewWrapper)
937
0
        return;
938
0
    bool bIsAction = m_pDrawViewWrapper->IsAction();
939
940
    // pop-up menu
941
0
    if(rCEvt.GetCommand() == CommandEventId::ContextMenu && !bIsAction)
942
0
    {
943
0
        pChartWindow->ReleaseMouse();
944
945
0
        if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() )
946
0
            impl_notifySelectionChangeListeners();
947
948
0
        rtl::Reference< VCLXPopupMenu > xPopupMenu = new VCLXPopupMenu();
949
950
0
        Point aPos( rCEvt.GetMousePosPixel() );
951
0
        if( !rCEvt.IsMouseEvent() )
952
0
        {
953
0
            aPos = pChartWindow->GetPointerState().maPos;
954
0
        }
955
956
0
        OUString aMenuName;
957
0
        if ( isShapeContext() )
958
            // #i12587# support for shapes in chart
959
0
            aMenuName = m_pDrawViewWrapper->IsTextEdit() ? std::u16string_view( u"drawtext" ) : std::u16string_view( u"draw" );
960
0
        else
961
0
        {
962
0
            ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
963
964
            // todo: the context menu should be specified by an xml file in uiconfig
965
0
            sal_Int16 nUniqueId = 1;
966
0
            if (eObjectType != OBJECTTYPE_DATA_TABLE)
967
0
            {
968
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:Cut"_ustr );
969
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:Copy"_ustr );
970
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:Paste"_ustr );
971
0
                xPopupMenu->insertSeparator( -1 );
972
0
            }
973
974
0
            rtl::Reference< Diagram > xDiagram = getFirstDiagram();
975
976
0
            OUString aFormatCommand( lcl_getFormatCommandForObjectCID( m_aSelection.getSelectedCID() ) );
977
0
            lcl_insertMenuCommand( xPopupMenu, nUniqueId++, aFormatCommand );
978
0
            if (eObjectType == OBJECTTYPE_TITLE && m_pDrawViewWrapper->IsTextEdit())
979
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FontDialog"_ustr );
980
981
            //some commands for dataseries and points:
982
983
0
            if( eObjectType == OBJECTTYPE_DATA_SERIES || eObjectType == OBJECTTYPE_DATA_POINT )
984
0
            {
985
0
                bool bIsPoint = ( eObjectType == OBJECTTYPE_DATA_POINT );
986
0
                rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getChartModel() );
987
0
                rtl::Reference< RegressionCurveModel > xTrendline = RegressionCurveHelper::getFirstCurveNotMeanValueLine( xSeries );
988
0
                bool bHasEquation = RegressionCurveHelper::hasEquation( xTrendline );
989
0
                rtl::Reference< RegressionCurveModel > xMeanValue = RegressionCurveHelper::getMeanValueLine( xSeries );
990
0
                bool bHasYErrorBars = StatisticsHelper::hasErrorBars( xSeries );
991
0
                bool bHasXErrorBars = StatisticsHelper::hasErrorBars( xSeries, false );
992
0
                bool bHasDataLabelsAtSeries = xSeries->hasDataLabelsAtSeries();
993
0
                bool bHasDataLabelsAtPoints = xSeries->hasDataLabelsAtPoints();
994
0
                bool bHasDataLabelAtPoint = false;
995
0
                sal_Int32 nPointIndex = -1;
996
0
                if( bIsPoint )
997
0
                {
998
0
                    nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( m_aSelection.getSelectedCID() );
999
0
                    bHasDataLabelAtPoint = xSeries->hasDataLabelAtPoint( nPointIndex );
1000
0
                }
1001
0
                bool bSelectedPointIsFormatted = false;
1002
0
                bool bHasFormattedDataPointsOtherThanSelected = false;
1003
1004
0
                if( xSeries.is() )
1005
0
                {
1006
0
                    uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
1007
                    // "AttributedDataPoints"
1008
0
                    if( xSeries->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS ) >>= aAttributedDataPointIndexList )
1009
0
                    {
1010
0
                        if( aAttributedDataPointIndexList.hasElements() )
1011
0
                        {
1012
0
                            if( bIsPoint )
1013
0
                            {
1014
0
                                auto aIt = std::find( aAttributedDataPointIndexList.begin(), aAttributedDataPointIndexList.end(), nPointIndex );
1015
0
                                if (aIt != aAttributedDataPointIndexList.end())
1016
0
                                    bSelectedPointIsFormatted = true;
1017
0
                                else
1018
0
                                    bHasFormattedDataPointsOtherThanSelected = true;
1019
0
                            }
1020
0
                            else
1021
0
                                bHasFormattedDataPointsOtherThanSelected = true;
1022
0
                        }
1023
0
                    }
1024
0
                }
1025
1026
0
                if( bIsPoint )
1027
0
                {
1028
0
                    if( bHasDataLabelAtPoint )
1029
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatDataLabel"_ustr );
1030
0
                    if( !bHasDataLabelAtPoint )
1031
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertDataLabel"_ustr );
1032
0
                    else
1033
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DeleteDataLabel"_ustr );
1034
0
                    if( bSelectedPointIsFormatted )
1035
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:ResetDataPoint"_ustr );
1036
1037
0
                    xPopupMenu->insertSeparator( -1 );
1038
1039
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatDataSeries"_ustr );
1040
0
                }
1041
1042
0
                rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeOfSeries( xSeries ) );
1043
0
                if( xChartType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK )
1044
0
                {
1045
0
                    try
1046
0
                    {
1047
0
                        bool bJapaneseStyle = false;
1048
0
                        xChartType->getPropertyValue( u"Japanese"_ustr ) >>= bJapaneseStyle;
1049
1050
0
                        if( bJapaneseStyle )
1051
0
                        {
1052
0
                            lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatStockLoss"_ustr );
1053
0
                            lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatStockGain"_ustr );
1054
0
                        }
1055
0
                    }
1056
0
                    catch( const uno::Exception & )
1057
0
                    {
1058
0
                        DBG_UNHANDLED_EXCEPTION("chart2");
1059
0
                    }
1060
0
                }
1061
1062
0
                if( bHasDataLabelsAtSeries )
1063
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatDataLabels"_ustr );
1064
0
                if( bHasEquation )
1065
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatTrendlineEquation"_ustr );
1066
0
                if( xMeanValue.is() )
1067
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatMeanValue"_ustr );
1068
0
                if( bHasXErrorBars )
1069
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatXErrorBars"_ustr );
1070
0
                if( bHasYErrorBars )
1071
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatYErrorBars"_ustr );
1072
1073
0
                xPopupMenu->insertSeparator( -1 );
1074
1075
0
                if( !bHasDataLabelsAtSeries )
1076
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertDataLabels"_ustr );
1077
1078
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertTrendline"_ustr );
1079
1080
0
                if( !xMeanValue.is() )
1081
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertMeanValue"_ustr );
1082
0
                if( !bHasXErrorBars )
1083
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertXErrorBars"_ustr );
1084
0
                if( !bHasYErrorBars )
1085
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertYErrorBars"_ustr );
1086
0
                if( bHasDataLabelsAtSeries || ( bHasDataLabelsAtPoints && bHasFormattedDataPointsOtherThanSelected ) )
1087
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DeleteDataLabels"_ustr );
1088
0
                if( bHasEquation )
1089
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DeleteTrendlineEquation"_ustr );
1090
0
                if( xMeanValue.is() )
1091
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DeleteMeanValue"_ustr );
1092
0
                if( bHasXErrorBars )
1093
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DeleteXErrorBars"_ustr );
1094
0
                if( bHasYErrorBars )
1095
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DeleteYErrorBars"_ustr );
1096
1097
0
                if( bHasFormattedDataPointsOtherThanSelected )
1098
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:ResetAllDataPoints"_ustr );
1099
1100
0
                xPopupMenu->insertSeparator( -1 );
1101
1102
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId, u".uno:ArrangeRow"_ustr );
1103
0
                rtl::Reference< VCLXPopupMenu > xArrangePopupMenu = new VCLXPopupMenu();
1104
0
                sal_Int16 nSubId = nUniqueId + 1;
1105
0
                lcl_insertMenuCommand( xArrangePopupMenu, nSubId++, u".uno:Forward"_ustr );
1106
0
                lcl_insertMenuCommand( xArrangePopupMenu, nSubId, u".uno:Backward"_ustr );
1107
0
                xPopupMenu->setPopupMenu( nUniqueId, xArrangePopupMenu );
1108
0
                nUniqueId = nSubId;
1109
0
                ++nUniqueId;
1110
0
            }
1111
0
            else if( eObjectType == OBJECTTYPE_DATA_CURVE )
1112
0
            {
1113
0
                lcl_insertMenuCommand( xPopupMenu,  nUniqueId++, u".uno:DeleteTrendline"_ustr );
1114
0
                lcl_insertMenuCommand( xPopupMenu,  nUniqueId++, u".uno:FormatTrendlineEquation"_ustr );
1115
0
                lcl_insertMenuCommand( xPopupMenu,  nUniqueId++, u".uno:InsertTrendlineEquation"_ustr );
1116
0
                lcl_insertMenuCommand( xPopupMenu,  nUniqueId++, u".uno:InsertTrendlineEquationAndR2"_ustr );
1117
0
                lcl_insertMenuCommand( xPopupMenu,  nUniqueId++, u".uno:InsertR2Value"_ustr );
1118
0
                lcl_insertMenuCommand( xPopupMenu,  nUniqueId++, u".uno:DeleteTrendlineEquation"_ustr );
1119
0
                lcl_insertMenuCommand( xPopupMenu,  nUniqueId++, u".uno:DeleteR2Value"_ustr );
1120
0
            }
1121
0
            else if( eObjectType == OBJECTTYPE_DATA_CURVE_EQUATION )
1122
0
            {
1123
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertR2Value"_ustr );
1124
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DeleteR2Value"_ustr );
1125
0
            }
1126
1127
            //some commands for axes: and grids
1128
1129
0
            else if( eObjectType  == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_GRID || eObjectType == OBJECTTYPE_SUBGRID )
1130
0
            {
1131
0
                rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getChartModel() );
1132
0
                if( xAxis.is() && xDiagram.is() )
1133
0
                {
1134
0
                    sal_Int32 nDimensionIndex = -1;
1135
0
                    sal_Int32 nCooSysIndex = -1;
1136
0
                    sal_Int32 nAxisIndex = -1;
1137
0
                    AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex );
1138
0
                    bool bIsSecondaryAxis = nAxisIndex!=0;
1139
0
                    bool bIsAxisVisible = AxisHelper::isAxisVisible( xAxis );
1140
0
                    bool bIsMajorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, true /*bMainGrid*/, xDiagram );
1141
0
                    bool bIsMinorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, false /*bMainGrid*/, xDiagram );
1142
0
                    bool bHasTitle = !TitleHelper::getCompleteString( xAxis->getTitleObject2() ).isEmpty();
1143
1144
0
                    if( eObjectType  != OBJECTTYPE_AXIS && bIsAxisVisible )
1145
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatAxis"_ustr );
1146
0
                    if( eObjectType != OBJECTTYPE_GRID && bIsMajorGridVisible && !bIsSecondaryAxis )
1147
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatMajorGrid"_ustr );
1148
0
                    if( eObjectType != OBJECTTYPE_SUBGRID && bIsMinorGridVisible && !bIsSecondaryAxis )
1149
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatMinorGrid"_ustr );
1150
1151
0
                    xPopupMenu->insertSeparator( -1 );
1152
1153
0
                    if( eObjectType  != OBJECTTYPE_AXIS && !bIsAxisVisible )
1154
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertAxis"_ustr );
1155
0
                    if( eObjectType != OBJECTTYPE_GRID && !bIsMajorGridVisible && !bIsSecondaryAxis )
1156
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertMajorGrid"_ustr );
1157
0
                    if( eObjectType != OBJECTTYPE_SUBGRID && !bIsMinorGridVisible && !bIsSecondaryAxis )
1158
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertMinorGrid"_ustr );
1159
0
                    if( !bHasTitle )
1160
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertAxisTitle"_ustr );
1161
1162
0
                    if( bIsAxisVisible )
1163
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DeleteAxis"_ustr );
1164
0
                    if( bIsMajorGridVisible && !bIsSecondaryAxis )
1165
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DeleteMajorGrid"_ustr );
1166
0
                    if( bIsMinorGridVisible && !bIsSecondaryAxis )
1167
0
                        lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DeleteMinorGrid"_ustr );
1168
0
                    if (bIsAxisVisible)
1169
0
                        lcl_insertMenuCommand(xPopupMenu,  nUniqueId++, u".uno:InsertDataTable"_ustr);
1170
0
                }
1171
0
            }
1172
0
            else if (eObjectType == OBJECTTYPE_DATA_TABLE)
1173
0
            {
1174
0
                lcl_insertMenuCommand(xPopupMenu,  nUniqueId++, u".uno:DeleteDataTable"_ustr);
1175
0
            }
1176
1177
0
            if( eObjectType == OBJECTTYPE_DATA_STOCK_LOSS )
1178
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatStockGain"_ustr );
1179
0
            else if( eObjectType == OBJECTTYPE_DATA_STOCK_GAIN )
1180
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:FormatStockLoss"_ustr );
1181
1182
0
            lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:TransformDialog"_ustr );
1183
1184
0
            if( eObjectType == OBJECTTYPE_PAGE || eObjectType == OBJECTTYPE_DIAGRAM
1185
0
                || eObjectType == OBJECTTYPE_DIAGRAM_WALL
1186
0
                || eObjectType == OBJECTTYPE_DIAGRAM_FLOOR
1187
0
                || eObjectType == OBJECTTYPE_UNKNOWN )
1188
0
            {
1189
0
                if( eObjectType != OBJECTTYPE_UNKNOWN )
1190
0
                    xPopupMenu->insertSeparator( -1 );
1191
0
                bool bHasLegend = LegendHelper::hasLegend( xDiagram );
1192
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertTitles"_ustr );
1193
0
                if( !bHasLegend )
1194
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertLegend"_ustr );
1195
0
                lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:InsertRemoveAxes"_ustr );
1196
0
                if( bHasLegend )
1197
0
                    lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DeleteLegend"_ustr );
1198
0
            }
1199
1200
0
            xPopupMenu->insertSeparator( -1 );
1201
0
            lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DiagramType"_ustr );
1202
0
            lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DataRanges"_ustr );
1203
0
            lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:DiagramData"_ustr );
1204
0
            lcl_insertMenuCommand( xPopupMenu, nUniqueId++, u".uno:View3D"_ustr );
1205
0
        }
1206
1207
0
        css::uno::Sequence< css::uno::Any > aArgs{
1208
0
            css::uno::Any(comphelper::makePropertyValue( u"IsContextMenu"_ustr, true )),
1209
0
            css::uno::Any(comphelper::makePropertyValue( u"Frame"_ustr, m_xFrame )),
1210
0
            css::uno::Any(comphelper::makePropertyValue( u"Value"_ustr, aMenuName ))
1211
0
        };
1212
1213
0
        css::uno::Reference< css::frame::XPopupMenuController > xPopupController(
1214
0
            m_xCC->getServiceManager()->createInstanceWithArgumentsAndContext(
1215
0
            u"com.sun.star.comp.framework.ResourceMenuController"_ustr, aArgs, m_xCC ), css::uno::UNO_QUERY );
1216
1217
0
        if ( !xPopupController.is() || !xPopupMenu.is() )
1218
0
            return;
1219
1220
0
        xPopupController->setPopupMenu( xPopupMenu );
1221
1222
0
        if (comphelper::LibreOfficeKit::isActive())
1223
0
        {
1224
0
            if (SfxViewShell* pViewShell = SfxViewShell::Current())
1225
0
            {
1226
0
                const ControllerCommandDispatch* pCommandDispatch = m_aDispatchContainer.getChartDispatcher();
1227
0
                if (pCommandDispatch)
1228
0
                {
1229
0
                    for (int nPos = 0, nCount = xPopupMenu->getItemCount(); nPos < nCount; ++nPos)
1230
0
                    {
1231
0
                        auto nItemId = xPopupMenu->getItemId(nPos);
1232
0
                        OUString aCommandURL = xPopupMenu->getCommand(nItemId);
1233
0
                        if (!pCommandDispatch->commandAvailable(aCommandURL))
1234
0
                            xPopupMenu->enableItem(nItemId, false);
1235
0
                    }
1236
0
                }
1237
1238
0
                boost::property_tree::ptree aMenu = SfxDispatcher::fillPopupMenu(xPopupMenu);
1239
0
                boost::property_tree::ptree aRoot;
1240
0
                aRoot.add_child("menu", aMenu);
1241
1242
0
                std::stringstream aStream;
1243
0
                boost::property_tree::write_json(aStream, aRoot, true);
1244
0
                pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU, OString(aStream.str()));
1245
0
            }
1246
0
        }
1247
0
        else
1248
0
        {
1249
0
            xPopupMenu->execute( css::uno::Reference< css::awt::XWindowPeer >( m_xFrame->getContainerWindow(), css::uno::UNO_QUERY ),
1250
0
                                 css::awt::Rectangle( aPos.X(), aPos.Y(), 0, 0 ),
1251
0
                                 css::awt::PopupMenuDirection::EXECUTE_DEFAULT );
1252
0
        }
1253
1254
0
        css::uno::Reference< css::lang::XComponent > xComponent( xPopupController, css::uno::UNO_QUERY );
1255
0
        if ( xComponent.is() )
1256
0
            xComponent->dispose();
1257
0
    }
1258
0
    else if( ( rCEvt.GetCommand() == CommandEventId::StartExtTextInput ) ||
1259
0
             ( rCEvt.GetCommand() == CommandEventId::ExtTextInput ) ||
1260
0
             ( rCEvt.GetCommand() == CommandEventId::EndExtTextInput ) ||
1261
0
             ( rCEvt.GetCommand() == CommandEventId::InputContextChange ) )
1262
0
    {
1263
        //#i84417# enable editing with IME
1264
0
        m_pDrawViewWrapper->Command( rCEvt, pChartWindow );
1265
0
    }
1266
0
}
1267
1268
bool ChartController::execute_KeyInput( const KeyEvent& rKEvt )
1269
0
{
1270
0
    SolarMutexGuard aGuard;
1271
0
    bool bReturn=false;
1272
1273
0
    DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
1274
0
    auto pChartWindow(GetChartWindow());
1275
0
    if (!pChartWindow || !pDrawViewWrapper)
1276
0
        return bReturn;
1277
1278
    // handle accelerators
1279
0
    if (!m_apAccelExecute && m_xFrame.is() && m_xCC.is())
1280
0
    {
1281
0
        m_apAccelExecute = ::svt::AcceleratorExecute::createAcceleratorHelper();
1282
0
        OSL_ASSERT(m_apAccelExecute);
1283
0
        if (m_apAccelExecute)
1284
0
            m_apAccelExecute->init( m_xCC, m_xFrame );
1285
0
    }
1286
1287
0
    vcl::KeyCode aKeyCode( rKEvt.GetKeyCode());
1288
0
    sal_uInt16 nCode = aKeyCode.GetCode();
1289
0
    bool bAlternate = aKeyCode.IsMod2();
1290
0
    bool bCtrl = aKeyCode.IsMod1();
1291
1292
0
    if (m_apAccelExecute)
1293
0
        bReturn = m_apAccelExecute->execute( aKeyCode );
1294
0
    if( bReturn )
1295
0
        return bReturn;
1296
1297
0
    if( pDrawViewWrapper->IsTextEdit() )
1298
0
    {
1299
0
        if( pDrawViewWrapper->KeyInput(rKEvt, pChartWindow) )
1300
0
        {
1301
0
            bReturn = true;
1302
0
            if( nCode == KEY_ESCAPE )
1303
0
            {
1304
0
                EndTextEdit();
1305
0
            }
1306
0
        }
1307
0
    }
1308
1309
    // keyboard accessibility
1310
0
    ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
1311
0
    if( ! bReturn )
1312
0
    {
1313
        // Navigation (Tab/F3/Home/End)
1314
0
        rtl::Reference<::chart::ChartModel> xChartDoc( getChartModel() );
1315
0
        ObjectKeyNavigation aObjNav( m_aSelection.getSelectedOID(), xChartDoc, m_xChartView.get() );
1316
0
        awt::KeyEvent aKeyEvent( ::svt::AcceleratorExecute::st_VCLKey2AWTKey( aKeyCode ));
1317
0
        bReturn = aObjNav.handleKeyEvent( aKeyEvent );
1318
0
        if( bReturn )
1319
0
        {
1320
0
            const ObjectIdentifier& aNewOID = aObjNav.getCurrentSelection();
1321
0
            uno::Any aNewSelection;
1322
0
            if ( aNewOID.isValid() && !ObjectHierarchy::isRootNode( aNewOID ) )
1323
0
            {
1324
0
                aNewSelection = aNewOID.getAny();
1325
0
            }
1326
0
            if ( m_eDragMode == SdrDragMode::Rotate && !SelectionHelper::isRotateableObject( aNewOID.getObjectCID(), getChartModel() ) )
1327
0
            {
1328
0
                m_eDragMode = SdrDragMode::Move;
1329
0
            }
1330
0
            bReturn = select( aNewSelection );
1331
0
        }
1332
0
    }
1333
1334
    // Position and Size (+/-/arrow-keys) or pie segment dragging
1335
0
    if( ! bReturn  )
1336
0
    {
1337
        // pie segment dragging
1338
        // note: could also be done for data series
1339
0
        if( eObjectType == OBJECTTYPE_DATA_POINT &&
1340
0
            ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) ==
1341
0
                ObjectIdentifier::getPieSegmentDragMethodServiceName())
1342
0
        {
1343
0
            bool bDrag = false;
1344
0
            bool bDragInside = false;
1345
0
            if( nCode == KEY_ADD ||
1346
0
                nCode == KEY_SUBTRACT )
1347
0
            {
1348
0
                bDrag = true;
1349
0
                bDragInside = ( nCode == KEY_SUBTRACT );
1350
0
            }
1351
0
            else if(
1352
0
                nCode == KEY_LEFT ||
1353
0
                nCode == KEY_RIGHT ||
1354
0
                nCode == KEY_UP ||
1355
0
                nCode == KEY_DOWN )
1356
0
            {
1357
0
                bDrag = true;
1358
0
                std::u16string_view aParameter( ObjectIdentifier::getDragParameterString( m_aSelection.getSelectedCID() ));
1359
0
                sal_Int32 nOffsetPercentDummy( 0 );
1360
0
                awt::Point aMinimumPosition( 0, 0 );
1361
0
                awt::Point aMaximumPosition( 0, 0 );
1362
0
                ObjectIdentifier::parsePieSegmentDragParameterString(
1363
0
                    aParameter, nOffsetPercentDummy, aMinimumPosition, aMaximumPosition );
1364
0
                aMaximumPosition.Y -= aMinimumPosition.Y;
1365
0
                aMaximumPosition.X -= aMinimumPosition.X;
1366
1367
0
                bDragInside =
1368
0
                    (nCode == KEY_RIGHT && (aMaximumPosition.X < 0)) ||
1369
0
                    (nCode == KEY_LEFT  && (aMaximumPosition.X > 0)) ||
1370
0
                    (nCode == KEY_DOWN  && (aMaximumPosition.Y < 0)) ||
1371
0
                    (nCode == KEY_UP    && (aMaximumPosition.Y > 0));
1372
0
            }
1373
1374
0
            if( bDrag )
1375
0
            {
1376
0
                double fAmount = bAlternate ? 0.01 : 0.05;
1377
0
                if( bDragInside )
1378
0
                    fAmount *= -1.0;
1379
1380
0
                bReturn = impl_DragDataPoint( m_aSelection.getSelectedCID(), fAmount );
1381
0
            }
1382
0
        }
1383
0
        else
1384
0
        {
1385
            // size
1386
0
            if( nCode == KEY_ADD ||
1387
0
                nCode == KEY_SUBTRACT )
1388
0
            {
1389
0
                if( eObjectType == OBJECTTYPE_DIAGRAM )
1390
0
                {
1391
                    // default 1 mm in each direction
1392
0
                    double fGrowAmountX = 200.0;
1393
0
                    double fGrowAmountY = 200.0;
1394
0
                    if (bAlternate)
1395
0
                    {
1396
                        // together with Alt-key: 1 px in each direction
1397
0
                        Size aPixelSize = pChartWindow->PixelToLogic( Size( 2, 2 ));
1398
0
                        fGrowAmountX = static_cast< double >( aPixelSize.Width());
1399
0
                        fGrowAmountY = static_cast< double >( aPixelSize.Height());
1400
0
                    }
1401
0
                    if( nCode == KEY_SUBTRACT )
1402
0
                    {
1403
0
                        fGrowAmountX = -fGrowAmountX;
1404
0
                        fGrowAmountY = -fGrowAmountY;
1405
0
                    }
1406
0
                    bReturn = impl_moveOrResizeObject(
1407
0
                        m_aSelection.getSelectedCID(), CENTERED_RESIZE_OBJECT, fGrowAmountX, fGrowAmountY );
1408
0
                }
1409
0
            }
1410
            // position
1411
0
            else if( nCode == KEY_LEFT  ||
1412
0
                     nCode == KEY_RIGHT ||
1413
0
                     nCode == KEY_UP ||
1414
0
                     nCode == KEY_DOWN )
1415
0
            {
1416
0
                if( m_aSelection.isDragableObjectSelected() )
1417
0
                {
1418
                    // default 1 mm
1419
0
                    double fShiftAmountX = 100.0;
1420
0
                    double fShiftAmountY = 100.0;
1421
0
                    if (bAlternate)
1422
0
                    {
1423
                        // together with Alt-key: 1 px
1424
0
                        Size aPixelSize = pChartWindow->PixelToLogic( Size( 1, 1 ));
1425
0
                        fShiftAmountX = static_cast< double >( aPixelSize.Width());
1426
0
                        fShiftAmountY = static_cast< double >( aPixelSize.Height());
1427
0
                    }
1428
0
                    switch( nCode )
1429
0
                    {
1430
0
                        case KEY_LEFT:
1431
0
                            fShiftAmountX = -fShiftAmountX;
1432
0
                            fShiftAmountY = 0.0;
1433
0
                            break;
1434
0
                        case KEY_RIGHT:
1435
0
                            fShiftAmountY = 0.0;
1436
0
                            break;
1437
0
                        case KEY_UP:
1438
0
                            fShiftAmountX = 0.0;
1439
0
                            fShiftAmountY = -fShiftAmountY;
1440
0
                            break;
1441
0
                        case KEY_DOWN:
1442
0
                            fShiftAmountX = 0.0;
1443
0
                            break;
1444
0
                    }
1445
0
                    if( !m_aSelection.getSelectedCID().isEmpty() )
1446
0
                    {
1447
                        //move chart objects
1448
0
                        if (eObjectType == OBJECTTYPE_DATA_LABEL)
1449
0
                        {
1450
0
                            SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
1451
0
                            if (pObj)
1452
0
                            {
1453
0
                                tools::Rectangle aRect = pObj->GetSnapRect();
1454
0
                                awt::Size aPageSize(getChartModel()->getPageSize());
1455
0
                                if ((fShiftAmountX > 0.0 && (aRect.Right() + fShiftAmountX > aPageSize.Width)) ||
1456
0
                                    (fShiftAmountX < 0.0 && (aRect.Left() + fShiftAmountX < 0)) ||
1457
0
                                    (fShiftAmountY > 0.0 && (aRect.Bottom() + fShiftAmountY > aPageSize.Height)) ||
1458
0
                                    (fShiftAmountY < 0.0 && (aRect.Top() + fShiftAmountY < 0)))
1459
0
                                    bReturn = false;
1460
0
                                else
1461
0
                                    bReturn = PositionAndSizeHelper::moveObject(
1462
0
                                        m_aSelection.getSelectedCID(), getChartModel(),
1463
0
                                        awt::Rectangle(aRect.Left() + fShiftAmountX, aRect.Top() + fShiftAmountY, aRect.getOpenWidth(), aRect.getOpenHeight()),
1464
0
                                        awt::Rectangle(aRect.Left(), aRect.Top(), 0, 0),
1465
0
                                        awt::Rectangle(0, 0, aPageSize.Width, aPageSize.Height));
1466
0
                            }
1467
0
                        }
1468
0
                        else
1469
0
                            bReturn = impl_moveOrResizeObject(
1470
0
                                m_aSelection.getSelectedCID(), MOVE_OBJECT, fShiftAmountX, fShiftAmountY );
1471
0
                    }
1472
0
                    else
1473
0
                    {
1474
                        //move additional shapes
1475
0
                        uno::Reference< drawing::XShape > xShape( m_aSelection.getSelectedAdditionalShape() );
1476
0
                        if( xShape.is() )
1477
0
                        {
1478
0
                            awt::Point aPos( xShape->getPosition() );
1479
0
                            awt::Size aSize( xShape->getSize() );
1480
0
                            awt::Size aPageSize( getChartModel()->getPageSize() );
1481
0
                            aPos.X = static_cast< tools::Long >( static_cast< double >( aPos.X ) + fShiftAmountX );
1482
0
                            aPos.Y = static_cast< tools::Long >( static_cast< double >( aPos.Y ) + fShiftAmountY );
1483
0
                            if( aPos.X + aSize.Width > aPageSize.Width )
1484
0
                                aPos.X = aPageSize.Width - aSize.Width;
1485
0
                            if( aPos.X < 0 )
1486
0
                                aPos.X = 0;
1487
0
                            if( aPos.Y + aSize.Height > aPageSize.Height )
1488
0
                                aPos.Y = aPageSize.Height - aSize.Height;
1489
0
                            if( aPos.Y < 0 )
1490
0
                                aPos.Y = 0;
1491
1492
0
                            xShape->setPosition( aPos );
1493
0
                        }
1494
0
                    }
1495
0
                }
1496
0
            }
1497
0
        }
1498
0
    }
1499
1500
    // dumping the shape
1501
0
    if( !bReturn && bCtrl && nCode == KEY_F12)
1502
0
    {
1503
0
        rtl::Reference< ChartModel > xChartModel = getChartModel();
1504
0
        if(xChartModel.is())
1505
0
        {
1506
0
            OUString aDump = xChartModel->dump(u"shapes"_ustr);
1507
0
            SAL_WARN("chart2", aDump);
1508
0
        }
1509
0
    }
1510
1511
    // text edit
1512
0
    if( ! bReturn &&
1513
0
        nCode == KEY_F2 )
1514
0
    {
1515
0
        if( eObjectType == OBJECTTYPE_TITLE )
1516
0
        {
1517
0
            executeDispatch_EditText();
1518
0
            bReturn = true;
1519
0
        }
1520
0
    }
1521
1522
    // deactivate inplace mode (this code should be unnecessary, but
1523
    // unfortunately is not)
1524
0
    if( ! bReturn &&
1525
0
        nCode == KEY_ESCAPE )
1526
0
    {
1527
0
        uno::Reference< frame::XDispatchHelper > xDispatchHelper( frame::DispatchHelper::create(m_xCC) );
1528
0
        uno::Sequence< beans::PropertyValue > aArgs;
1529
0
        xDispatchHelper->executeDispatch(
1530
0
            uno::Reference< frame::XDispatchProvider >( m_xFrame, uno::UNO_QUERY ),
1531
0
            u".uno:TerminateInplaceActivation"_ustr,
1532
0
            u"_parent"_ustr,
1533
0
            frame::FrameSearchFlag::PARENT,
1534
0
            aArgs );
1535
0
        bReturn = true;
1536
0
    }
1537
1538
0
    if( ! bReturn &&
1539
0
        (nCode == KEY_DELETE || nCode == KEY_BACKSPACE ))
1540
0
    {
1541
0
        bReturn = executeDispatch_Delete();
1542
0
        if( ! bReturn )
1543
0
        {
1544
0
            std::shared_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pChartWindow->GetFrameWeld(),
1545
0
                                                          VclMessageType::Info, VclButtonsType::Ok,
1546
0
                                                          SchResId(STR_ACTION_NOTPOSSIBLE)));
1547
0
            xInfoBox->runAsync(xInfoBox, [] (int) {});
1548
0
        }
1549
0
    }
1550
1551
0
    return bReturn;
1552
0
}
1553
1554
bool ChartController::requestQuickHelp(
1555
    ::Point aAtLogicPosition,
1556
    bool bIsBalloonHelp,
1557
    OUString & rOutQuickHelpText,
1558
    awt::Rectangle & rOutEqualRect )
1559
0
{
1560
0
    rtl::Reference<::chart::ChartModel> xChartModel;
1561
0
    if( m_aModel.is())
1562
0
        xChartModel = getChartModel();
1563
0
    if( !xChartModel.is())
1564
0
        return false;
1565
1566
    // help text
1567
0
    OUString aCID;
1568
0
    if( m_pDrawViewWrapper )
1569
0
    {
1570
0
        aCID = SelectionHelper::getHitObjectCID(
1571
0
            aAtLogicPosition, *m_pDrawViewWrapper );
1572
0
    }
1573
0
    bool bResult( !aCID.isEmpty());
1574
1575
0
    if( bResult )
1576
0
    {
1577
        // get help text
1578
0
        rOutQuickHelpText = ObjectNameProvider::getHelpText( aCID, xChartModel, bIsBalloonHelp /* bVerbose */ );
1579
1580
        // set rectangle
1581
0
        if( m_xChartView )
1582
0
            rOutEqualRect = m_xChartView->getRectangleOfObject( aCID, true );
1583
0
    }
1584
1585
0
    return bResult;
1586
0
}
1587
1588
// XSelectionSupplier (optional interface)
1589
sal_Bool SAL_CALL ChartController::select( const uno::Any& rSelection )
1590
0
{
1591
0
    bool bSuccess = false;
1592
1593
0
    if ( rSelection.hasValue() )
1594
0
    {
1595
0
        if (rSelection.getValueType() == cppu::UnoType<OUString>::get())
1596
0
        {
1597
0
            OUString aNewCID;
1598
0
            if ( ( rSelection >>= aNewCID ) && m_aSelection.setSelection( aNewCID ) )
1599
0
            {
1600
0
                bSuccess = true;
1601
0
            }
1602
0
        }
1603
0
        else if (uno::Reference<drawing::XShape> xShape; rSelection >>= xShape)
1604
0
        {
1605
0
            if (m_aSelection.setSelection(xShape))
1606
0
            {
1607
0
                bSuccess = true;
1608
0
            }
1609
0
        }
1610
0
    }
1611
0
    else
1612
0
    {
1613
0
        if ( m_aSelection.hasSelection() )
1614
0
        {
1615
0
            m_aSelection.clearSelection();
1616
0
            bSuccess = true;
1617
0
        }
1618
0
    }
1619
1620
0
    if ( bSuccess )
1621
0
    {
1622
0
        SolarMutexGuard aGuard;
1623
0
        if ( m_pDrawViewWrapper && m_pDrawViewWrapper->IsTextEdit() )
1624
0
        {
1625
0
            EndTextEdit();
1626
0
        }
1627
0
        impl_selectObjectAndNotiy();
1628
0
        auto pChartWindow(GetChartWindow());
1629
0
        if ( pChartWindow )
1630
0
        {
1631
0
            pChartWindow->Invalidate();
1632
0
        }
1633
0
        return true;
1634
0
    }
1635
1636
0
    return false;
1637
0
}
1638
1639
uno::Any SAL_CALL ChartController::getSelection()
1640
0
{
1641
0
    uno::Any aReturn;
1642
0
    if ( m_aSelection.hasSelection() )
1643
0
    {
1644
0
        OUString aCID( m_aSelection.getSelectedCID() );
1645
0
        if ( !aCID.isEmpty() )
1646
0
        {
1647
0
            aReturn <<= aCID;
1648
0
        }
1649
0
        else
1650
0
        {
1651
            // #i12587# support for shapes in chart
1652
0
            aReturn <<= m_aSelection.getSelectedAdditionalShape();
1653
0
        }
1654
0
    }
1655
0
    return aReturn;
1656
0
}
1657
1658
void SAL_CALL ChartController::addSelectionChangeListener( const uno::Reference<view::XSelectionChangeListener> & xListener )
1659
0
{
1660
0
    SolarMutexGuard aGuard;
1661
0
    if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode?
1662
0
        return; //behave passive if already disposed or suspended
1663
1664
    //--add listener
1665
0
    std::unique_lock aGuard2(m_aLifeTimeManager.m_aAccessMutex);
1666
0
    m_aLifeTimeManager.m_aSelectionChangeListeners.addInterface( aGuard2, xListener );
1667
0
}
1668
1669
void SAL_CALL ChartController::removeSelectionChangeListener( const uno::Reference<view::XSelectionChangeListener> & xListener )
1670
0
{
1671
0
    SolarMutexGuard aGuard;
1672
0
    if( impl_isDisposedOrSuspended() ) //@todo? allow removing of listeners in suspend mode?
1673
0
        return; //behave passive if already disposed or suspended
1674
1675
    //--remove listener
1676
0
    std::unique_lock aGuard2(m_aLifeTimeManager.m_aAccessMutex);
1677
0
    m_aLifeTimeManager.m_aSelectionChangeListeners.removeInterface( aGuard2, xListener );
1678
0
}
1679
1680
void ChartController::impl_notifySelectionChangeListeners()
1681
0
{
1682
0
    std::unique_lock aGuard(m_aLifeTimeManager.m_aAccessMutex);
1683
0
    if( m_aLifeTimeManager.m_aSelectionChangeListeners.getLength(aGuard) )
1684
0
    {
1685
0
        uno::Reference< view::XSelectionSupplier > xSelectionSupplier(this);
1686
0
        lang::EventObject aEvent( xSelectionSupplier );
1687
0
        m_aLifeTimeManager.m_aSelectionChangeListeners.notifyEach(aGuard, &view::XSelectionChangeListener::selectionChanged, aEvent);
1688
0
    }
1689
0
}
1690
1691
void ChartController::impl_selectObjectAndNotiy()
1692
0
{
1693
0
    {
1694
0
        SolarMutexGuard aGuard;
1695
0
        DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
1696
0
        if( pDrawViewWrapper )
1697
0
        {
1698
0
            pDrawViewWrapper->SetDragMode( m_eDragMode );
1699
0
            m_aSelection.applySelection( m_pDrawViewWrapper.get() );
1700
0
        }
1701
0
    }
1702
0
    impl_notifySelectionChangeListeners();
1703
0
}
1704
1705
bool ChartController::impl_moveOrResizeObject(
1706
    const OUString & rCID,
1707
    eMoveOrResizeType eType,
1708
    double fAmountLogicX,
1709
    double fAmountLogicY )
1710
0
{
1711
0
    bool bResult = false;
1712
0
    bool bNeedResize = ( eType == CENTERED_RESIZE_OBJECT );
1713
1714
0
    rtl::Reference<::chart::ChartModel> xChartModel( getChartModel() );
1715
0
    uno::Reference< beans::XPropertySet > xObjProp(
1716
0
        ObjectIdentifier::getObjectPropertySet( rCID, xChartModel ));
1717
0
    if( xObjProp.is())
1718
0
    {
1719
0
        awt::Size aRefSize = xChartModel->getPageSize();
1720
1721
0
        chart2::RelativePosition aRelPos;
1722
0
        chart2::RelativeSize     aRelSize;
1723
0
        bool bDeterminePos  = !(xObjProp->getPropertyValue( u"RelativePosition"_ustr) >>= aRelPos);
1724
0
        bool bDetermineSize = !bNeedResize || !(xObjProp->getPropertyValue( u"RelativeSize"_ustr) >>= aRelSize);
1725
1726
0
        if( ( bDeterminePos || bDetermineSize ) &&
1727
0
            ( aRefSize.Width > 0 && aRefSize.Height > 0 ) )
1728
0
        {
1729
0
            ChartView * pValueProvider( m_xChartView.get() );
1730
0
            if( pValueProvider )
1731
0
            {
1732
0
                awt::Rectangle aRect( pValueProvider->getRectangleOfObject( rCID ));
1733
0
                double fWidth = static_cast< double >( aRefSize.Width );
1734
0
                double fHeight = static_cast< double >( aRefSize.Height );
1735
0
                if( bDetermineSize )
1736
0
                {
1737
0
                    aRelSize.Primary   = static_cast< double >( aRect.Width ) / fWidth;
1738
0
                    aRelSize.Secondary = static_cast< double >( aRect.Height ) / fHeight;
1739
0
                }
1740
0
                if( bDeterminePos )
1741
0
                {
1742
0
                    if( bNeedResize && aRelSize.Primary > 0.0 && aRelSize.Secondary > 0.0 )
1743
0
                    {
1744
0
                        aRelPos.Primary   = (static_cast< double >( aRect.X ) / fWidth) +
1745
0
                            (aRelSize.Primary / 2.0);
1746
0
                        aRelPos.Secondary = (static_cast< double >( aRect.Y ) / fHeight) +
1747
0
                            (aRelSize.Secondary / 2.0);
1748
0
                        aRelPos.Anchor = drawing::Alignment_CENTER;
1749
0
                    }
1750
0
                    else
1751
0
                    {
1752
0
                        aRelPos.Primary   = static_cast< double >( aRect.X ) / fWidth;
1753
0
                        aRelPos.Secondary = static_cast< double >( aRect.Y ) / fHeight;
1754
0
                        aRelPos.Anchor = drawing::Alignment_TOP_LEFT;
1755
0
                    }
1756
0
                }
1757
0
            }
1758
0
        }
1759
1760
0
        if( eType == CENTERED_RESIZE_OBJECT )
1761
0
            bResult = lcl_GrowAndShiftLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY );
1762
0
        else if( eType == MOVE_OBJECT )
1763
0
            bResult = lcl_MoveObjectLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY );
1764
1765
0
        if( bResult )
1766
0
        {
1767
0
            ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::ActionType::Move);
1768
0
            if( bNeedResize )
1769
0
                eActionType = ActionDescriptionProvider::ActionType::Resize;
1770
1771
0
            ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID );
1772
0
            UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription(
1773
0
                    eActionType, ObjectNameProvider::getName( eObjectType )), m_xUndoManager );
1774
0
            {
1775
0
                ControllerLockGuardUNO aCLGuard( xChartModel );
1776
0
                xObjProp->setPropertyValue( u"RelativePosition"_ustr, uno::Any( aRelPos ));
1777
0
                if( bNeedResize || (eObjectType == OBJECTTYPE_DIAGRAM) )//Also set an explicit size at the diagram when an explicit position is set
1778
0
                    xObjProp->setPropertyValue( u"RelativeSize"_ustr, uno::Any( aRelSize ));
1779
0
            }
1780
0
            aUndoGuard.commit();
1781
0
        }
1782
0
    }
1783
0
    return bResult;
1784
0
}
1785
1786
bool ChartController::impl_DragDataPoint( std::u16string_view rCID, double fAdditionalOffset )
1787
0
{
1788
0
    bool bResult = false;
1789
0
    if( fAdditionalOffset < -1.0 || fAdditionalOffset > 1.0 || fAdditionalOffset == 0.0 )
1790
0
        return bResult;
1791
1792
0
    sal_Int32 nDataPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rCID );
1793
0
    rtl::Reference< DataSeries > xSeries =
1794
0
        ObjectIdentifier::getDataSeriesForCID( rCID, getChartModel() );
1795
0
    if( xSeries.is())
1796
0
    {
1797
0
        try
1798
0
        {
1799
0
            uno::Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex( nDataPointIndex ));
1800
0
            double fOffset = 0.0;
1801
0
            if( xPointProp.is() &&
1802
0
                (xPointProp->getPropertyValue( u"Offset"_ustr ) >>= fOffset ) &&
1803
0
                (( fAdditionalOffset > 0.0 && fOffset < 1.0 ) || (fOffset > 0.0)) )
1804
0
            {
1805
0
                fOffset += fAdditionalOffset;
1806
0
                if( fOffset > 1.0 )
1807
0
                    fOffset = 1.0;
1808
0
                else if( fOffset < 0.0 )
1809
0
                    fOffset = 0.0;
1810
0
                xPointProp->setPropertyValue( u"Offset"_ustr, uno::Any( fOffset ));
1811
0
                bResult = true;
1812
0
            }
1813
0
        }
1814
0
        catch( const uno::Exception & )
1815
0
        {
1816
0
            DBG_UNHANDLED_EXCEPTION("chart2");
1817
0
        }
1818
0
    }
1819
1820
0
    return bResult;
1821
0
}
1822
1823
void ChartController::impl_SetMousePointer( const MouseEvent & rEvent )
1824
0
{
1825
0
    SolarMutexGuard aGuard;
1826
0
    auto pChartWindow(GetChartWindow());
1827
1828
0
    if (!m_pDrawViewWrapper || !pChartWindow)
1829
0
        return;
1830
1831
0
    Point aMousePos( pChartWindow->PixelToLogic( rEvent.GetPosPixel()));
1832
0
    sal_uInt16 nModifier = rEvent.GetModifier();
1833
0
    bool bLeftDown = rEvent.IsLeft();
1834
1835
    // Check if object is for field button and set the normal arrow pointer in this case
1836
0
    SdrObject* pObject = m_pDrawViewWrapper->getHitObject(aMousePos);
1837
0
    if (pObject && pObject->GetName().startsWith("FieldButton"))
1838
0
    {
1839
0
        pChartWindow->SetPointer(PointerStyle::Arrow);
1840
0
        return;
1841
0
    }
1842
1843
0
    if ( m_pDrawViewWrapper->IsTextEdit() )
1844
0
    {
1845
0
        if( m_pDrawViewWrapper->IsTextEditHit( aMousePos ) )
1846
0
        {
1847
0
            pChartWindow->SetPointer( m_pDrawViewWrapper->GetPreferredPointer(
1848
0
                aMousePos, pChartWindow->GetOutDev(), nModifier, bLeftDown ) );
1849
0
            return;
1850
0
        }
1851
0
    }
1852
0
    else if( m_pDrawViewWrapper->IsAction() )
1853
0
    {
1854
0
        return;//don't change pointer during running action
1855
0
    }
1856
1857
0
    SdrHdl* pHitSelectionHdl = nullptr;
1858
0
    if( m_aSelection.isResizeableObjectSelected() )
1859
0
        pHitSelectionHdl = m_pDrawViewWrapper->PickHandle( aMousePos );
1860
1861
0
    if( pHitSelectionHdl )
1862
0
    {
1863
0
        PointerStyle aPointer = m_pDrawViewWrapper->GetPreferredPointer(
1864
0
            aMousePos, pChartWindow->GetOutDev(), nModifier, bLeftDown );
1865
0
        bool bForceArrowPointer = false;
1866
1867
0
        ObjectIdentifier aOID( m_aSelection.getSelectedOID() );
1868
1869
0
        switch( aPointer)
1870
0
        {
1871
0
            case PointerStyle::NSize:
1872
0
            case PointerStyle::SSize:
1873
0
            case PointerStyle::WSize:
1874
0
            case PointerStyle::ESize:
1875
0
            case PointerStyle::NWSize:
1876
0
            case PointerStyle::NESize:
1877
0
            case PointerStyle::SWSize:
1878
0
            case PointerStyle::SESize:
1879
0
                if( ! m_aSelection.isResizeableObjectSelected() )
1880
0
                    bForceArrowPointer = true;
1881
0
                break;
1882
0
            case PointerStyle::Move:
1883
0
                if ( !aOID.isDragableObject() )
1884
0
                    bForceArrowPointer = true;
1885
0
                break;
1886
0
            case PointerStyle::MovePoint:
1887
0
            case PointerStyle::MoveBezierWeight:
1888
                // there is no point-editing in a chart
1889
                // the PointerStyle::MoveBezierWeight appears in 3d data points
1890
0
                bForceArrowPointer = true;
1891
0
                break;
1892
0
            default:
1893
0
                break;
1894
0
        }
1895
1896
0
        if( bForceArrowPointer )
1897
0
            pChartWindow->SetPointer( PointerStyle::Arrow );
1898
0
        else
1899
0
            pChartWindow->SetPointer( aPointer );
1900
1901
0
        return;
1902
0
    }
1903
1904
    // #i12587# support for shapes in chart
1905
0
    if ( m_eDrawMode == CHARTDRAW_INSERT &&
1906
0
         ( !m_pDrawViewWrapper->IsMarkedHit( aMousePos ) || !m_aSelection.isDragableObjectSelected() ) )
1907
0
    {
1908
0
        PointerStyle ePointerStyle = PointerStyle::DrawRect;
1909
0
        SdrObjKind eKind = m_pDrawViewWrapper->GetCurrentObjIdentifier();
1910
0
        switch ( eKind )
1911
0
        {
1912
0
            case SdrObjKind::Line:
1913
0
                {
1914
0
                    ePointerStyle = PointerStyle::DrawLine;
1915
0
                }
1916
0
                break;
1917
0
            case SdrObjKind::Rectangle:
1918
0
            case SdrObjKind::CustomShape:
1919
0
                {
1920
0
                    ePointerStyle = PointerStyle::DrawRect;
1921
0
                }
1922
0
                break;
1923
0
            case SdrObjKind::CircleOrEllipse:
1924
0
                {
1925
0
                    ePointerStyle = PointerStyle::DrawEllipse;
1926
0
                }
1927
0
                break;
1928
0
            case SdrObjKind::FreehandLine:
1929
0
                {
1930
0
                    ePointerStyle = PointerStyle::DrawPolygon;
1931
0
                }
1932
0
                break;
1933
0
            case SdrObjKind::Text:
1934
0
                {
1935
0
                    ePointerStyle = PointerStyle::DrawText;
1936
0
                }
1937
0
                break;
1938
0
            case SdrObjKind::Caption:
1939
0
                {
1940
0
                    ePointerStyle = PointerStyle::DrawCaption;
1941
0
                }
1942
0
                break;
1943
0
            default:
1944
0
                {
1945
0
                    ePointerStyle = PointerStyle::DrawRect;
1946
0
                }
1947
0
                break;
1948
0
        }
1949
0
        pChartWindow->SetPointer( ePointerStyle );
1950
0
        return;
1951
0
    }
1952
1953
0
    OUString aHitObjectCID(
1954
0
        SelectionHelper::getHitObjectCID(
1955
0
            aMousePos, *m_pDrawViewWrapper, true /*bGetDiagramInsteadOf_Wall*/ ));
1956
1957
0
    if( m_pDrawViewWrapper->IsTextEdit() )
1958
0
    {
1959
0
        if( aHitObjectCID == m_aSelection.getSelectedCID() )
1960
0
        {
1961
0
            pChartWindow->SetPointer( PointerStyle::Arrow );
1962
0
            return;
1963
0
        }
1964
0
    }
1965
1966
0
    if( aHitObjectCID.isEmpty() )
1967
0
    {
1968
        //additional shape was hit
1969
0
        pChartWindow->SetPointer( PointerStyle::Move );
1970
0
    }
1971
0
    else if( ObjectIdentifier::isDragableObject( aHitObjectCID ) )
1972
0
    {
1973
0
        if( (m_eDragMode == SdrDragMode::Rotate)
1974
0
            && SelectionHelper::isRotateableObject( aHitObjectCID
1975
0
                , getChartModel() ) )
1976
0
            pChartWindow->SetPointer( PointerStyle::Rotate );
1977
0
        else
1978
0
        {
1979
0
            ObjectType eHitObjectType = ObjectIdentifier::getObjectType( aHitObjectCID );
1980
0
            if( eHitObjectType == OBJECTTYPE_DATA_POINT )
1981
0
            {
1982
0
                if( !ObjectIdentifier::areSiblings(aHitObjectCID,m_aSelection.getSelectedCID())
1983
0
                    && !ObjectIdentifier::areIdenticalObjects(aHitObjectCID,m_aSelection.getSelectedCID()) )
1984
0
                {
1985
0
                    pChartWindow->SetPointer( PointerStyle::Arrow );
1986
0
                    return;
1987
0
                }
1988
0
            }
1989
0
            pChartWindow->SetPointer( PointerStyle::Move );
1990
0
        }
1991
0
    }
1992
0
    else
1993
0
        pChartWindow->SetPointer( PointerStyle::Arrow );
1994
0
}
1995
1996
void ChartController::sendPopupRequest(std::u16string_view rCID, tools::Rectangle aRectangle)
1997
0
{
1998
0
    ChartModel* pChartModel = m_aModel->getModel().get();
1999
0
    if (!pChartModel)
2000
0
        return;
2001
2002
0
    chart2api::AbstractPivotTableDataProvider* pPivotTableDataProvider =
2003
0
        dynamic_cast<chart2api::AbstractPivotTableDataProvider*>(pChartModel->getDataProvider().get());
2004
0
    if (!pPivotTableDataProvider)
2005
0
        return;
2006
2007
0
    OUString sPivotTableName = pPivotTableDataProvider->getPivotTableName();
2008
2009
0
    css::uno::Reference<css::awt::XRequestCallback> xPopupRequest = pChartModel->getPopupRequest();
2010
0
    PopupRequest* pPopupRequest = dynamic_cast<PopupRequest*>(xPopupRequest.get());
2011
0
    if (!pPopupRequest)
2012
0
        return;
2013
2014
    // Get dimension index from CID
2015
0
    size_t nStartPos = rCID.rfind('.');
2016
0
    nStartPos = (nStartPos == std::u16string_view::npos) ? 0 : (nStartPos + 1);
2017
0
    sal_Int32 nEndPos = rCID.size();
2018
0
    std::u16string_view sDimensionIndex = rCID.substr(nStartPos, nEndPos - nStartPos);
2019
0
    sal_Int32 nDimensionIndex = o3tl::toInt32(sDimensionIndex);
2020
2021
0
    awt::Rectangle xRectangle {
2022
0
        sal_Int32(aRectangle.Left()),
2023
0
        sal_Int32(aRectangle.Top()),
2024
0
        sal_Int32(aRectangle.GetWidth()),
2025
0
        sal_Int32(aRectangle.GetHeight())
2026
0
    };
2027
2028
0
    uno::Sequence<beans::PropertyValue> aCallbackData = comphelper::InitPropertySequence(
2029
0
    {
2030
0
        {"Rectangle",      uno::Any(xRectangle)},
2031
0
        {"DimensionIndex", uno::Any(sal_Int32(nDimensionIndex))},
2032
0
        {"PivotTableName", uno::Any(sPivotTableName)},
2033
0
    });
2034
2035
0
    pPopupRequest->getCallback()->notify(uno::Any(aCallbackData));
2036
0
}
2037
2038
} //namespace chart
2039
2040
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */