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