1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <string_view>
24 #include <ChartController.hxx>
25 #include <ChartView.hxx>
26 #include <PositionAndSizeHelper.hxx>
27 #include <ObjectIdentifier.hxx>
28 #include <ChartWindow.hxx>
30 #include <ChartModel.hxx>
31 #include <ChartModelHelper.hxx>
32 #include <ChartType.hxx>
33 #include <DiagramHelper.hxx>
34 #include <Diagram.hxx>
35 #include <TitleHelper.hxx>
36 #include "UndoGuard.hxx"
37 #include <ControllerLockGuard.hxx>
38 #include <ObjectNameProvider.hxx>
39 #include <strings.hrc>
40 #include "DragMethod_PieSegment.hxx"
41 #include "DragMethod_RotateDiagram.hxx"
42 #include <ObjectHierarchy.hxx>
43 #include <chartview/ExplicitValueProvider.hxx>
44 #include <RelativePositionHelper.hxx>
45 #include <chartview/DrawModelWrapper.hxx>
46 #include <RegressionCurveHelper.hxx>
47 #include <RegressionCurveModel.hxx>
48 #include <StatisticsHelper.hxx>
49 #include <DataSeries.hxx>
50 #include <DataSeriesHelper.hxx>
51 #include <DataSeriesProperties.hxx>
53 #include <AxisHelper.hxx>
54 #include <LegendHelper.hxx>
55 #include <servicenames_charttypes.hxx>
56 #include "DrawCommandDispatch.hxx"
57 #include <PopupRequest.hxx>
58 #include "ControllerCommandDispatch.hxx"
60 #include <com/sun/star/chart2/RelativePosition.hpp>
61 #include <com/sun/star/chart2/RelativeSize.hpp>
62 #include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
64 #include <com/sun/star/awt/PopupMenuDirection.hpp>
65 #include <com/sun/star/frame/DispatchHelper.hpp>
66 #include <com/sun/star/frame/FrameSearchFlag.hpp>
67 #include <com/sun/star/frame/XPopupMenuController.hpp>
68 #include <com/sun/star/awt/Rectangle.hpp>
70 #include <comphelper/lok.hxx>
71 #include <comphelper/propertysequence.hxx>
72 #include <comphelper/propertyvalue.hxx>
74 #include <sfx2/viewsh.hxx>
75 #include <svx/ActionDescriptionProvider.hxx>
76 #include <svx/obj3d.hxx>
77 #include <svx/scene3d.hxx>
78 #include <svx/svddrgmt.hxx>
79 #include <vcl/commandevent.hxx>
80 #include <vcl/event.hxx>
81 #include <vcl/svapp.hxx>
82 #include <vcl/settings.hxx>
83 #include <vcl/weld.hxx>
84 #include <vcl/ptrstyle.hxx>
85 #include <svtools/acceleratorexecute.hxx>
86 #include <comphelper/diagnose_ex.hxx>
87 #include <toolkit/awt/vclxmenu.hxx>
88 #include <sal/log.hxx>
89 #include <o3tl/string_view.hxx>
91 #include <boost/property_tree/json_parser.hpp>
92 #include <sfx2/dispatch.hxx>
93 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
95 #define DRGPIX 2 // Drag MinMove in Pixel
97 using namespace ::com::sun::star
;
98 using namespace ::com::sun::star::chart2
;
99 using namespace ::chart::DataSeriesProperties
;
100 using ::com::sun::star::uno::Reference
;
107 bool lcl_GrowAndShiftLogic(
108 RelativePosition
& rInOutRelPos
,
109 RelativeSize
& rInOutRelSize
,
110 const awt::Size
& rRefSize
,
114 if( rRefSize
.Width
== 0 ||
115 rRefSize
.Height
== 0 )
118 double fRelativeGrowX
= fGrowLogicX
/ rRefSize
.Width
;
119 double fRelativeGrowY
= fGrowLogicY
/ rRefSize
.Height
;
121 return ::chart::RelativePositionHelper::centerGrow(
122 rInOutRelPos
, rInOutRelSize
,
123 fRelativeGrowX
, fRelativeGrowY
);
126 bool lcl_MoveObjectLogic(
127 RelativePosition
& rInOutRelPos
,
128 RelativeSize
const & rObjectSize
,
129 const awt::Size
& rRefSize
,
131 double fShiftLogicY
)
133 if( rRefSize
.Width
== 0 ||
134 rRefSize
.Height
== 0 )
137 double fRelativeShiftX
= fShiftLogicX
/ rRefSize
.Width
;
138 double fRelativeShiftY
= fShiftLogicY
/ rRefSize
.Height
;
140 return ::chart::RelativePositionHelper::moveObject(
141 rInOutRelPos
, rObjectSize
,
142 fRelativeShiftX
, fRelativeShiftY
);
145 void lcl_insertMenuCommand(
146 const uno::Reference
< awt::XPopupMenu
> & xMenu
,
147 sal_Int16 nId
, const OUString
& rCommand
)
149 xMenu
->insertItem( nId
, u
""_ustr
, 0, -1 );
150 xMenu
->setCommand( nId
, rCommand
);
153 OUString
lcl_getFormatCommandForObjectCID( std::u16string_view rCID
)
155 OUString
aDispatchCommand( u
".uno:FormatSelection"_ustr
);
157 ObjectType eObjectType
= ObjectIdentifier::getObjectType( rCID
);
161 case OBJECTTYPE_DIAGRAM
:
162 case OBJECTTYPE_DIAGRAM_WALL
:
163 aDispatchCommand
= ".uno:FormatWall";
165 case OBJECTTYPE_DIAGRAM_FLOOR
:
166 aDispatchCommand
= ".uno:FormatFloor";
168 case OBJECTTYPE_PAGE
:
169 aDispatchCommand
= ".uno:FormatChartArea";
171 case OBJECTTYPE_LEGEND
:
172 aDispatchCommand
= ".uno:FormatLegend";
174 case OBJECTTYPE_TITLE
:
175 aDispatchCommand
= ".uno:FormatTitle";
177 case OBJECTTYPE_LEGEND_ENTRY
:
178 case OBJECTTYPE_DATA_SERIES
:
179 aDispatchCommand
= ".uno:FormatDataSeries";
181 case OBJECTTYPE_AXIS
:
182 case OBJECTTYPE_AXIS_UNITLABEL
:
183 aDispatchCommand
= ".uno:FormatAxis";
185 case OBJECTTYPE_GRID
:
186 aDispatchCommand
= ".uno:FormatMajorGrid";
188 case OBJECTTYPE_SUBGRID
:
189 aDispatchCommand
= ".uno:FormatMinorGrid";
191 case OBJECTTYPE_DATA_LABELS
:
192 aDispatchCommand
= ".uno:FormatDataLabels";
194 case OBJECTTYPE_DATA_LABEL
:
195 aDispatchCommand
= ".uno:FormatDataLabel";
197 case OBJECTTYPE_DATA_POINT
:
198 aDispatchCommand
= ".uno:FormatDataPoint";
200 case OBJECTTYPE_DATA_AVERAGE_LINE
:
201 aDispatchCommand
= ".uno:FormatMeanValue";
203 case OBJECTTYPE_DATA_ERRORS_X
:
204 aDispatchCommand
= ".uno:FormatXErrorBars";
206 case OBJECTTYPE_DATA_ERRORS_Y
:
207 aDispatchCommand
= ".uno:FormatYErrorBars";
209 case OBJECTTYPE_DATA_ERRORS_Z
:
210 aDispatchCommand
= ".uno:FormatZErrorBars";
212 case OBJECTTYPE_DATA_CURVE
:
213 aDispatchCommand
= ".uno:FormatTrendline";
215 case OBJECTTYPE_DATA_CURVE_EQUATION
:
216 aDispatchCommand
= ".uno:FormatTrendlineEquation";
218 case OBJECTTYPE_DATA_STOCK_RANGE
:
219 aDispatchCommand
= ".uno:FormatSelection";
221 case OBJECTTYPE_DATA_STOCK_LOSS
:
222 aDispatchCommand
= ".uno:FormatStockLoss";
224 case OBJECTTYPE_DATA_STOCK_GAIN
:
225 aDispatchCommand
= ".uno:FormatStockGain";
227 default: //OBJECTTYPE_UNKNOWN
230 return aDispatchCommand
;
233 } // anonymous namespace
236 void SAL_CALL
ChartController::setPosSize(
243 SolarMutexGuard aGuard
;
244 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
245 auto pChartWindow(GetChartWindow());
247 if(!(xWindow
.is() && pChartWindow
))
250 Size aLogicSize
= pChartWindow
->PixelToLogic( Size( Width
, Height
), MapMode( MapUnit::Map100thMM
) );
252 //todo: for standalone chart: detect whether we are standalone
253 //change map mode to fit new size
254 awt::Size aModelPageSize
= ChartModelHelper::getPageSize( getChartModel() );
255 sal_Int32 nScaleXNumerator
= aLogicSize
.Width();
256 sal_Int32 nScaleXDenominator
= aModelPageSize
.Width
;
257 sal_Int32 nScaleYNumerator
= aLogicSize
.Height();
258 sal_Int32 nScaleYDenominator
= aModelPageSize
.Height
;
262 Fraction(nScaleXNumerator
, nScaleXDenominator
),
263 Fraction(nScaleYNumerator
, nScaleYDenominator
) );
264 pChartWindow
->SetMapMode(aNewMapMode
);
265 pChartWindow
->setPosSizePixel( X
, Y
, Width
, Height
, static_cast<PosSizeFlags
>(Flags
) );
267 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
268 if( m_xChartView
.is() )
270 auto aZoomFactors(::comphelper::InitPropertySequence({
271 { "ScaleXNumerator", uno::Any( nScaleXNumerator
) },
272 { "ScaleXDenominator", uno::Any( nScaleXDenominator
) },
273 { "ScaleYNumerator", uno::Any( nScaleYNumerator
) },
274 { "ScaleYDenominator", uno::Any( nScaleYDenominator
) }
276 m_xChartView
->setPropertyValue( u
"ZoomFactors"_ustr
, uno::Any( aZoomFactors
));
279 //a correct work area is at least necessary for correct values in the position and size dialog and for dragging area
280 if(m_pDrawViewWrapper
)
282 tools::Rectangle
aRect(Point(0,0), pChartWindow
->GetOutDev()->GetOutputSize());
283 m_pDrawViewWrapper
->SetWorkArea( aRect
);
285 pChartWindow
->Invalidate();
288 awt::Rectangle SAL_CALL
ChartController::getPosSize()
291 awt::Rectangle
aRet(0, 0, 0, 0);
293 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
295 aRet
= xWindow
->getPosSize();
300 void SAL_CALL
ChartController::setVisible( sal_Bool Visible
)
303 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
306 xWindow
->setVisible( Visible
);
309 void SAL_CALL
ChartController::setEnable( sal_Bool Enable
)
312 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
315 xWindow
->setEnable( Enable
);
318 void SAL_CALL
ChartController::setFocus()
321 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
327 void SAL_CALL
ChartController::addWindowListener(
328 const uno::Reference
< awt::XWindowListener
>& xListener
)
331 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
334 xWindow
->addWindowListener( xListener
);
337 void SAL_CALL
ChartController::removeWindowListener(
338 const uno::Reference
< awt::XWindowListener
>& xListener
)
341 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
344 xWindow
->removeWindowListener( xListener
);
347 void SAL_CALL
ChartController::addFocusListener(
348 const uno::Reference
< awt::XFocusListener
>& xListener
)
351 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
354 xWindow
->addFocusListener( xListener
);
357 void SAL_CALL
ChartController::removeFocusListener(
358 const uno::Reference
< awt::XFocusListener
>& xListener
)
361 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
364 xWindow
->removeFocusListener( xListener
);
367 void SAL_CALL
ChartController::addKeyListener(
368 const uno::Reference
< awt::XKeyListener
>& xListener
)
371 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
374 xWindow
->addKeyListener( xListener
);
377 void SAL_CALL
ChartController::removeKeyListener(
378 const uno::Reference
< awt::XKeyListener
>& xListener
)
381 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
384 xWindow
->removeKeyListener( xListener
);
387 void SAL_CALL
ChartController::addMouseListener(
388 const uno::Reference
< awt::XMouseListener
>& xListener
)
391 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
394 xWindow
->addMouseListener( xListener
);
397 void SAL_CALL
ChartController::removeMouseListener(
398 const uno::Reference
< awt::XMouseListener
>& xListener
)
401 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
404 xWindow
->removeMouseListener( xListener
);
407 void SAL_CALL
ChartController::addMouseMotionListener(
408 const uno::Reference
< awt::XMouseMotionListener
>& xListener
)
411 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
414 xWindow
->addMouseMotionListener( xListener
);
417 void SAL_CALL
ChartController::removeMouseMotionListener(
418 const uno::Reference
< awt::XMouseMotionListener
>& xListener
)
421 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
424 xWindow
->removeMouseMotionListener( xListener
);
427 void SAL_CALL
ChartController::addPaintListener(
428 const uno::Reference
< awt::XPaintListener
>& xListener
)
431 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
434 xWindow
->addPaintListener( xListener
);
437 void SAL_CALL
ChartController::removePaintListener(
438 const uno::Reference
< awt::XPaintListener
>& xListener
)
441 uno::Reference
<awt::XWindow
> xWindow
= m_xViewWindow
;
444 xWindow
->removePaintListener( xListener
);
447 // impl vcl window controller methods
448 void ChartController::PrePaint()
450 // forward VCLs PrePaint window event to DrawingLayer
451 DrawViewWrapper
* pDrawViewWrapper
= m_pDrawViewWrapper
.get();
453 if (pDrawViewWrapper
)
455 pDrawViewWrapper
->PrePaint();
459 void ChartController::execute_Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
463 rtl::Reference
<ChartModel
> xModel(getChartModel());
464 //OSL_ENSURE( xModel.is(), "ChartController::execute_Paint: have no model to paint");
468 //better performance for big data
469 if (m_xChartView
.is())
471 awt::Size
aResolution(1000, 1000);
473 SolarMutexGuard aGuard
;
474 auto pChartWindow(GetChartWindow());
477 aResolution
.Width
= pChartWindow
->GetSizePixel().Width();
478 aResolution
.Height
= pChartWindow
->GetSizePixel().Height();
481 m_xChartView
->setPropertyValue( u
"Resolution"_ustr
, uno::Any( aResolution
));
484 if (m_xChartView
.is())
485 m_xChartView
->update();
488 SolarMutexGuard aGuard
;
489 DrawViewWrapper
* pDrawViewWrapper
= m_pDrawViewWrapper
.get();
490 if (pDrawViewWrapper
)
491 pDrawViewWrapper
->CompleteRedraw(&rRenderContext
, vcl::Region(rRect
));
494 catch( const uno::Exception
& )
496 DBG_UNHANDLED_EXCEPTION("chart2");
503 static bool isDoubleClick( const MouseEvent
& rMEvt
)
505 return rMEvt
.GetClicks() == 2 && rMEvt
.IsLeft() &&
506 !rMEvt
.IsMod1() && !rMEvt
.IsMod2() && !rMEvt
.IsShift();
509 void ChartController::startDoubleClickWaiting()
511 SolarMutexGuard aGuard
;
513 m_bWaitingForDoubleClick
= true;
515 sal_uInt64 nDblClkTime
= 500;
516 auto pChartWindow(GetChartWindow());
519 const MouseSettings
& rMSettings
= pChartWindow
->GetSettings().GetMouseSettings();
520 nDblClkTime
= rMSettings
.GetDoubleClickTime();
522 m_aDoubleClickTimer
.SetTimeout( nDblClkTime
);
523 m_aDoubleClickTimer
.Start();
526 void ChartController::stopDoubleClickWaiting()
528 m_aDoubleClickTimer
.Stop();
529 m_bWaitingForDoubleClick
= false;
532 IMPL_LINK_NOARG(ChartController
, DoubleClickWaitingHdl
, Timer
*, void)
534 m_bWaitingForDoubleClick
= false;
536 if( m_bWaitingForMouseUp
|| !m_aSelection
.maybeSwitchSelectionAfterSingleClickWasEnsured() )
539 impl_selectObjectAndNotiy();
540 SolarMutexGuard aGuard
;
541 auto pChartWindow(GetChartWindow());
544 vcl::Window::PointerState
aPointerState( pChartWindow
->GetPointerState() );
545 MouseEvent
aMouseEvent(
548 MouseEventModifiers::NONE
,
549 static_cast< sal_uInt16
>( aPointerState
.mnState
)/*nButtons*/,
551 impl_SetMousePointer( aMouseEvent
);
555 void ChartController::execute_MouseButtonDown( const MouseEvent
& rMEvt
)
557 SolarMutexGuard aGuard
;
559 m_bWaitingForMouseUp
= true;
560 m_bFieldButtonDown
= false;
562 if( isDoubleClick(rMEvt
) )
563 stopDoubleClickWaiting();
565 startDoubleClickWaiting();
567 m_aSelection
.remindSelectionBeforeMouseDown();
569 DrawViewWrapper
* pDrawViewWrapper
= m_pDrawViewWrapper
.get();
570 auto pChartWindow(GetChartWindow());
571 if(!pChartWindow
|| !pDrawViewWrapper
)
574 Point aMPos
= pChartWindow
->PixelToLogic(rMEvt
.GetPosPixel());
576 // Check if button was clicked
577 SdrObject
* pObject
= pDrawViewWrapper
->getHitObject(aMPos
);
580 OUString aCID
= pObject
->GetName();
581 if (aCID
.startsWith("FieldButton"))
583 m_bFieldButtonDown
= true;
584 return; // Don't take any action if button was clicked
588 if ( rMEvt
.GetButtons() == MOUSE_LEFT
)
590 pChartWindow
->GrabFocus();
591 pChartWindow
->CaptureMouse();
594 if( pDrawViewWrapper
->IsTextEdit() )
597 if ( pDrawViewWrapper
->IsTextEditHit( aMPos
) ||
598 // #i12587# support for shapes in chart
599 ( rMEvt
.IsRight() && pDrawViewWrapper
->PickAnything( rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
) == SdrHitKind::MarkedObject
) )
601 pDrawViewWrapper
->MouseButtonDown(rMEvt
, pChartWindow
->GetOutDev());
610 //abort running action
611 if( pDrawViewWrapper
->IsAction() )
613 if( rMEvt
.IsRight() )
614 pDrawViewWrapper
->BckAction();
618 if( isDoubleClick(rMEvt
) ) //do not change selection if double click
619 return;//double click is handled further in mousebutton up
621 SdrHdl
* pHitSelectionHdl
= nullptr;
622 //switch from move to resize if handle is hit on a resizable object
623 if( m_aSelection
.isResizeableObjectSelected() )
624 pHitSelectionHdl
= pDrawViewWrapper
->PickHandle( aMPos
);
625 //only change selection if no selection handles are hit
626 if( !pHitSelectionHdl
)
628 // #i12587# support for shapes in chart
629 if ( m_eDrawMode
== CHARTDRAW_INSERT
&&
630 ( !pDrawViewWrapper
->IsMarkedHit( aMPos
) || !m_aSelection
.isDragableObjectSelected() ) )
632 if ( m_aSelection
.hasSelection() )
634 m_aSelection
.clearSelection();
636 if ( !pDrawViewWrapper
->IsAction() )
638 if ( pDrawViewWrapper
->GetCurrentObjIdentifier() == SdrObjKind::Caption
)
640 Size
aCaptionSize( 2268, 1134 );
641 pDrawViewWrapper
->BegCreateCaptionObj( aMPos
, aCaptionSize
);
645 pDrawViewWrapper
->BegCreateObj( aMPos
);
647 SdrObject
* pObj
= pDrawViewWrapper
->GetCreateObj();
648 DrawCommandDispatch
* pDrawCommandDispatch
= m_aDispatchContainer
.getDrawCommandDispatch();
649 if ( pObj
&& m_pDrawModelWrapper
&& pDrawCommandDispatch
)
651 SfxItemSet
aSet( m_pDrawModelWrapper
->GetItemPool() );
652 pDrawCommandDispatch
->setAttributes( pObj
);
653 pDrawCommandDispatch
->setLineEnds( aSet
);
654 pObj
->SetMergedItemSet( aSet
);
657 impl_SetMousePointer( rMEvt
);
661 m_aSelection
.adaptSelectionToNewPos(
665 m_bWaitingForDoubleClick
);
667 if( !m_aSelection
.isRotateableObjectSelected( getChartModel() ) )
669 m_eDragMode
= SdrDragMode::Move
;
670 pDrawViewWrapper
->SetDragMode(m_eDragMode
);
673 m_aSelection
.applySelection(pDrawViewWrapper
);
675 if( m_aSelection
.isDragableObjectSelected()
676 && !rMEvt
.IsRight() )
679 sal_uInt16 nDrgLog
= static_cast<sal_uInt16
>(pChartWindow
->PixelToLogic(Size(DRGPIX
,0)).Width());
680 SdrDragMethod
* pDragMethod
= nullptr;
682 //change selection to 3D scene if rotate mode
683 SdrDragMode eDragMode
= pDrawViewWrapper
->GetDragMode();
684 if( eDragMode
==SdrDragMode::Rotate
)
686 E3dScene
* pScene
= SelectionHelper::getSceneToRotate( pDrawViewWrapper
->getNamedSdrObject( m_aSelection
.getSelectedCID() ) );
689 DragMethod_RotateDiagram::RotationDirection
eRotationDirection(DragMethod_RotateDiagram::ROTATIONDIRECTION_FREE
);
692 SdrHdlKind eKind
= pHitSelectionHdl
->GetKind();
693 if( eKind
==SdrHdlKind::Upper
|| eKind
==SdrHdlKind::Lower
)
694 eRotationDirection
= DragMethod_RotateDiagram::ROTATIONDIRECTION_X
;
695 else if( eKind
==SdrHdlKind::Left
|| eKind
==SdrHdlKind::Right
)
696 eRotationDirection
= DragMethod_RotateDiagram::ROTATIONDIRECTION_Y
;
697 else if( eKind
==SdrHdlKind::UpperLeft
|| eKind
==SdrHdlKind::UpperRight
|| eKind
==SdrHdlKind::LowerLeft
|| eKind
==SdrHdlKind::LowerRight
)
698 eRotationDirection
= DragMethod_RotateDiagram::ROTATIONDIRECTION_Z
;
700 pDragMethod
= new DragMethod_RotateDiagram( *pDrawViewWrapper
, m_aSelection
.getSelectedCID(), getChartModel(), eRotationDirection
);
705 std::u16string_view
aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( m_aSelection
.getSelectedCID() ) );
706 if( aDragMethodServiceName
== ObjectIdentifier::getPieSegmentDragMethodServiceName() )
707 pDragMethod
= new DragMethod_PieSegment( *pDrawViewWrapper
, m_aSelection
.getSelectedCID(), getChartModel() );
709 pDrawViewWrapper
->SdrView::BegDragObj(aMPos
, nullptr, pHitSelectionHdl
, nDrgLog
, pDragMethod
);
712 impl_SetMousePointer( rMEvt
);
715 void ChartController::execute_MouseMove( const MouseEvent
& rMEvt
)
717 SolarMutexGuard aGuard
;
719 DrawViewWrapper
* pDrawViewWrapper
= m_pDrawViewWrapper
.get();
720 auto pChartWindow(GetChartWindow());
721 if(!pChartWindow
|| !pDrawViewWrapper
)
724 if( m_pDrawViewWrapper
->IsTextEdit() )
726 if( m_pDrawViewWrapper
->MouseMove(rMEvt
,pChartWindow
->GetOutDev()) )
730 if(pDrawViewWrapper
->IsAction())
732 pDrawViewWrapper
->MovAction( pChartWindow
->PixelToLogic( rMEvt
.GetPosPixel() ) );
735 impl_SetMousePointer( rMEvt
);
738 void ChartController::execute_MouseButtonUp( const MouseEvent
& rMEvt
)
740 ControllerLockGuardUNO
aCLGuard( getChartModel() );
741 bool bMouseUpWithoutMouseDown
= !m_bWaitingForMouseUp
;
742 m_bWaitingForMouseUp
= false;
743 bool bNotifySelectionChange
= false;
744 bool bEditText
= false;
746 SolarMutexGuard aGuard
;
748 DrawViewWrapper
* pDrawViewWrapper
= m_pDrawViewWrapper
.get();
749 auto pChartWindow(GetChartWindow());
750 if(!pChartWindow
|| !pDrawViewWrapper
)
753 Point aMPos
= pChartWindow
->PixelToLogic(rMEvt
.GetPosPixel());
755 // Check if button was clicked
756 if (m_bFieldButtonDown
)
758 m_bFieldButtonDown
= false;
759 SdrObject
* pObject
= pDrawViewWrapper
->getHitObject(aMPos
);
762 OUString aCID
= pObject
->GetName();
763 if (aCID
.startsWith("FieldButton"))
765 sendPopupRequest(aCID
, pObject
->GetCurrentBoundRect());
771 if(pDrawViewWrapper
->IsTextEdit())
773 if( pDrawViewWrapper
->MouseButtonUp(rMEvt
,pChartWindow
->GetOutDev()) )
777 // #i12587# support for shapes in chart
778 if ( m_eDrawMode
== CHARTDRAW_INSERT
&& pDrawViewWrapper
->IsCreateObj() )
780 pDrawViewWrapper
->EndCreateObj( SdrCreateCmd::ForceEnd
);
782 HiddenUndoContext
aUndoContext( m_xUndoManager
);
783 // don't want the positioning Undo action to appear in the UI
784 impl_switchDiagramPositioningToExcludingPositioning();
786 if ( pDrawViewWrapper
->GetMarkedObjectList().GetMarkCount() != 0 )
788 if ( pDrawViewWrapper
->GetCurrentObjIdentifier() == SdrObjKind::Text
)
790 executeDispatch_EditText();
794 SdrObject
* pObj
= pDrawViewWrapper
->getSelectedObject();
797 uno::Reference
< drawing::XShape
> xShape( pObj
->getUnoShape(), uno::UNO_QUERY
);
800 m_aSelection
.setSelection( xShape
);
801 m_aSelection
.applySelection( pDrawViewWrapper
);
808 m_aSelection
.adaptSelectionToNewPos( aMPos
, pDrawViewWrapper
, rMEvt
.IsRight(), m_bWaitingForDoubleClick
);
809 m_aSelection
.applySelection( pDrawViewWrapper
);
810 setDrawMode( CHARTDRAW_SELECT
);
813 else if ( pDrawViewWrapper
->IsDragObj() )
815 bool bDraggingDone
= false;
816 SdrDragMethod
* pDragMethod
= pDrawViewWrapper
->SdrView::GetDragMethod();
817 bool bIsMoveOnly
= pDragMethod
&& pDragMethod
->getMoveOnly();
818 DragMethod_Base
* pChartDragMethod
= dynamic_cast< DragMethod_Base
* >(pDragMethod
);
819 if( pChartDragMethod
)
821 UndoGuard
aUndoGuard( pChartDragMethod
->getUndoDescription(),
824 if( pDrawViewWrapper
->EndDragObj() )
826 bDraggingDone
= true;
831 if( !bDraggingDone
&& pDrawViewWrapper
->EndDragObj() )
836 SdrObject
* pObj
= pDrawViewWrapper
->getSelectedObject();
839 tools::Rectangle aObjectRect
= pObj
->GetSnapRect();
840 tools::Rectangle aOldObjectRect
= pObj
->GetLastBoundRect();
841 awt::Size
aPageSize( ChartModelHelper::getPageSize( getChartModel() ) );
842 tools::Rectangle
aPageRect( 0,0,aPageSize
.Width
,aPageSize
.Height
);
844 const E3dObject
* pE3dObject(DynCastE3dObject(pObj
));
845 if(nullptr != pE3dObject
)
847 E3dScene
* pScene(pE3dObject
->getRootE3dSceneFromE3dObject());
848 if(nullptr != pScene
)
850 aObjectRect
= pScene
->GetSnapRect();
854 ActionDescriptionProvider::ActionType
eActionType(ActionDescriptionProvider::ActionType::Move
);
855 if( !bIsMoveOnly
&& m_aSelection
.isResizeableObjectSelected() )
856 eActionType
= ActionDescriptionProvider::ActionType::Resize
;
858 ObjectType eObjectType
= ObjectIdentifier::getObjectType( m_aSelection
.getSelectedCID() );
860 UndoGuard
aUndoGuard(
861 ActionDescriptionProvider::createDescription( eActionType
, ObjectNameProvider::getName( eObjectType
)),
864 bool bChanged
= false;
865 rtl::Reference
< ChartModel
> xModel
= getChartModel();
866 if ( eObjectType
== OBJECTTYPE_LEGEND
)
867 bChanged
= DiagramHelper::switchDiagramPositioningToExcludingPositioning( *xModel
, false , true );
869 bool bMoved
= PositionAndSizeHelper::moveObject( m_aSelection
.getSelectedCID()
871 , awt::Rectangle(aObjectRect
.Left(),aObjectRect
.Top(),aObjectRect
.getOpenWidth(),aObjectRect
.getOpenHeight())
872 , awt::Rectangle(aOldObjectRect
.Left(), aOldObjectRect
.Top(), 0, 0)
873 , awt::Rectangle(aPageRect
.Left(),aPageRect
.Top(),aPageRect
.getOpenWidth(),aPageRect
.getOpenHeight()) );
875 if( bMoved
|| bChanged
)
877 bDraggingDone
= true;
882 catch( const uno::Exception
& )
884 DBG_UNHANDLED_EXCEPTION("chart2");
886 //all wanted model changes will take effect
887 //and all unwanted view modifications are cleaned
890 if( !bDraggingDone
) //mouse wasn't moved while dragging
892 bool bClickedTwiceOnDragableObject
= SelectionHelper::isDragableObjectHitTwice( aMPos
, m_aSelection
.getSelectedCID(), *pDrawViewWrapper
);
893 bool bIsRotateable
= m_aSelection
.isRotateableObjectSelected( getChartModel() );
895 //toggle between move and rotate
896 if( bIsRotateable
&& bClickedTwiceOnDragableObject
&& m_eDragMode
==SdrDragMode::Move
)
897 m_eDragMode
=SdrDragMode::Rotate
;
899 m_eDragMode
=SdrDragMode::Move
;
901 pDrawViewWrapper
->SetDragMode(m_eDragMode
);
903 if( !m_bWaitingForDoubleClick
&& m_aSelection
.maybeSwitchSelectionAfterSingleClickWasEnsured() )
905 impl_selectObjectAndNotiy();
909 m_aSelection
.resetPossibleSelectionAfterSingleClickWasEnsured();
912 //@todo ForcePointer(&rMEvt);
913 pChartWindow
->ReleaseMouse();
915 // In tiled rendering drag mode could be not yet over on the call
916 // that should handle the double-click, so better to perform this check
918 if( isDoubleClick(rMEvt
) && !bMouseUpWithoutMouseDown
/*#i106966#*/ )
920 Point aMousePixel
= rMEvt
.GetPosPixel();
921 execute_DoubleClick( &aMousePixel
, bEditText
);
924 if( m_aSelection
.isSelectionDifferentFromBeforeMouseDown() )
925 bNotifySelectionChange
= true;
928 impl_SetMousePointer( rMEvt
);
930 if(bNotifySelectionChange
|| bEditText
)
931 impl_notifySelectionChangeListeners();
934 void ChartController::execute_DoubleClick( const Point
* pMousePixel
, bool &bEditText
)
936 const SfxViewShell
* pViewShell
= SfxViewShell::Current();
937 bool notAllowed
= pViewShell
&& (pViewShell
->isLOKMobilePhone() || pViewShell
->IsLokReadOnlyView());
941 if ( m_aSelection
.hasSelection() )
943 OUString
aCID( m_aSelection
.getSelectedCID() );
944 if ( !aCID
.isEmpty() )
946 ObjectType eObjectType
= ObjectIdentifier::getObjectType( aCID
);
947 if ( eObjectType
== OBJECTTYPE_TITLE
)
954 // #i12587# support for shapes in chart
955 SdrObject
* pObj
= DrawViewWrapper::getSdrObject( m_aSelection
.getSelectedAdditionalShape() );
956 if ( DynCastSdrTextObj(pObj
) != nullptr )
965 executeDispatch_EditText( pMousePixel
);
969 executeDispatch_ObjectProperties();
973 void ChartController::execute_Resize()
975 SolarMutexGuard aGuard
;
976 auto pChartWindow(GetChartWindow());
978 pChartWindow
->Invalidate();
981 void ChartController::execute_Command( const CommandEvent
& rCEvt
)
983 SolarMutexGuard aGuard
;
984 auto pChartWindow(GetChartWindow());
985 DrawViewWrapper
* pDrawViewWrapper
= m_pDrawViewWrapper
.get();
986 if(!pChartWindow
|| !pDrawViewWrapper
)
988 bool bIsAction
= m_pDrawViewWrapper
->IsAction();
991 if(rCEvt
.GetCommand() == CommandEventId::ContextMenu
&& !bIsAction
)
993 pChartWindow
->ReleaseMouse();
995 if( m_aSelection
.isSelectionDifferentFromBeforeMouseDown() )
996 impl_notifySelectionChangeListeners();
998 rtl::Reference
< VCLXPopupMenu
> xPopupMenu
= new VCLXPopupMenu();
1000 Point
aPos( rCEvt
.GetMousePosPixel() );
1001 if( !rCEvt
.IsMouseEvent() )
1003 aPos
= pChartWindow
->GetPointerState().maPos
;
1007 if ( isShapeContext() )
1008 // #i12587# support for shapes in chart
1009 aMenuName
= m_pDrawViewWrapper
->IsTextEdit() ? std::u16string_view( u
"drawtext" ) : std::u16string_view( u
"draw" );
1012 ObjectType eObjectType
= ObjectIdentifier::getObjectType( m_aSelection
.getSelectedCID() );
1014 // todo: the context menu should be specified by an xml file in uiconfig
1015 sal_Int16 nUniqueId
= 1;
1016 if (eObjectType
!= OBJECTTYPE_DATA_TABLE
)
1018 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:Cut"_ustr
);
1019 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:Copy"_ustr
);
1020 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:Paste"_ustr
);
1021 xPopupMenu
->insertSeparator( -1 );
1024 rtl::Reference
< Diagram
> xDiagram
= getFirstDiagram();
1026 OUString
aFormatCommand( lcl_getFormatCommandForObjectCID( m_aSelection
.getSelectedCID() ) );
1027 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, aFormatCommand
);
1028 if (eObjectType
== OBJECTTYPE_TITLE
&& m_pDrawViewWrapper
->IsTextEdit())
1029 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FontDialog"_ustr
);
1031 //some commands for dataseries and points:
1033 if( eObjectType
== OBJECTTYPE_DATA_SERIES
|| eObjectType
== OBJECTTYPE_DATA_POINT
)
1035 bool bIsPoint
= ( eObjectType
== OBJECTTYPE_DATA_POINT
);
1036 rtl::Reference
< DataSeries
> xSeries
= ObjectIdentifier::getDataSeriesForCID( m_aSelection
.getSelectedCID(), getChartModel() );
1037 rtl::Reference
< RegressionCurveModel
> xTrendline
= RegressionCurveHelper::getFirstCurveNotMeanValueLine( xSeries
);
1038 bool bHasEquation
= RegressionCurveHelper::hasEquation( xTrendline
);
1039 rtl::Reference
< RegressionCurveModel
> xMeanValue
= RegressionCurveHelper::getMeanValueLine( xSeries
);
1040 bool bHasYErrorBars
= StatisticsHelper::hasErrorBars( xSeries
);
1041 bool bHasXErrorBars
= StatisticsHelper::hasErrorBars( xSeries
, false );
1042 bool bHasDataLabelsAtSeries
= DataSeriesHelper::hasDataLabelsAtSeries( xSeries
);
1043 bool bHasDataLabelsAtPoints
= DataSeriesHelper::hasDataLabelsAtPoints( xSeries
);
1044 bool bHasDataLabelAtPoint
= false;
1045 sal_Int32 nPointIndex
= -1;
1048 nPointIndex
= ObjectIdentifier::getIndexFromParticleOrCID( m_aSelection
.getSelectedCID() );
1049 bHasDataLabelAtPoint
= DataSeriesHelper::hasDataLabelAtPoint( xSeries
, nPointIndex
);
1051 bool bSelectedPointIsFormatted
= false;
1052 bool bHasFormattedDataPointsOtherThanSelected
= false;
1056 uno::Sequence
< sal_Int32
> aAttributedDataPointIndexList
;
1057 // "AttributedDataPoints"
1058 if( xSeries
->getFastPropertyValue( PROP_DATASERIES_ATTRIBUTED_DATA_POINTS
) >>= aAttributedDataPointIndexList
)
1060 if( aAttributedDataPointIndexList
.hasElements() )
1064 auto aIt
= std::find( aAttributedDataPointIndexList
.begin(), aAttributedDataPointIndexList
.end(), nPointIndex
);
1065 if (aIt
!= aAttributedDataPointIndexList
.end())
1066 bSelectedPointIsFormatted
= true;
1068 bHasFormattedDataPointsOtherThanSelected
= true;
1071 bHasFormattedDataPointsOtherThanSelected
= true;
1078 if( bHasDataLabelAtPoint
)
1079 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatDataLabel"_ustr
);
1080 if( !bHasDataLabelAtPoint
)
1081 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertDataLabel"_ustr
);
1083 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteDataLabel"_ustr
);
1084 if( bSelectedPointIsFormatted
)
1085 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:ResetDataPoint"_ustr
);
1087 xPopupMenu
->insertSeparator( -1 );
1089 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatDataSeries"_ustr
);
1092 rtl::Reference
< ChartType
> xChartType( xDiagram
->getChartTypeOfSeries( xSeries
) );
1093 if( xChartType
->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK
)
1097 bool bJapaneseStyle
= false;
1098 xChartType
->getPropertyValue( u
"Japanese"_ustr
) >>= bJapaneseStyle
;
1100 if( bJapaneseStyle
)
1102 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatStockLoss"_ustr
);
1103 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatStockGain"_ustr
);
1106 catch( const uno::Exception
& )
1108 DBG_UNHANDLED_EXCEPTION("chart2");
1112 if( bHasDataLabelsAtSeries
)
1113 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatDataLabels"_ustr
);
1115 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatTrendlineEquation"_ustr
);
1116 if( xMeanValue
.is() )
1117 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatMeanValue"_ustr
);
1118 if( bHasXErrorBars
)
1119 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatXErrorBars"_ustr
);
1120 if( bHasYErrorBars
)
1121 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatYErrorBars"_ustr
);
1123 xPopupMenu
->insertSeparator( -1 );
1125 if( !bHasDataLabelsAtSeries
)
1126 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertDataLabels"_ustr
);
1128 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertTrendline"_ustr
);
1130 if( !xMeanValue
.is() )
1131 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertMeanValue"_ustr
);
1132 if( !bHasXErrorBars
)
1133 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertXErrorBars"_ustr
);
1134 if( !bHasYErrorBars
)
1135 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertYErrorBars"_ustr
);
1136 if( bHasDataLabelsAtSeries
|| ( bHasDataLabelsAtPoints
&& bHasFormattedDataPointsOtherThanSelected
) )
1137 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteDataLabels"_ustr
);
1139 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteTrendlineEquation"_ustr
);
1140 if( xMeanValue
.is() )
1141 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteMeanValue"_ustr
);
1142 if( bHasXErrorBars
)
1143 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteXErrorBars"_ustr
);
1144 if( bHasYErrorBars
)
1145 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteYErrorBars"_ustr
);
1147 if( bHasFormattedDataPointsOtherThanSelected
)
1148 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:ResetAllDataPoints"_ustr
);
1150 xPopupMenu
->insertSeparator( -1 );
1152 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
, u
".uno:ArrangeRow"_ustr
);
1153 rtl::Reference
< VCLXPopupMenu
> xArrangePopupMenu
= new VCLXPopupMenu();
1154 sal_Int16 nSubId
= nUniqueId
+ 1;
1155 lcl_insertMenuCommand( xArrangePopupMenu
, nSubId
++, u
".uno:Forward"_ustr
);
1156 lcl_insertMenuCommand( xArrangePopupMenu
, nSubId
, u
".uno:Backward"_ustr
);
1157 xPopupMenu
->setPopupMenu( nUniqueId
, xArrangePopupMenu
);
1161 else if( eObjectType
== OBJECTTYPE_DATA_CURVE
)
1163 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteTrendline"_ustr
);
1164 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatTrendlineEquation"_ustr
);
1165 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertTrendlineEquation"_ustr
);
1166 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertTrendlineEquationAndR2"_ustr
);
1167 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertR2Value"_ustr
);
1168 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteTrendlineEquation"_ustr
);
1169 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteR2Value"_ustr
);
1171 else if( eObjectType
== OBJECTTYPE_DATA_CURVE_EQUATION
)
1173 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertR2Value"_ustr
);
1174 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteR2Value"_ustr
);
1177 //some commands for axes: and grids
1179 else if( eObjectType
== OBJECTTYPE_AXIS
|| eObjectType
== OBJECTTYPE_GRID
|| eObjectType
== OBJECTTYPE_SUBGRID
)
1181 rtl::Reference
< Axis
> xAxis
= ObjectIdentifier::getAxisForCID( m_aSelection
.getSelectedCID(), getChartModel() );
1182 if( xAxis
.is() && xDiagram
.is() )
1184 sal_Int32 nDimensionIndex
= -1;
1185 sal_Int32 nCooSysIndex
= -1;
1186 sal_Int32 nAxisIndex
= -1;
1187 AxisHelper::getIndicesForAxis( xAxis
, xDiagram
, nCooSysIndex
, nDimensionIndex
, nAxisIndex
);
1188 bool bIsSecondaryAxis
= nAxisIndex
!=0;
1189 bool bIsAxisVisible
= AxisHelper::isAxisVisible( xAxis
);
1190 bool bIsMajorGridVisible
= AxisHelper::isGridShown( nDimensionIndex
, nCooSysIndex
, true /*bMainGrid*/, xDiagram
);
1191 bool bIsMinorGridVisible
= AxisHelper::isGridShown( nDimensionIndex
, nCooSysIndex
, false /*bMainGrid*/, xDiagram
);
1192 bool bHasTitle
= !TitleHelper::getCompleteString( xAxis
->getTitleObject2() ).isEmpty();
1194 if( eObjectType
!= OBJECTTYPE_AXIS
&& bIsAxisVisible
)
1195 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatAxis"_ustr
);
1196 if( eObjectType
!= OBJECTTYPE_GRID
&& bIsMajorGridVisible
&& !bIsSecondaryAxis
)
1197 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatMajorGrid"_ustr
);
1198 if( eObjectType
!= OBJECTTYPE_SUBGRID
&& bIsMinorGridVisible
&& !bIsSecondaryAxis
)
1199 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatMinorGrid"_ustr
);
1201 xPopupMenu
->insertSeparator( -1 );
1203 if( eObjectType
!= OBJECTTYPE_AXIS
&& !bIsAxisVisible
)
1204 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertAxis"_ustr
);
1205 if( eObjectType
!= OBJECTTYPE_GRID
&& !bIsMajorGridVisible
&& !bIsSecondaryAxis
)
1206 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertMajorGrid"_ustr
);
1207 if( eObjectType
!= OBJECTTYPE_SUBGRID
&& !bIsMinorGridVisible
&& !bIsSecondaryAxis
)
1208 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertMinorGrid"_ustr
);
1210 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertAxisTitle"_ustr
);
1212 if( bIsAxisVisible
)
1213 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteAxis"_ustr
);
1214 if( bIsMajorGridVisible
&& !bIsSecondaryAxis
)
1215 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteMajorGrid"_ustr
);
1216 if( bIsMinorGridVisible
&& !bIsSecondaryAxis
)
1217 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteMinorGrid"_ustr
);
1219 lcl_insertMenuCommand(xPopupMenu
, nUniqueId
++, u
".uno:InsertDataTable"_ustr
);
1222 else if (eObjectType
== OBJECTTYPE_DATA_TABLE
)
1224 lcl_insertMenuCommand(xPopupMenu
, nUniqueId
++, u
".uno:DeleteDataTable"_ustr
);
1227 if( eObjectType
== OBJECTTYPE_DATA_STOCK_LOSS
)
1228 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatStockGain"_ustr
);
1229 else if( eObjectType
== OBJECTTYPE_DATA_STOCK_GAIN
)
1230 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:FormatStockLoss"_ustr
);
1232 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:TransformDialog"_ustr
);
1234 if( eObjectType
== OBJECTTYPE_PAGE
|| eObjectType
== OBJECTTYPE_DIAGRAM
1235 || eObjectType
== OBJECTTYPE_DIAGRAM_WALL
1236 || eObjectType
== OBJECTTYPE_DIAGRAM_FLOOR
1237 || eObjectType
== OBJECTTYPE_UNKNOWN
)
1239 if( eObjectType
!= OBJECTTYPE_UNKNOWN
)
1240 xPopupMenu
->insertSeparator( -1 );
1241 bool bHasLegend
= LegendHelper::hasLegend( xDiagram
);
1242 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertTitles"_ustr
);
1244 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertLegend"_ustr
);
1245 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:InsertRemoveAxes"_ustr
);
1247 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DeleteLegend"_ustr
);
1250 xPopupMenu
->insertSeparator( -1 );
1251 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DiagramType"_ustr
);
1252 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DataRanges"_ustr
);
1253 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:DiagramData"_ustr
);
1254 lcl_insertMenuCommand( xPopupMenu
, nUniqueId
++, u
".uno:View3D"_ustr
);
1257 css::uno::Sequence
< css::uno::Any
> aArgs
{
1258 css::uno::Any(comphelper::makePropertyValue( u
"IsContextMenu"_ustr
, true )),
1259 css::uno::Any(comphelper::makePropertyValue( u
"Frame"_ustr
, m_xFrame
)),
1260 css::uno::Any(comphelper::makePropertyValue( u
"Value"_ustr
, aMenuName
))
1263 css::uno::Reference
< css::frame::XPopupMenuController
> xPopupController(
1264 m_xCC
->getServiceManager()->createInstanceWithArgumentsAndContext(
1265 u
"com.sun.star.comp.framework.ResourceMenuController"_ustr
, aArgs
, m_xCC
), css::uno::UNO_QUERY
);
1267 if ( !xPopupController
.is() || !xPopupMenu
.is() )
1270 xPopupController
->setPopupMenu( xPopupMenu
);
1272 if (comphelper::LibreOfficeKit::isActive())
1274 if (SfxViewShell
* pViewShell
= SfxViewShell::Current())
1276 ControllerCommandDispatch
* pCommandDispatch
= dynamic_cast<ControllerCommandDispatch
*>(m_aDispatchContainer
.getChartDispatcher().get());
1277 if (pCommandDispatch
)
1279 for (int nPos
= 0, nCount
= xPopupMenu
->getItemCount(); nPos
< nCount
; ++nPos
)
1281 auto nItemId
= xPopupMenu
->getItemId(nPos
);
1282 OUString aCommandURL
= xPopupMenu
->getCommand(nItemId
);
1283 if (!pCommandDispatch
->commandAvailable(aCommandURL
))
1284 xPopupMenu
->enableItem(nItemId
, false);
1288 boost::property_tree::ptree aMenu
= SfxDispatcher::fillPopupMenu(xPopupMenu
);
1289 boost::property_tree::ptree aRoot
;
1290 aRoot
.add_child("menu", aMenu
);
1292 std::stringstream aStream
;
1293 boost::property_tree::write_json(aStream
, aRoot
, true);
1294 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU
, OString(aStream
.str()));
1299 xPopupMenu
->execute( css::uno::Reference
< css::awt::XWindowPeer
>( m_xFrame
->getContainerWindow(), css::uno::UNO_QUERY
),
1300 css::awt::Rectangle( aPos
.X(), aPos
.Y(), 0, 0 ),
1301 css::awt::PopupMenuDirection::EXECUTE_DEFAULT
);
1304 css::uno::Reference
< css::lang::XComponent
> xComponent( xPopupController
, css::uno::UNO_QUERY
);
1305 if ( xComponent
.is() )
1306 xComponent
->dispose();
1308 else if( ( rCEvt
.GetCommand() == CommandEventId::StartExtTextInput
) ||
1309 ( rCEvt
.GetCommand() == CommandEventId::ExtTextInput
) ||
1310 ( rCEvt
.GetCommand() == CommandEventId::EndExtTextInput
) ||
1311 ( rCEvt
.GetCommand() == CommandEventId::InputContextChange
) )
1313 //#i84417# enable editing with IME
1314 m_pDrawViewWrapper
->Command( rCEvt
, pChartWindow
);
1318 bool ChartController::execute_KeyInput( const KeyEvent
& rKEvt
)
1320 SolarMutexGuard aGuard
;
1323 DrawViewWrapper
* pDrawViewWrapper
= m_pDrawViewWrapper
.get();
1324 auto pChartWindow(GetChartWindow());
1325 if (!pChartWindow
|| !pDrawViewWrapper
)
1328 // handle accelerators
1329 if (!m_apAccelExecute
&& m_xFrame
.is() && m_xCC
.is())
1331 m_apAccelExecute
= ::svt::AcceleratorExecute::createAcceleratorHelper();
1332 OSL_ASSERT(m_apAccelExecute
);
1333 if (m_apAccelExecute
)
1334 m_apAccelExecute
->init( m_xCC
, m_xFrame
);
1337 vcl::KeyCode
aKeyCode( rKEvt
.GetKeyCode());
1338 sal_uInt16 nCode
= aKeyCode
.GetCode();
1339 bool bAlternate
= aKeyCode
.IsMod2();
1340 bool bCtrl
= aKeyCode
.IsMod1();
1342 if (m_apAccelExecute
)
1343 bReturn
= m_apAccelExecute
->execute( aKeyCode
);
1348 if( pDrawViewWrapper
->IsTextEdit() )
1350 if( pDrawViewWrapper
->KeyInput(rKEvt
, pChartWindow
) )
1353 if( nCode
== KEY_ESCAPE
)
1361 // keyboard accessibility
1362 ObjectType eObjectType
= ObjectIdentifier::getObjectType( m_aSelection
.getSelectedCID() );
1365 // Navigation (Tab/F3/Home/End)
1366 rtl::Reference
<::chart::ChartModel
> xChartDoc( getChartModel() );
1367 ObjectKeyNavigation
aObjNav( m_aSelection
.getSelectedOID(), xChartDoc
, m_xChartView
.get() );
1368 awt::KeyEvent
aKeyEvent( ::svt::AcceleratorExecute::st_VCLKey2AWTKey( aKeyCode
));
1369 bReturn
= aObjNav
.handleKeyEvent( aKeyEvent
);
1372 const ObjectIdentifier
& aNewOID
= aObjNav
.getCurrentSelection();
1373 uno::Any aNewSelection
;
1374 if ( aNewOID
.isValid() && !ObjectHierarchy::isRootNode( aNewOID
) )
1376 aNewSelection
= aNewOID
.getAny();
1378 if ( m_eDragMode
== SdrDragMode::Rotate
&& !SelectionHelper::isRotateableObject( aNewOID
.getObjectCID(), getChartModel() ) )
1380 m_eDragMode
= SdrDragMode::Move
;
1382 bReturn
= select( aNewSelection
);
1386 // Position and Size (+/-/arrow-keys) or pie segment dragging
1389 // pie segment dragging
1390 // note: could also be done for data series
1391 if( eObjectType
== OBJECTTYPE_DATA_POINT
&&
1392 ObjectIdentifier::getDragMethodServiceName( m_aSelection
.getSelectedCID() ) ==
1393 ObjectIdentifier::getPieSegmentDragMethodServiceName())
1396 bool bDragInside
= false;
1397 if( nCode
== KEY_ADD
||
1398 nCode
== KEY_SUBTRACT
)
1401 bDragInside
= ( nCode
== KEY_SUBTRACT
);
1404 nCode
== KEY_LEFT
||
1405 nCode
== KEY_RIGHT
||
1410 std::u16string_view
aParameter( ObjectIdentifier::getDragParameterString( m_aSelection
.getSelectedCID() ));
1411 sal_Int32
nOffsetPercentDummy( 0 );
1412 awt::Point
aMinimumPosition( 0, 0 );
1413 awt::Point
aMaximumPosition( 0, 0 );
1414 ObjectIdentifier::parsePieSegmentDragParameterString(
1415 aParameter
, nOffsetPercentDummy
, aMinimumPosition
, aMaximumPosition
);
1416 aMaximumPosition
.Y
-= aMinimumPosition
.Y
;
1417 aMaximumPosition
.X
-= aMinimumPosition
.X
;
1420 (nCode
== KEY_RIGHT
&& (aMaximumPosition
.X
< 0)) ||
1421 (nCode
== KEY_LEFT
&& (aMaximumPosition
.X
> 0)) ||
1422 (nCode
== KEY_DOWN
&& (aMaximumPosition
.Y
< 0)) ||
1423 (nCode
== KEY_UP
&& (aMaximumPosition
.Y
> 0));
1428 double fAmount
= bAlternate
? 0.01 : 0.05;
1432 bReturn
= impl_DragDataPoint( m_aSelection
.getSelectedCID(), fAmount
);
1438 if( nCode
== KEY_ADD
||
1439 nCode
== KEY_SUBTRACT
)
1441 if( eObjectType
== OBJECTTYPE_DIAGRAM
)
1443 // default 1 mm in each direction
1444 double fGrowAmountX
= 200.0;
1445 double fGrowAmountY
= 200.0;
1448 // together with Alt-key: 1 px in each direction
1449 Size aPixelSize
= pChartWindow
->PixelToLogic( Size( 2, 2 ));
1450 fGrowAmountX
= static_cast< double >( aPixelSize
.Width());
1451 fGrowAmountY
= static_cast< double >( aPixelSize
.Height());
1453 if( nCode
== KEY_SUBTRACT
)
1455 fGrowAmountX
= -fGrowAmountX
;
1456 fGrowAmountY
= -fGrowAmountY
;
1458 bReturn
= impl_moveOrResizeObject(
1459 m_aSelection
.getSelectedCID(), CENTERED_RESIZE_OBJECT
, fGrowAmountX
, fGrowAmountY
);
1463 else if( nCode
== KEY_LEFT
||
1464 nCode
== KEY_RIGHT
||
1468 if( m_aSelection
.isDragableObjectSelected() )
1471 double fShiftAmountX
= 100.0;
1472 double fShiftAmountY
= 100.0;
1475 // together with Alt-key: 1 px
1476 Size aPixelSize
= pChartWindow
->PixelToLogic( Size( 1, 1 ));
1477 fShiftAmountX
= static_cast< double >( aPixelSize
.Width());
1478 fShiftAmountY
= static_cast< double >( aPixelSize
.Height());
1483 fShiftAmountX
= -fShiftAmountX
;
1484 fShiftAmountY
= 0.0;
1487 fShiftAmountY
= 0.0;
1490 fShiftAmountX
= 0.0;
1491 fShiftAmountY
= -fShiftAmountY
;
1494 fShiftAmountX
= 0.0;
1497 if( !m_aSelection
.getSelectedCID().isEmpty() )
1499 //move chart objects
1500 if (eObjectType
== OBJECTTYPE_DATA_LABEL
)
1502 SdrObject
* pObj
= pDrawViewWrapper
->getSelectedObject();
1505 tools::Rectangle aRect
= pObj
->GetSnapRect();
1506 awt::Size
aPageSize(ChartModelHelper::getPageSize(getChartModel()));
1507 if ((fShiftAmountX
> 0.0 && (aRect
.Right() + fShiftAmountX
> aPageSize
.Width
)) ||
1508 (fShiftAmountX
< 0.0 && (aRect
.Left() + fShiftAmountX
< 0)) ||
1509 (fShiftAmountY
> 0.0 && (aRect
.Bottom() + fShiftAmountY
> aPageSize
.Height
)) ||
1510 (fShiftAmountY
< 0.0 && (aRect
.Top() + fShiftAmountY
< 0)))
1513 bReturn
= PositionAndSizeHelper::moveObject(
1514 m_aSelection
.getSelectedCID(), getChartModel(),
1515 awt::Rectangle(aRect
.Left() + fShiftAmountX
, aRect
.Top() + fShiftAmountY
, aRect
.getOpenWidth(), aRect
.getOpenHeight()),
1516 awt::Rectangle(aRect
.Left(), aRect
.Top(), 0, 0),
1517 awt::Rectangle(0, 0, aPageSize
.Width
, aPageSize
.Height
));
1521 bReturn
= impl_moveOrResizeObject(
1522 m_aSelection
.getSelectedCID(), MOVE_OBJECT
, fShiftAmountX
, fShiftAmountY
);
1526 //move additional shapes
1527 uno::Reference
< drawing::XShape
> xShape( m_aSelection
.getSelectedAdditionalShape() );
1530 awt::Point
aPos( xShape
->getPosition() );
1531 awt::Size
aSize( xShape
->getSize() );
1532 awt::Size
aPageSize( ChartModelHelper::getPageSize( getChartModel() ) );
1533 aPos
.X
= static_cast< tools::Long
>( static_cast< double >( aPos
.X
) + fShiftAmountX
);
1534 aPos
.Y
= static_cast< tools::Long
>( static_cast< double >( aPos
.Y
) + fShiftAmountY
);
1535 if( aPos
.X
+ aSize
.Width
> aPageSize
.Width
)
1536 aPos
.X
= aPageSize
.Width
- aSize
.Width
;
1539 if( aPos
.Y
+ aSize
.Height
> aPageSize
.Height
)
1540 aPos
.Y
= aPageSize
.Height
- aSize
.Height
;
1544 xShape
->setPosition( aPos
);
1552 // dumping the shape
1553 if( !bReturn
&& bCtrl
&& nCode
== KEY_F12
)
1555 rtl::Reference
< ChartModel
> xChartModel
= getChartModel();
1556 if(xChartModel
.is())
1558 OUString aDump
= xChartModel
->dump(u
"shapes"_ustr
);
1559 SAL_WARN("chart2", aDump
);
1567 if( eObjectType
== OBJECTTYPE_TITLE
)
1569 executeDispatch_EditText();
1574 // deactivate inplace mode (this code should be unnecessary, but
1575 // unfortunately is not)
1577 nCode
== KEY_ESCAPE
)
1579 uno::Reference
< frame::XDispatchHelper
> xDispatchHelper( frame::DispatchHelper::create(m_xCC
) );
1580 uno::Sequence
< beans::PropertyValue
> aArgs
;
1581 xDispatchHelper
->executeDispatch(
1582 uno::Reference
< frame::XDispatchProvider
>( m_xFrame
, uno::UNO_QUERY
),
1583 u
".uno:TerminateInplaceActivation"_ustr
,
1585 frame::FrameSearchFlag::PARENT
,
1591 (nCode
== KEY_DELETE
|| nCode
== KEY_BACKSPACE
))
1593 bReturn
= executeDispatch_Delete();
1596 std::shared_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(pChartWindow
->GetFrameWeld(),
1597 VclMessageType::Info
, VclButtonsType::Ok
,
1598 SchResId(STR_ACTION_NOTPOSSIBLE
)));
1599 xInfoBox
->runAsync(xInfoBox
, [] (int) {});
1606 bool ChartController::requestQuickHelp(
1607 ::Point aAtLogicPosition
,
1608 bool bIsBalloonHelp
,
1609 OUString
& rOutQuickHelpText
,
1610 awt::Rectangle
& rOutEqualRect
)
1612 rtl::Reference
<::chart::ChartModel
> xChartModel
;
1614 xChartModel
= getChartModel();
1615 if( !xChartModel
.is())
1620 if( m_pDrawViewWrapper
)
1622 aCID
= SelectionHelper::getHitObjectCID(
1623 aAtLogicPosition
, *m_pDrawViewWrapper
);
1625 bool bResult( !aCID
.isEmpty());
1630 rOutQuickHelpText
= ObjectNameProvider::getHelpText( aCID
, xChartModel
, bIsBalloonHelp
/* bVerbose */ );
1634 rOutEqualRect
= m_xChartView
->getRectangleOfObject( aCID
, true );
1640 // XSelectionSupplier (optional interface)
1641 sal_Bool SAL_CALL
ChartController::select( const uno::Any
& rSelection
)
1643 bool bSuccess
= false;
1645 if ( rSelection
.hasValue() )
1647 if (rSelection
.getValueType() == cppu::UnoType
<OUString
>::get())
1650 if ( ( rSelection
>>= aNewCID
) && m_aSelection
.setSelection( aNewCID
) )
1655 else if (uno::Reference
<drawing::XShape
> xShape
; rSelection
>>= xShape
)
1657 if (m_aSelection
.setSelection(xShape
))
1665 if ( m_aSelection
.hasSelection() )
1667 m_aSelection
.clearSelection();
1674 SolarMutexGuard aGuard
;
1675 if ( m_pDrawViewWrapper
&& m_pDrawViewWrapper
->IsTextEdit() )
1679 impl_selectObjectAndNotiy();
1680 auto pChartWindow(GetChartWindow());
1683 pChartWindow
->Invalidate();
1691 uno::Any SAL_CALL
ChartController::getSelection()
1694 if ( m_aSelection
.hasSelection() )
1696 OUString
aCID( m_aSelection
.getSelectedCID() );
1697 if ( !aCID
.isEmpty() )
1703 // #i12587# support for shapes in chart
1704 aReturn
<<= m_aSelection
.getSelectedAdditionalShape();
1710 void SAL_CALL
ChartController::addSelectionChangeListener( const uno::Reference
<view::XSelectionChangeListener
> & xListener
)
1712 SolarMutexGuard aGuard
;
1713 if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode?
1714 return; //behave passive if already disposed or suspended
1717 std::unique_lock
aGuard2(m_aLifeTimeManager
.m_aAccessMutex
);
1718 m_aLifeTimeManager
.m_aSelectionChangeListeners
.addInterface( aGuard2
, xListener
);
1721 void SAL_CALL
ChartController::removeSelectionChangeListener( const uno::Reference
<view::XSelectionChangeListener
> & xListener
)
1723 SolarMutexGuard aGuard
;
1724 if( impl_isDisposedOrSuspended() ) //@todo? allow removing of listeners in suspend mode?
1725 return; //behave passive if already disposed or suspended
1728 std::unique_lock
aGuard2(m_aLifeTimeManager
.m_aAccessMutex
);
1729 m_aLifeTimeManager
.m_aSelectionChangeListeners
.removeInterface( aGuard2
, xListener
);
1732 void ChartController::impl_notifySelectionChangeListeners()
1734 std::unique_lock
aGuard(m_aLifeTimeManager
.m_aAccessMutex
);
1735 if( m_aLifeTimeManager
.m_aSelectionChangeListeners
.getLength(aGuard
) )
1737 uno::Reference
< view::XSelectionSupplier
> xSelectionSupplier(this);
1738 lang::EventObject
aEvent( xSelectionSupplier
);
1739 m_aLifeTimeManager
.m_aSelectionChangeListeners
.notifyEach(aGuard
, &view::XSelectionChangeListener::selectionChanged
, aEvent
);
1743 void ChartController::impl_selectObjectAndNotiy()
1746 SolarMutexGuard aGuard
;
1747 DrawViewWrapper
* pDrawViewWrapper
= m_pDrawViewWrapper
.get();
1748 if( pDrawViewWrapper
)
1750 pDrawViewWrapper
->SetDragMode( m_eDragMode
);
1751 m_aSelection
.applySelection( m_pDrawViewWrapper
.get() );
1754 impl_notifySelectionChangeListeners();
1757 bool ChartController::impl_moveOrResizeObject(
1758 const OUString
& rCID
,
1759 eMoveOrResizeType eType
,
1760 double fAmountLogicX
,
1761 double fAmountLogicY
)
1763 bool bResult
= false;
1764 bool bNeedResize
= ( eType
== CENTERED_RESIZE_OBJECT
);
1766 rtl::Reference
<::chart::ChartModel
> xChartModel( getChartModel() );
1767 uno::Reference
< beans::XPropertySet
> xObjProp(
1768 ObjectIdentifier::getObjectPropertySet( rCID
, xChartModel
));
1771 awt::Size aRefSize
= ChartModelHelper::getPageSize( xChartModel
);
1773 chart2::RelativePosition aRelPos
;
1774 chart2::RelativeSize aRelSize
;
1775 bool bDeterminePos
= !(xObjProp
->getPropertyValue( u
"RelativePosition"_ustr
) >>= aRelPos
);
1776 bool bDetermineSize
= !bNeedResize
|| !(xObjProp
->getPropertyValue( u
"RelativeSize"_ustr
) >>= aRelSize
);
1778 if( ( bDeterminePos
|| bDetermineSize
) &&
1779 ( aRefSize
.Width
> 0 && aRefSize
.Height
> 0 ) )
1781 ExplicitValueProvider
* pValueProvider( m_xChartView
.get() );
1782 if( pValueProvider
)
1784 awt::Rectangle
aRect( pValueProvider
->getRectangleOfObject( rCID
));
1785 double fWidth
= static_cast< double >( aRefSize
.Width
);
1786 double fHeight
= static_cast< double >( aRefSize
.Height
);
1787 if( bDetermineSize
)
1789 aRelSize
.Primary
= static_cast< double >( aRect
.Width
) / fWidth
;
1790 aRelSize
.Secondary
= static_cast< double >( aRect
.Height
) / fHeight
;
1794 if( bNeedResize
&& aRelSize
.Primary
> 0.0 && aRelSize
.Secondary
> 0.0 )
1796 aRelPos
.Primary
= (static_cast< double >( aRect
.X
) / fWidth
) +
1797 (aRelSize
.Primary
/ 2.0);
1798 aRelPos
.Secondary
= (static_cast< double >( aRect
.Y
) / fHeight
) +
1799 (aRelSize
.Secondary
/ 2.0);
1800 aRelPos
.Anchor
= drawing::Alignment_CENTER
;
1804 aRelPos
.Primary
= static_cast< double >( aRect
.X
) / fWidth
;
1805 aRelPos
.Secondary
= static_cast< double >( aRect
.Y
) / fHeight
;
1806 aRelPos
.Anchor
= drawing::Alignment_TOP_LEFT
;
1812 if( eType
== CENTERED_RESIZE_OBJECT
)
1813 bResult
= lcl_GrowAndShiftLogic( aRelPos
, aRelSize
, aRefSize
, fAmountLogicX
, fAmountLogicY
);
1814 else if( eType
== MOVE_OBJECT
)
1815 bResult
= lcl_MoveObjectLogic( aRelPos
, aRelSize
, aRefSize
, fAmountLogicX
, fAmountLogicY
);
1819 ActionDescriptionProvider::ActionType
eActionType(ActionDescriptionProvider::ActionType::Move
);
1821 eActionType
= ActionDescriptionProvider::ActionType::Resize
;
1823 ObjectType eObjectType
= ObjectIdentifier::getObjectType( rCID
);
1824 UndoGuard
aUndoGuard( ActionDescriptionProvider::createDescription(
1825 eActionType
, ObjectNameProvider::getName( eObjectType
)), m_xUndoManager
);
1827 ControllerLockGuardUNO
aCLGuard( xChartModel
);
1828 xObjProp
->setPropertyValue( u
"RelativePosition"_ustr
, uno::Any( aRelPos
));
1829 if( bNeedResize
|| (eObjectType
== OBJECTTYPE_DIAGRAM
) )//Also set an explicit size at the diagram when an explicit position is set
1830 xObjProp
->setPropertyValue( u
"RelativeSize"_ustr
, uno::Any( aRelSize
));
1832 aUndoGuard
.commit();
1838 bool ChartController::impl_DragDataPoint( std::u16string_view rCID
, double fAdditionalOffset
)
1840 bool bResult
= false;
1841 if( fAdditionalOffset
< -1.0 || fAdditionalOffset
> 1.0 || fAdditionalOffset
== 0.0 )
1844 sal_Int32 nDataPointIndex
= ObjectIdentifier::getIndexFromParticleOrCID( rCID
);
1845 rtl::Reference
< DataSeries
> xSeries
=
1846 ObjectIdentifier::getDataSeriesForCID( rCID
, getChartModel() );
1851 uno::Reference
< beans::XPropertySet
> xPointProp( xSeries
->getDataPointByIndex( nDataPointIndex
));
1852 double fOffset
= 0.0;
1853 if( xPointProp
.is() &&
1854 (xPointProp
->getPropertyValue( u
"Offset"_ustr
) >>= fOffset
) &&
1855 (( fAdditionalOffset
> 0.0 && fOffset
< 1.0 ) || (fOffset
> 0.0)) )
1857 fOffset
+= fAdditionalOffset
;
1860 else if( fOffset
< 0.0 )
1862 xPointProp
->setPropertyValue( u
"Offset"_ustr
, uno::Any( fOffset
));
1866 catch( const uno::Exception
& )
1868 DBG_UNHANDLED_EXCEPTION("chart2");
1875 void ChartController::impl_SetMousePointer( const MouseEvent
& rEvent
)
1877 SolarMutexGuard aGuard
;
1878 auto pChartWindow(GetChartWindow());
1880 if (!m_pDrawViewWrapper
|| !pChartWindow
)
1883 Point
aMousePos( pChartWindow
->PixelToLogic( rEvent
.GetPosPixel()));
1884 sal_uInt16 nModifier
= rEvent
.GetModifier();
1885 bool bLeftDown
= rEvent
.IsLeft();
1887 // Check if object is for field button and set the normal arrow pointer in this case
1888 SdrObject
* pObject
= m_pDrawViewWrapper
->getHitObject(aMousePos
);
1889 if (pObject
&& pObject
->GetName().startsWith("FieldButton"))
1891 pChartWindow
->SetPointer(PointerStyle::Arrow
);
1895 if ( m_pDrawViewWrapper
->IsTextEdit() )
1897 if( m_pDrawViewWrapper
->IsTextEditHit( aMousePos
) )
1899 pChartWindow
->SetPointer( m_pDrawViewWrapper
->GetPreferredPointer(
1900 aMousePos
, pChartWindow
->GetOutDev(), nModifier
, bLeftDown
) );
1904 else if( m_pDrawViewWrapper
->IsAction() )
1906 return;//don't change pointer during running action
1909 SdrHdl
* pHitSelectionHdl
= nullptr;
1910 if( m_aSelection
.isResizeableObjectSelected() )
1911 pHitSelectionHdl
= m_pDrawViewWrapper
->PickHandle( aMousePos
);
1913 if( pHitSelectionHdl
)
1915 PointerStyle aPointer
= m_pDrawViewWrapper
->GetPreferredPointer(
1916 aMousePos
, pChartWindow
->GetOutDev(), nModifier
, bLeftDown
);
1917 bool bForceArrowPointer
= false;
1919 ObjectIdentifier
aOID( m_aSelection
.getSelectedOID() );
1923 case PointerStyle::NSize
:
1924 case PointerStyle::SSize
:
1925 case PointerStyle::WSize
:
1926 case PointerStyle::ESize
:
1927 case PointerStyle::NWSize
:
1928 case PointerStyle::NESize
:
1929 case PointerStyle::SWSize
:
1930 case PointerStyle::SESize
:
1931 if( ! m_aSelection
.isResizeableObjectSelected() )
1932 bForceArrowPointer
= true;
1934 case PointerStyle::Move
:
1935 if ( !aOID
.isDragableObject() )
1936 bForceArrowPointer
= true;
1938 case PointerStyle::MovePoint
:
1939 case PointerStyle::MoveBezierWeight
:
1940 // there is no point-editing in a chart
1941 // the PointerStyle::MoveBezierWeight appears in 3d data points
1942 bForceArrowPointer
= true;
1948 if( bForceArrowPointer
)
1949 pChartWindow
->SetPointer( PointerStyle::Arrow
);
1951 pChartWindow
->SetPointer( aPointer
);
1956 // #i12587# support for shapes in chart
1957 if ( m_eDrawMode
== CHARTDRAW_INSERT
&&
1958 ( !m_pDrawViewWrapper
->IsMarkedHit( aMousePos
) || !m_aSelection
.isDragableObjectSelected() ) )
1960 PointerStyle ePointerStyle
= PointerStyle::DrawRect
;
1961 SdrObjKind eKind
= m_pDrawViewWrapper
->GetCurrentObjIdentifier();
1964 case SdrObjKind::Line
:
1966 ePointerStyle
= PointerStyle::DrawLine
;
1969 case SdrObjKind::Rectangle
:
1970 case SdrObjKind::CustomShape
:
1972 ePointerStyle
= PointerStyle::DrawRect
;
1975 case SdrObjKind::CircleOrEllipse
:
1977 ePointerStyle
= PointerStyle::DrawEllipse
;
1980 case SdrObjKind::FreehandLine
:
1982 ePointerStyle
= PointerStyle::DrawPolygon
;
1985 case SdrObjKind::Text
:
1987 ePointerStyle
= PointerStyle::DrawText
;
1990 case SdrObjKind::Caption
:
1992 ePointerStyle
= PointerStyle::DrawCaption
;
1997 ePointerStyle
= PointerStyle::DrawRect
;
2001 pChartWindow
->SetPointer( ePointerStyle
);
2005 OUString
aHitObjectCID(
2006 SelectionHelper::getHitObjectCID(
2007 aMousePos
, *m_pDrawViewWrapper
, true /*bGetDiagramInsteadOf_Wall*/ ));
2009 if( m_pDrawViewWrapper
->IsTextEdit() )
2011 if( aHitObjectCID
== m_aSelection
.getSelectedCID() )
2013 pChartWindow
->SetPointer( PointerStyle::Arrow
);
2018 if( aHitObjectCID
.isEmpty() )
2020 //additional shape was hit
2021 pChartWindow
->SetPointer( PointerStyle::Move
);
2023 else if( ObjectIdentifier::isDragableObject( aHitObjectCID
) )
2025 if( (m_eDragMode
== SdrDragMode::Rotate
)
2026 && SelectionHelper::isRotateableObject( aHitObjectCID
2027 , getChartModel() ) )
2028 pChartWindow
->SetPointer( PointerStyle::Rotate
);
2031 ObjectType eHitObjectType
= ObjectIdentifier::getObjectType( aHitObjectCID
);
2032 if( eHitObjectType
== OBJECTTYPE_DATA_POINT
)
2034 if( !ObjectIdentifier::areSiblings(aHitObjectCID
,m_aSelection
.getSelectedCID())
2035 && !ObjectIdentifier::areIdenticalObjects(aHitObjectCID
,m_aSelection
.getSelectedCID()) )
2037 pChartWindow
->SetPointer( PointerStyle::Arrow
);
2041 pChartWindow
->SetPointer( PointerStyle::Move
);
2045 pChartWindow
->SetPointer( PointerStyle::Arrow
);
2048 void ChartController::sendPopupRequest(std::u16string_view rCID
, tools::Rectangle aRectangle
)
2050 ChartModel
* pChartModel
= m_aModel
->getModel().get();
2054 uno::Reference
<chart2::data::XPivotTableDataProvider
> xPivotTableDataProvider
;
2055 xPivotTableDataProvider
.set(pChartModel
->getDataProvider(), uno::UNO_QUERY
);
2056 if (!xPivotTableDataProvider
.is())
2059 OUString sPivotTableName
= xPivotTableDataProvider
->getPivotTableName();
2061 css::uno::Reference
<css::awt::XRequestCallback
> xPopupRequest
= pChartModel
->getPopupRequest();
2062 PopupRequest
* pPopupRequest
= dynamic_cast<PopupRequest
*>(xPopupRequest
.get());
2066 // Get dimension index from CID
2067 size_t nStartPos
= rCID
.rfind('.');
2068 nStartPos
= (nStartPos
== std::u16string_view::npos
) ? 0 : (nStartPos
+ 1);
2069 sal_Int32 nEndPos
= rCID
.size();
2070 std::u16string_view sDimensionIndex
= rCID
.substr(nStartPos
, nEndPos
- nStartPos
);
2071 sal_Int32 nDimensionIndex
= o3tl::toInt32(sDimensionIndex
);
2073 awt::Rectangle xRectangle
{
2074 sal_Int32(aRectangle
.Left()),
2075 sal_Int32(aRectangle
.Top()),
2076 sal_Int32(aRectangle
.GetWidth()),
2077 sal_Int32(aRectangle
.GetHeight())
2080 uno::Sequence
<beans::PropertyValue
> aCallbackData
= comphelper::InitPropertySequence(
2082 {"Rectangle", uno::Any(xRectangle
)},
2083 {"DimensionIndex", uno::Any(sal_Int32(nDimensionIndex
))},
2084 {"PivotTableName", uno::Any(sPivotTableName
)},
2087 pPopupRequest
->getCallback()->notify(uno::Any(aCallbackData
));
2092 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */