Disable chart doubleclick on mobile
[LibreOffice.git] / chart2 / source / controller / main / ChartController_Window.cxx
blob75f44d234a040d1082484bb19becb6d78b3515d4
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 <ChartModel.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 <AxisHelper.hxx>
43 #include <LegendHelper.hxx>
44 #include <servicenames_charttypes.hxx>
45 #include "DrawCommandDispatch.hxx"
46 #include <PopupRequest.hxx>
48 #include <com/sun/star/chart2/RelativePosition.hpp>
49 #include <com/sun/star/chart2/RelativeSize.hpp>
50 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
51 #include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
52 #include <com/sun/star/chart2/XChartDocument.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>
60 #include <com/sun/star/qa/XDumper.hpp>
62 #include <comphelper/lok.hxx>
63 #include <comphelper/propertysequence.hxx>
64 #include <comphelper/propertyvalue.hxx>
65 #include <comphelper/sequence.hxx>
67 #include <toolkit/awt/vclxmenu.hxx>
69 #include <sfx2/viewsh.hxx>
70 #include <sfx2/ipclient.hxx>
71 #include <svx/ActionDescriptionProvider.hxx>
72 #include <svx/obj3d.hxx>
73 #include <svx/scene3d.hxx>
74 #include <svx/svddrgmt.hxx>
75 #include <vcl/commandevent.hxx>
76 #include <vcl/event.hxx>
77 #include <vcl/svapp.hxx>
78 #include <vcl/settings.hxx>
79 #include <vcl/weld.hxx>
80 #include <vcl/ptrstyle.hxx>
81 #include <svtools/acceleratorexecute.hxx>
82 #include <tools/diagnose_ex.h>
83 #include <sal/log.hxx>
85 #include <comphelper/lok.hxx>
86 #include <sfx2/lokhelper.hxx>
88 #define DRGPIX 2 // Drag MinMove in Pixel
90 using namespace ::com::sun::star;
91 using namespace ::com::sun::star::chart2;
92 using ::com::sun::star::uno::Reference;
94 namespace chart
97 namespace
99 bool lcl_GrowAndShiftLogic(
100 RelativePosition & rInOutRelPos,
101 RelativeSize & rInOutRelSize,
102 const awt::Size & rRefSize,
103 double fGrowLogicX,
104 double fGrowLogicY )
106 if( rRefSize.Width == 0 ||
107 rRefSize.Height == 0 )
108 return false;
110 double fRelativeGrowX = fGrowLogicX / rRefSize.Width;
111 double fRelativeGrowY = fGrowLogicY / rRefSize.Height;
113 return ::chart::RelativePositionHelper::centerGrow(
114 rInOutRelPos, rInOutRelSize,
115 fRelativeGrowX, fRelativeGrowY );
118 bool lcl_MoveObjectLogic(
119 RelativePosition & rInOutRelPos,
120 RelativeSize const & rObjectSize,
121 const awt::Size & rRefSize,
122 double fShiftLogicX,
123 double fShiftLogicY )
125 if( rRefSize.Width == 0 ||
126 rRefSize.Height == 0 )
127 return false;
129 double fRelativeShiftX = fShiftLogicX / rRefSize.Width;
130 double fRelativeShiftY = fShiftLogicY / rRefSize.Height;
132 return ::chart::RelativePositionHelper::moveObject(
133 rInOutRelPos, rObjectSize,
134 fRelativeShiftX, fRelativeShiftY );
137 void lcl_insertMenuCommand(
138 const uno::Reference< awt::XPopupMenu > & xMenu,
139 sal_Int16 nId, const OUString & rCommand )
141 xMenu->insertItem( nId, "", 0, -1 );
142 xMenu->setCommand( nId, rCommand );
145 OUString lcl_getFormatCommandForObjectCID( const OUString& rCID )
147 OUString aDispatchCommand( ".uno:FormatSelection" );
149 ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID );
151 switch(eObjectType)
153 case OBJECTTYPE_DIAGRAM:
154 case OBJECTTYPE_DIAGRAM_WALL:
155 aDispatchCommand = ".uno:FormatWall";
156 break;
157 case OBJECTTYPE_DIAGRAM_FLOOR:
158 aDispatchCommand = ".uno:FormatFloor";
159 break;
160 case OBJECTTYPE_PAGE:
161 aDispatchCommand = ".uno:FormatChartArea";
162 break;
163 case OBJECTTYPE_LEGEND:
164 aDispatchCommand = ".uno:FormatLegend";
165 break;
166 case OBJECTTYPE_TITLE:
167 aDispatchCommand = ".uno:FormatTitle";
168 break;
169 case OBJECTTYPE_LEGEND_ENTRY:
170 aDispatchCommand = ".uno:FormatDataSeries";
171 break;
172 case OBJECTTYPE_AXIS:
173 case OBJECTTYPE_AXIS_UNITLABEL:
174 aDispatchCommand = ".uno:FormatAxis";
175 break;
176 case OBJECTTYPE_GRID:
177 aDispatchCommand = ".uno:FormatMajorGrid";
178 break;
179 case OBJECTTYPE_SUBGRID:
180 aDispatchCommand = ".uno:FormatMinorGrid";
181 break;
182 case OBJECTTYPE_DATA_LABELS:
183 aDispatchCommand = ".uno:FormatDataLabels";
184 break;
185 case OBJECTTYPE_DATA_SERIES:
186 aDispatchCommand = ".uno:FormatDataSeries";
187 break;
188 case OBJECTTYPE_DATA_LABEL:
189 aDispatchCommand = ".uno:FormatDataLabel";
190 break;
191 case OBJECTTYPE_DATA_POINT:
192 aDispatchCommand = ".uno:FormatDataPoint";
193 break;
194 case OBJECTTYPE_DATA_AVERAGE_LINE:
195 aDispatchCommand = ".uno:FormatMeanValue";
196 break;
197 case OBJECTTYPE_DATA_ERRORS_X:
198 aDispatchCommand = ".uno:FormatXErrorBars";
199 break;
200 case OBJECTTYPE_DATA_ERRORS_Y:
201 aDispatchCommand = ".uno:FormatYErrorBars";
202 break;
203 case OBJECTTYPE_DATA_ERRORS_Z:
204 aDispatchCommand = ".uno:FormatZErrorBars";
205 break;
206 case OBJECTTYPE_DATA_CURVE:
207 aDispatchCommand = ".uno:FormatTrendline";
208 break;
209 case OBJECTTYPE_DATA_CURVE_EQUATION:
210 aDispatchCommand = ".uno:FormatTrendlineEquation";
211 break;
212 case OBJECTTYPE_DATA_STOCK_RANGE:
213 aDispatchCommand = ".uno:FormatSelection";
214 break;
215 case OBJECTTYPE_DATA_STOCK_LOSS:
216 aDispatchCommand = ".uno:FormatStockLoss";
217 break;
218 case OBJECTTYPE_DATA_STOCK_GAIN:
219 aDispatchCommand = ".uno:FormatStockGain";
220 break;
221 default: //OBJECTTYPE_UNKNOWN
222 break;
224 return aDispatchCommand;
227 } // anonymous namespace
229 // awt::XWindow
230 void SAL_CALL ChartController::setPosSize(
231 sal_Int32 X,
232 sal_Int32 Y,
233 sal_Int32 Width,
234 sal_Int32 Height,
235 sal_Int16 Flags )
237 SolarMutexGuard aGuard;
238 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
239 auto pChartWindow(GetChartWindow());
241 if(xWindow.is() && pChartWindow)
243 Size aLogicSize = pChartWindow->PixelToLogic( Size( Width, Height ), MapMode( MapUnit::Map100thMM ) );
245 //todo: for standalone chart: detect whether we are standalone
246 //change map mode to fit new size
247 awt::Size aModelPageSize = ChartModelHelper::getPageSize( getModel() );
248 sal_Int32 nScaleXNumerator = aLogicSize.Width();
249 sal_Int32 nScaleXDenominator = aModelPageSize.Width;
250 sal_Int32 nScaleYNumerator = aLogicSize.Height();
251 sal_Int32 nScaleYDenominator = aModelPageSize.Height;
252 MapMode aNewMapMode(
253 MapUnit::Map100thMM,
254 Point(0,0),
255 Fraction(nScaleXNumerator, nScaleXDenominator),
256 Fraction(nScaleYNumerator, nScaleYDenominator) );
257 pChartWindow->SetMapMode(aNewMapMode);
258 pChartWindow->setPosSizePixel( X, Y, Width, Height, static_cast<PosSizeFlags>(Flags) );
260 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
261 uno::Reference< beans::XPropertySet > xProp( m_xChartView, uno::UNO_QUERY );
262 if( xProp.is() )
264 auto aZoomFactors(::comphelper::InitPropertySequence({
265 { "ScaleXNumerator", uno::Any( nScaleXNumerator ) },
266 { "ScaleXDenominator", uno::Any( nScaleXDenominator ) },
267 { "ScaleYNumerator", uno::Any( nScaleYNumerator ) },
268 { "ScaleYDenominator", uno::Any( nScaleYDenominator ) }
269 }));
270 xProp->setPropertyValue( "ZoomFactors", uno::Any( aZoomFactors ));
273 //a correct work area is at least necessary for correct values in the position and size dialog and for dragging area
274 if(m_pDrawViewWrapper)
276 tools::Rectangle aRect(Point(0,0), pChartWindow->GetOutputSize());
277 m_pDrawViewWrapper->SetWorkArea( aRect );
279 pChartWindow->Invalidate();
283 awt::Rectangle SAL_CALL ChartController::getPosSize()
285 //@todo
286 awt::Rectangle aRet(0, 0, 0, 0);
288 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
289 if(xWindow.is())
290 aRet = xWindow->getPosSize();
292 return aRet;
295 void SAL_CALL ChartController::setVisible( sal_Bool Visible )
297 //@todo
298 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
300 if(xWindow.is())
301 xWindow->setVisible( Visible );
304 void SAL_CALL ChartController::setEnable( sal_Bool Enable )
306 //@todo
307 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
309 if(xWindow.is())
310 xWindow->setEnable( Enable );
313 void SAL_CALL ChartController::setFocus()
315 //@todo
316 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
318 if(xWindow.is())
319 xWindow->setFocus();
322 void SAL_CALL ChartController::addWindowListener(
323 const uno::Reference< awt::XWindowListener >& xListener )
325 //@todo
326 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
328 if(xWindow.is())
329 xWindow->addWindowListener( xListener );
332 void SAL_CALL ChartController::removeWindowListener(
333 const uno::Reference< awt::XWindowListener >& xListener )
335 //@todo
336 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
338 if(xWindow.is())
339 xWindow->removeWindowListener( xListener );
342 void SAL_CALL ChartController::addFocusListener(
343 const uno::Reference< awt::XFocusListener >& xListener )
345 //@todo
346 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
348 if(xWindow.is())
349 xWindow->addFocusListener( xListener );
352 void SAL_CALL ChartController::removeFocusListener(
353 const uno::Reference< awt::XFocusListener >& xListener )
355 //@todo
356 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
358 if(xWindow.is())
359 xWindow->removeFocusListener( xListener );
362 void SAL_CALL ChartController::addKeyListener(
363 const uno::Reference< awt::XKeyListener >& xListener )
365 //@todo
366 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
368 if(xWindow.is())
369 xWindow->addKeyListener( xListener );
372 void SAL_CALL ChartController::removeKeyListener(
373 const uno::Reference< awt::XKeyListener >& xListener )
375 //@todo
376 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
378 if(xWindow.is())
379 xWindow->removeKeyListener( xListener );
382 void SAL_CALL ChartController::addMouseListener(
383 const uno::Reference< awt::XMouseListener >& xListener )
385 //@todo
386 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
388 if(xWindow.is())
389 xWindow->addMouseListener( xListener );
392 void SAL_CALL ChartController::removeMouseListener(
393 const uno::Reference< awt::XMouseListener >& xListener )
395 //@todo
396 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
398 if(xWindow.is())
399 xWindow->removeMouseListener( xListener );
402 void SAL_CALL ChartController::addMouseMotionListener(
403 const uno::Reference< awt::XMouseMotionListener >& xListener )
405 //@todo
406 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
408 if(xWindow.is())
409 xWindow->addMouseMotionListener( xListener );
412 void SAL_CALL ChartController::removeMouseMotionListener(
413 const uno::Reference< awt::XMouseMotionListener >& xListener )
415 //@todo
416 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
418 if(xWindow.is())
419 xWindow->removeMouseMotionListener( xListener );
422 void SAL_CALL ChartController::addPaintListener(
423 const uno::Reference< awt::XPaintListener >& xListener )
425 //@todo
426 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
428 if(xWindow.is())
429 xWindow->addPaintListener( xListener );
432 void SAL_CALL ChartController::removePaintListener(
433 const uno::Reference< awt::XPaintListener >& xListener )
435 //@todo
436 uno::Reference<awt::XWindow> xWindow = m_xViewWindow;
438 if(xWindow.is())
439 xWindow->removePaintListener( xListener );
442 // impl vcl window controller methods
443 void ChartController::PrePaint()
445 // forward VCLs PrePaint window event to DrawingLayer
446 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
448 if (pDrawViewWrapper)
450 pDrawViewWrapper->PrePaint();
454 void ChartController::execute_Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
458 uno::Reference<frame::XModel> xModel(getModel());
459 //OSL_ENSURE( xModel.is(), "ChartController::execute_Paint: have no model to paint");
460 if (!xModel.is())
461 return;
463 //better performance for big data
464 uno::Reference<beans::XPropertySet> xProp(m_xChartView, uno::UNO_QUERY);
465 if (xProp.is())
467 awt::Size aResolution(1000, 1000);
469 SolarMutexGuard aGuard;
470 auto pChartWindow(GetChartWindow());
471 if (pChartWindow)
473 aResolution.Width = pChartWindow->GetSizePixel().Width();
474 aResolution.Height = pChartWindow->GetSizePixel().Height();
477 xProp->setPropertyValue( "Resolution", uno::Any( aResolution ));
480 uno::Reference< util::XUpdatable > xUpdatable( m_xChartView, uno::UNO_QUERY );
481 if (xUpdatable.is())
482 xUpdatable->update();
485 SolarMutexGuard aGuard;
486 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
487 if (pDrawViewWrapper)
488 pDrawViewWrapper->CompleteRedraw(&rRenderContext, vcl::Region(rRect));
491 catch( const uno::Exception & )
493 DBG_UNHANDLED_EXCEPTION("chart2");
495 catch( ... )
500 static bool isDoubleClick( const MouseEvent& rMEvt )
502 return rMEvt.GetClicks() == 2 && rMEvt.IsLeft() &&
503 !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsShift();
506 void ChartController::startDoubleClickWaiting()
508 SolarMutexGuard aGuard;
510 m_bWaitingForDoubleClick = true;
512 sal_uInt64 nDblClkTime = 500;
513 auto pChartWindow(GetChartWindow());
514 if( pChartWindow )
516 const MouseSettings& rMSettings = pChartWindow->GetSettings().GetMouseSettings();
517 nDblClkTime = rMSettings.GetDoubleClickTime();
519 m_aDoubleClickTimer.SetTimeout( nDblClkTime );
520 m_aDoubleClickTimer.Start();
523 void ChartController::stopDoubleClickWaiting()
525 m_aDoubleClickTimer.Stop();
526 m_bWaitingForDoubleClick = false;
529 IMPL_LINK_NOARG(ChartController, DoubleClickWaitingHdl, Timer *, void)
531 m_bWaitingForDoubleClick = false;
533 if( !m_bWaitingForMouseUp && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() )
535 impl_selectObjectAndNotiy();
536 SolarMutexGuard aGuard;
537 auto pChartWindow(GetChartWindow());
538 if( pChartWindow )
540 vcl::Window::PointerState aPointerState( pChartWindow->GetPointerState() );
541 MouseEvent aMouseEvent(
542 aPointerState.maPos,
543 1/*nClicks*/,
544 MouseEventModifiers::NONE,
545 static_cast< sal_uInt16 >( aPointerState.mnState )/*nButtons*/,
546 0/*nModifier*/ );
547 impl_SetMousePointer( aMouseEvent );
552 void ChartController::execute_MouseButtonDown( const MouseEvent& rMEvt )
554 SolarMutexGuard aGuard;
556 m_bWaitingForMouseUp = true;
557 m_bFieldButtonDown = false;
559 if( isDoubleClick(rMEvt) )
560 stopDoubleClickWaiting();
561 else
562 startDoubleClickWaiting();
564 m_aSelection.remindSelectionBeforeMouseDown();
566 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
567 auto pChartWindow(GetChartWindow());
568 if(!pChartWindow || !pDrawViewWrapper )
569 return;
571 Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel());
573 // Check if button was clicked
574 SdrObject* pObject = pDrawViewWrapper->getHitObject(aMPos);
575 if (pObject)
577 OUString aCID = pObject->GetName();
578 if (aCID.startsWith("FieldButton"))
580 m_bFieldButtonDown = true;
581 return; // Don't take any action if button was clicked
585 if ( rMEvt.GetButtons() == MOUSE_LEFT )
587 pChartWindow->GrabFocus();
588 pChartWindow->CaptureMouse();
591 if( pDrawViewWrapper->IsTextEdit() )
593 SdrViewEvent aVEvt;
594 if ( pDrawViewWrapper->IsTextEditHit( aMPos ) ||
595 // #i12587# support for shapes in chart
596 ( rMEvt.IsRight() && pDrawViewWrapper->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt ) == SdrHitKind::MarkedObject ) )
598 pDrawViewWrapper->MouseButtonDown(rMEvt, pChartWindow);
599 return;
601 else
603 EndTextEdit();
607 //abort running action
608 if( pDrawViewWrapper->IsAction() )
610 if( rMEvt.IsRight() )
611 pDrawViewWrapper->BckAction();
612 return;
615 if( isDoubleClick(rMEvt) ) //do not change selection if double click
616 return;//double click is handled further in mousebutton up
618 SdrHdl* pHitSelectionHdl = nullptr;
619 //switch from move to resize if handle is hit on a resizable object
620 if( m_aSelection.isResizeableObjectSelected() )
621 pHitSelectionHdl = pDrawViewWrapper->PickHandle( aMPos );
622 //only change selection if no selection handles are hit
623 if( !pHitSelectionHdl )
625 // #i12587# support for shapes in chart
626 if ( m_eDrawMode == CHARTDRAW_INSERT &&
627 ( !pDrawViewWrapper->IsMarkedHit( aMPos ) || !m_aSelection.isDragableObjectSelected() ) )
629 if ( m_aSelection.hasSelection() )
631 m_aSelection.clearSelection();
633 if ( !pDrawViewWrapper->IsAction() )
635 if ( pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_CAPTION )
637 Size aCaptionSize( 2268, 1134 );
638 pDrawViewWrapper->BegCreateCaptionObj( aMPos, aCaptionSize );
640 else
642 pDrawViewWrapper->BegCreateObj( aMPos);
644 SdrObject* pObj = pDrawViewWrapper->GetCreateObj();
645 DrawCommandDispatch* pDrawCommandDispatch = m_aDispatchContainer.getDrawCommandDispatch();
646 if ( pObj && m_pDrawModelWrapper && pDrawCommandDispatch )
648 SfxItemSet aSet( m_pDrawModelWrapper->GetItemPool() );
649 pDrawCommandDispatch->setAttributes( pObj );
650 pDrawCommandDispatch->setLineEnds( aSet );
651 pObj->SetMergedItemSet( aSet );
654 impl_SetMousePointer( rMEvt );
655 return;
658 m_aSelection.adaptSelectionToNewPos(
659 aMPos,
660 pDrawViewWrapper,
661 rMEvt.IsRight(),
662 m_bWaitingForDoubleClick );
664 if( !m_aSelection.isRotateableObjectSelected( getModel() ) )
666 m_eDragMode = SdrDragMode::Move;
667 pDrawViewWrapper->SetDragMode(m_eDragMode);
670 m_aSelection.applySelection(pDrawViewWrapper);
672 if( m_aSelection.isDragableObjectSelected()
673 && !rMEvt.IsRight() )
675 //start drag
676 sal_uInt16 nDrgLog = static_cast<sal_uInt16>(pChartWindow->PixelToLogic(Size(DRGPIX,0)).Width());
677 SdrDragMethod* pDragMethod = nullptr;
679 //change selection to 3D scene if rotate mode
680 SdrDragMode eDragMode = pDrawViewWrapper->GetDragMode();
681 if( eDragMode==SdrDragMode::Rotate )
683 E3dScene* pScene = SelectionHelper::getSceneToRotate( pDrawViewWrapper->getNamedSdrObject( m_aSelection.getSelectedCID() ) );
684 if( pScene )
686 DragMethod_RotateDiagram::RotationDirection eRotationDirection(DragMethod_RotateDiagram::ROTATIONDIRECTION_FREE);
687 if(pHitSelectionHdl)
689 SdrHdlKind eKind = pHitSelectionHdl->GetKind();
690 if( eKind==SdrHdlKind::Upper || eKind==SdrHdlKind::Lower )
691 eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_X;
692 else if( eKind==SdrHdlKind::Left || eKind==SdrHdlKind::Right )
693 eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Y;
694 else if( eKind==SdrHdlKind::UpperLeft || eKind==SdrHdlKind::UpperRight || eKind==SdrHdlKind::LowerLeft || eKind==SdrHdlKind::LowerRight )
695 eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Z;
697 pDragMethod = new DragMethod_RotateDiagram( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getModel(), eRotationDirection );
700 else
702 OUString aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) );
703 if( aDragMethodServiceName == ObjectIdentifier::getPieSegmentDragMethodServiceName() )
704 pDragMethod = new DragMethod_PieSegment( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getModel() );
706 pDrawViewWrapper->SdrView::BegDragObj(aMPos, nullptr, pHitSelectionHdl, nDrgLog, pDragMethod);
709 impl_SetMousePointer( rMEvt );
712 void ChartController::execute_MouseMove( const MouseEvent& rMEvt )
714 SolarMutexGuard aGuard;
716 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
717 auto pChartWindow(GetChartWindow());
718 if(!pChartWindow || !pDrawViewWrapper)
719 return;
721 if( m_pDrawViewWrapper->IsTextEdit() )
723 if( m_pDrawViewWrapper->MouseMove(rMEvt,pChartWindow) )
724 return;
727 if(pDrawViewWrapper->IsAction())
729 pDrawViewWrapper->MovAction( pChartWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
732 impl_SetMousePointer( rMEvt );
735 void ChartController::execute_MouseButtonUp( const MouseEvent& rMEvt )
737 ControllerLockGuardUNO aCLGuard( getModel() );
738 bool bMouseUpWithoutMouseDown = !m_bWaitingForMouseUp;
739 m_bWaitingForMouseUp = false;
740 bool bNotifySelectionChange = false;
742 SolarMutexGuard aGuard;
744 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
745 auto pChartWindow(GetChartWindow());
746 if(!pChartWindow || !pDrawViewWrapper)
747 return;
749 Point aMPos = pChartWindow->PixelToLogic(rMEvt.GetPosPixel());
751 // Check if button was clicked
752 if (m_bFieldButtonDown)
754 m_bFieldButtonDown = false;
755 SdrObject* pObject = pDrawViewWrapper->getHitObject(aMPos);
756 if (pObject)
758 OUString aCID = pObject->GetName();
759 if (aCID.startsWith("FieldButton"))
761 sendPopupRequest(aCID, pObject->GetCurrentBoundRect());
762 return;
767 if(pDrawViewWrapper->IsTextEdit())
769 if( pDrawViewWrapper->MouseButtonUp(rMEvt,pChartWindow) )
770 return;
773 // #i12587# support for shapes in chart
774 if ( m_eDrawMode == CHARTDRAW_INSERT && pDrawViewWrapper->IsCreateObj() )
776 pDrawViewWrapper->EndCreateObj( SdrCreateCmd::ForceEnd );
778 HiddenUndoContext aUndoContext( m_xUndoManager );
779 // don't want the positioning Undo action to appear in the UI
780 impl_switchDiagramPositioningToExcludingPositioning();
782 if ( pDrawViewWrapper->AreObjectsMarked() )
784 if ( pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_TEXT )
786 executeDispatch_EditText();
788 else
790 SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
791 if ( pObj )
793 uno::Reference< drawing::XShape > xShape( pObj->getUnoShape(), uno::UNO_QUERY );
794 if ( xShape.is() )
796 m_aSelection.setSelection( xShape );
797 m_aSelection.applySelection( pDrawViewWrapper );
802 else
804 m_aSelection.adaptSelectionToNewPos( aMPos, pDrawViewWrapper, rMEvt.IsRight(), m_bWaitingForDoubleClick );
805 m_aSelection.applySelection( pDrawViewWrapper );
806 setDrawMode( CHARTDRAW_SELECT );
809 else if ( pDrawViewWrapper->IsDragObj() )
811 bool bDraggingDone = false;
812 SdrDragMethod* pDragMethod = pDrawViewWrapper->SdrView::GetDragMethod();
813 bool bIsMoveOnly = pDragMethod && pDragMethod->getMoveOnly();
814 DragMethod_Base* pChartDragMethod = dynamic_cast< DragMethod_Base* >(pDragMethod);
815 if( pChartDragMethod )
817 UndoGuard aUndoGuard( pChartDragMethod->getUndoDescription(),
818 m_xUndoManager );
820 if( pDrawViewWrapper->EndDragObj() )
822 bDraggingDone = true;
823 aUndoGuard.commit();
827 if( !bDraggingDone && pDrawViewWrapper->EndDragObj() )
831 //end move or size
832 SdrObject* pObj = pDrawViewWrapper->getSelectedObject();
833 if( pObj )
835 tools::Rectangle aObjectRect = pObj->GetSnapRect();
836 awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) );
837 tools::Rectangle aPageRect( 0,0,aPageSize.Width,aPageSize.Height );
839 const E3dObject* pE3dObject(dynamic_cast< const E3dObject*>(pObj));
840 if(nullptr != pE3dObject)
842 E3dScene* pScene(pE3dObject->getRootE3dSceneFromE3dObject());
843 if(nullptr != pScene)
845 aObjectRect = pScene->GetSnapRect();
849 ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::ActionType::Move);
850 if( !bIsMoveOnly && m_aSelection.isResizeableObjectSelected() )
851 eActionType = ActionDescriptionProvider::ActionType::Resize;
853 ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
855 UndoGuard aUndoGuard(
856 ActionDescriptionProvider::createDescription( eActionType, ObjectNameProvider::getName( eObjectType)),
857 m_xUndoManager );
859 bool bChanged = false;
860 ChartModel* pModel = dynamic_cast<ChartModel*>(getModel().get());
861 assert(pModel);
862 if ( eObjectType == OBJECTTYPE_LEGEND )
863 bChanged = DiagramHelper::switchDiagramPositioningToExcludingPositioning( *pModel, false , true );
865 bool bMoved = PositionAndSizeHelper::moveObject( m_aSelection.getSelectedCID()
866 , getModel()
867 , awt::Rectangle(aObjectRect.getX(),aObjectRect.getY(),aObjectRect.getWidth(),aObjectRect.getHeight())
868 , awt::Rectangle(aPageRect.getX(),aPageRect.getY(),aPageRect.getWidth(),aPageRect.getHeight()) );
870 if( bMoved || bChanged )
872 bDraggingDone = true;
873 aUndoGuard.commit();
877 catch( const uno::Exception & )
879 DBG_UNHANDLED_EXCEPTION("chart2");
881 //all wanted model changes will take effect
882 //and all unwanted view modifications are cleaned
885 if( !bDraggingDone ) //mouse wasn't moved while dragging
887 bool bClickedTwiceOnDragableObject = SelectionHelper::isDragableObjectHitTwice( aMPos, m_aSelection.getSelectedCID(), *pDrawViewWrapper );
888 bool bIsRotateable = m_aSelection.isRotateableObjectSelected( getModel() );
890 //toggle between move and rotate
891 if( bIsRotateable && bClickedTwiceOnDragableObject && m_eDragMode==SdrDragMode::Move )
892 m_eDragMode=SdrDragMode::Rotate;
893 else
894 m_eDragMode=SdrDragMode::Move;
896 pDrawViewWrapper->SetDragMode(m_eDragMode);
898 if( !m_bWaitingForDoubleClick && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() )
900 impl_selectObjectAndNotiy();
903 else
904 m_aSelection.resetPossibleSelectionAfterSingleClickWasEnsured();
907 //@todo ForcePointer(&rMEvt);
908 pChartWindow->ReleaseMouse();
910 // In tiled rendering drag mode could be not yet over on the call
911 // that should handle the double-click, so better to perform this check
912 // always.
913 if( isDoubleClick(rMEvt) && !bMouseUpWithoutMouseDown /*#i106966#*/ )
915 Point aMousePixel = rMEvt.GetPosPixel();
916 execute_DoubleClick( &aMousePixel );
919 if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() )
920 bNotifySelectionChange = true;
923 impl_SetMousePointer( rMEvt );
925 if(bNotifySelectionChange)
926 impl_notifySelectionChangeListeners();
929 void ChartController::execute_DoubleClick( const Point* pMousePixel )
931 bool isMobile = comphelper::LibreOfficeKit::isMobile(SfxLokHelper::getView());
932 if (isMobile)
933 return;
935 bool bEditText = false;
936 if ( m_aSelection.hasSelection() )
938 OUString aCID( m_aSelection.getSelectedCID() );
939 if ( !aCID.isEmpty() )
941 ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID );
942 if ( eObjectType == OBJECTTYPE_TITLE )
944 bEditText = true;
947 else
949 // #i12587# support for shapes in chart
950 SdrObject* pObj = DrawViewWrapper::getSdrObject( m_aSelection.getSelectedAdditionalShape() );
951 if ( dynamic_cast< const SdrTextObj* >(pObj) != nullptr )
953 bEditText = true;
958 if ( bEditText )
960 executeDispatch_EditText( pMousePixel );
962 else
964 executeDispatch_ObjectProperties();
968 void ChartController::execute_Resize()
970 SolarMutexGuard aGuard;
971 auto pChartWindow(GetChartWindow());
972 if(pChartWindow)
973 pChartWindow->Invalidate();
976 void ChartController::execute_Command( const CommandEvent& rCEvt )
978 SolarMutexGuard aGuard;
979 auto pChartWindow(GetChartWindow());
980 bool bIsAction = false;
982 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
983 if(!pChartWindow || !pDrawViewWrapper)
984 return;
985 bIsAction = m_pDrawViewWrapper->IsAction();
988 // pop-up menu
989 if(rCEvt.GetCommand() == CommandEventId::ContextMenu && !bIsAction)
992 if(pChartWindow)
993 pChartWindow->ReleaseMouse();
996 if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() )
997 impl_notifySelectionChangeListeners();
999 css::uno::Reference< css::awt::XPopupMenu > xPopupMenu( m_xCC->getServiceManager()->createInstanceWithContext(
1000 "com.sun.star.awt.PopupMenu", m_xCC ), css::uno::UNO_QUERY );
1002 Point aPos( rCEvt.GetMousePosPixel() );
1003 if( !rCEvt.IsMouseEvent() )
1005 if(pChartWindow)
1006 aPos = pChartWindow->GetPointerState().maPos;
1009 OUString aMenuName;
1010 if ( isShapeContext() )
1011 // #i12587# support for shapes in chart
1012 aMenuName = m_pDrawViewWrapper->IsTextEdit() ? OUString( "drawtext" ) : OUString( "draw" );
1013 else
1015 // todo: the context menu should be specified by an xml file in uiconfig
1016 if( xPopupMenu.is())
1018 sal_Int16 nUniqueId = 1;
1019 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Cut" );
1020 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Copy" );
1021 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:Paste" );
1022 xPopupMenu->insertSeparator( -1 );
1024 ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
1025 Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( getModel() );
1027 OUString aFormatCommand( lcl_getFormatCommandForObjectCID( m_aSelection.getSelectedCID() ) );
1028 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, aFormatCommand );
1030 //some commands for dataseries and points:
1032 if( eObjectType == OBJECTTYPE_DATA_SERIES || eObjectType == OBJECTTYPE_DATA_POINT )
1034 bool bIsPoint = ( eObjectType == OBJECTTYPE_DATA_POINT );
1035 uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() );
1036 uno::Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY );
1037 Reference< chart2::XRegressionCurve > xTrendline( RegressionCurveHelper::getFirstCurveNotMeanValueLine( xCurveCnt ) );
1038 bool bHasEquation = RegressionCurveHelper::hasEquation( xTrendline );
1039 Reference< chart2::XRegressionCurve > xMeanValue( RegressionCurveHelper::getMeanValueLine( xCurveCnt ) );
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;
1046 if( bIsPoint )
1048 nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( m_aSelection.getSelectedCID() );
1049 bHasDataLabelAtPoint = DataSeriesHelper::hasDataLabelAtPoint( xSeries, nPointIndex );
1051 bool bSelectedPointIsFormatted = false;
1052 bool bHasFormattedDataPointsOtherThanSelected = false;
1054 Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY );
1055 if( xSeriesProperties.is() )
1057 uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
1058 if( xSeriesProperties->getPropertyValue( "AttributedDataPoints" ) >>= aAttributedDataPointIndexList )
1060 if( aAttributedDataPointIndexList.hasElements() )
1062 if( bIsPoint )
1064 auto aIndices( comphelper::sequenceToContainer<std::vector< sal_Int32 >>( aAttributedDataPointIndexList ) );
1065 std::vector< sal_Int32 >::iterator aIt = std::find( aIndices.begin(), aIndices.end(), nPointIndex );
1066 if( aIt != aIndices.end())
1067 bSelectedPointIsFormatted = true;
1068 else
1069 bHasFormattedDataPointsOtherThanSelected = true;
1071 else
1072 bHasFormattedDataPointsOtherThanSelected = true;
1077 if( bIsPoint )
1079 if( bHasDataLabelAtPoint )
1080 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatDataLabel" );
1081 if( !bHasDataLabelAtPoint )
1082 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertDataLabel" );
1083 else
1084 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteDataLabel" );
1085 if( bSelectedPointIsFormatted )
1086 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:ResetDataPoint" );
1088 xPopupMenu->insertSeparator( -1 );
1090 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatDataSeries" );
1093 Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ) );
1094 if( xChartType->getChartType() == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK )
1098 Reference< beans::XPropertySet > xChartTypeProp( xChartType, uno::UNO_QUERY );
1099 if( xChartTypeProp.is() )
1101 bool bJapaneseStyle = false;
1102 xChartTypeProp->getPropertyValue( "Japanese" ) >>= bJapaneseStyle;
1104 if( bJapaneseStyle )
1106 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockLoss" );
1107 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockGain" );
1111 catch( const uno::Exception & )
1113 DBG_UNHANDLED_EXCEPTION("chart2");
1117 if( bHasDataLabelsAtSeries )
1118 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatDataLabels" );
1119 if( bHasEquation )
1120 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatTrendlineEquation" );
1121 if( xMeanValue.is() )
1122 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatMeanValue" );
1123 if( bHasXErrorBars )
1124 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatXErrorBars" );
1125 if( bHasYErrorBars )
1126 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatYErrorBars" );
1128 xPopupMenu->insertSeparator( -1 );
1130 if( !bHasDataLabelsAtSeries )
1131 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertDataLabels" );
1133 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTrendline" );
1135 if( !xMeanValue.is() )
1136 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertMeanValue" );
1137 if( !bHasXErrorBars )
1138 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertXErrorBars" );
1139 if( !bHasYErrorBars )
1140 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertYErrorBars" );
1141 if( bHasDataLabelsAtSeries || ( bHasDataLabelsAtPoints && bHasFormattedDataPointsOtherThanSelected ) )
1142 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteDataLabels" );
1143 if( bHasEquation )
1144 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteTrendlineEquation" );
1145 if( xMeanValue.is() )
1146 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteMeanValue" );
1147 if( bHasXErrorBars )
1148 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteXErrorBars" );
1149 if( bHasYErrorBars )
1150 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteYErrorBars" );
1152 if( bHasFormattedDataPointsOtherThanSelected )
1153 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:ResetAllDataPoints" );
1155 xPopupMenu->insertSeparator( -1 );
1157 lcl_insertMenuCommand( xPopupMenu, nUniqueId, ".uno:ArrangeRow" );
1158 uno::Reference< awt::XPopupMenu > xArrangePopupMenu(
1159 m_xCC->getServiceManager()->createInstanceWithContext(
1160 "com.sun.star.awt.PopupMenu", m_xCC ), uno::UNO_QUERY );
1161 if( xArrangePopupMenu.is() )
1163 sal_Int16 nSubId = nUniqueId + 1;
1164 lcl_insertMenuCommand( xArrangePopupMenu, nSubId++, ".uno:Forward" );
1165 lcl_insertMenuCommand( xArrangePopupMenu, nSubId, ".uno:Backward" );
1166 xPopupMenu->setPopupMenu( nUniqueId, xArrangePopupMenu );
1167 nUniqueId = nSubId;
1169 ++nUniqueId;
1171 else if( eObjectType == OBJECTTYPE_DATA_CURVE )
1173 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteTrendline" );
1174 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatTrendlineEquation" );
1175 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTrendlineEquation" );
1176 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTrendlineEquationAndR2" );
1177 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertR2Value" );
1178 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteTrendlineEquation" );
1179 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteR2Value" );
1181 else if( eObjectType == OBJECTTYPE_DATA_CURVE_EQUATION )
1183 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertR2Value" );
1184 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteR2Value" );
1187 //some commands for axes: and grids
1189 else if( eObjectType == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_GRID || eObjectType == OBJECTTYPE_SUBGRID )
1191 Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() );
1192 if( xAxis.is() && xDiagram.is() )
1194 sal_Int32 nDimensionIndex = -1;
1195 sal_Int32 nCooSysIndex = -1;
1196 sal_Int32 nAxisIndex = -1;
1197 AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex );
1198 bool bIsSecondaryAxis = nAxisIndex!=0;
1199 bool bIsAxisVisible = AxisHelper::isAxisVisible( xAxis );
1200 bool bIsMajorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, true /*bMainGrid*/, xDiagram );
1201 bool bIsMinorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, false /*bMainGrid*/, xDiagram );
1202 bool bHasTitle = false;
1203 uno::Reference< XTitled > xTitled( xAxis, uno::UNO_QUERY );
1204 if( xTitled.is())
1205 bHasTitle = !TitleHelper::getCompleteString( xTitled->getTitleObject() ).isEmpty();
1207 if( eObjectType != OBJECTTYPE_AXIS && bIsAxisVisible )
1208 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatAxis" );
1209 if( eObjectType != OBJECTTYPE_GRID && bIsMajorGridVisible && !bIsSecondaryAxis )
1210 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatMajorGrid" );
1211 if( eObjectType != OBJECTTYPE_SUBGRID && bIsMinorGridVisible && !bIsSecondaryAxis )
1212 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatMinorGrid" );
1214 xPopupMenu->insertSeparator( -1 );
1216 if( eObjectType != OBJECTTYPE_AXIS && !bIsAxisVisible )
1217 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertAxis" );
1218 if( eObjectType != OBJECTTYPE_GRID && !bIsMajorGridVisible && !bIsSecondaryAxis )
1219 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertMajorGrid" );
1220 if( eObjectType != OBJECTTYPE_SUBGRID && !bIsMinorGridVisible && !bIsSecondaryAxis )
1221 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertMinorGrid" );
1222 if( !bHasTitle )
1223 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertAxisTitle" );
1225 if( bIsAxisVisible )
1226 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteAxis" );
1227 if( bIsMajorGridVisible && !bIsSecondaryAxis )
1228 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteMajorGrid" );
1229 if( bIsMinorGridVisible && !bIsSecondaryAxis )
1230 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteMinorGrid" );
1234 if( eObjectType == OBJECTTYPE_DATA_STOCK_LOSS )
1235 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockGain" );
1236 else if( eObjectType == OBJECTTYPE_DATA_STOCK_GAIN )
1237 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:FormatStockLoss" );
1239 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:TransformDialog" );
1241 if( eObjectType == OBJECTTYPE_PAGE || eObjectType == OBJECTTYPE_DIAGRAM
1242 || eObjectType == OBJECTTYPE_DIAGRAM_WALL
1243 || eObjectType == OBJECTTYPE_DIAGRAM_FLOOR
1244 || eObjectType == OBJECTTYPE_UNKNOWN )
1246 if( eObjectType != OBJECTTYPE_UNKNOWN )
1247 xPopupMenu->insertSeparator( -1 );
1248 bool bHasLegend = LegendHelper::hasLegend( xDiagram );
1249 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertTitles" );
1250 if( !bHasLegend )
1251 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertLegend" );
1252 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:InsertRemoveAxes" );
1253 if( bHasLegend )
1254 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DeleteLegend" );
1257 xPopupMenu->insertSeparator( -1 );
1258 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DiagramType" );
1259 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DataRanges" );
1260 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:DiagramData" );
1261 lcl_insertMenuCommand( xPopupMenu, nUniqueId++, ".uno:View3D" );
1265 css::uno::Sequence< css::uno::Any > aArgs( 3 );
1266 aArgs[0] <<= comphelper::makePropertyValue( "IsContextMenu", true );
1267 aArgs[1] <<= comphelper::makePropertyValue( "Frame", m_xFrame );
1268 aArgs[2] <<= comphelper::makePropertyValue( "Value", aMenuName );
1270 css::uno::Reference< css::frame::XPopupMenuController > xPopupController(
1271 m_xCC->getServiceManager()->createInstanceWithArgumentsAndContext(
1272 "com.sun.star.comp.framework.ResourceMenuController", aArgs, m_xCC ), css::uno::UNO_QUERY );
1274 if ( !xPopupController.is() || !xPopupMenu.is() )
1275 return;
1277 if (comphelper::LibreOfficeKit::isActive())
1279 PopupMenu* pPopupMenu = static_cast<PopupMenu*>(comphelper::getUnoTunnelImplementation<VCLXMenu>(xPopupMenu)->GetMenu());
1280 pPopupMenu->SetLOKNotifier(SfxViewShell::Current());
1282 // the context menu expects a position related to the document window,
1283 // not to the chart window
1284 SfxInPlaceClient* pIPClient = SfxViewShell::Current()->GetIPClient();
1285 if (pIPClient)
1287 vcl::Window* pRootWin = pIPClient->GetEditWin();
1288 if (pRootWin)
1290 Point aOffset = pChartWindow->GetOffsetPixelFrom(*pRootWin);
1291 aPos += aOffset;
1296 xPopupController->setPopupMenu( xPopupMenu );
1297 xPopupMenu->execute( css::uno::Reference< css::awt::XWindowPeer >( m_xFrame->getContainerWindow(), css::uno::UNO_QUERY ),
1298 css::awt::Rectangle( aPos.X(), aPos.Y(), 0, 0 ),
1299 css::awt::PopupMenuDirection::EXECUTE_DEFAULT );
1301 css::uno::Reference< css::lang::XComponent > xComponent( xPopupController, css::uno::UNO_QUERY );
1302 if ( xComponent.is() )
1303 xComponent->dispose();
1305 else if( ( rCEvt.GetCommand() == CommandEventId::StartExtTextInput ) ||
1306 ( rCEvt.GetCommand() == CommandEventId::ExtTextInput ) ||
1307 ( rCEvt.GetCommand() == CommandEventId::EndExtTextInput ) ||
1308 ( rCEvt.GetCommand() == CommandEventId::InputContextChange ) )
1310 //#i84417# enable editing with IME
1311 if( m_pDrawViewWrapper )
1312 m_pDrawViewWrapper->Command( rCEvt, pChartWindow );
1316 bool ChartController::execute_KeyInput( const KeyEvent& rKEvt )
1318 SolarMutexGuard aGuard;
1319 bool bReturn=false;
1321 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
1322 auto pChartWindow(GetChartWindow());
1323 if (!pChartWindow || !pDrawViewWrapper)
1324 return bReturn;
1326 // handle accelerators
1327 if (!m_apAccelExecute && m_xFrame.is() && m_xCC.is())
1329 m_apAccelExecute = ::svt::AcceleratorExecute::createAcceleratorHelper();
1330 OSL_ASSERT(m_apAccelExecute);
1331 if (m_apAccelExecute)
1332 m_apAccelExecute->init( m_xCC, m_xFrame );
1335 vcl::KeyCode aKeyCode( rKEvt.GetKeyCode());
1336 sal_uInt16 nCode = aKeyCode.GetCode();
1337 bool bAlternate = aKeyCode.IsMod2();
1338 bool bCtrl = aKeyCode.IsMod1();
1340 if (m_apAccelExecute)
1341 bReturn = m_apAccelExecute->execute( aKeyCode );
1342 if( bReturn )
1343 return bReturn;
1346 if( pDrawViewWrapper->IsTextEdit() )
1348 if( pDrawViewWrapper->KeyInput(rKEvt, pChartWindow) )
1350 bReturn = true;
1351 if( nCode == KEY_ESCAPE )
1353 EndTextEdit();
1359 // keyboard accessibility
1360 ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() );
1361 if( ! bReturn )
1363 // Navigation (Tab/F3/Home/End)
1364 uno::Reference< XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY );
1365 ObjectKeyNavigation aObjNav( m_aSelection.getSelectedOID(), xChartDoc, comphelper::getUnoTunnelImplementation<ExplicitValueProvider>( m_xChartView ));
1366 awt::KeyEvent aKeyEvent( ::svt::AcceleratorExecute::st_VCLKey2AWTKey( aKeyCode ));
1367 bReturn = aObjNav.handleKeyEvent( aKeyEvent );
1368 if( bReturn )
1370 const ObjectIdentifier& aNewOID = aObjNav.getCurrentSelection();
1371 uno::Any aNewSelection;
1372 if ( aNewOID.isValid() && !ObjectHierarchy::isRootNode( aNewOID ) )
1374 aNewSelection = aNewOID.getAny();
1376 if ( m_eDragMode == SdrDragMode::Rotate && !SelectionHelper::isRotateableObject( aNewOID.getObjectCID(), getModel() ) )
1378 m_eDragMode = SdrDragMode::Move;
1380 bReturn = select( aNewSelection );
1384 // Position and Size (+/-/arrow-keys) or pie segment dragging
1385 if( ! bReturn )
1387 // pie segment dragging
1388 // note: could also be done for data series
1389 if( eObjectType == OBJECTTYPE_DATA_POINT &&
1390 ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) ==
1391 ObjectIdentifier::getPieSegmentDragMethodServiceName())
1393 bool bDrag = false;
1394 bool bDragInside = false;
1395 if( nCode == KEY_ADD ||
1396 nCode == KEY_SUBTRACT )
1398 bDrag = true;
1399 bDragInside = ( nCode == KEY_SUBTRACT );
1401 else if(
1402 nCode == KEY_LEFT ||
1403 nCode == KEY_RIGHT ||
1404 nCode == KEY_UP ||
1405 nCode == KEY_DOWN )
1407 bDrag = true;
1408 OUString aParameter( ObjectIdentifier::getDragParameterString( m_aSelection.getSelectedCID() ));
1409 sal_Int32 nOffsetPercentDummy( 0 );
1410 awt::Point aMinimumPosition( 0, 0 );
1411 awt::Point aMaximumPosition( 0, 0 );
1412 ObjectIdentifier::parsePieSegmentDragParameterString(
1413 aParameter, nOffsetPercentDummy, aMinimumPosition, aMaximumPosition );
1414 aMaximumPosition.Y -= aMinimumPosition.Y;
1415 aMaximumPosition.X -= aMinimumPosition.X;
1417 bDragInside =
1418 (nCode == KEY_RIGHT && (aMaximumPosition.X < 0)) ||
1419 (nCode == KEY_LEFT && (aMaximumPosition.X > 0)) ||
1420 (nCode == KEY_DOWN && (aMaximumPosition.Y < 0)) ||
1421 (nCode == KEY_UP && (aMaximumPosition.Y > 0));
1424 if( bDrag )
1426 double fAmount = bAlternate ? 0.01 : 0.05;
1427 if( bDragInside )
1428 fAmount *= -1.0;
1430 bReturn = impl_DragDataPoint( m_aSelection.getSelectedCID(), fAmount );
1433 else
1435 // size
1436 if( nCode == KEY_ADD ||
1437 nCode == KEY_SUBTRACT )
1439 if( eObjectType == OBJECTTYPE_DIAGRAM )
1441 // default 1 mm in each direction
1442 double fGrowAmountX = 200.0;
1443 double fGrowAmountY = 200.0;
1444 if (bAlternate)
1446 // together with Alt-key: 1 px in each direction
1447 Size aPixelSize = pChartWindow->PixelToLogic( Size( 2, 2 ));
1448 fGrowAmountX = static_cast< double >( aPixelSize.Width());
1449 fGrowAmountY = static_cast< double >( aPixelSize.Height());
1451 if( nCode == KEY_SUBTRACT )
1453 fGrowAmountX = -fGrowAmountX;
1454 fGrowAmountY = -fGrowAmountY;
1456 bReturn = impl_moveOrResizeObject(
1457 m_aSelection.getSelectedCID(), CENTERED_RESIZE_OBJECT, fGrowAmountX, fGrowAmountY );
1460 // position
1461 else if( nCode == KEY_LEFT ||
1462 nCode == KEY_RIGHT ||
1463 nCode == KEY_UP ||
1464 nCode == KEY_DOWN )
1466 if( m_aSelection.isDragableObjectSelected() )
1468 // default 1 mm
1469 double fShiftAmountX = 100.0;
1470 double fShiftAmountY = 100.0;
1471 if (bAlternate)
1473 // together with Alt-key: 1 px
1474 Size aPixelSize = pChartWindow->PixelToLogic( Size( 1, 1 ));
1475 fShiftAmountX = static_cast< double >( aPixelSize.Width());
1476 fShiftAmountY = static_cast< double >( aPixelSize.Height());
1478 switch( nCode )
1480 case KEY_LEFT:
1481 fShiftAmountX = -fShiftAmountX;
1482 fShiftAmountY = 0.0;
1483 break;
1484 case KEY_RIGHT:
1485 fShiftAmountY = 0.0;
1486 break;
1487 case KEY_UP:
1488 fShiftAmountX = 0.0;
1489 fShiftAmountY = -fShiftAmountY;
1490 break;
1491 case KEY_DOWN:
1492 fShiftAmountX = 0.0;
1493 break;
1495 if( !m_aSelection.getSelectedCID().isEmpty() )
1497 //move chart objects
1498 bReturn = impl_moveOrResizeObject(
1499 m_aSelection.getSelectedCID(), MOVE_OBJECT, fShiftAmountX, fShiftAmountY );
1501 else
1503 //move additional shapes
1504 uno::Reference< drawing::XShape > xShape( m_aSelection.getSelectedAdditionalShape() );
1505 if( xShape.is() )
1507 awt::Point aPos( xShape->getPosition() );
1508 awt::Size aSize( xShape->getSize() );
1509 awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) );
1510 aPos.X = static_cast< long >( static_cast< double >( aPos.X ) + fShiftAmountX );
1511 aPos.Y = static_cast< long >( static_cast< double >( aPos.Y ) + fShiftAmountY );
1512 if( aPos.X + aSize.Width > aPageSize.Width )
1513 aPos.X = aPageSize.Width - aSize.Width;
1514 if( aPos.X < 0 )
1515 aPos.X = 0;
1516 if( aPos.Y + aSize.Height > aPageSize.Height )
1517 aPos.Y = aPageSize.Height - aSize.Height;
1518 if( aPos.Y < 0 )
1519 aPos.Y = 0;
1521 xShape->setPosition( aPos );
1529 // dumping the shape
1530 if( !bReturn && bCtrl && nCode == KEY_F12)
1532 uno::Reference< qa::XDumper > xChartModel( getModel(), uno::UNO_QUERY );
1533 if(xChartModel.is())
1535 OUString aDump = xChartModel->dump();
1536 SAL_WARN("chart2", aDump);
1540 // text edit
1541 if( ! bReturn &&
1542 nCode == KEY_F2 )
1544 if( eObjectType == OBJECTTYPE_TITLE )
1546 executeDispatch_EditText();
1547 bReturn = true;
1551 // deactivate inplace mode (this code should be unnecessary, but
1552 // unfortunately is not)
1553 if( ! bReturn &&
1554 nCode == KEY_ESCAPE )
1556 uno::Reference< frame::XDispatchHelper > xDispatchHelper( frame::DispatchHelper::create(m_xCC) );
1557 uno::Sequence< beans::PropertyValue > aArgs;
1558 xDispatchHelper->executeDispatch(
1559 uno::Reference< frame::XDispatchProvider >( m_xFrame, uno::UNO_QUERY ),
1560 ".uno:TerminateInplaceActivation",
1561 "_parent",
1562 frame::FrameSearchFlag::PARENT,
1563 aArgs );
1564 bReturn = true;
1567 if( ! bReturn &&
1568 (nCode == KEY_DELETE || nCode == KEY_BACKSPACE ))
1570 bReturn = executeDispatch_Delete();
1571 if( ! bReturn )
1573 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pChartWindow->GetFrameWeld(),
1574 VclMessageType::Info, VclButtonsType::Ok,
1575 SchResId(STR_ACTION_NOTPOSSIBLE)));
1576 xInfoBox->run();
1580 return bReturn;
1583 bool ChartController::requestQuickHelp(
1584 ::Point aAtLogicPosition,
1585 bool bIsBalloonHelp,
1586 OUString & rOutQuickHelpText,
1587 awt::Rectangle & rOutEqualRect )
1589 uno::Reference< frame::XModel > xChartModel;
1590 if( m_aModel.is())
1591 xChartModel.set( getModel() );
1592 if( !xChartModel.is())
1593 return false;
1595 // help text
1596 OUString aCID;
1597 if( m_pDrawViewWrapper )
1599 aCID = SelectionHelper::getHitObjectCID(
1600 aAtLogicPosition, *m_pDrawViewWrapper );
1602 bool bResult( !aCID.isEmpty());
1604 if( bResult )
1606 // get help text
1607 rOutQuickHelpText = ObjectNameProvider::getHelpText( aCID, xChartModel, bIsBalloonHelp /* bVerbose */ );
1609 // set rectangle
1610 ExplicitValueProvider * pValueProvider(
1611 comphelper::getUnoTunnelImplementation<ExplicitValueProvider>( m_xChartView ));
1612 if( pValueProvider )
1613 rOutEqualRect = pValueProvider->getRectangleOfObject( aCID, true );
1616 return bResult;
1619 // XSelectionSupplier (optional interface)
1620 sal_Bool SAL_CALL ChartController::select( const uno::Any& rSelection )
1622 bool bSuccess = false;
1624 if ( rSelection.hasValue() )
1626 const uno::Type& rType = rSelection.getValueType();
1627 if ( rType == cppu::UnoType< OUString >::get() )
1629 OUString aNewCID;
1630 if ( ( rSelection >>= aNewCID ) && m_aSelection.setSelection( aNewCID ) )
1632 bSuccess = true;
1635 else if ( rType == cppu::UnoType<drawing::XShape>::get() )
1637 uno::Reference< drawing::XShape > xShape;
1638 if ( ( rSelection >>= xShape ) && m_aSelection.setSelection( xShape ) )
1640 bSuccess = true;
1644 else
1646 if ( m_aSelection.hasSelection() )
1648 m_aSelection.clearSelection();
1649 bSuccess = true;
1653 if ( bSuccess )
1655 SolarMutexGuard aGuard;
1656 if ( m_pDrawViewWrapper && m_pDrawViewWrapper->IsTextEdit() )
1658 EndTextEdit();
1660 impl_selectObjectAndNotiy();
1661 auto pChartWindow(GetChartWindow());
1662 if ( pChartWindow )
1664 pChartWindow->Invalidate();
1666 return true;
1669 return false;
1672 uno::Any SAL_CALL ChartController::getSelection()
1674 uno::Any aReturn;
1675 if ( m_aSelection.hasSelection() )
1677 OUString aCID( m_aSelection.getSelectedCID() );
1678 if ( !aCID.isEmpty() )
1680 if ( comphelper::LibreOfficeKit::isActive() )
1682 sal_Int32 nPos = aCID.lastIndexOf('/');
1683 OUString sFirst = aCID.copy(0, nPos);
1684 OUString sSecond = aCID.copy(nPos);
1685 aCID = sFirst;
1686 aCID += "/Draggable=" + OUString::number(static_cast<int>(isSelectedObjectDraggable()));
1687 aCID += ":Resizable=" + OUString::number(static_cast<int>(isSelectedObjectResizable()));
1688 aCID += ":Rotatable=" + OUString::number(static_cast<int>(isSelectedObjectRotatable()));
1689 aCID += sSecond;
1691 aReturn <<= aCID;
1693 else
1695 // #i12587# support for shapes in chart
1696 aReturn <<= m_aSelection.getSelectedAdditionalShape();
1699 return aReturn;
1702 void SAL_CALL ChartController::addSelectionChangeListener( const uno::Reference<view::XSelectionChangeListener> & xListener )
1704 SolarMutexGuard aGuard;
1705 if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode?
1706 return; //behave passive if already disposed or suspended
1708 //--add listener
1709 m_aLifeTimeManager.m_aListenerContainer.addInterface( cppu::UnoType<view::XSelectionChangeListener>::get(), xListener );
1712 void SAL_CALL ChartController::removeSelectionChangeListener( const uno::Reference<view::XSelectionChangeListener> & xListener )
1714 SolarMutexGuard aGuard;
1715 if( impl_isDisposedOrSuspended() ) //@todo? allow removing of listeners in suspend mode?
1716 return; //behave passive if already disposed or suspended
1718 //--remove listener
1719 m_aLifeTimeManager.m_aListenerContainer.removeInterface( cppu::UnoType<view::XSelectionChangeListener>::get(), xListener );
1722 void ChartController::impl_notifySelectionChangeListeners()
1724 ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer
1725 .getContainer( cppu::UnoType<view::XSelectionChangeListener>::get() );
1726 if( pIC )
1728 uno::Reference< view::XSelectionSupplier > xSelectionSupplier(this);
1729 lang::EventObject aEvent( xSelectionSupplier );
1730 ::cppu::OInterfaceIteratorHelper aIt( *pIC );
1731 while( aIt.hasMoreElements() )
1733 uno::Reference< view::XSelectionChangeListener > xListener( aIt.next(), uno::UNO_QUERY );
1734 if( xListener.is() )
1735 xListener->selectionChanged( aEvent );
1740 void ChartController::impl_selectObjectAndNotiy()
1743 SolarMutexGuard aGuard;
1744 DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper.get();
1745 if( pDrawViewWrapper )
1747 pDrawViewWrapper->SetDragMode( m_eDragMode );
1748 m_aSelection.applySelection( m_pDrawViewWrapper.get() );
1751 impl_notifySelectionChangeListeners();
1754 bool ChartController::impl_moveOrResizeObject(
1755 const OUString & rCID,
1756 eMoveOrResizeType eType,
1757 double fAmountLogicX,
1758 double fAmountLogicY )
1760 bool bResult = false;
1761 bool bNeedResize = ( eType == CENTERED_RESIZE_OBJECT );
1763 uno::Reference< frame::XModel > xChartModel( getModel() );
1764 uno::Reference< beans::XPropertySet > xObjProp(
1765 ObjectIdentifier::getObjectPropertySet( rCID, xChartModel ));
1766 if( xObjProp.is())
1768 awt::Size aRefSize = ChartModelHelper::getPageSize( xChartModel );
1770 chart2::RelativePosition aRelPos;
1771 chart2::RelativeSize aRelSize;
1772 bool bDeterminePos = !(xObjProp->getPropertyValue( "RelativePosition") >>= aRelPos);
1773 bool bDetermineSize = !bNeedResize || !(xObjProp->getPropertyValue( "RelativeSize") >>= aRelSize);
1775 if( ( bDeterminePos || bDetermineSize ) &&
1776 ( aRefSize.Width > 0 && aRefSize.Height > 0 ) )
1778 ExplicitValueProvider * pValueProvider(
1779 comphelper::getUnoTunnelImplementation<ExplicitValueProvider>( m_xChartView ));
1780 if( pValueProvider )
1782 awt::Rectangle aRect( pValueProvider->getRectangleOfObject( rCID ));
1783 double fWidth = static_cast< double >( aRefSize.Width );
1784 double fHeight = static_cast< double >( aRefSize.Height );
1785 if( bDetermineSize )
1787 aRelSize.Primary = static_cast< double >( aRect.Width ) / fWidth;
1788 aRelSize.Secondary = static_cast< double >( aRect.Height ) / fHeight;
1790 if( bDeterminePos )
1792 if( bNeedResize && aRelSize.Primary > 0.0 && aRelSize.Secondary > 0.0 )
1794 aRelPos.Primary = (static_cast< double >( aRect.X ) / fWidth) +
1795 (aRelSize.Primary / 2.0);
1796 aRelPos.Secondary = (static_cast< double >( aRect.Y ) / fHeight) +
1797 (aRelSize.Secondary / 2.0);
1798 aRelPos.Anchor = drawing::Alignment_CENTER;
1800 else
1802 aRelPos.Primary = static_cast< double >( aRect.X ) / fWidth;
1803 aRelPos.Secondary = static_cast< double >( aRect.Y ) / fHeight;
1804 aRelPos.Anchor = drawing::Alignment_TOP_LEFT;
1810 if( eType == CENTERED_RESIZE_OBJECT )
1811 bResult = lcl_GrowAndShiftLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY );
1812 else if( eType == MOVE_OBJECT )
1813 bResult = lcl_MoveObjectLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY );
1815 if( bResult )
1817 ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::ActionType::Move);
1818 if( bNeedResize )
1819 eActionType = ActionDescriptionProvider::ActionType::Resize;
1821 ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID );
1822 UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription(
1823 eActionType, ObjectNameProvider::getName( eObjectType )), m_xUndoManager );
1825 ControllerLockGuardUNO aCLGuard( xChartModel );
1826 xObjProp->setPropertyValue( "RelativePosition", uno::Any( aRelPos ));
1827 if( bNeedResize || (eObjectType == OBJECTTYPE_DIAGRAM) )//Also set an explicit size at the diagram when an explicit position is set
1828 xObjProp->setPropertyValue( "RelativeSize", uno::Any( aRelSize ));
1830 aUndoGuard.commit();
1833 return bResult;
1836 bool ChartController::impl_DragDataPoint( const OUString & rCID, double fAdditionalOffset )
1838 bool bResult = false;
1839 if( fAdditionalOffset < -1.0 || fAdditionalOffset > 1.0 || fAdditionalOffset == 0.0 )
1840 return bResult;
1842 sal_Int32 nDataPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rCID );
1843 uno::Reference< chart2::XDataSeries > xSeries(
1844 ObjectIdentifier::getDataSeriesForCID( rCID, getModel() ));
1845 if( xSeries.is())
1849 uno::Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex( nDataPointIndex ));
1850 double fOffset = 0.0;
1851 if( xPointProp.is() &&
1852 (xPointProp->getPropertyValue( "Offset" ) >>= fOffset ) &&
1853 (( fAdditionalOffset > 0.0 && fOffset < 1.0 ) || (fOffset > 0.0)) )
1855 fOffset += fAdditionalOffset;
1856 if( fOffset > 1.0 )
1857 fOffset = 1.0;
1858 else if( fOffset < 0.0 )
1859 fOffset = 0.0;
1860 xPointProp->setPropertyValue( "Offset", uno::Any( fOffset ));
1861 bResult = true;
1864 catch( const uno::Exception & )
1866 DBG_UNHANDLED_EXCEPTION("chart2");
1870 return bResult;
1873 void ChartController::impl_SetMousePointer( const MouseEvent & rEvent )
1875 SolarMutexGuard aGuard;
1876 auto pChartWindow(GetChartWindow());
1878 if (!m_pDrawViewWrapper || !pChartWindow)
1879 return;
1881 Point aMousePos( pChartWindow->PixelToLogic( rEvent.GetPosPixel()));
1882 sal_uInt16 nModifier = rEvent.GetModifier();
1883 bool bLeftDown = rEvent.IsLeft();
1885 // Check if object is for field button and set the normal arrow pointer in this case
1886 SdrObject* pObject = m_pDrawViewWrapper->getHitObject(aMousePos);
1887 if (pObject && pObject->GetName().startsWith("FieldButton"))
1889 pChartWindow->SetPointer(PointerStyle::Arrow);
1890 return;
1893 if ( m_pDrawViewWrapper->IsTextEdit() )
1895 if( m_pDrawViewWrapper->IsTextEditHit( aMousePos ) )
1897 pChartWindow->SetPointer( m_pDrawViewWrapper->GetPreferredPointer(
1898 aMousePos, pChartWindow, nModifier, bLeftDown ) );
1899 return;
1902 else if( m_pDrawViewWrapper->IsAction() )
1904 return;//don't change pointer during running action
1907 SdrHdl* pHitSelectionHdl = nullptr;
1908 if( m_aSelection.isResizeableObjectSelected() )
1909 pHitSelectionHdl = m_pDrawViewWrapper->PickHandle( aMousePos );
1911 if( pHitSelectionHdl )
1913 PointerStyle aPointer = m_pDrawViewWrapper->GetPreferredPointer(
1914 aMousePos, pChartWindow, nModifier, bLeftDown );
1915 bool bForceArrowPointer = false;
1917 ObjectIdentifier aOID( m_aSelection.getSelectedOID() );
1919 switch( aPointer)
1921 case PointerStyle::NSize:
1922 case PointerStyle::SSize:
1923 case PointerStyle::WSize:
1924 case PointerStyle::ESize:
1925 case PointerStyle::NWSize:
1926 case PointerStyle::NESize:
1927 case PointerStyle::SWSize:
1928 case PointerStyle::SESize:
1929 if( ! m_aSelection.isResizeableObjectSelected() )
1930 bForceArrowPointer = true;
1931 break;
1932 case PointerStyle::Move:
1933 if ( !aOID.isDragableObject() )
1934 bForceArrowPointer = true;
1935 break;
1936 case PointerStyle::MovePoint:
1937 case PointerStyle::MoveBezierWeight:
1938 // there is no point-editing in a chart
1939 // the PointerStyle::MoveBezierWeight appears in 3d data points
1940 bForceArrowPointer = true;
1941 break;
1942 default:
1943 break;
1946 if( bForceArrowPointer )
1947 pChartWindow->SetPointer( PointerStyle::Arrow );
1948 else
1949 pChartWindow->SetPointer( aPointer );
1951 return;
1954 // #i12587# support for shapes in chart
1955 if ( m_eDrawMode == CHARTDRAW_INSERT &&
1956 ( !m_pDrawViewWrapper->IsMarkedHit( aMousePos ) || !m_aSelection.isDragableObjectSelected() ) )
1958 PointerStyle ePointerStyle = PointerStyle::DrawRect;
1959 SdrObjKind eKind = static_cast< SdrObjKind >( m_pDrawViewWrapper->GetCurrentObjIdentifier() );
1960 switch ( eKind )
1962 case OBJ_LINE:
1964 ePointerStyle = PointerStyle::DrawLine;
1966 break;
1967 case OBJ_RECT:
1968 case OBJ_CUSTOMSHAPE:
1970 ePointerStyle = PointerStyle::DrawRect;
1972 break;
1973 case OBJ_CIRC:
1975 ePointerStyle = PointerStyle::DrawEllipse;
1977 break;
1978 case OBJ_FREELINE:
1980 ePointerStyle = PointerStyle::DrawPolygon;
1982 break;
1983 case OBJ_TEXT:
1985 ePointerStyle = PointerStyle::DrawText;
1987 break;
1988 case OBJ_CAPTION:
1990 ePointerStyle = PointerStyle::DrawCaption;
1992 break;
1993 default:
1995 ePointerStyle = PointerStyle::DrawRect;
1997 break;
1999 pChartWindow->SetPointer( ePointerStyle );
2000 return;
2003 OUString aHitObjectCID(
2004 SelectionHelper::getHitObjectCID(
2005 aMousePos, *m_pDrawViewWrapper, true /*bGetDiagramInsteadOf_Wall*/ ));
2007 if( m_pDrawViewWrapper->IsTextEdit() )
2009 if( aHitObjectCID == m_aSelection.getSelectedCID() )
2011 pChartWindow->SetPointer( PointerStyle::Arrow );
2012 return;
2016 if( aHitObjectCID.isEmpty() )
2018 //additional shape was hit
2019 pChartWindow->SetPointer( PointerStyle::Move );
2021 else if( ObjectIdentifier::isDragableObject( aHitObjectCID ) )
2023 if( (m_eDragMode == SdrDragMode::Rotate)
2024 && SelectionHelper::isRotateableObject( aHitObjectCID
2025 , getModel() ) )
2026 pChartWindow->SetPointer( PointerStyle::Rotate );
2027 else
2029 ObjectType eHitObjectType = ObjectIdentifier::getObjectType( aHitObjectCID );
2030 if( eHitObjectType == OBJECTTYPE_DATA_POINT )
2032 if( !ObjectIdentifier::areSiblings(aHitObjectCID,m_aSelection.getSelectedCID())
2033 && !ObjectIdentifier::areIdenticalObjects(aHitObjectCID,m_aSelection.getSelectedCID()) )
2035 pChartWindow->SetPointer( PointerStyle::Arrow );
2036 return;
2039 pChartWindow->SetPointer( PointerStyle::Move );
2042 else
2043 pChartWindow->SetPointer( PointerStyle::Arrow );
2046 css::uno::Reference<css::uno::XInterface> const & ChartController::getChartView() const
2048 return m_xChartView;
2051 void ChartController::sendPopupRequest(OUString const & rCID, tools::Rectangle aRectangle)
2053 ChartModel* pChartModel = dynamic_cast<ChartModel*>(m_aModel->getModel().get());
2054 if (!pChartModel)
2055 return;
2057 uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider;
2058 xPivotTableDataProvider.set(pChartModel->getDataProvider(), uno::UNO_QUERY);
2059 if (!xPivotTableDataProvider.is())
2060 return;
2062 OUString sPivotTableName = xPivotTableDataProvider->getPivotTableName();
2064 PopupRequest* pPopupRequest = dynamic_cast<PopupRequest*>(pChartModel->getPopupRequest().get());
2065 if (!pPopupRequest)
2066 return;
2068 // Get dimension index from CID
2069 sal_Int32 nStartPos = rCID.lastIndexOf('.');
2070 nStartPos++;
2071 sal_Int32 nEndPos = rCID.getLength();
2072 OUString sDimensionIndex = rCID.copy(nStartPos, nEndPos - nStartPos);
2073 sal_Int32 nDimensionIndex = sDimensionIndex.toInt32();
2075 awt::Rectangle xRectangle {
2076 sal_Int32(aRectangle.Left()),
2077 sal_Int32(aRectangle.Top()),
2078 sal_Int32(aRectangle.GetWidth()),
2079 sal_Int32(aRectangle.GetHeight())
2082 uno::Sequence<beans::PropertyValue> aCallbackData = comphelper::InitPropertySequence(
2084 {"Rectangle", uno::makeAny<awt::Rectangle>(xRectangle)},
2085 {"DimensionIndex", uno::makeAny<sal_Int32>(nDimensionIndex)},
2086 {"PivotTableName", uno::makeAny<OUString>(sPivotTableName)},
2089 pPopupRequest->getCallback()->notify(uno::makeAny(aCallbackData));
2092 } //namespace chart
2094 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */