Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / chart2 / source / controller / main / ChartController_Window.cxx
blob9c3993095e47f9e3b9b457413a7e252410b71f35
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <ChartController.hxx>
21 #include <PositionAndSizeHelper.hxx>
22 #include <ObjectIdentifier.hxx>
23 #include <ChartWindow.hxx>
24 #include <ResId.hxx>
25 #include <CommonConverters.hxx>
26 #include <ChartModelHelper.hxx>
27 #include <DiagramHelper.hxx>
28 #include <TitleHelper.hxx>
29 #include "UndoGuard.hxx"
30 #include <ControllerLockGuard.hxx>
31 #include <ObjectNameProvider.hxx>
32 #include <strings.hrc>
33 #include "DragMethod_PieSegment.hxx"
34 #include "DragMethod_RotateDiagram.hxx"
35 #include <ObjectHierarchy.hxx>
36 #include <chartview/ExplicitValueProvider.hxx>
37 #include <RelativePositionHelper.hxx>
38 #include <chartview/DrawModelWrapper.hxx>
39 #include <RegressionCurveHelper.hxx>
40 #include <StatisticsHelper.hxx>
41 #include <DataSeriesHelper.hxx>
42 #include <ContainerHelper.hxx>
43 #include <AxisHelper.hxx>
44 #include <LegendHelper.hxx>
45 #include <servicenames_charttypes.hxx>
46 #include "DrawCommandDispatch.hxx"
47 #include <PopupRequest.hxx>
49 #include <com/sun/star/chart2/RelativePosition.hpp>
50 #include <com/sun/star/chart2/RelativeSize.hpp>
51 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
52 #include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
54 #include <com/sun/star/awt/PopupMenuDirection.hpp>
55 #include <com/sun/star/frame/DispatchHelper.hpp>
56 #include <com/sun/star/frame/FrameSearchFlag.hpp>
57 #include <com/sun/star/frame/XPopupMenuController.hpp>
58 #include <com/sun/star/util/XUpdatable.hpp>
59 #include <com/sun/star/awt/Rectangle.hpp>
61 #include <comphelper/lok.hxx>
62 #include <comphelper/propertysequence.hxx>
63 #include <comphelper/propertyvalue.hxx>
64 #include <comphelper/sequence.hxx>
66 #include <toolkit/awt/vclxmenu.hxx>
68 #include <sfx2/viewsh.hxx>
69 #include <sfx2/ipclient.hxx>
70 #include <svx/svxids.hrc>
71 #include <svx/ActionDescriptionProvider.hxx>
72 #include <svx/obj3d.hxx>
73 #include <svx/scene3d.hxx>
74 #include <svx/svddrgmt.hxx>
75 #include <vcl/svapp.hxx>
76 #include <vcl/settings.hxx>
77 #include <vcl/weld.hxx>
78 #include <rtl/math.hxx>
79 #include <svtools/acceleratorexecute.hxx>
80 #include <tools/diagnose_ex.h>
82 #define DRGPIX 2 // Drag MinMove in Pixel
84 using namespace ::com::sun::star;
85 using namespace ::com::sun::star::chart2;
86 using ::com::sun::star::uno::Reference;
88 namespace chart
91 namespace
93 bool lcl_GrowAndShiftLogic(
94 RelativePosition & rInOutRelPos,
95 RelativeSize & rInOutRelSize,
96 const awt::Size & rRefSize,
97 double fGrowLogicX,
98 double fGrowLogicY )
100 if( rRefSize.Width == 0 ||
101 rRefSize.Height == 0 )
102 return false;
104 double fRelativeGrowX = fGrowLogicX / rRefSize.Width;
105 double fRelativeGrowY = fGrowLogicY / rRefSize.Height;
107 return ::chart::RelativePositionHelper::centerGrow(
108 rInOutRelPos, rInOutRelSize,
109 fRelativeGrowX, fRelativeGrowY );
112 bool lcl_MoveObjectLogic(
113 RelativePosition & rInOutRelPos,
114 RelativeSize const & rObjectSize,
115 const awt::Size & rRefSize,
116 double fShiftLogicX,
117 double fShiftLogicY )
119 if( rRefSize.Width == 0 ||
120 rRefSize.Height == 0 )
121 return false;
123 double fRelativeShiftX = fShiftLogicX / rRefSize.Width;
124 double fRelativeShiftY = fShiftLogicY / rRefSize.Height;
126 return ::chart::RelativePositionHelper::moveObject(
127 rInOutRelPos, rObjectSize,
128 fRelativeShiftX, fRelativeShiftY );
131 void lcl_insertMenuCommand(
132 const uno::Reference< awt::XPopupMenu > & xMenu,
133 sal_Int16 nId, const OUString & rCommand )
135 xMenu->insertItem( nId, "", 0, -1 );
136 xMenu->setCommand( nId, rCommand );
139 OUString lcl_getFormatCommandForObjectCID( const OUString& rCID )
141 OUString aDispatchCommand( ".uno:FormatSelection" );
143 ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID );
145 switch(eObjectType)
147 case OBJECTTYPE_DIAGRAM:
148 case OBJECTTYPE_DIAGRAM_WALL:
149 aDispatchCommand = ".uno:FormatWall";
150 break;
151 case OBJECTTYPE_DIAGRAM_FLOOR:
152 aDispatchCommand = ".uno:FormatFloor";
153 break;
154 case OBJECTTYPE_PAGE:
155 aDispatchCommand = ".uno:FormatChartArea";
156 break;
157 case OBJECTTYPE_LEGEND:
158 aDispatchCommand = ".uno:FormatLegend";
159 break;
160 case OBJECTTYPE_TITLE:
161 aDispatchCommand = ".uno:FormatTitle";
162 break;
163 case OBJECTTYPE_LEGEND_ENTRY:
164 aDispatchCommand = ".uno:FormatDataSeries";
165 break;
166 case OBJECTTYPE_AXIS:
167 case OBJECTTYPE_AXIS_UNITLABEL:
168 aDispatchCommand = ".uno:FormatAxis";
169 break;
170 case OBJECTTYPE_GRID:
171 aDispatchCommand = ".uno:FormatMajorGrid";
172 break;
173 case OBJECTTYPE_SUBGRID:
174 aDispatchCommand = ".uno:FormatMinorGrid";
175 break;
176 case OBJECTTYPE_DATA_LABELS:
177 aDispatchCommand = ".uno:FormatDataLabels";
178 break;
179 case OBJECTTYPE_DATA_SERIES:
180 aDispatchCommand = ".uno:FormatDataSeries";
181 break;
182 case OBJECTTYPE_DATA_LABEL:
183 aDispatchCommand = ".uno:FormatDataLabel";
184 break;
185 case OBJECTTYPE_DATA_POINT:
186 aDispatchCommand = ".uno:FormatDataPoint";
187 break;
188 case OBJECTTYPE_DATA_AVERAGE_LINE:
189 aDispatchCommand = ".uno:FormatMeanValue";
190 break;
191 case OBJECTTYPE_DATA_ERRORS_X:
192 aDispatchCommand = ".uno:FormatXErrorBars";
193 break;
194 case OBJECTTYPE_DATA_ERRORS_Y:
195 aDispatchCommand = ".uno:FormatYErrorBars";
196 break;
197 case OBJECTTYPE_DATA_ERRORS_Z:
198 aDispatchCommand = ".uno:FormatZErrorBars";
199 break;
200 case OBJECTTYPE_DATA_CURVE:
201 aDispatchCommand = ".uno:FormatTrendline";
202 break;
203 case OBJECTTYPE_DATA_CURVE_EQUATION:
204 aDispatchCommand = ".uno:FormatTrendlineEquation";
205 break;
206 case OBJECTTYPE_DATA_STOCK_RANGE:
207 aDispatchCommand = ".uno:FormatSelection";
208 break;
209 case OBJECTTYPE_DATA_STOCK_LOSS:
210 aDispatchCommand = ".uno:FormatStockLoss";
211 break;
212 case OBJECTTYPE_DATA_STOCK_GAIN:
213 aDispatchCommand = ".uno:FormatStockGain";
214 break;
215 default: //OBJECTTYPE_UNKNOWN
216 break;
218 return aDispatchCommand;
221 } // anonymous namespace
223 // awt::XWindow
224 void SAL_CALL ChartController::setPosSize(
225 sal_Int32 X,
226 sal_Int32 Y,
227 sal_Int32 Width,
228 sal_Int32 Height,
229 sal_Int16 Flags )
231 SolarMutexGuard aGuard;
232 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
233 auto pChartWindow(GetChartWindow());
235 if(xWindow.is() && pChartWindow)
237 Size aLogicSize = pChartWindow->PixelToLogic( Size( Width, Height ), MapMode( MapUnit::Map100thMM ) );
239 //todo: for standalone chart: detect whether we are standalone
240 //change map mode to fit new size
241 awt::Size aModelPageSize = ChartModelHelper::getPageSize( getModel() );
242 sal_Int32 nScaleXNumerator = aLogicSize.Width();
243 sal_Int32 nScaleXDenominator = aModelPageSize.Width;
244 sal_Int32 nScaleYNumerator = aLogicSize.Height();
245 sal_Int32 nScaleYDenominator = aModelPageSize.Height;
246 MapMode aNewMapMode(
247 MapUnit::Map100thMM,
248 Point(0,0),
249 Fraction(nScaleXNumerator, nScaleXDenominator),
250 Fraction(nScaleYNumerator, nScaleYDenominator) );
251 pChartWindow->SetMapMode(aNewMapMode);
252 pChartWindow->setPosSizePixel( X, Y, Width, Height, static_cast<PosSizeFlags>(Flags) );
254 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
255 uno::Reference< beans::XPropertySet > xProp( m_xChartView, uno::UNO_QUERY );
256 if( xProp.is() )
258 auto aZoomFactors(::comphelper::InitPropertySequence({
259 { "ScaleXNumerator", uno::Any( nScaleXNumerator ) },
260 { "ScaleXDenominator", uno::Any( nScaleXDenominator ) },
261 { "ScaleYNumerator", uno::Any( nScaleYNumerator ) },
262 { "ScaleYDenominator", uno::Any( nScaleYDenominator ) }
263 }));
264 xProp->setPropertyValue( "ZoomFactors", uno::Any( aZoomFactors ));
267 //a correct work area is at least necessary for correct values in the position and size dialog and for dragging area
268 if(m_pDrawViewWrapper)
270 tools::Rectangle aRect(Point(0,0), pChartWindow->GetOutputSize());
271 m_pDrawViewWrapper->SetWorkArea( aRect );
273 pChartWindow->Invalidate();
277 awt::Rectangle SAL_CALL ChartController::getPosSize()
279 //@todo
280 awt::Rectangle aRet(0, 0, 0, 0);
282 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
283 if(xWindow.is())
284 aRet = xWindow->getPosSize();
286 return aRet;
289 void SAL_CALL ChartController::setVisible( sal_Bool Visible )
291 //@todo
292 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
294 if(xWindow.is())
295 xWindow->setVisible( Visible );
298 void SAL_CALL ChartController::setEnable( sal_Bool Enable )
300 //@todo
301 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
303 if(xWindow.is())
304 xWindow->setEnable( Enable );
307 void SAL_CALL ChartController::setFocus()
309 //@todo
310 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
312 if(xWindow.is())
313 xWindow->setFocus();
316 void SAL_CALL ChartController::addWindowListener(
317 const uno::Reference< awt::XWindowListener >& xListener )
319 //@todo
320 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
322 if(xWindow.is())
323 xWindow->addWindowListener( xListener );
326 void SAL_CALL ChartController::removeWindowListener(
327 const uno::Reference< awt::XWindowListener >& xListener )
329 //@todo
330 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
332 if(xWindow.is())
333 xWindow->removeWindowListener( xListener );
336 void SAL_CALL ChartController::addFocusListener(
337 const uno::Reference< awt::XFocusListener >& xListener )
339 //@todo
340 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
342 if(xWindow.is())
343 xWindow->addFocusListener( xListener );
346 void SAL_CALL ChartController::removeFocusListener(
347 const uno::Reference< awt::XFocusListener >& xListener )
349 //@todo
350 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
352 if(xWindow.is())
353 xWindow->removeFocusListener( xListener );
356 void SAL_CALL ChartController::addKeyListener(
357 const uno::Reference< awt::XKeyListener >& xListener )
359 //@todo
360 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
362 if(xWindow.is())
363 xWindow->addKeyListener( xListener );
366 void SAL_CALL ChartController::removeKeyListener(
367 const uno::Reference< awt::XKeyListener >& xListener )
369 //@todo
370 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
372 if(xWindow.is())
373 xWindow->removeKeyListener( xListener );
376 void SAL_CALL ChartController::addMouseListener(
377 const uno::Reference< awt::XMouseListener >& xListener )
379 //@todo
380 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
382 if(xWindow.is())
383 xWindow->addMouseListener( xListener );
386 void SAL_CALL ChartController::removeMouseListener(
387 const uno::Reference< awt::XMouseListener >& xListener )
389 //@todo
390 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
392 if(xWindow.is())
393 xWindow->removeMouseListener( xListener );
396 void SAL_CALL ChartController::addMouseMotionListener(
397 const uno::Reference< awt::XMouseMotionListener >& xListener )
399 //@todo
400 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
402 if(xWindow.is())
403 xWindow->addMouseMotionListener( xListener );
406 void SAL_CALL ChartController::removeMouseMotionListener(
407 const uno::Reference< awt::XMouseMotionListener >& xListener )
409 //@todo
410 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
412 if(xWindow.is())
413 xWindow->removeMouseMotionListener( xListener );
416 void SAL_CALL ChartController::addPaintListener(
417 const uno::Reference< awt::XPaintListener >& xListener )
419 //@todo
420 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
422 if(xWindow.is())
423 xWindow->addPaintListener( xListener );
426 void SAL_CALL ChartController::removePaintListener(
427 const uno::Reference< awt::XPaintListener >& xListener )
429 //@todo
430 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
432 if(xWindow.is())
433 xWindow->removePaintListener( xListener );
436 // impl vcl window controller methods
437 void ChartController::PrePaint()
439 // forward VCLs PrePaint window event to DrawingLayer
440 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
442 if (pDrawViewWrapper)
444 pDrawViewWrapper->PrePaint();
448 void ChartController::execute_Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
452 uno::Reference<frame::XModel> xModel(getModel());
453 //OSL_ENSURE( xModel.is(), "ChartController::execute_Paint: have no model to paint");
454 if (!xModel.is())
455 return;
457 //better performance for big data
458 uno::Reference<beans::XPropertySet> xProp(m_xChartView, uno::UNO_QUERY);
459 if (xProp.is())
461 awt::Size aResolution(1000, 1000);
463 SolarMutexGuard aGuard;
464 auto pChartWindow(GetChartWindow());
465 if (pChartWindow)
467 aResolution.Width = pChartWindow->GetSizePixel().Width();
468 aResolution.Height = pChartWindow->GetSizePixel().Height();
471 xProp->setPropertyValue( "Resolution", uno::Any( aResolution ));
474 uno::Reference< util::XUpdatable > xUpdatable( m_xChartView, uno::UNO_QUERY );
475 if (xUpdatable.is())
476 xUpdatable->update();
479 SolarMutexGuard aGuard;
480 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
481 if (pDrawViewWrapper)
482 pDrawViewWrapper->CompleteRedraw(&rRenderContext, vcl::Region(rRect));
485 catch( const uno::Exception & )
487 DBG_UNHANDLED_EXCEPTION("chart2");
489 catch( ... )
494 bool isDoubleClick( const MouseEvent& rMEvt )
496 return rMEvt.GetClicks() == 2 && rMEvt.IsLeft() &&
497 !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsShift();
500 void ChartController::startDoubleClickWaiting()
502 SolarMutexGuard aGuard;
504 m_bWaitingForDoubleClick = true;
506 sal_uInt64 nDblClkTime = 500;
507 auto pChartWindow(GetChartWindow());
508 if( pChartWindow )
510 const MouseSettings& rMSettings = pChartWindow->GetSettings().GetMouseSettings();
511 nDblClkTime = rMSettings.GetDoubleClickTime();
513 m_aDoubleClickTimer.SetTimeout( nDblClkTime );
514 m_aDoubleClickTimer.Start();
517 void ChartController::stopDoubleClickWaiting()
519 m_aDoubleClickTimer.Stop();
520 m_bWaitingForDoubleClick = false;
523 IMPL_LINK_NOARG(ChartController, DoubleClickWaitingHdl, Timer *, void)
525 m_bWaitingForDoubleClick = false;
527 if( !m_bWaitingForMouseUp && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() )
529 impl_selectObjectAndNotiy();
530 SolarMutexGuard aGuard;
531 auto pChartWindow(GetChartWindow());
532 if( pChartWindow )
534 vcl::Window::PointerState aPointerState( pChartWindow->GetPointerState() );
535 MouseEvent aMouseEvent(
536 aPointerState.maPos,
537 1/*nClicks*/,
538 MouseEventModifiers::NONE,
539 static_cast< sal_uInt16 >( aPointerState.mnState )/*nButtons*/,
540 0/*nModifier*/ );
541 impl_SetMousePointer( aMouseEvent );
546 void ChartController::execute_MouseButtonDown( const MouseEvent& rMEvt )
548 SolarMutexGuard aGuard;
550 m_bWaitingForMouseUp = true;
551 m_bFieldButtonDown = false;
553 if( isDoubleClick(rMEvt) )
554 stopDoubleClickWaiting();
555 else
556 startDoubleClickWaiting();
558 m_aSelection.remindSelectionBeforeMouseDown();
560 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
561 auto pChartWindow(GetChartWindow());
562 if(!pChartWindow || !pDrawViewWrapper )
563 return;
565 Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel());
567 // Check if button was clicked
568 SdrObject* pObject = pDrawViewWrapper->getHitObject(aMPos);
569 if (pObject)
571 OUString aCID = pObject->GetName();
572 if (aCID.startsWith("FieldButton"))
574 m_bFieldButtonDown = true;
575 return; // Don't take any action if button was clicked
579 if ( rMEvt.GetButtons() == MOUSE_LEFT )
581 pChartWindow->GrabFocus();
582 pChartWindow->CaptureMouse();
585 if( pDrawViewWrapper->IsTextEdit() )
587 SdrViewEvent aVEvt;
588 if ( pDrawViewWrapper->IsTextEditHit( aMPos ) ||
589 // #i12587# support for shapes in chart
590 ( rMEvt.IsRight() && pDrawViewWrapper->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt ) == SdrHitKind::MarkedObject ) )
592 pDrawViewWrapper->MouseButtonDown(rMEvt, pChartWindow);
593 return;
595 else
597 EndTextEdit();
601 //abort running action
602 if( pDrawViewWrapper->IsAction() )
604 if( rMEvt.IsRight() )
605 pDrawViewWrapper->BckAction();
606 return;
609 if( isDoubleClick(rMEvt) ) //do not change selection if double click
610 return;//double click is handled further in mousebutton up
612 SdrHdl* pHitSelectionHdl = nullptr;
613 //switch from move to resize if handle is hit on a resizable object
614 if( m_aSelection.isResizeableObjectSelected() )
615 pHitSelectionHdl = pDrawViewWrapper->PickHandle( aMPos );
616 //only change selection if no selection handles are hit
617 if( !pHitSelectionHdl )
619 // #i12587# support for shapes in chart
620 if ( m_eDrawMode == CHARTDRAW_INSERT &&
621 ( !pDrawViewWrapper->IsMarkedHit( aMPos ) || !m_aSelection.isDragableObjectSelected() ) )
623 if ( m_aSelection.hasSelection() )
625 m_aSelection.clearSelection();
627 if ( !pDrawViewWrapper->IsAction() )
629 if ( pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_CAPTION )
631 Size aCaptionSize( 2268, 1134 );
632 pDrawViewWrapper->BegCreateCaptionObj( aMPos, aCaptionSize );
634 else
636 pDrawViewWrapper->BegCreateObj( aMPos);
638 SdrObject* pObj = pDrawViewWrapper->GetCreateObj();
639 DrawCommandDispatch* pDrawCommandDispatch = m_aDispatchContainer.getDrawCommandDispatch();
640 if ( pObj && m_pDrawModelWrapper && pDrawCommandDispatch )
642 SfxItemSet aSet( m_pDrawModelWrapper->GetItemPool() );
643 pDrawCommandDispatch->setAttributes( pObj );
644 pDrawCommandDispatch->setLineEnds( aSet );
645 pObj->SetMergedItemSet( aSet );
648 impl_SetMousePointer( rMEvt );
649 return;
652 m_aSelection.adaptSelectionToNewPos(
653 aMPos,
654 pDrawViewWrapper,
655 rMEvt.IsRight(),
656 m_bWaitingForDoubleClick );
658 if( !m_aSelection.isRotateableObjectSelected( getModel() ) )
660 m_eDragMode = SdrDragMode::Move;
661 pDrawViewWrapper->SetDragMode(m_eDragMode);
664 m_aSelection.applySelection(pDrawViewWrapper);
666 if( m_aSelection.isDragableObjectSelected()
667 && !rMEvt.IsRight() )
669 //start drag
670 sal_uInt16 nDrgLog = static_cast<sal_uInt16>(pChartWindow->PixelToLogic(Size(DRGPIX,0)).Width());
671 SdrDragMethod* pDragMethod = nullptr;
673 //change selection to 3D scene if rotate mode
674 SdrDragMode eDragMode = pDrawViewWrapper->GetDragMode();
675 if( eDragMode==SdrDragMode::Rotate )
677 E3dScene* pScene = SelectionHelper::getSceneToRotate( pDrawViewWrapper->getNamedSdrObject( m_aSelection.getSelectedCID() ) );
678 if( pScene )
680 DragMethod_RotateDiagram::RotationDirection eRotationDirection(DragMethod_RotateDiagram::ROTATIONDIRECTION_FREE);
681 if(pHitSelectionHdl)
683 SdrHdlKind eKind = pHitSelectionHdl->GetKind();
684 if( eKind==SdrHdlKind::Upper || eKind==SdrHdlKind::Lower )
685 eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_X;
686 else if( eKind==SdrHdlKind::Left || eKind==SdrHdlKind::Right )
687 eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Y;
688 else if( eKind==SdrHdlKind::UpperLeft || eKind==SdrHdlKind::UpperRight || eKind==SdrHdlKind::LowerLeft || eKind==SdrHdlKind::LowerRight )
689 eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Z;
691 pDragMethod = new DragMethod_RotateDiagram( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getModel(), eRotationDirection );
694 else
696 OUString aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) );
697 if( aDragMethodServiceName == ObjectIdentifier::getPieSegmentDragMethodServiceName() )
698 pDragMethod = new DragMethod_PieSegment( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getModel() );
700 pDrawViewWrapper->SdrView::BegDragObj(aMPos, nullptr, pHitSelectionHdl, nDrgLog, pDragMethod);
703 impl_SetMousePointer( rMEvt );
706 void ChartController::execute_MouseMove( const MouseEvent& rMEvt )
708 SolarMutexGuard aGuard;
710 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
711 auto pChartWindow(GetChartWindow());
712 if(!pChartWindow || !pDrawViewWrapper)
713 return;
715 if( m_pDrawViewWrapper->IsTextEdit() )
717 if( m_pDrawViewWrapper->MouseMove(rMEvt,pChartWindow) )
718 return;
721 if(pDrawViewWrapper->IsAction())
723 pDrawViewWrapper->MovAction( pChartWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
726 impl_SetMousePointer( rMEvt );
729 void ChartController::execute_MouseButtonUp( const MouseEvent& rMEvt )
731 ControllerLockGuardUNO aCLGuard( getModel() );
732 bool bMouseUpWithoutMouseDown = !m_bWaitingForMouseUp;
733 m_bWaitingForMouseUp = false;
734 bool bNotifySelectionChange = false;
736 SolarMutexGuard aGuard;
738 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
739 auto pChartWindow(GetChartWindow());
740 if(!pChartWindow || !pDrawViewWrapper)
741 return;
743 Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel());
745 // Check if button was clicked
746 if (m_bFieldButtonDown)
748 m_bFieldButtonDown = false;
749 SdrObject* pObject = pDrawViewWrapper->getHitObject(aMPos);
750 if (pObject)
752 OUString aCID = pObject->GetName();
753 if (aCID.startsWith("FieldButton"))
755 sendPopupRequest(aCID, pObject->GetCurrentBoundRect());
756 return;
761 if(pDrawViewWrapper->IsTextEdit())
763 if( pDrawViewWrapper->MouseButtonUp(rMEvt,pChartWindow) )
764 return;
767 // #i12587# support for shapes in chart
768 if ( m_eDrawMode == CHARTDRAW_INSERT && pDrawViewWrapper->IsCreateObj() )
770 pDrawViewWrapper->EndCreateObj( SdrCreateCmd::ForceEnd );
772 HiddenUndoContext aUndoContext( m_xUndoManager );
773 // don't want the positioning Undo action to appear in the UI
774 impl_switchDiagramPositioningToExcludingPositioning();
776 if ( pDrawViewWrapper->AreObjectsMarked() )
778 if ( pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_TEXT )
780 executeDispatch_EditText();
782 else
784 SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
785 if ( pObj )
787 uno::Reference< drawing::XShape > xShape( pObj->getUnoShape(), uno::UNO_QUERY );
788 if ( xShape.is() )
790 m_aSelection.setSelection( xShape );
791 m_aSelection.applySelection( pDrawViewWrapper );
796 else
798 m_aSelection.adaptSelectionToNewPos( aMPos, pDrawViewWrapper, rMEvt.IsRight(), m_bWaitingForDoubleClick );
799 m_aSelection.applySelection( pDrawViewWrapper );
800 setDrawMode( CHARTDRAW_SELECT );
803 else if ( pDrawViewWrapper->IsDragObj() )
805 bool bDraggingDone = false;
806 SdrDragMethod* pDragMethod = pDrawViewWrapper->SdrView::GetDragMethod();
807 bool bIsMoveOnly = pDragMethod && pDragMethod->getMoveOnly();
808 DragMethod_Base* pChartDragMethod = dynamic_cast< DragMethod_Base* >(pDragMethod);
809 if( pChartDragMethod )
811 UndoGuard aUndoGuard( pChartDragMethod->getUndoDescription(),
812 m_xUndoManager );
814 if( pDrawViewWrapper->EndDragObj() )
816 bDraggingDone = true;
817 aUndoGuard.commit();
821 if( !bDraggingDone && pDrawViewWrapper->EndDragObj() )
825 //end move or size
826 SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
827 if( pObj )
829 tools::Rectangle aObjectRect = pObj->GetSnapRect();
830 awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) );
831 tools::Rectangle aPageRect( 0,0,aPageSize.Width,aPageSize.Height );
833 const E3dObject* pE3dObject = dynamic_cast< const E3dObject*>( pObj );
834 if( pE3dObject )
835 aObjectRect = pE3dObject->GetScene()->GetSnapRect();
837 ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::ActionType::Move);
838 if( !bIsMoveOnly && m_aSelection.isResizeableObjectSelected() )
839 eActionType = ActionDescriptionProvider::ActionType::Resize;
841 ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
843 UndoGuard aUndoGuard(
844 ActionDescriptionProvider::createDescription( eActionType, ObjectNameProvider::getName( eObjectType)),
845 m_xUndoManager );
847 bool bChanged = false;
848 ChartModel* pModel = dynamic_cast<ChartModel*>(getModel().get());
849 if ( eObjectType == OBJECTTYPE_LEGEND )
850 bChanged = DiagramHelper::switchDiagramPositioningToExcludingPositioning( *pModel, false , true );
852 bool bMoved = PositionAndSizeHelper::moveObject( m_aSelection.getSelectedCID()
853 , getModel()
854 , awt::Rectangle(aObjectRect.getX(),aObjectRect.getY(),aObjectRect.getWidth(),aObjectRect.getHeight())
855 , awt::Rectangle(aPageRect.getX(),aPageRect.getY(),aPageRect.getWidth(),aPageRect.getHeight()) );
857 if( bMoved || bChanged )
859 bDraggingDone = true;
860 aUndoGuard.commit();
864 catch( const uno::Exception & )
866 DBG_UNHANDLED_EXCEPTION("chart2");
868 //all wanted model changes will take effect
869 //and all unwanted view modifications are cleaned
872 if( !bDraggingDone ) //mouse wasn't moved while dragging
874 bool bClickedTwiceOnDragableObject = SelectionHelper::isDragableObjectHitTwice( aMPos, m_aSelection.getSelectedCID(), *pDrawViewWrapper );
875 bool bIsRotateable = m_aSelection.isRotateableObjectSelected( getModel() );
877 //toggle between move and rotate
878 if( bIsRotateable && bClickedTwiceOnDragableObject && m_eDragMode==SdrDragMode::Move )
879 m_eDragMode=SdrDragMode::Rotate;
880 else
881 m_eDragMode=SdrDragMode::Move;
883 pDrawViewWrapper->SetDragMode(m_eDragMode);
885 if( !m_bWaitingForDoubleClick && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() )
887 impl_selectObjectAndNotiy();
890 else
891 m_aSelection.resetPossibleSelectionAfterSingleClickWasEnsured();
893 // In tiled rendering drag mode could be not yet over on the call
894 // that should handle the double-click, so better to perform this check
895 // always.
896 if( isDoubleClick(rMEvt) && !bMouseUpWithoutMouseDown /*#i106966#*/ )
898 Point aMousePixel = rMEvt.GetPosPixel();
899 execute_DoubleClick( &aMousePixel );
902 //@todo ForcePointer(&rMEvt);
903 pChartWindow->ReleaseMouse();
905 if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() )
906 bNotifySelectionChange = true;
909 impl_SetMousePointer( rMEvt );
911 if(bNotifySelectionChange)
912 impl_notifySelectionChangeListeners();
915 void ChartController::execute_DoubleClick( const Point* pMousePixel )
917 bool bEditText = false;
918 if ( m_aSelection.hasSelection() )
920 OUString aCID( m_aSelection.getSelectedCID() );
921 if ( !aCID.isEmpty() )
923 ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID );
924 if ( eObjectType == OBJECTTYPE_TITLE )
926 bEditText = true;
929 else
931 // #i12587# support for shapes in chart
932 SdrObject* pObj = DrawViewWrapper::getSdrObject( m_aSelection.getSelectedAdditionalShape() );
933 if ( dynamic_cast< const SdrTextObj* >(pObj) != nullptr )
935 bEditText = true;
940 if ( bEditText )
942 executeDispatch_EditText( pMousePixel );
944 else
946 executeDispatch_ObjectProperties();
950 void ChartController::execute_Resize()
952 SolarMutexGuard aGuard;
953 auto pChartWindow(GetChartWindow());
954 if(pChartWindow)
955 pChartWindow->Invalidate();
958 void ChartController::execute_Command( const CommandEvent& rCEvt )
960 SolarMutexGuard aGuard;
961 auto pChartWindow(GetChartWindow());
962 bool bIsAction = false;
964 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
965 if(!pChartWindow || !pDrawViewWrapper)
966 return;
967 bIsAction = m_pDrawViewWrapper->IsAction();
970 // pop-up menu
971 if(rCEvt.GetCommand() == CommandEventId::ContextMenu && !bIsAction)
974 if(pChartWindow)
975 pChartWindow->ReleaseMouse();
978 if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() )
979 impl_notifySelectionChangeListeners();
981 css::uno::Reference< css::awt::XPopupMenu > xPopupMenu( m_xCC->getServiceManager()->createInstanceWithContext(
982 "com.sun.star.awt.PopupMenu", m_xCC ), css::uno::UNO_QUERY );
984 Point aPos( rCEvt.GetMousePosPixel() );
985 if( !rCEvt.IsMouseEvent() )
987 if(pChartWindow)
988 aPos = pChartWindow->GetPointerState().maPos;
991 OUString aMenuName;
992 if ( isShapeContext() )
993 // #i12587# support for shapes in chart
994 aMenuName = m_pDrawViewWrapper->IsTextEdit() ? OUString( "drawtext" ) : OUString( "draw" );
995 else
997 // todo: the context menu should be specified by an xml file in uiconfig
998 if( xPopupMenu.is())
1000 sal_Int16 nUniqueId = 1;
1001 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Cut" );
1002 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Copy" );
1003 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Paste" );
1004 xPopupMenu->insertSeparator( -1 );
1006 ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
1007 Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( getModel() );
1009 OUString aFormatCommand( lcl_getFormatCommandForObjectCID( m_aSelection.getSelectedCID() ) );
1010 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, aFormatCommand );
1012 //some commands for dataseries and points:
1014 if( eObjectType == OBJECTTYPE_DATA_SERIES || eObjectType == OBJECTTYPE_DATA_POINT )
1016 bool bIsPoint = ( eObjectType == OBJECTTYPE_DATA_POINT );
1017 uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() );
1018 uno::Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY );
1019 Reference< chart2::XRegressionCurve > xTrendline( RegressionCurveHelper::getFirstCurveNotMeanValueLine( xCurveCnt ) );
1020 bool bHasEquation = RegressionCurveHelper::hasEquation( xTrendline );
1021 Reference< chart2::XRegressionCurve > xMeanValue( RegressionCurveHelper::getMeanValueLine( xCurveCnt ) );
1022 bool bHasYErrorBars = StatisticsHelper::hasErrorBars( xSeries );
1023 bool bHasXErrorBars = StatisticsHelper::hasErrorBars( xSeries, false );
1024 bool bHasDataLabelsAtSeries = DataSeriesHelper::hasDataLabelsAtSeries( xSeries );
1025 bool bHasDataLabelsAtPoints = DataSeriesHelper::hasDataLabelsAtPoints( xSeries );
1026 bool bHasDataLabelAtPoint = false;
1027 sal_Int32 nPointIndex = -1;
1028 if( bIsPoint )
1030 nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( m_aSelection.getSelectedCID() );
1031 bHasDataLabelAtPoint = DataSeriesHelper::hasDataLabelAtPoint( xSeries, nPointIndex );
1033 bool bSelectedPointIsFormatted = false;
1034 bool bHasFormattedDataPointsOtherThanSelected = false;
1036 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
1037 if( xSeriesProperties.is() )
1039 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
1040 if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
1042 if( aAttributedDataPointIndexList.hasElements() )
1044 if( bIsPoint )
1046 std::vector< sal_Int32 > aIndices( ContainerHelper::SequenceToVector( aAttributedDataPointIndexList ) );
1047 std::vector< sal_Int32 >::iterator aIt = std::find( aIndices.begin(), aIndices.end(), nPointIndex );
1048 if( aIt != aIndices.end())
1049 bSelectedPointIsFormatted = true;
1050 else
1051 bHasFormattedDataPointsOtherThanSelected = true;
1053 else
1054 bHasFormattedDataPointsOtherThanSelected = true;
1059 if( bIsPoint )
1061 if( bHasDataLabelAtPoint )
1062 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatDataLabel" );
1063 if( !bHasDataLabelAtPoint )
1064 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertDataLabel" );
1065 else
1066 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteDataLabel" );
1067 if( bSelectedPointIsFormatted )
1068 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:ResetDataPoint" );
1070 xPopupMenu->insertSeparator( -1 );
1072 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatDataSeries" );
1075 Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ) );
1076 if( xChartType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK )
1080 Reference< beans::XPropertySet > xChartTypeProp( xChartType, uno::UNO_QUERY );
1081 if( xChartTypeProp.is() )
1083 bool bJapaneseStyle = false;
1084 xChartTypeProp->getPropertyValue( "Japanese" ) >>= bJapaneseStyle;
1086 if( bJapaneseStyle )
1088 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockLoss" );
1089 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockGain" );
1093 catch( const uno::Exception & )
1095 DBG_UNHANDLED_EXCEPTION("chart2");
1099 if( bHasDataLabelsAtSeries )
1100 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatDataLabels" );
1101 if( bHasEquation )
1102 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatTrendlineEquation" );
1103 if( xMeanValue.is() )
1104 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatMeanValue" );
1105 if( bHasXErrorBars )
1106 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatXErrorBars" );
1107 if( bHasYErrorBars )
1108 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatYErrorBars" );
1110 xPopupMenu->insertSeparator( -1 );
1112 if( !bHasDataLabelsAtSeries )
1113 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertDataLabels" );
1115 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTrendline" );
1117 if( !xMeanValue.is() )
1118 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertMeanValue" );
1119 if( !bHasXErrorBars )
1120 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertXErrorBars" );
1121 if( !bHasYErrorBars )
1122 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertYErrorBars" );
1123 if( bHasDataLabelsAtSeries || ( bHasDataLabelsAtPoints && bHasFormattedDataPointsOtherThanSelected ) )
1124 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteDataLabels" );
1125 if( bHasEquation )
1126 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteTrendlineEquation" );
1127 if( xMeanValue.is() )
1128 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteMeanValue" );
1129 if( bHasXErrorBars )
1130 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteXErrorBars" );
1131 if( bHasYErrorBars )
1132 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteYErrorBars" );
1134 if( bHasFormattedDataPointsOtherThanSelected )
1135 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:ResetAllDataPoints" );
1137 xPopupMenu->insertSeparator( -1 );
1139 lcl_insertMenuCommand( xPopupMenu, nUniqueId, ".uno:ArrangeRow" );
1140 uno::Reference< awt::XPopupMenu > xArrangePopupMenu(
1141 m_xCC->getServiceManager()->createInstanceWithContext(
1142 "com.sun.star.awt.PopupMenu", m_xCC ), uno::UNO_QUERY );
1143 if( xArrangePopupMenu.is() )
1145 sal_Int16 nSubId = nUniqueId + 1;
1146 lcl_insertMenuCommand( xArrangePopupMenu, nSubId++, ".uno:Forward" );
1147 lcl_insertMenuCommand( xArrangePopupMenu, nSubId, ".uno:Backward" );
1148 xPopupMenu->setPopupMenu( nUniqueId, xArrangePopupMenu );
1149 nUniqueId = nSubId;
1151 ++nUniqueId;
1153 else if( eObjectType == OBJECTTYPE_DATA_CURVE )
1155 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteTrendline" );
1156 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatTrendlineEquation" );
1157 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTrendlineEquation" );
1158 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTrendlineEquationAndR2" );
1159 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertR2Value" );
1160 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteTrendlineEquation" );
1161 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteR2Value" );
1163 else if( eObjectType == OBJECTTYPE_DATA_CURVE_EQUATION )
1165 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertR2Value" );
1166 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteR2Value" );
1169 //some commands for axes: and grids
1171 else if( eObjectType == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_GRID || eObjectType == OBJECTTYPE_SUBGRID )
1173 Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() );
1174 if( xAxis.is() && xDiagram.is() )
1176 sal_Int32 nDimensionIndex = -1;
1177 sal_Int32 nCooSysIndex = -1;
1178 sal_Int32 nAxisIndex = -1;
1179 AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex );
1180 bool bIsSecondaryAxis = nAxisIndex!=0;
1181 bool bIsAxisVisible = AxisHelper::isAxisVisible( xAxis );
1182 bool bIsMajorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, true /*bMainGrid*/, xDiagram );
1183 bool bIsMinorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, false /*bMainGrid*/, xDiagram );
1184 bool bHasTitle = false;
1185 uno::Reference< XTitled > xTitled( xAxis, uno::UNO_QUERY );
1186 if( xTitled.is())
1187 bHasTitle = !TitleHelper::getCompleteString( xTitled->getTitleObject() ).isEmpty();
1189 if( eObjectType != OBJECTTYPE_AXIS && bIsAxisVisible )
1190 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatAxis" );
1191 if( eObjectType != OBJECTTYPE_GRID && bIsMajorGridVisible && !bIsSecondaryAxis )
1192 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatMajorGrid" );
1193 if( eObjectType != OBJECTTYPE_SUBGRID && bIsMinorGridVisible && !bIsSecondaryAxis )
1194 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatMinorGrid" );
1196 xPopupMenu->insertSeparator( -1 );
1198 if( eObjectType != OBJECTTYPE_AXIS && !bIsAxisVisible )
1199 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertAxis" );
1200 if( eObjectType != OBJECTTYPE_GRID && !bIsMajorGridVisible && !bIsSecondaryAxis )
1201 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertMajorGrid" );
1202 if( eObjectType != OBJECTTYPE_SUBGRID && !bIsMinorGridVisible && !bIsSecondaryAxis )
1203 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertMinorGrid" );
1204 if( !bHasTitle )
1205 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertAxisTitle" );
1207 if( bIsAxisVisible )
1208 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteAxis" );
1209 if( bIsMajorGridVisible && !bIsSecondaryAxis )
1210 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteMajorGrid" );
1211 if( bIsMinorGridVisible && !bIsSecondaryAxis )
1212 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteMinorGrid" );
1216 if( eObjectType == OBJECTTYPE_DATA_STOCK_LOSS )
1217 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockGain" );
1218 else if( eObjectType == OBJECTTYPE_DATA_STOCK_GAIN )
1219 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockLoss" );
1221 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:TransformDialog" );
1223 if( eObjectType == OBJECTTYPE_PAGE || eObjectType == OBJECTTYPE_DIAGRAM
1224 || eObjectType == OBJECTTYPE_DIAGRAM_WALL
1225 || eObjectType == OBJECTTYPE_DIAGRAM_FLOOR
1226 || eObjectType == OBJECTTYPE_UNKNOWN )
1228 if( eObjectType != OBJECTTYPE_UNKNOWN )
1229 xPopupMenu->insertSeparator( -1 );
1230 bool bHasLegend = LegendHelper::hasLegend( xDiagram );
1231 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTitles" );
1232 if( !bHasLegend )
1233 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertLegend" );
1234 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertRemoveAxes" );
1235 if( bHasLegend )
1236 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteLegend" );
1239 xPopupMenu->insertSeparator( -1 );
1240 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DiagramType" );
1241 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DataRanges" );
1242 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DiagramData" );
1243 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:View3D" );
1247 css::uno::Sequence< css::uno::Any > aArgs( 3 );
1248 aArgs[0] <<= comphelper::makePropertyValue( "IsContextMenu", true );
1249 aArgs[1] <<= comphelper::makePropertyValue( "Frame", m_xFrame );
1250 aArgs[2] <<= comphelper::makePropertyValue( "Value", aMenuName );
1252 css::uno::Reference< css::frame::XPopupMenuController > xPopupController(
1253 m_xCC->getServiceManager()->createInstanceWithArgumentsAndContext(
1254 "com.sun.star.comp.framework.ResourceMenuController", aArgs, m_xCC ), css::uno::UNO_QUERY );
1256 if ( !xPopupController.is() || !xPopupMenu.is() )
1257 return;
1259 if (comphelper::LibreOfficeKit::isActive())
1261 PopupMenu* pPopupMenu = static_cast<PopupMenu*>(VCLXMenu::GetImplementation(xPopupMenu)->GetMenu());
1262 pPopupMenu->SetLOKNotifier(SfxViewShell::Current());
1264 // the context menu expects a position related to the document window,
1265 // not to the chart window
1266 SfxInPlaceClient* pIPClient = SfxViewShell::Current()->GetIPClient();
1267 if (pIPClient)
1269 vcl::Window* pRootWin = pIPClient->GetEditWin();
1270 if (pRootWin)
1272 Point aOffset = pChartWindow->GetOffsetPixelFrom(*pRootWin);
1273 aPos += aOffset;
1278 xPopupController->setPopupMenu( xPopupMenu );
1279 xPopupMenu->execute( css::uno::Reference< css::awt::XWindowPeer >( m_xFrame->getContainerWindow(), css::uno::UNO_QUERY ),
1280 css::awt::Rectangle( aPos.X(), aPos.Y(), 0, 0 ),
1281 css::awt::PopupMenuDirection::EXECUTE_DEFAULT );
1283 css::uno::Reference< css::lang::XComponent > xComponent( xPopupController, css::uno::UNO_QUERY );
1284 if ( xComponent.is() )
1285 xComponent->dispose();
1287 else if( ( rCEvt.GetCommand() == CommandEventId::StartExtTextInput ) ||
1288 ( rCEvt.GetCommand() == CommandEventId::ExtTextInput ) ||
1289 ( rCEvt.GetCommand() == CommandEventId::EndExtTextInput ) ||
1290 ( rCEvt.GetCommand() == CommandEventId::InputContextChange ) )
1292 //#i84417# enable editing with IME
1293 if( m_pDrawViewWrapper )
1294 m_pDrawViewWrapper->Command( rCEvt, pChartWindow );
1298 bool ChartController::execute_KeyInput( const KeyEvent& rKEvt )
1300 SolarMutexGuard aGuard;
1301 bool bReturn=false;
1303 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
1304 auto pChartWindow(GetChartWindow());
1305 if(!pChartWindow || !pDrawViewWrapper)
1306 return bReturn;
1308 // handle accelerators
1309 if( ! m_apAccelExecute.get() && m_xFrame.is() && m_xCC.is() )
1311 m_apAccelExecute = ::svt::AcceleratorExecute::createAcceleratorHelper();
1312 OSL_ASSERT( m_apAccelExecute.get());
1313 if( m_apAccelExecute.get() )
1314 m_apAccelExecute->init( m_xCC, m_xFrame );
1317 vcl::KeyCode aKeyCode( rKEvt.GetKeyCode());
1318 sal_uInt16 nCode = aKeyCode.GetCode();
1319 bool bAlternate = aKeyCode.IsMod2();
1320 bool bCtrl = aKeyCode.IsMod1();
1322 if( m_apAccelExecute.get() )
1323 bReturn = m_apAccelExecute->execute( aKeyCode );
1324 if( bReturn )
1325 return bReturn;
1328 if( pDrawViewWrapper->IsTextEdit() )
1330 if( pDrawViewWrapper->KeyInput(rKEvt, pChartWindow) )
1332 bReturn = true;
1333 if( nCode == KEY_ESCAPE )
1335 EndTextEdit();
1341 // keyboard accessibility
1342 ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
1343 if( ! bReturn )
1345 // Navigation (Tab/F3/Home/End)
1346 uno::Reference< XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY );
1347 ObjectKeyNavigation aObjNav( m_aSelection.getSelectedOID(), xChartDoc, ExplicitValueProvider::getExplicitValueProvider( m_xChartView ));
1348 awt::KeyEvent aKeyEvent( ::svt::AcceleratorExecute::st_VCLKey2AWTKey( aKeyCode ));
1349 bReturn = aObjNav.handleKeyEvent( aKeyEvent );
1350 if( bReturn )
1352 ObjectIdentifier aNewOID = aObjNav.getCurrentSelection();
1353 uno::Any aNewSelection;
1354 if ( aNewOID.isValid() && !ObjectHierarchy::isRootNode( aNewOID ) )
1356 aNewSelection = aNewOID.getAny();
1358 if ( m_eDragMode == SdrDragMode::Rotate && !SelectionHelper::isRotateableObject( aNewOID.getObjectCID(), getModel() ) )
1360 m_eDragMode = SdrDragMode::Move;
1362 bReturn = select( aNewSelection );
1366 // Position and Size (+/-/arrow-keys) or pie segment dragging
1367 if( ! bReturn )
1369 // pie segment dragging
1370 // note: could also be done for data series
1371 if( eObjectType == OBJECTTYPE_DATA_POINT &&
1372 ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) ==
1373 ObjectIdentifier::getPieSegmentDragMethodServiceName())
1375 bool bDrag = false;
1376 bool bDragInside = false;
1377 if( nCode == KEY_ADD ||
1378 nCode == KEY_SUBTRACT )
1380 bDrag = true;
1381 bDragInside = ( nCode == KEY_SUBTRACT );
1383 else if(
1384 nCode == KEY_LEFT ||
1385 nCode == KEY_RIGHT ||
1386 nCode == KEY_UP ||
1387 nCode == KEY_DOWN )
1389 bDrag = true;
1390 OUString aParameter( ObjectIdentifier::getDragParameterString( m_aSelection.getSelectedCID() ));
1391 sal_Int32 nOffsetPercentDummy( 0 );
1392 awt::Point aMinimumPosition( 0, 0 );
1393 awt::Point aMaximumPosition( 0, 0 );
1394 ObjectIdentifier::parsePieSegmentDragParameterString(
1395 aParameter, nOffsetPercentDummy, aMinimumPosition, aMaximumPosition );
1396 aMaximumPosition.Y -= aMinimumPosition.Y;
1397 aMaximumPosition.X -= aMinimumPosition.X;
1399 bDragInside =
1400 (nCode == KEY_RIGHT && (aMaximumPosition.X < 0)) ||
1401 (nCode == KEY_LEFT && (aMaximumPosition.X > 0)) ||
1402 (nCode == KEY_DOWN && (aMaximumPosition.Y < 0)) ||
1403 (nCode == KEY_UP && (aMaximumPosition.Y > 0));
1406 if( bDrag )
1408 double fAmount = bAlternate ? 0.01 : 0.05;
1409 if( bDragInside )
1410 fAmount *= -1.0;
1412 bReturn = impl_DragDataPoint( m_aSelection.getSelectedCID(), fAmount );
1415 else
1417 // size
1418 if( nCode == KEY_ADD ||
1419 nCode == KEY_SUBTRACT )
1421 if( eObjectType == OBJECTTYPE_DIAGRAM )
1423 // default 1 mm in each direction
1424 double fGrowAmountX = 200.0;
1425 double fGrowAmountY = 200.0;
1426 if( bAlternate && pChartWindow )
1428 // together with Alt-key: 1 px in each direction
1429 if( pChartWindow )
1431 Size aPixelSize = pChartWindow->PixelToLogic( Size( 2, 2 ));
1432 fGrowAmountX = static_cast< double >( aPixelSize.Width());
1433 fGrowAmountY = static_cast< double >( aPixelSize.Height());
1436 if( nCode == KEY_SUBTRACT )
1438 fGrowAmountX = -fGrowAmountX;
1439 fGrowAmountY = -fGrowAmountY;
1441 bReturn = impl_moveOrResizeObject(
1442 m_aSelection.getSelectedCID(), CENTERED_RESIZE_OBJECT, fGrowAmountX, fGrowAmountY );
1445 // position
1446 else if( nCode == KEY_LEFT ||
1447 nCode == KEY_RIGHT ||
1448 nCode == KEY_UP ||
1449 nCode == KEY_DOWN )
1451 if( m_aSelection.isDragableObjectSelected() )
1453 // default 1 mm
1454 double fShiftAmountX = 100.0;
1455 double fShiftAmountY = 100.0;
1456 if( bAlternate && pChartWindow )
1458 // together with Alt-key: 1 px
1459 if(pChartWindow)
1461 Size aPixelSize = pChartWindow->PixelToLogic( Size( 1, 1 ));
1462 fShiftAmountX = static_cast< double >( aPixelSize.Width());
1463 fShiftAmountY = static_cast< double >( aPixelSize.Height());
1466 switch( nCode )
1468 case KEY_LEFT:
1469 fShiftAmountX = -fShiftAmountX;
1470 fShiftAmountY = 0.0;
1471 break;
1472 case KEY_RIGHT:
1473 fShiftAmountY = 0.0;
1474 break;
1475 case KEY_UP:
1476 fShiftAmountX = 0.0;
1477 fShiftAmountY = -fShiftAmountY;
1478 break;
1479 case KEY_DOWN:
1480 fShiftAmountX = 0.0;
1481 break;
1483 if( !m_aSelection.getSelectedCID().isEmpty() )
1485 //move chart objects
1486 bReturn = impl_moveOrResizeObject(
1487 m_aSelection.getSelectedCID(), MOVE_OBJECT, fShiftAmountX, fShiftAmountY );
1489 else
1491 //move additional shapes
1492 uno::Reference< drawing::XShape > xShape( m_aSelection.getSelectedAdditionalShape() );
1493 if( xShape.is() )
1495 awt::Point aPos( xShape->getPosition() );
1496 awt::Size aSize( xShape->getSize() );
1497 awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) );
1498 aPos.X = static_cast< long >( static_cast< double >( aPos.X ) + fShiftAmountX );
1499 aPos.Y = static_cast< long >( static_cast< double >( aPos.Y ) + fShiftAmountY );
1500 if( aPos.X + aSize.Width > aPageSize.Width )
1501 aPos.X = aPageSize.Width - aSize.Width;
1502 if( aPos.X < 0 )
1503 aPos.X = 0;
1504 if( aPos.Y + aSize.Height > aPageSize.Height )
1505 aPos.Y = aPageSize.Height - aSize.Height;
1506 if( aPos.Y < 0 )
1507 aPos.Y = 0;
1509 xShape->setPosition( aPos );
1517 // dumping the shape
1518 if( !bReturn && bCtrl && nCode == KEY_F12)
1520 uno::Reference< qa::XDumper > xChartModel( getModel(), uno::UNO_QUERY );
1521 if(xChartModel.is())
1523 OUString aDump = xChartModel->dump();
1524 SAL_WARN("chart2", aDump);
1528 // text edit
1529 if( ! bReturn &&
1530 nCode == KEY_F2 )
1532 if( eObjectType == OBJECTTYPE_TITLE )
1534 executeDispatch_EditText();
1535 bReturn = true;
1539 // deactivate inplace mode (this code should be unnecessary, but
1540 // unfortunately is not)
1541 if( ! bReturn &&
1542 nCode == KEY_ESCAPE )
1544 uno::Reference< frame::XDispatchHelper > xDispatchHelper( frame::DispatchHelper::create(m_xCC) );
1545 uno::Sequence< beans::PropertyValue > aArgs;
1546 xDispatchHelper->executeDispatch(
1547 uno::Reference< frame::XDispatchProvider >( m_xFrame, uno::UNO_QUERY ),
1548 ".uno:TerminateInplaceActivation",
1549 "_parent",
1550 frame::FrameSearchFlag::PARENT,
1551 aArgs );
1552 bReturn = true;
1555 if( ! bReturn &&
1556 (nCode == KEY_DELETE || nCode == KEY_BACKSPACE ))
1558 bReturn = executeDispatch_Delete();
1559 if( ! bReturn )
1561 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pChartWindow ? pChartWindow->GetFrameWeld() : nullptr,
1562 VclMessageType::Info, VclButtonsType::Ok,
1563 SchResId(STR_ACTION_NOTPOSSIBLE)));
1564 xInfoBox->run();
1568 return bReturn;
1571 bool ChartController::requestQuickHelp(
1572 ::Point aAtLogicPosition,
1573 bool bIsBalloonHelp,
1574 OUString & rOutQuickHelpText,
1575 awt::Rectangle & rOutEqualRect )
1577 uno::Reference< frame::XModel > xChartModel;
1578 if( m_aModel.is())
1579 xChartModel.set( getModel() );
1580 if( !xChartModel.is())
1581 return false;
1583 // help text
1584 OUString aCID;
1585 if( m_pDrawViewWrapper )
1587 aCID = SelectionHelper::getHitObjectCID(
1588 aAtLogicPosition, *m_pDrawViewWrapper );
1590 bool bResult( !aCID.isEmpty());
1592 if( bResult )
1594 // get help text
1595 rOutQuickHelpText = ObjectNameProvider::getHelpText( aCID, xChartModel, bIsBalloonHelp /* bVerbose */ );
1597 // set rectangle
1598 ExplicitValueProvider * pValueProvider(
1599 ExplicitValueProvider::getExplicitValueProvider( m_xChartView ));
1600 if( pValueProvider )
1601 rOutEqualRect = pValueProvider->getRectangleOfObject( aCID, true );
1604 return bResult;
1607 // XSelectionSupplier (optional interface)
1608 sal_Bool SAL_CALL ChartController::select( const uno::Any& rSelection )
1610 bool bSuccess = false;
1612 if ( rSelection.hasValue() )
1614 const uno::Type& rType = rSelection.getValueType();
1615 if ( rType == cppu::UnoType< OUString >::get() )
1617 OUString aNewCID;
1618 if ( ( rSelection >>= aNewCID ) && m_aSelection.setSelection( aNewCID ) )
1620 bSuccess = true;
1623 else if ( rType == cppu::UnoType<drawing::XShape>::get() )
1625 uno::Reference< drawing::XShape > xShape;
1626 if ( ( rSelection >>= xShape ) && m_aSelection.setSelection( xShape ) )
1628 bSuccess = true;
1632 else
1634 if ( m_aSelection.hasSelection() )
1636 m_aSelection.clearSelection();
1637 bSuccess = true;
1641 if ( bSuccess )
1643 SolarMutexGuard aGuard;
1644 if ( m_pDrawViewWrapper && m_pDrawViewWrapper->IsTextEdit() )
1646 EndTextEdit();
1648 impl_selectObjectAndNotiy();
1649 auto pChartWindow(GetChartWindow());
1650 if ( pChartWindow )
1652 pChartWindow->Invalidate();
1654 return true;
1657 return false;
1660 uno::Any SAL_CALL ChartController::getSelection()
1662 uno::Any aReturn;
1663 if ( m_aSelection.hasSelection() )
1665 OUString aCID( m_aSelection.getSelectedCID() );
1666 if ( !aCID.isEmpty() )
1668 aReturn <<= aCID;
1670 else
1672 // #i12587# support for shapes in chart
1673 aReturn <<= m_aSelection.getSelectedAdditionalShape();
1676 return aReturn;
1679 void SAL_CALL ChartController::addSelectionChangeListener( const uno::Reference<view::XSelectionChangeListener> & xListener )
1681 SolarMutexGuard aGuard;
1682 if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode?
1683 return; //behave passive if already disposed or suspended
1685 //--add listener
1686 m_aLifeTimeManager.m_aListenerContainer.addInterface( cppu::UnoType<view::XSelectionChangeListener>::get(), xListener );
1689 void SAL_CALL ChartController::removeSelectionChangeListener( const uno::Reference<view::XSelectionChangeListener> & xListener )
1691 SolarMutexGuard aGuard;
1692 if( impl_isDisposedOrSuspended() ) //@todo? allow removing of listeners in suspend mode?
1693 return; //behave passive if already disposed or suspended
1695 //--remove listener
1696 m_aLifeTimeManager.m_aListenerContainer.removeInterface( cppu::UnoType<view::XSelectionChangeListener>::get(), xListener );
1699 void ChartController::impl_notifySelectionChangeListeners()
1701 ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer
1702 .getContainer( cppu::UnoType<view::XSelectionChangeListener>::get() );
1703 if( pIC )
1705 uno::Reference< view::XSelectionSupplier > xSelectionSupplier(this);
1706 lang::EventObject aEvent( xSelectionSupplier );
1707 ::cppu::OInterfaceIteratorHelper aIt( *pIC );
1708 while( aIt.hasMoreElements() )
1710 uno::Reference< view::XSelectionChangeListener > xListener( aIt.next(), uno::UNO_QUERY );
1711 if( xListener.is() )
1712 xListener->selectionChanged( aEvent );
1717 void ChartController::impl_selectObjectAndNotiy()
1720 SolarMutexGuard aGuard;
1721 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper;
1722 if( pDrawViewWrapper )
1724 pDrawViewWrapper->SetDragMode( m_eDragMode );
1725 m_aSelection.applySelection( m_pDrawViewWrapper );
1728 impl_notifySelectionChangeListeners();
1731 bool ChartController::impl_moveOrResizeObject(
1732 const OUString & rCID,
1733 eMoveOrResizeType eType,
1734 double fAmountLogicX,
1735 double fAmountLogicY )
1737 bool bResult = false;
1738 bool bNeedResize = ( eType == CENTERED_RESIZE_OBJECT );
1740 uno::Reference< frame::XModel > xChartModel( getModel() );
1741 uno::Reference< beans::XPropertySet > xObjProp(
1742 ObjectIdentifier::getObjectPropertySet( rCID, xChartModel ));
1743 if( xObjProp.is())
1745 awt::Size aRefSize = ChartModelHelper::getPageSize( xChartModel );
1747 chart2::RelativePosition aRelPos;
1748 chart2::RelativeSize aRelSize;
1749 bool bDeterminePos = !(xObjProp->getPropertyValue( "RelativePosition") >>= aRelPos);
1750 bool bDetermineSize = !bNeedResize || !(xObjProp->getPropertyValue( "RelativeSize") >>= aRelSize);
1752 if( ( bDeterminePos || bDetermineSize ) &&
1753 ( aRefSize.Width > 0 && aRefSize.Height > 0 ) )
1755 ExplicitValueProvider * pValueProvider(
1756 ExplicitValueProvider::getExplicitValueProvider( m_xChartView ));
1757 if( pValueProvider )
1759 awt::Rectangle aRect( pValueProvider->getRectangleOfObject( rCID ));
1760 double fWidth = static_cast< double >( aRefSize.Width );
1761 double fHeight = static_cast< double >( aRefSize.Height );
1762 if( bDetermineSize )
1764 aRelSize.Primary = static_cast< double >( aRect.Width ) / fWidth;
1765 aRelSize.Secondary = static_cast< double >( aRect.Height ) / fHeight;
1767 if( bDeterminePos )
1769 if( bNeedResize && aRelSize.Primary > 0.0 && aRelSize.Secondary > 0.0 )
1771 aRelPos.Primary = (static_cast< double >( aRect.X ) / fWidth) +
1772 (aRelSize.Primary / 2.0);
1773 aRelPos.Secondary = (static_cast< double >( aRect.Y ) / fHeight) +
1774 (aRelSize.Secondary / 2.0);
1775 aRelPos.Anchor = drawing::Alignment_CENTER;
1777 else
1779 aRelPos.Primary = static_cast< double >( aRect.X ) / fWidth;
1780 aRelPos.Secondary = static_cast< double >( aRect.Y ) / fHeight;
1781 aRelPos.Anchor = drawing::Alignment_TOP_LEFT;
1787 if( eType == CENTERED_RESIZE_OBJECT )
1788 bResult = lcl_GrowAndShiftLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY );
1789 else if( eType == MOVE_OBJECT )
1790 bResult = lcl_MoveObjectLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY );
1792 if( bResult )
1794 ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::ActionType::Move);
1795 if( bNeedResize )
1796 eActionType = ActionDescriptionProvider::ActionType::Resize;
1798 ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID );
1799 UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription(
1800 eActionType, ObjectNameProvider::getName( eObjectType )), m_xUndoManager );
1802 ControllerLockGuardUNO aCLGuard( xChartModel );
1803 xObjProp->setPropertyValue( "RelativePosition", uno::Any( aRelPos ));
1804 if( bNeedResize || (eObjectType == OBJECTTYPE_DIAGRAM) )//Also set an explicit size at the diagram when an explicit position is set
1805 xObjProp->setPropertyValue( "RelativeSize", uno::Any( aRelSize ));
1807 aUndoGuard.commit();
1810 return bResult;
1813 bool ChartController::impl_DragDataPoint( const OUString & rCID, double fAdditionalOffset )
1815 bool bResult = false;
1816 if( fAdditionalOffset < -1.0 || fAdditionalOffset > 1.0 || fAdditionalOffset == 0.0 )
1817 return bResult;
1819 sal_Int32 nDataPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rCID );
1820 uno::Reference< chart2::XDataSeries > xSeries(
1821 ObjectIdentifier::getDataSeriesForCID( rCID, getModel() ));
1822 if( xSeries.is())
1826 uno::Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex( nDataPointIndex ));
1827 double fOffset = 0.0;
1828 if( xPointProp.is() &&
1829 (xPointProp->getPropertyValue( "Offset" ) >>= fOffset ) &&
1830 (( fAdditionalOffset > 0.0 && fOffset < 1.0 ) || (fOffset > 0.0)) )
1832 fOffset += fAdditionalOffset;
1833 if( fOffset > 1.0 )
1834 fOffset = 1.0;
1835 else if( fOffset < 0.0 )
1836 fOffset = 0.0;
1837 xPointProp->setPropertyValue( "Offset", uno::Any( fOffset ));
1838 bResult = true;
1841 catch( const uno::Exception & )
1843 DBG_UNHANDLED_EXCEPTION("chart2");
1847 return bResult;
1850 void ChartController::impl_SetMousePointer( const MouseEvent & rEvent )
1852 SolarMutexGuard aGuard;
1853 auto pChartWindow(GetChartWindow());
1855 if (!m_pDrawViewWrapper || !pChartWindow)
1856 return;
1858 Point aMousePos( pChartWindow->PixelToLogic( rEvent.GetPosPixel()));
1859 sal_uInt16 nModifier = rEvent.GetModifier();
1860 bool bLeftDown = rEvent.IsLeft();
1862 // Check if object is for field button and set the normal arrow pointer in this case
1863 SdrObject* pObject = m_pDrawViewWrapper->getHitObject(aMousePos);
1864 if (pObject && pObject->GetName().startsWith("FieldButton"))
1866 pChartWindow->SetPointer(Pointer(PointerStyle::Arrow));
1867 return;
1870 if ( m_pDrawViewWrapper->IsTextEdit() )
1872 if( m_pDrawViewWrapper->IsTextEditHit( aMousePos ) )
1874 pChartWindow->SetPointer( m_pDrawViewWrapper->GetPreferredPointer(
1875 aMousePos, pChartWindow, nModifier, bLeftDown ) );
1876 return;
1879 else if( m_pDrawViewWrapper->IsAction() )
1881 return;//don't change pointer during running action
1884 SdrHdl* pHitSelectionHdl = nullptr;
1885 if( m_aSelection.isResizeableObjectSelected() )
1886 pHitSelectionHdl = m_pDrawViewWrapper->PickHandle( aMousePos );
1888 if( pHitSelectionHdl )
1890 Pointer aPointer = m_pDrawViewWrapper->GetPreferredPointer(
1891 aMousePos, pChartWindow, nModifier, bLeftDown );
1892 bool bForceArrowPointer = false;
1894 ObjectIdentifier aOID( m_aSelection.getSelectedOID() );
1896 switch( aPointer.GetStyle())
1898 case PointerStyle::NSize:
1899 case PointerStyle::SSize:
1900 case PointerStyle::WSize:
1901 case PointerStyle::ESize:
1902 case PointerStyle::NWSize:
1903 case PointerStyle::NESize:
1904 case PointerStyle::SWSize:
1905 case PointerStyle::SESize:
1906 if( ! m_aSelection.isResizeableObjectSelected() )
1907 bForceArrowPointer = true;
1908 break;
1909 case PointerStyle::Move:
1910 if ( !aOID.isDragableObject() )
1911 bForceArrowPointer = true;
1912 break;
1913 case PointerStyle::MovePoint:
1914 case PointerStyle::MoveBezierWeight:
1915 // there is no point-editing in a chart
1916 // the PointerStyle::MoveBezierWeight appears in 3d data points
1917 bForceArrowPointer = true;
1918 break;
1919 default:
1920 break;
1923 if( bForceArrowPointer )
1924 pChartWindow->SetPointer( Pointer( PointerStyle::Arrow ));
1925 else
1926 pChartWindow->SetPointer( aPointer );
1928 return;
1931 // #i12587# support for shapes in chart
1932 if ( m_eDrawMode == CHARTDRAW_INSERT &&
1933 ( !m_pDrawViewWrapper->IsMarkedHit( aMousePos ) || !m_aSelection.isDragableObjectSelected() ) )
1935 PointerStyle ePointerStyle = PointerStyle::DrawRect;
1936 SdrObjKind eKind = static_cast< SdrObjKind >( m_pDrawViewWrapper->GetCurrentObjIdentifier() );
1937 switch ( eKind )
1939 case OBJ_LINE:
1941 ePointerStyle = PointerStyle::DrawLine;
1943 break;
1944 case OBJ_RECT:
1945 case OBJ_CUSTOMSHAPE:
1947 ePointerStyle = PointerStyle::DrawRect;
1949 break;
1950 case OBJ_CIRC:
1952 ePointerStyle = PointerStyle::DrawEllipse;
1954 break;
1955 case OBJ_FREELINE:
1957 ePointerStyle = PointerStyle::DrawPolygon;
1959 break;
1960 case OBJ_TEXT:
1962 ePointerStyle = PointerStyle::DrawText;
1964 break;
1965 case OBJ_CAPTION:
1967 ePointerStyle = PointerStyle::DrawCaption;
1969 break;
1970 default:
1972 ePointerStyle = PointerStyle::DrawRect;
1974 break;
1976 pChartWindow->SetPointer( Pointer( ePointerStyle ) );
1977 return;
1980 OUString aHitObjectCID(
1981 SelectionHelper::getHitObjectCID(
1982 aMousePos, *m_pDrawViewWrapper, true /*bGetDiagramInsteadOf_Wall*/ ));
1984 if( m_pDrawViewWrapper->IsTextEdit() )
1986 if( aHitObjectCID == m_aSelection.getSelectedCID() )
1988 pChartWindow->SetPointer( Pointer( PointerStyle::Arrow ));
1989 return;
1993 if( aHitObjectCID.isEmpty() )
1995 //additional shape was hit
1996 pChartWindow->SetPointer( PointerStyle::Move );
1998 else if( ObjectIdentifier::isDragableObject( aHitObjectCID ) )
2000 if( (m_eDragMode == SdrDragMode::Rotate)
2001 && SelectionHelper::isRotateableObject( aHitObjectCID
2002 , getModel() ) )
2003 pChartWindow->SetPointer( Pointer( PointerStyle::Rotate ) );
2004 else
2006 ObjectType eHitObjectType = ObjectIdentifier::getObjectType( aHitObjectCID );
2007 if( eHitObjectType == OBJECTTYPE_DATA_POINT )
2009 if( !ObjectIdentifier::areSiblings(aHitObjectCID,m_aSelection.getSelectedCID())
2010 && !ObjectIdentifier::areIdenticalObjects(aHitObjectCID,m_aSelection.getSelectedCID()) )
2012 pChartWindow->SetPointer( Pointer( PointerStyle::Arrow ));
2013 return;
2016 pChartWindow->SetPointer( PointerStyle::Move );
2019 else
2020 pChartWindow->SetPointer( Pointer( PointerStyle::Arrow ));
2023 css::uno::Reference<css::uno::XInterface> const & ChartController::getChartView()
2025 return m_xChartView;
2028 void ChartController::sendPopupRequest(OUString const & rCID, tools::Rectangle aRectangle)
2030 ChartModel* pChartModel = dynamic_cast<ChartModel*>(m_aModel->getModel().get());
2031 if (!pChartModel)
2032 return;
2034 uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider;
2035 xPivotTableDataProvider.set(pChartModel->getDataProvider(), uno::UNO_QUERY);
2036 if (!xPivotTableDataProvider.is())
2037 return;
2039 OUString sPivotTableName = xPivotTableDataProvider->getPivotTableName();
2041 PopupRequest* pPopupRequest = dynamic_cast<PopupRequest*>(pChartModel->getPopupRequest().get());
2042 if (!pPopupRequest)
2043 return;
2045 // Get dimension index from CID
2046 sal_Int32 nStartPos = rCID.lastIndexOf('.');
2047 nStartPos++;
2048 sal_Int32 nEndPos = rCID.getLength();
2049 OUString sDimensionIndex = rCID.copy(nStartPos, nEndPos - nStartPos);
2050 sal_Int32 nDimensionIndex = sDimensionIndex.toInt32();
2052 awt::Rectangle xRectangle {
2053 sal_Int32(aRectangle.Left()),
2054 sal_Int32(aRectangle.Top()),
2055 sal_Int32(aRectangle.GetWidth()),
2056 sal_Int32(aRectangle.GetHeight())
2059 uno::Sequence<beans::PropertyValue> aCallbackData = comphelper::InitPropertySequence(
2061 {"Rectangle", uno::makeAny<awt::Rectangle>(xRectangle)},
2062 {"DimensionIndex", uno::makeAny<sal_Int32>(nDimensionIndex)},
2063 {"PivotTableName", uno::makeAny<OUString>(sPivotTableName)},
2066 pPopupRequest->getCallback()->notify(uno::makeAny(aCallbackData));
2069 } //namespace chart
2071 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */