LibreOffice Module chart2 (master) 1
ChartController.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 <memory>
21#include <sal/config.h>
22
23#include <config_wasm_strip.h>
24#include <ChartController.hxx>
25#include <ChartView.hxx>
26#include <servicenames.hxx>
27#include <ResId.hxx>
28#include <dlg_DataSource.hxx>
29#include <ChartModel.hxx>
30#include <ChartModelHelper.hxx>
31#include <ChartType.hxx>
33#include <DataSeries.hxx>
34#include <Diagram.hxx>
35#include <strings.hrc>
37#include <ChartViewHelper.hxx>
38
39#include <ChartWindow.hxx>
41#include <DrawViewWrapper.hxx>
42#include <ObjectIdentifier.hxx>
43#include <DiagramHelper.hxx>
45#include "UndoGuard.hxx"
47
48#include <dlg_ChartType.hxx>
49#if !ENABLE_WASM_STRIP_ACCESSIBILITY
51#endif
53#include "ShapeController.hxx"
54#include "UndoActions.hxx"
56
60
61#include <com/sun/star/awt/XVclWindowPeer.hpp>
62#include <com/sun/star/frame/XController2.hpp>
63#include <com/sun/star/util/CloseVetoException.hpp>
64#include <com/sun/star/util/XModeChangeBroadcaster.hpp>
65#include <com/sun/star/frame/LayoutManagerEvents.hpp>
66#include <com/sun/star/frame/XLayoutManagerEventBroadcaster.hpp>
67#include <com/sun/star/ui/XSidebar.hpp>
68#include <com/sun/star/chart2/XDataProviderAccess.hpp>
69#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
70
71#include <sal/log.hxx>
72#include <tools/debug.hxx>
75#include <utility>
76#include <vcl/svapp.hxx>
77#include <vcl/weld.hxx>
78#include <osl/mutex.hxx>
79#include <comphelper/lok.hxx>
80
82
83#include <com/sun/star/frame/XLayoutManager.hpp>
84
85// this is needed to properly destroy the unique_ptr to the AcceleratorExecute
86// object in the DTOR
90
91// enable the following define to let the controller listen to model changes and
92// react on this by rebuilding the view
93#define TEST_ENABLE_MODIFY_LISTENER
94
95namespace chart
96{
97
98using namespace ::com::sun::star;
99using namespace ::com::sun::star::accessibility;
100using namespace ::com::sun::star::chart2;
101using ::com::sun::star::uno::Reference;
102using ::com::sun::star::uno::Sequence;
103
104ChartController::ChartController(uno::Reference<uno::XComponentContext> xContext) :
105 m_aLifeTimeManager( nullptr ),
106 m_bSuspended( false ),
107 m_xCC(std::move(xContext)),
108 m_aModel( nullptr, m_aModelMutex ),
109 m_eDragMode(SdrDragMode::Move),
110 m_aDoubleClickTimer("chart2 ChartController m_aDoubleClickTimer"),
111 m_bWaitingForDoubleClick(false),
112 m_bWaitingForMouseUp(false),
113 m_bFieldButtonDown(false),
114 m_bConnectingToView(false),
115 m_bDisposed(false),
116 m_aDispatchContainer( m_xCC ),
117 m_eDrawMode( CHARTDRAW_SELECT ),
118 mpSelectionChangeHandler(new svx::sidebar::SelectionChangeHandler(
119 [this]() { return this->GetContextName(); },
121{
122 m_aDoubleClickTimer.SetInvokeHandler( LINK( this, ChartController, DoubleClickWaitingHdl ) );
123}
124
126{
128}
129
131 m_xModel(std::move( xModel )),
132 m_bOwnership( true )
133{
134}
135
137{
138}
139
141{
142 if(m_xModel)
143 {
144 //if you need to be able to veto against the destruction of the model
145 // you must add as a close listener
146
147 //otherwise you 'can' add as closelistener or 'must' add as dispose event listener
148
149 m_xModel->addCloseListener(
150 static_cast<util::XCloseListener*>(pController) );
151 }
152}
153
155{
156 if(m_xModel)
157 m_xModel->removeCloseListener(
158 static_cast<util::XCloseListener*>(pController) );
159}
160
162{
163 if(!m_bOwnership)
164 return;
165
166 try
167 {
168 if(m_xModel.is())
169 {
170 try
171 {
172 //@todo ? are we allowed to use sal_True here if we have the explicit ownership?
173 //I think yes, because there might be other CloseListeners later in the list which might be interested still
174 //but make sure that we do not throw the CloseVetoException here ourselves
175 //so stop listening before trying to terminate or check the source of queryclosing event
176 m_xModel->close(true);
177
178 m_bOwnership = false;
179 }
180 catch( const util::CloseVetoException& )
181 {
182 //since we have indicated to give up the ownership with parameter true in close call
183 //the one who has thrown the CloseVetoException is the new owner
184
185 SAL_WARN_IF( m_bOwnership, "chart2.main", "a well known owner has caught a CloseVetoException after calling close(true)");
186 m_bOwnership = false;
187 return;
188 }
189
190 }
191 }
192 catch(const uno::Exception&)
193 {
194 DBG_UNHANDLED_EXCEPTION( "chart2", "Termination of model failed" );
195 }
196}
197
198ChartController::TheModelRef::TheModelRef( TheModel* pTheModel, osl::Mutex& rMutex ) :
199 m_rModelMutex(rMutex)
200{
201 osl::Guard< osl::Mutex > aGuard( m_rModelMutex );
202 m_xTheModel = pTheModel;
203}
204ChartController::TheModelRef::TheModelRef( const TheModelRef& rTheModel, ::osl::Mutex& rMutex ) :
205 m_rModelMutex(rMutex)
206{
207 osl::Guard< osl::Mutex > aGuard( m_rModelMutex );
208 m_xTheModel = rTheModel.m_xTheModel;
209}
211{
212 osl::Guard< osl::Mutex > aGuard( m_rModelMutex );
213 m_xTheModel = pTheModel;
214 return *this;
215}
217{
218 osl::Guard< osl::Mutex > aGuard( m_rModelMutex );
219 m_xTheModel = rTheModel.operator->();
220 return *this;
221}
223{
224 osl::Guard< osl::Mutex > aGuard( m_rModelMutex );
225 m_xTheModel.clear();
226}
228{
229 return m_xTheModel.is();
230}
231
232namespace {
233
234rtl::Reference<ChartType> getChartType(const rtl::Reference<ChartModel>& xChartDoc)
235{
236 rtl::Reference<Diagram > xDiagram = xChartDoc->getFirstChartDiagram();
237 if (!xDiagram.is())
238 return nullptr;
239
240 const std::vector< rtl::Reference< BaseCoordinateSystem > > & xCooSysSequence( xDiagram->getBaseCoordinateSystems());
241 if (xCooSysSequence.empty())
242 return nullptr;
243
244 return xCooSysSequence[0]->getChartTypes2()[0];
245}
246
247}
248
250{
251 if (m_bDisposed)
252 return OUString();
253
254 uno::Any aAny = getSelection();
255 if (!aAny.hasValue())
256 return "Chart";
257
258 OUString aCID;
259 aAny >>= aCID;
260
261 if (aCID.isEmpty())
262 return "Chart";
263
265 switch (eObjectID)
266 {
268 return "Series";
272 return "ErrorBar";
273 case OBJECTTYPE_AXIS:
274 return "Axis";
275 case OBJECTTYPE_GRID:
276 return "Grid";
278 {
279 rtl::Reference<ChartType> xChartType = getChartType(getChartModel());
280 if (xChartType.is() && xChartType->getChartType() == "com.sun.star.chart2.PieChartType")
281 return "ChartElements";
282 break;
283 }
286 return "Trendline";
287 default:
288 break;
289 }
290
291 return "Chart";
292}
293
294// private methods
295
297{
298 if( m_aLifeTimeManager.impl_isDisposed() )
299 return true;
300
301 if( m_bSuspended )
302 {
303 OSL_FAIL( "This Controller is suspended" );
304 return true;
305 }
306 return false;
307}
308
309// lang::XServiceInfo
310
312{
314}
315
316sal_Bool SAL_CALL ChartController::supportsService( const OUString& rServiceName )
317{
318 return cppu::supportsService(this, rServiceName);
319}
320
321css::uno::Sequence< OUString > SAL_CALL ChartController::getSupportedServiceNames()
322{
323 return {
325 "com.sun.star.frame.Controller"
327 };
328}
329
330namespace {
331
332uno::Reference<ui::XSidebar> getSidebarFromModel(const uno::Reference<frame::XModel>& xModel)
333{
334 uno::Reference<container::XChild> xChild(xModel, uno::UNO_QUERY);
335 if (!xChild.is())
336 return nullptr;
337
338 uno::Reference<frame::XModel> xParent (xChild->getParent(), uno::UNO_QUERY);
339 if (!xParent.is())
340 return nullptr;
341
342 uno::Reference<frame::XController2> xController(xParent->getCurrentController(), uno::UNO_QUERY);
343 if (!xController.is())
344 return nullptr;
345
346 uno::Reference<ui::XSidebarProvider> xSidebarProvider = xController->getSidebar();
347 if (!xSidebarProvider.is())
348 return nullptr;
349
350 return xSidebarProvider->getSidebar();
351}
352
353}
354
355// XController
356
358 const uno::Reference<frame::XFrame>& xFrame )
359{
360 SolarMutexGuard aGuard;
361
362 if( impl_isDisposedOrSuspended() ) //@todo? allow attaching the frame while suspended?
363 return; //behave passive if already disposed or suspended
364
365 if(m_xFrame.is()) //what happens, if we do have a Frame already??
366 {
367 //@todo? throw exception?
368 OSL_FAIL( "there is already a frame attached to the controller" );
369 return;
370 }
371
372 //--attach frame
373 m_xFrame = xFrame; //the frameloader is responsible to call xFrame->setComponent
374
375 // Only notify after setting the frame, otherwise notification will fail
376 mpSelectionChangeHandler->Connect();
377
378 uno::Reference<ui::XSidebar> xSidebar = getSidebarFromModel(getChartModel());
379 if (xSidebar.is())
380 {
381 auto pSidebar = dynamic_cast<sfx2::sidebar::SidebarController*>(xSidebar.get());
382 assert(pSidebar);
383 pSidebar->registerSidebarForFrame(this);
384 pSidebar->updateModel(getChartModel());
385 css::lang::EventObject aEvent;
386 mpSelectionChangeHandler->selectionChanged(aEvent);
387 }
388
389 //add as disposelistener to the frame (due to persistent reference) ??...:
390
391 //the frame is considered to be owner of this controller and will live longer than we do
392 //the frame or the disposer of the frame has the duty to call suspend and dispose on this object
393 //so we do not need to add as lang::XEventListener for DisposingEvents right?
394
395 //@todo nothing right???
396
397 //create view @todo is this the correct place here??
398
399 vcl::Window* pParent = nullptr;
400 //get the window parent from the frame to use as parent for our new window
401 if(xFrame.is())
402 {
403 uno::Reference<awt::XWindow> xContainerWindow = xFrame->getContainerWindow();
404 if (xContainerWindow)
405 xContainerWindow->setVisible(true);
406 pParent = VCLUnoHelper::GetWindow( xContainerWindow );
407 }
408
409 {
410 // calls to VCL
411 SolarMutexGuard aSolarGuard;
412 auto pChartWindow = VclPtr<ChartWindow>::Create(this,pParent,pParent?pParent->GetStyle():0);
413 pChartWindow->SetBackground();//no Background
414 m_xViewWindow.set( pChartWindow->GetComponentInterface(), uno::UNO_QUERY );
415 pChartWindow->Show();
417 new ChartDropTargetHelper( pChartWindow->GetDropTarget(), getChartModel()));
418
420 }
421
422 //create the menu
423 {
424 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
425 if( xPropSet.is() )
426 {
427 try
428 {
430 xPropSet->getPropertyValue( "LayoutManager" ) >>= xLayoutManager;
431 if ( xLayoutManager.is() )
432 {
433 xLayoutManager->lock();
434 xLayoutManager->requestElement( "private:resource/menubar/menubar" );
435 //@todo: createElement should become unnecessary, remove when #i79198# is fixed
436 xLayoutManager->createElement( "private:resource/toolbar/standardbar" );
437 xLayoutManager->requestElement( "private:resource/toolbar/standardbar" );
438 //@todo: createElement should become unnecessary, remove when #i79198# is fixed
439 xLayoutManager->createElement( "private:resource/toolbar/toolbar" );
440 xLayoutManager->requestElement( "private:resource/toolbar/toolbar" );
441
442 // #i12587# support for shapes in chart
443 xLayoutManager->createElement( "private:resource/toolbar/drawbar" );
444 xLayoutManager->requestElement( "private:resource/toolbar/drawbar" );
445
446 xLayoutManager->requestElement( "private:resource/statusbar/statusbar" );
447 xLayoutManager->unlock();
448
449 // add as listener to get notified when
450 m_xLayoutManagerEventBroadcaster.set( xLayoutManager, uno::UNO_QUERY );
452 m_xLayoutManagerEventBroadcaster->addLayoutManagerEventListener( this );
453 }
454 }
455 catch( const uno::Exception & )
456 {
457 DBG_UNHANDLED_EXCEPTION("chart2");
458 }
459 }
460 }
461}
462
463//XModeChangeListener
464void SAL_CALL ChartController::modeChanged( const util::ModeChangeEvent& rEvent )
465{
466 SolarMutexGuard aGuard;
467 auto pChartWindow(GetChartWindow());
468 //adjust controller to view status changes
469
470 if( rEvent.NewMode == "dirty" )
471 {
472 //the view has become dirty, we should repaint it if we have a window
473 if( pChartWindow )
474 pChartWindow->ForceInvalidate();
475 }
476 else if( rEvent.NewMode == "invalid" )
477 {
478 //the view is about to become invalid so end all actions on it
480 if( m_pDrawViewWrapper && m_pDrawViewWrapper->IsTextEdit() )
481 this->EndTextEdit();
483 {
484 m_pDrawViewWrapper->UnmarkAll();
485 m_pDrawViewWrapper->HideSdrPage();
486 }
487 }
488 else
489 {
490 //the view was rebuild so we can start some actions on it again
492 {
493 if(pChartWindow && m_aModel.is() )
494 {
495 m_bConnectingToView = true;
496
499 {
500 {
502 m_pDrawViewWrapper->ReInit();
503 }
504
505 //reselect object
508 else
510
512
513 {
514 if( pChartWindow )
515 pChartWindow->Invalidate();
516 }
517 }
518
519 m_bConnectingToView = false;
520 }
521 }
522 }
523}
524
526{
528
529 //is called to attach the controller to a new model.
530 //return true if attach was successfully, false otherwise (e.g. if you do not work with a model)
531
533 if( impl_isDisposedOrSuspended() ) //@todo? allow attaching a new model while suspended?
534 return false; //behave passive if already disposed or suspended
535 aGuard.clear();
536
537 ::chart::ChartModel* pChartModel = dynamic_cast<::chart::ChartModel*>(xModel.get());
538 assert(!xModel || pChartModel);
539
540 TheModelRef aNewModelRef( new TheModel(pChartModel), m_aModelMutex);
541 TheModelRef aOldModelRef(m_aModel,m_aModelMutex);
542 m_aModel = aNewModelRef;
543
544 //--handle relations to the old model if any
545 if( aOldModelRef.is() )
546 {
547 if( m_xChartView.is() )
548 m_xChartView->removeModeChangeListener(this);
549 m_pDrawModelWrapper.reset();
550
551 aOldModelRef->removeListener( this );
552 #ifdef TEST_ENABLE_MODIFY_LISTENER
553 if( aOldModelRef->getModel().is())
554 aOldModelRef->getModel()->removeModifyListener( this );
555#endif
556 }
557
558 //--handle relations to the new model
559 aNewModelRef->addListener( this );
560
561 aGuard.reset(); // lock for m_aDispatchContainer access
562 // set new model at dispatchers
563 m_aDispatchContainer.setModel( aNewModelRef->getModel());
565 pDispatch->initialize();
566
567 // the dispatch container will return "this" for all commands returned by
568 // impl_getAvailableCommands(). That means, for those commands dispatch()
569 // is called here at the ChartController.
571
573 pDrawDispatch->initialize();
574 m_aDispatchContainer.setDrawCommandDispatch( pDrawDispatch.get() );
575
576 rtl::Reference<ShapeController> pShapeController = new ShapeController( m_xCC, this );
577 pShapeController->initialize();
578 m_aDispatchContainer.setShapeController( pShapeController.get() );
579 aGuard.clear();
580
581#ifdef TEST_ENABLE_MODIFY_LISTENER
582 if( aNewModelRef->getModel().is())
583 aNewModelRef->getModel()->addModifyListener( this );
584#endif
585
586 // #i119999# Do not do this per default to allow the user to deselect the chart OLE with a single press to ESC
587 // select chart area per default:
588 // select( uno::Any( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ) );
589
591 if( xFact.is())
592 {
593 m_xChartView = dynamic_cast<::chart::ChartView*>(xFact->createInstance( CHART_VIEW_SERVICE_NAME ).get());
595 m_xChartView->addModeChangeListener(this);
596 }
597
598 //the frameloader is responsible to call xModel->connectController
599 {
600 SolarMutexGuard aGuard2;
601 auto pChartWindow(GetChartWindow());
602 if( pChartWindow )
603 pChartWindow->Invalidate();
604 }
605
606 m_xUndoManager.set( getChartModel()->getUndoManager(), uno::UNO_SET_THROW );
607
608 return true;
609}
610
612{
613 //provides access to owner frame of this controller
614 //return the frame containing this controller
615
616 return m_xFrame;
617}
618
620{
621 return getChartModel();
622}
623
625{
626 //provides access to currently attached model
627 //returns the currently attached model
628
629 //return nothing, if you do not have a model
631 if(aModelRef.is())
632 return aModelRef->getModel();
633
634 return nullptr;
635}
636
638{
639 return getChartModel()->getFirstChartDiagram();
640}
641
643{
644 //provides access to current view status
645 //set of data that can be used to restore the current view status at later time
646 // by using XController::restoreViewData()
647
648 SolarMutexGuard aGuard;
650 return uno::Any(); //behave passive if already disposed or suspended //@todo? or throw an exception??
651
652 //-- collect current view state
653 uno::Any aRet;
655
656 return aRet;
657}
658
660 const uno::Any& /* Value */ )
661{
662 //restores the view status using the data gotten from a previous call to XController::getViewData()
663
664 SolarMutexGuard aGuard;
666 return; //behave passive if already disposed or suspended //@todo? or throw an exception??
667
669}
670
672{
673 //is called to prepare the controller for closing the view
674 //bSuspend==true: force the controller to suspend his work
675 //bSuspend==false try to reactivate the controller
676 //returns true if request was accepted and of course successfully finished, false otherwise
677
678 //we may show dialogs here to ask the user for saving changes ... @todo?
679
680 SolarMutexGuard aGuard;
681 if( m_aLifeTimeManager.impl_isDisposed() )
682 return false; //behave passive if already disposed, return false because request was not accepted //@todo? correct
683
684 if(bool(bSuspend) == m_bSuspended)
685 {
686 OSL_FAIL( "new suspend mode equals old suspend mode" );
687 return true;
688 }
689
690 //change suspend mode
691 m_bSuspended = bSuspend;
692 return true;
693}
694
695// css::frame::XController2
696
697css::uno::Reference<css::awt::XWindow> SAL_CALL ChartController::getComponentWindow()
698{
699 // it is a special characteristic of ChartController
700 // that it simultaneously provides the XWindow functionality
701 return this;
702}
703
704OUString SAL_CALL ChartController::getViewControllerName() { return {}; }
705
706css::uno::Sequence<css::beans::PropertyValue> SAL_CALL ChartController::getCreationArguments()
707{
708 return {};
709}
710
711css::uno::Reference<css::ui::XSidebarProvider> SAL_CALL ChartController::getSidebar() { return {}; }
712
714{
715 SolarMutexGuard aGuard;
717 {
719 {
720 bool bLokCalcGlobalRTL = false;
722 {
724 if (xChartModel.is())
725 {
726 uno::Reference<css::sheet::XSpreadsheetDocument> xSSDoc(xChartModel->getParent(), uno::UNO_QUERY);
727 if (xSSDoc.is())
728 bLokCalcGlobalRTL = true;
729 }
730 }
731
732 m_pDrawViewWrapper.reset( new DrawViewWrapper(m_pDrawModelWrapper->getSdrModel(),GetChartWindow()->GetOutDev()) );
733 m_pDrawViewWrapper->SetNegativeX(bLokCalcGlobalRTL);
734 m_pDrawViewWrapper->attachParentReferenceDevice( getChartModel() );
735 }
736 }
737}
738
740{
742 {
743 SolarMutexGuard aGuard;
744 if( m_pDrawViewWrapper->IsTextEdit() )
745 this->EndTextEdit();
746 m_pDrawViewWrapper.reset();
747 }
748}
749
750// XComponent (base of XController)
751
753{
754 m_bDisposed = true;
755
756 mpSelectionChangeHandler->selectionChanged(css::lang::EventObject());
757 mpSelectionChangeHandler->Disconnect();
758
759 if (getModel().is())
760 {
761 uno::Reference<ui::XSidebar> xSidebar = getSidebarFromModel(getChartModel());
762 if (sfx2::sidebar::SidebarController* pSidebar = dynamic_cast<sfx2::sidebar::SidebarController*>(xSidebar.get()))
763 {
764 pSidebar->unregisterSidebarForFrame(this);
765 }
766 }
767
768 try
769 {
770 //This object should release all resources and references in the
771 //easiest possible manner
772 //This object must notify all registered listeners using the method
773 //<member>XEventListener::disposing</member>
774
775 //hold no mutex
776 if( !m_aLifeTimeManager.dispose() )
777 return;
778
779// OSL_ENSURE( m_bSuspended, "dispose was called but controller is not suspended" );
780
782
783 //end range highlighting
784 if( m_aModel.is())
785 {
788 if( xDataReceiver.is() )
789 xSelectionChangeListener.set( xDataReceiver->getRangeHighlighter(), uno::UNO_QUERY );
790 if( xSelectionChangeListener.is() )
791 {
793 lang::EventObject aEvent( xController );
794 xSelectionChangeListener->disposing( aEvent );
795 }
796 }
797
798 //--release all resources and references
799 {
800 if( m_xChartView.is() )
801 m_xChartView->removeModeChangeListener(this);
802
804 SolarMutexGuard aSolarGuard;
806 m_pDrawModelWrapper.reset();
807
808 m_apDropTargetHelper.reset();
809
810 //the accessible view is disposed within window destructor of m_pChartWindow
811 if(m_xViewWindow.is())
812 m_xViewWindow->dispose(); //ChartWindow is deleted via UNO due to dispose of m_xViewWindow (triggered by Framework (Controller pretends to be XWindow also))
813 m_xChartView.clear();
814 }
815
816 // remove as listener to layout manager events
818 {
819 m_xLayoutManagerEventBroadcaster->removeLayoutManagerEventListener( this );
821 }
822
823 m_xFrame.clear();
824 m_xUndoManager.clear();
825
827 m_aModel = nullptr;
828
829 if( aModelRef.is())
830 {
832 if(xModel.is())
833 xModel->disconnectController( uno::Reference< frame::XController >( this ));
834
835 aModelRef->removeListener( this );
836#ifdef TEST_ENABLE_MODIFY_LISTENER
837 try
838 {
839 if( aModelRef->getModel().is())
840 aModelRef->getModel()->removeModifyListener( this );
841 }
842 catch( const uno::Exception & )
843 {
844 DBG_UNHANDLED_EXCEPTION("chart2");
845 }
846#endif
847 aModelRef->tryTermination();
848 }
849
851 //e.g. release further resources and references
852
855 }
856 catch( const uno::Exception & )
857 {
858 DBG_UNHANDLED_EXCEPTION("chart2");
859 assert(!m_xChartView.is());
860 }
861 }
862
864 const uno::Reference<lang::XEventListener>& xListener )
865{
866 if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode?
867 return; //behave passive if already disposed or suspended
868
869 //--add listener
870 std::unique_lock aGuard2(m_aLifeTimeManager.m_aAccessMutex);
871 m_aLifeTimeManager.m_aEventListeners.addInterface( aGuard2, xListener );
872}
873
875 const uno::Reference<lang::XEventListener>& xListener )
876{
877 SolarMutexGuard aGuard;
878 if( m_aLifeTimeManager.impl_isDisposed(false) )
879 return; //behave passive if already disposed or suspended
880
881 //--remove listener
882 std::unique_lock aGuard2(m_aLifeTimeManager.m_aAccessMutex);
883 m_aLifeTimeManager.m_aEventListeners.removeInterface( aGuard2, xListener );
884}
885
886// util::XCloseListener
888 const lang::EventObject& rSource,
889 sal_Bool /*bGetsOwnership*/ )
890{
891 //do not use the m_aControllerMutex here because this call is not allowed to block
892
894
895 if( !aModelRef.is() )
896 return;
897
898 if( uno::Reference<XInterface>(static_cast<cppu::OWeakObject*>(aModelRef->getModel().get())) != rSource.Source )
899 {
900 OSL_FAIL( "queryClosing was called on a controller from an unknown source" );
901 return;
902 }
903
904 //@ todo prepare to closing model -> don't start any further hindering actions
905}
906
908 const lang::EventObject& rSource )
909{
910 //Listener should deregister himself and release all references to the closing object.
911
913 if( !impl_releaseThisModel( rSource.Source ) )
914 return;
915
916 //--stop listening to the closing model
917 aModelRef->removeListener( this );
918
919 // #i79087# If the model using this controller is closed, the frame is
920 // expected to be closed as well
921 Reference< util::XCloseable > xFrameCloseable( m_xFrame, uno::UNO_QUERY );
922 if( xFrameCloseable.is())
923 {
924 try
925 {
926 xFrameCloseable->close( false /* DeliverOwnership */ );
927 m_xFrame.clear();
928 }
929 catch( const util::CloseVetoException & )
930 {
931 // closing was vetoed
932 }
933 }
934}
935
937 const uno::Reference< uno::XInterface > & xModel )
938{
939 bool bReleaseModel = false;
940 {
941 ::osl::Guard< ::osl::Mutex > aGuard( m_aModelMutex );
943 {
944 m_aModel = nullptr;
945 m_xUndoManager.clear();
946 bReleaseModel = true;
947 }
948 }
949 if( bReleaseModel )
950 {
953 }
954 return bReleaseModel;
955}
956
957// util::XEventListener (base of XCloseListener)
959 const lang::EventObject& rSource )
960{
961 if( !impl_releaseThisModel( rSource.Source ))
962 {
963 if( rSource.Source == m_xLayoutManagerEventBroadcaster )
965 }
966}
967
969 const lang::EventObject& aSource,
970 sal_Int16 eLayoutEvent,
971 const uno::Any& /* aInfo */ )
972{
973 if( eLayoutEvent == frame::LayoutManagerEvents::MERGEDMENUBAR )
974 {
975 Reference< frame::XLayoutManager > xLM( aSource.Source, uno::UNO_QUERY );
976 if( xLM.is())
977 {
978 xLM->createElement( "private:resource/statusbar/statusbar" );
979 xLM->requestElement( "private:resource/statusbar/statusbar" );
980 }
981 }
982}
983
984// XDispatchProvider (required interface)
985
986namespace
987{
988
989bool lcl_isFormatObjectCommand( std::u16string_view aCommand )
990{
991 return aCommand == u"MainTitle"
992 || aCommand == u"SubTitle"
993 || aCommand == u"XTitle"
994 || aCommand == u"YTitle"
995 || aCommand == u"ZTitle"
996 || aCommand == u"SecondaryXTitle"
997 || aCommand == u"SecondaryYTitle"
998 || aCommand == u"AllTitles"
999 || aCommand == u"DiagramAxisX"
1000 || aCommand == u"DiagramAxisY"
1001 || aCommand == u"DiagramAxisZ"
1002 || aCommand == u"DiagramAxisA"
1003 || aCommand == u"DiagramAxisB"
1004 || aCommand == u"DiagramAxisAll"
1005 || aCommand == u"DiagramGridXMain"
1006 || aCommand == u"DiagramGridYMain"
1007 || aCommand == u"DiagramGridZMain"
1008 || aCommand == u"DiagramGridXHelp"
1009 || aCommand == u"DiagramGridYHelp"
1010 || aCommand == u"DiagramGridZHelp"
1011 || aCommand == u"DiagramGridAll"
1012
1013 || aCommand == u"DiagramWall"
1014 || aCommand == u"DiagramFloor"
1015 || aCommand == u"DiagramArea"
1016 || aCommand == u"Legend"
1017
1018 || aCommand == u"FormatWall"
1019 || aCommand == u"FormatFloor"
1020 || aCommand == u"FormatChartArea"
1021 || aCommand == u"FormatLegend"
1022
1023 || aCommand == u"FormatTitle"
1024 || aCommand == u"FormatAxis"
1025 || aCommand == u"FormatDataSeries"
1026 || aCommand == u"FormatDataPoint"
1027 || aCommand == u"FormatDataLabels"
1028 || aCommand == u"FormatDataLabel"
1029 || aCommand == u"FormatXErrorBars"
1030 || aCommand == u"FormatYErrorBars"
1031 || aCommand == u"FormatMeanValue"
1032 || aCommand == u"FormatTrendline"
1033 || aCommand == u"FormatTrendlineEquation"
1034 || aCommand == u"FormatStockLoss"
1035 || aCommand == u"FormatStockGain"
1036 || aCommand == u"FormatMajorGrid"
1037 || aCommand == u"FormatMinorGrid";
1038}
1039
1040} // anonymous namespace
1041
1042uno::Reference<frame::XDispatch> SAL_CALL
1044 const util::URL& rURL,
1045 const OUString& rTargetFrameName,
1046 sal_Int32 /* nSearchFlags */)
1047{
1048 SolarMutexGuard aGuard;
1049
1050 if ( !m_aLifeTimeManager.impl_isDisposed() && getModel().is() )
1051 {
1052 if( !rTargetFrameName.isEmpty() && rTargetFrameName == "_self" )
1054 }
1056}
1057
1061{
1063
1064 if ( !m_aLifeTimeManager.impl_isDisposed() )
1065 {
1066 return m_aDispatchContainer.getDispatchesForURLs( xDescripts );
1067 }
1069}
1070
1071// frame::XDispatch
1072
1074 const util::URL& rURL,
1076{
1077 OUString aCommand = rURL.Path;
1078
1079 if(aCommand == "LOKSetTextSelection")
1080 {
1081 if (rArgs.getLength() == 3)
1082 {
1083 sal_Int32 nType = -1;
1084 rArgs[0].Value >>= nType;
1085 sal_Int32 nX = 0;
1086 rArgs[1].Value >>= nX;
1087 sal_Int32 nY = 0;
1088 rArgs[2].Value >>= nY;
1090 }
1091 }
1092 else if (aCommand == "LOKTransform")
1093 {
1094 if (rArgs[0].Name == "Action")
1095 {
1096 OUString sAction;
1097 if ((rArgs[0].Value >>= sAction) && sAction == "PieSegmentDragging")
1098 {
1099 if (rArgs[1].Name == "Offset")
1100 {
1101 sal_Int32 nOffset;
1102 if (rArgs[1].Value >>= nOffset)
1103 {
1105 }
1106 }
1107 }
1108 }
1109 else
1110 {
1111 this->executeDispatch_PositionAndSize(&rArgs);
1112 }
1113 }
1114 else if(aCommand == "FillColor")
1115 {
1116 if (rArgs.getLength() > 0)
1117 {
1118 sal_uInt32 nColor;
1119 if (rArgs[0].Value >>= nColor)
1120 this->executeDispatch_FillColor(nColor);
1121 }
1122 }
1123 else if(aCommand == "XLineColor")
1124 {
1125 if (rArgs.getLength() > 0)
1126 {
1127 sal_Int32 nColor = -1;
1128 rArgs[0].Value >>= nColor;
1129 this->executeDispatch_LineColor(nColor);
1130 }
1131 }
1132 else if(aCommand == "LineWidth")
1133 {
1134 if (rArgs.getLength() > 0)
1135 {
1136 sal_Int32 nWidth = -1;
1137 rArgs[0].Value >>= nWidth;
1138 this->executeDispatch_LineWidth(nWidth);
1139 }
1140 }
1141 else if(aCommand.startsWith("FillGradient"))
1142 {
1143 this->executeDispatch_FillGradient(aCommand.subView(aCommand.indexOf('=') + 1));
1144 }
1145 else if(aCommand == "Paste")
1146 this->executeDispatch_Paste();
1147 else if(aCommand == "Copy" )
1148 this->executeDispatch_Copy();
1149 else if(aCommand == "Cut" )
1150 this->executeDispatch_Cut();
1151 else if(aCommand == "DataRanges" )
1153 else if(aCommand == "Update" ) //Update Chart
1154 {
1156 SolarMutexGuard aGuard;
1157 auto pChartWindow(GetChartWindow());
1158 if( pChartWindow )
1159 pChartWindow->Invalidate();
1160 }
1161 else if(aCommand == "DiagramData" )
1163 //insert objects
1164 else if( aCommand == "InsertTitles"
1165 || aCommand == "InsertMenuTitles")
1167 else if( aCommand == "InsertMenuLegend" )
1169 else if( aCommand == "InsertLegend" )
1171 else if( aCommand == "DeleteLegend" )
1173 else if( aCommand == "InsertMenuDataLabels" )
1175 else if( aCommand == "InsertMenuAxes"
1176 || aCommand == "InsertRemoveAxes" )
1178 else if( aCommand == "InsertMenuGrids" )
1180 else if( aCommand == "InsertMenuTrendlines" )
1182 else if( aCommand == "InsertMenuMeanValues" )
1184 else if( aCommand == "InsertMenuXErrorBars" )
1186 else if( aCommand == "InsertMenuYErrorBars" )
1188 else if( aCommand == "InsertMenuDataTable" )
1190 else if( aCommand == "InsertSymbol" )
1192 else if( aCommand == "InsertTrendline" )
1194 else if( aCommand == "DeleteTrendline" )
1196 else if( aCommand == "InsertMeanValue" )
1198 else if( aCommand == "DeleteMeanValue" )
1200 else if( aCommand == "InsertXErrorBars" )
1202 else if( aCommand == "InsertYErrorBars" )
1204 else if( aCommand == "DeleteXErrorBars" )
1206 else if( aCommand == "DeleteYErrorBars" )
1208 else if( aCommand == "InsertTrendlineEquation" )
1210 else if( aCommand == "DeleteTrendlineEquation" )
1212 else if( aCommand == "InsertTrendlineEquationAndR2" )
1214 else if( aCommand == "InsertR2Value" )
1216 else if( aCommand == "DeleteR2Value")
1218 else if( aCommand == "InsertDataLabels" )
1220 else if( aCommand == "InsertDataLabel" )
1222 else if( aCommand == "DeleteDataLabels")
1224 else if( aCommand == "DeleteDataLabel" )
1226 else if( aCommand == "ResetAllDataPoints" )
1228 else if( aCommand == "ResetDataPoint" )
1230 else if( aCommand == "InsertAxis" )
1232 else if( aCommand == "InsertMajorGrid" )
1234 else if( aCommand == "InsertMinorGrid" )
1236 else if( aCommand == "InsertAxisTitle" )
1238 else if( aCommand == "DeleteAxis" )
1240 else if( aCommand == "DeleteMajorGrid")
1242 else if( aCommand == "DeleteMinorGrid" )
1244 else if( aCommand == "InsertDataTable" )
1246 else if( aCommand == "DeleteDataTable" )
1248 //format objects
1249 else if( aCommand == "FormatSelection" )
1251 else if( aCommand == "TransformDialog" )
1252 {
1253 if ( isShapeContext() )
1254 {
1255 this->impl_ShapeControllerDispatch( rURL, rArgs );
1256 }
1257 else
1258 {
1260 }
1261 }
1262 else if( lcl_isFormatObjectCommand(aCommand) )
1263 this->executeDispatch_FormatObject(rURL.Path);
1264 //more format
1265 else if( aCommand == "DiagramType" )
1267 else if( aCommand == "View3D" )
1268 this->executeDispatch_View3D();
1269 else if ( aCommand == "Forward" )
1270 {
1271 if ( isShapeContext() )
1272 {
1273 this->impl_ShapeControllerDispatch( rURL, rArgs );
1274 }
1275 else
1276 {
1277 this->executeDispatch_MoveSeries( true );
1278 }
1279 }
1280 else if ( aCommand == "Backward" )
1281 {
1282 if ( isShapeContext() )
1283 {
1284 this->impl_ShapeControllerDispatch( rURL, rArgs );
1285 }
1286 else
1287 {
1288 this->executeDispatch_MoveSeries( false );
1289 }
1290 }
1291 else if( aCommand == "NewArrangement")
1293 else if( aCommand == "ToggleLegend" )
1295 else if( aCommand == "ToggleGridHorizontal" )
1297 else if( aCommand == "ToggleGridVertical" )
1299 else if( aCommand == "ScaleText" )
1301 else if( aCommand == "StatusBarVisible" )
1302 {
1303 // workaround: this should not be necessary.
1304 uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY );
1305 if( xPropSet.is() )
1306 {
1308 xPropSet->getPropertyValue( "LayoutManager" ) >>= xLayoutManager;
1309 if ( xLayoutManager.is() )
1310 {
1311 bool bIsVisible( xLayoutManager->isElementVisible( "private:resource/statusbar/statusbar" ));
1312 if( bIsVisible )
1313 {
1314 xLayoutManager->hideElement( "private:resource/statusbar/statusbar" );
1315 xLayoutManager->destroyElement( "private:resource/statusbar/statusbar" );
1316 }
1317 else
1318 {
1319 xLayoutManager->createElement( "private:resource/statusbar/statusbar" );
1320 xLayoutManager->showElement( "private:resource/statusbar/statusbar" );
1321 }
1322 // @todo: update menu state (checkmark next to "Statusbar").
1323 }
1324 }
1325 }
1326}
1327
1329 const uno::Reference<frame::XStatusListener >& /* xControl */,
1330 const util::URL& /* aURL */ )
1331{
1332 //@todo
1333}
1334
1336 const uno::Reference<frame::XStatusListener >& /* xControl */,
1337 const util::URL& /* aURL */ )
1338{
1339 //@todo
1340}
1341
1342// XContextMenuInterception (optional interface)
1344 const uno::Reference< ui::XContextMenuInterceptor >& /* xInterceptor */)
1345{
1346 //@todo
1347}
1348
1350 const uno::Reference< ui::XContextMenuInterceptor > & /* xInterceptor */)
1351{
1352 //@todo
1353}
1354
1355// ____ XEmbeddedClient ____
1356// implementation see: ChartController_EditData.cxx
1357
1359{
1360 UndoLiveUpdateGuard aUndoGuard(
1361 SchResId( STR_ACTION_EDIT_CHARTTYPE ), m_xUndoManager );
1362
1363 SolarMutexGuard aSolarGuard;
1364 //prepare and open dialog
1366 if (aDlg.run() == RET_OK)
1367 {
1369 aUndoGuard.commit();
1370 }
1371}
1372
1374{
1375 //convert properties to ItemSet
1377 OSL_ENSURE( xChartDoc.is(), "Invalid XChartDocument" );
1378 if( !xChartDoc.is() )
1379 return;
1380
1381 // If there is a data table we should ask user if we really want to destroy it
1382 // and switch to data ranges.
1383 ChartModel& rModel = *xChartDoc;
1384 if ( rModel.hasInternalDataProvider() )
1385 {
1386 // Check if we will able to create data provider later
1387 css::uno::Reference< com::sun::star::chart2::XDataProviderAccess > xCreatorDoc(
1388 rModel.getParent(), uno::UNO_QUERY);
1389 if (!xCreatorDoc.is())
1390 return;
1391
1392 SolarMutexGuard aSolarGuard;
1393
1394 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetChartFrame(),
1395 VclMessageType::Question, VclButtonsType::YesNo, SchResId(STR_DLG_REMOVE_DATA_TABLE)));
1396 // If "No" then just return
1397 if (xQueryBox->run() == RET_NO)
1398 return;
1399
1400 // Remove data table
1401 rModel.removeDataProviders();
1402
1403 // Ask parent document to create new data provider
1404
1405 uno::Reference< data::XDataProvider > xDataProvider = xCreatorDoc->createDataProvider();
1406 SAL_WARN_IF( !xDataProvider.is(), "chart2.main", "Data provider was not created" );
1407 if (xDataProvider.is())
1408 {
1409 rModel.attachDataProvider(xDataProvider);
1410 }
1411 }
1412
1413 UndoLiveUpdateGuard aUndoGuard(
1414 SchResId(STR_ACTION_EDIT_DATA_RANGES), m_xUndoManager);
1415
1416 SolarMutexGuard aSolarGuard;
1417 ::chart::DataSourceDialog aDlg(GetChartFrame(), xChartDoc);
1418 if (aDlg.run() == RET_OK)
1419 {
1421 aUndoGuard.commit();
1422 }
1423}
1424
1426{
1428
1429 //get selected series
1430 OUString aObjectCID(m_aSelection.getSelectedCID());
1431 rtl::Reference< DataSeries > xGivenDataSeries = ObjectIdentifier::getDataSeriesForCID( //yyy todo also legend entries and labels?
1432 aObjectCID, getChartModel() );
1433
1434 UndoGuardWithSelection aUndoGuard(
1437 SchResId(STR_OBJECT_DATASERIES)),
1439
1440 bool bChanged = getFirstDiagram()->moveSeries( xGivenDataSeries, bForward );
1441 if( bChanged )
1442 {
1444 aUndoGuard.commit();
1445 }
1446}
1447
1448// ____ XMultiServiceFactory ____
1450 ChartController::createInstance( const OUString& aServiceSpecifier )
1451{
1453
1454#if !ENABLE_WASM_STRIP_ACCESSIBILITY
1455 if( aServiceSpecifier == CHART_ACCESSIBLE_TEXT_SERVICE_NAME )
1456 xResult.set( impl_createAccessibleTextContext());
1457#else
1458 (void)aServiceSpecifier;
1459#endif
1460
1461 return xResult;
1462}
1463
1466 const OUString& ServiceSpecifier,
1467 const uno::Sequence< uno::Any >& /* Arguments */ )
1468{
1469 // ignore Arguments
1470 return createInstance( ServiceSpecifier );
1471}
1472
1475{
1477 return aServiceNames;
1478}
1479
1480// ____ XModifyListener ____
1482 const lang::EventObject& /* aEvent */ )
1483{
1484 // the source can also be a subobject of the ChartModel
1485 // @todo: change the source in ChartModel to always be the model itself ?
1486 //todo? update menu states ?
1487}
1488
1489void ChartController::NotifyUndoActionHdl( std::unique_ptr<SdrUndoAction> pUndoAction )
1490{
1491 ENSURE_OR_RETURN_VOID( pUndoAction, "invalid Undo action" );
1492
1493 OUString aObjectCID = m_aSelection.getSelectedCID();
1494 if ( !aObjectCID.isEmpty() )
1495 return;
1496
1497 try
1498 {
1500 const Reference< document::XUndoManager > xUndoManager( xSuppUndo->getUndoManager(), uno::UNO_SET_THROW );
1501 const Reference< document::XUndoAction > xAction( new impl::ShapeUndoElement( std::move(pUndoAction) ) );
1502 xUndoManager->addUndoAction( xAction );
1503 }
1504 catch( const uno::Exception& )
1505 {
1506 DBG_UNHANDLED_EXCEPTION("chart2");
1507 }
1508}
1509
1511{
1512 if( !m_pDrawModelWrapper )
1513 {
1514 if( m_xChartView )
1515 m_pDrawModelWrapper = m_xChartView->getDrawModelWrapper();
1516 if ( m_pDrawModelWrapper )
1517 {
1518 m_pDrawModelWrapper->getSdrModel().SetNotifyUndoActionHdl(
1519 std::bind(&ChartController::NotifyUndoActionHdl, this, std::placeholders::_1) );
1520 }
1521 }
1522 return m_pDrawModelWrapper.get();
1523}
1524
1526{
1527 if ( !m_pDrawViewWrapper )
1528 {
1530 }
1531 return m_pDrawViewWrapper.get();
1532}
1533
1534
1536{
1537 // clients getting the naked VCL Window from UNO should always have the
1538 // solar mutex (and keep it over the lifetime of this ptr), as VCL might
1539 // might deinit otherwise
1541 if(!m_xViewWindow.is())
1542 return nullptr;
1543 return dynamic_cast<ChartWindow*>(VCLUnoHelper::GetWindow(m_xViewWindow));
1544}
1545
1547{
1548 // clients getting the naked VCL Window from UNO should always have the
1549 // solar mutex (and keep it over the lifetime of this ptr), as VCL might
1550 // might deinit otherwise
1553}
1554
1556{
1558}
1559
1561{
1562 if(rxShape.is())
1563 {
1564 m_aSelection.setSelection(rxShape);
1566 }
1567}
1568
1569
1570
1572{
1573#if !ENABLE_WASM_STRIP_ACCESSIBILITY
1576 return xResult;
1577#else
1579#endif
1580}
1581
1583{
1584 SolarMutexGuard aGuard;
1585 auto pChartWindow(GetChartWindow());
1586 if( pChartWindow )
1587 {
1588 Reference< lang::XInitialization > xInit( pChartWindow->GetAccessible(false), uno::UNO_QUERY );
1589 if(xInit.is())
1590 {
1591 uno::Sequence< uno::Any > aArguments(3);//empty arguments -> invalid accessible
1592 xInit->initialize(aArguments);
1593 }
1594 }
1595}
1597{
1598 SolarMutexGuard aGuard;
1599 auto pChartWindow(GetChartWindow());
1600 if( pChartWindow )
1601 this->impl_initializeAccessible( Reference< lang::XInitialization >( pChartWindow->GetAccessible(false), uno::UNO_QUERY ) );
1602}
1604{
1605 if(!xInit.is())
1606 return;
1607
1609 {
1610 SolarMutexGuard aGuard;
1611 auto pChartWindow(GetChartWindow());
1612 if( pChartWindow )
1613 {
1614 vcl::Window* pParentWin( pChartWindow->GetAccessibleParentWindow());
1615 if( pParentWin )
1616 xParent.set( pParentWin->GetAccessible());
1617 }
1618 }
1619 uno::Sequence< uno::Any > aArguments{ uno::Any(uno::Reference<view::XSelectionSupplier>(this)),
1620 uno::Any(getModel()),
1621 uno::Any(uno::Reference<XInterface>(static_cast<cppu::OWeakObject*>(m_xChartView.get()))),
1622 uno::Any(xParent),
1624
1625 xInit->initialize(aArguments);
1626}
1627
1629{
1630 static const o3tl::sorted_vector< OUString > s_AvailableCommands {
1631 // commands for container forward
1632 "AddDirect", "NewDoc", "Open",
1633 "Save", "SaveAs", "SendMail",
1634 "EditDoc", "ExportDirectToPDF", "PrintDefault",
1635
1636 // own commands
1637 "Cut", "Copy", "Paste",
1638 "DataRanges", "DiagramData",
1639 // insert objects
1640 "InsertMenuTitles", "InsertTitles",
1641 "InsertMenuLegend", "InsertLegend", "DeleteLegend",
1642 "InsertMenuDataLabels",
1643 "InsertMenuAxes", "InsertRemoveAxes", "InsertMenuGrids",
1644 "InsertSymbol",
1645 "InsertTrendlineEquation", "InsertTrendlineEquationAndR2",
1646 "InsertR2Value", "DeleteR2Value",
1647 "InsertMenuTrendlines", "InsertTrendline",
1648 "InsertMenuMeanValues", "InsertMeanValue",
1649 "InsertMenuXErrorBars", "InsertXErrorBars",
1650 "InsertMenuYErrorBars", "InsertYErrorBars",
1651 "InsertDataLabels", "InsertDataLabel",
1652 "DeleteTrendline", "DeleteMeanValue", "DeleteTrendlineEquation",
1653 "DeleteXErrorBars", "DeleteYErrorBars",
1654 "DeleteDataLabels", "DeleteDataLabel",
1655 "InsertMenuDataTable",
1656 "InsertDataTable", "DeleteDataTable",
1657 //format objects
1658 "FormatSelection", "TransformDialog",
1659 "DiagramType", "View3D",
1660 "Forward", "Backward",
1661 "MainTitle", "SubTitle",
1662 "XTitle", "YTitle", "ZTitle",
1663 "SecondaryXTitle", "SecondaryYTitle",
1664 "AllTitles", "Legend",
1665 "DiagramAxisX", "DiagramAxisY", "DiagramAxisZ",
1666 "DiagramAxisA", "DiagramAxisB", "DiagramAxisAll",
1667 "DiagramGridXMain", "DiagramGridYMain", "DiagramGridZMain",
1668 "DiagramGridXHelp", "DiagramGridYHelp", "DiagramGridZHelp",
1669 "DiagramGridAll",
1670 "DiagramWall", "DiagramFloor", "DiagramArea",
1671
1672 //context menu - format objects entries
1673 "FormatWall", "FormatFloor", "FormatChartArea",
1674 "FormatLegend",
1675
1676 "FormatAxis", "FormatTitle",
1677 "FormatDataSeries", "FormatDataPoint",
1678 "ResetAllDataPoints", "ResetDataPoint",
1679 "FormatDataLabels", "FormatDataLabel",
1680 "FormatMeanValue", "FormatTrendline", "FormatTrendlineEquation",
1681 "FormatXErrorBars", "FormatYErrorBars",
1682 "FormatStockLoss", "FormatStockGain",
1683
1684 "FormatMajorGrid", "InsertMajorGrid", "DeleteMajorGrid",
1685 "FormatMinorGrid", "InsertMinorGrid", "DeleteMinorGrid",
1686 "InsertAxis", "DeleteAxis", "InsertAxisTitle",
1687
1688 // toolbar commands
1689 "ToggleGridHorizontal", "ToggleGridVertical", "ToggleLegend", "ScaleText",
1690 "NewArrangement", "Update",
1691 "DefaultColors", "BarWidth", "NumberOfLines",
1692 "ArrangeRow",
1693 "StatusBarVisible",
1694 "ChartElementSelector"};
1695 return s_AvailableCommands;
1696}
1697
1699{
1701}
1702
1703} //namespace chart
1704
1705extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1707 css::uno::Sequence<css::uno::Any> const &)
1708{
1709 return cppu::acquire(new chart::ChartController(context));
1710}
1711
1712/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_chart2_ChartController_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
AnyEventRef aEvent
static OUString createDescription(ActionType eActionType, std::u16string_view rObjectName)
static bool GetLayoutRTL()
static weld::Window * GetFrameWeld(const css::uno::Reference< css::awt::XWindow > &rWindow)
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
static VclPtr< reference_type > Create(Arg &&... arg)
rtl::Reference< TheModel > m_xTheModel
TheModelRef(TheModel *pTheModel, ::osl::Mutex &rMutex)
TheModelRef & operator=(ChartController::TheModel *pTheModel)
const rtl::Reference<::chart::ChartModel > & getModel() const
TheModel(rtl::Reference<::chart::ChartModel > xModel)
void removeListener(ChartController *pController)
void addListener(ChartController *pController)
virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches(const css::uno::Sequence< css::frame::DispatchDescriptor > &xDescripts) override
virtual sal_Bool SAL_CALL suspend(sal_Bool bSuspend) override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
void executeDispatch_LineColor(sal_uInt32 nColor)
void executeDispatch_DeleteErrorBars(bool bYError)
rtl::Reference<::chart::ChartModel > getChartModel()
css::uno::Reference< css::accessibility::XAccessible > CreateAccessible()
virtual void SAL_CALL restoreViewData(const css::uno::Any &rValue) override
virtual css::uno::Any SAL_CALL getViewData() override
void executeDispatch_MoveSeries(bool bForward)
virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch(const css::util::URL &rURL, const OUString &rTargetFrameName, sal_Int32 nSearchFlags) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual css::uno::Reference< css::awt::XWindow > SAL_CALL getComponentWindow() override
void executeDispatch_FillGradient(std::u16string_view sJSONGradient)
std::unique_ptr< DrawViewWrapper > m_pDrawViewWrapper
css::uno::Reference< css::awt::XWindow > m_xViewWindow
css::uno::Reference< css::document::XUndoManager > m_xUndoManager
void executeDispatch_LOKPieSegmentDragging(int nOffset)
virtual void SAL_CALL dispatch(const css::util::URL &aURL, const css::uno::Sequence< css::beans::PropertyValue > &aArgs) override
void executeDispatch_FillColor(sal_uInt32 nColor)
DrawViewWrapper * GetDrawViewWrapper()
std::unique_ptr< DropTargetHelper > m_apDropTargetHelper
bool isAdditionalShapeSelected() const
void executeDispatch_LOKSetTextSelection(int nType, int nX, int nY)
ChartWindow * GetChartWindow() const
bool impl_isDisposedOrSuspended() const
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(const OUString &ServiceSpecifier, const css::uno::Sequence< css::uno::Any > &Arguments) override
virtual css::uno::Reference< css::ui::XSidebarProvider > SAL_CALL getSidebar() override
virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener > &xControl, const css::util::URL &aURL) override
std::shared_ptr< DrawModelWrapper > m_pDrawModelWrapper
mutable::osl::Mutex m_aModelMutex
virtual void SAL_CALL modeChanged(const css::util::ModeChangeEvent &_rSource) override
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
rtl::Reference<::chart::ChartView > m_xChartView
bool impl_releaseThisModel(const css::uno::Reference< css::uno::XInterface > &xModel)
virtual sal_Bool SAL_CALL attachModel(const css::uno::Reference< css::frame::XModel > &xModel) override
weld::Window * GetChartFrame()
virtual void SAL_CALL registerContextMenuInterceptor(const css::uno::Reference< css::ui::XContextMenuInterceptor > &xInterceptor) override
virtual void SAL_CALL queryClosing(const css::lang::EventObject &Source, sal_Bool GetsOwnership) override
virtual OUString SAL_CALL getViewControllerName() override
virtual void SAL_CALL notifyClosing(const css::lang::EventObject &Source) override
virtual css::uno::Any SAL_CALL getSelection() override
virtual void SAL_CALL layoutEvent(const css::lang::EventObject &aSource, ::sal_Int16 eLayoutEvent, const css::uno::Any &aInfo) override
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(const OUString &aServiceSpecifier) override
mutable::apphelper::LifeTimeManager m_aLifeTimeManager
virtual void SAL_CALL dispose() override
DrawModelWrapper * GetDrawModelWrapper()
virtual css::uno::Reference< css::frame::XFrame > SAL_CALL getFrame() override
virtual void SAL_CALL modified(const css::lang::EventObject &aEvent) override
void SetAndApplySelection(const css::uno::Reference< css::drawing::XShape > &rxShape)
virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getCreationArguments() override
css::uno::Reference< css::accessibility::XAccessibleContext > impl_createAccessibleTextContext()
Creates a helper accessibility class that must be initialized via XInitialization.
css::uno::Reference< css::frame::XFrame > m_xFrame
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
void executeDispatch_DeleteDataTable()
Delete a data table from the chart.
CommandDispatchContainer m_aDispatchContainer
void executeDispatch_LineWidth(sal_uInt32 nWidth)
rtl::Reference<::chart::Diagram > getFirstDiagram()
void executeDispatch_PositionAndSize(const ::css::uno::Sequence< ::css::beans::PropertyValue > *pArgs=nullptr)
rtl::Reference< svx::sidebar::SelectionChangeHandler > mpSelectionChangeHandler
virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames() override
static const o3tl::sorted_vector< OUString > & impl_getAvailableCommands()
void impl_ShapeControllerDispatch(const css::util::URL &rURL, const css::uno::Sequence< css::beans::PropertyValue > &rArgs)
virtual OUString SAL_CALL getImplementationName() override
virtual void SAL_CALL attachFrame(const css::uno::Reference< css::frame::XFrame > &xFrame) override
css::uno::Reference< css::frame::XLayoutManagerEventBroadcaster > m_xLayoutManagerEventBroadcaster
void executeDispatch_FormatObject(std::u16string_view rDispatchCommand)
virtual css::uno::Reference< css::frame::XModel > SAL_CALL getModel() override
virtual ~ChartController() override
void executeDispatch_InsertDataTable()
Create and insert a data table to the chart.
virtual void SAL_CALL releaseContextMenuInterceptor(const css::uno::Reference< css::ui::XContextMenuInterceptor > &xInterceptor) override
void NotifyUndoActionHdl(std::unique_ptr< SdrUndoAction >)
css::uno::Reference< css::uno::XComponentContext > m_xCC
void executeDispatch_InsertErrorBars(bool bYError)
virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener > &xControl, const css::util::URL &aURL) override
void executeDispatch_InsertTrendlineEquation(bool bInsertR2=false)
ViewElementListProvider getViewElementListProvider()
static void triggerRangeHighlighting(const rtl::Reference<::chart::ChartModel > &xModel)
static void setViewToDirtyState(const rtl::Reference<::chart::ChartModel > &xChartModel)
The ChartView is responsible to manage the generation of Drawing Objects for visualization on a given...
Definition: ChartView.hxx:98
The ChartWindow collects events from the window and forwards them the to the controller thus the cont...
Definition: ChartWindow.hxx:33
void setModel(const rtl::Reference<::chart::ChartModel > &xModel)
void setDrawCommandDispatch(DrawCommandDispatch *pDispatch)
css::uno::Reference< css::frame::XDispatch > getDispatchForURL(const css::util::URL &rURL)
Returns the dispatch that is able to do the command given in rURL, if implemented here.
css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > getDispatchesForURLs(const css::uno::Sequence< css::frame::DispatchDescriptor > &aDescriptors)
void setShapeController(ShapeController *pController)
void setChartDispatch(const css::uno::Reference< css::frame::XDispatch > &rChartDispatch, o3tl::sorted_vector< OUString > &&rChartCommands)
Set a chart dispatcher that is used for all commands contained in rChartCommands.
This class is a CommandDispatch that is responsible for all commands that the ChartController support...
This guard calls lockControllers at the given Model in the CTOR and unlockControllers in the DTOR.
virtual short run() override
This is a CommandDispatch implementation for drawing objects.
static rtl::Reference< ::chart::DataSeries > getDataSeriesForCID(std::u16string_view rObjectCID, const rtl::Reference<::chart::ChartModel > &xChartModel)
static OUString getMovedSeriesCID(std::u16string_view rObjectCID, bool bForward)
ObjectType getObjectType() const
bool hasSelection() const
bool isAdditionalShapeSelected() const
OUString const & getSelectedCID() const
void applySelection(DrawViewWrapper *pDrawViewWrapper)
bool setSelection(const OUString &rCID)
This is a CommandDispatch implementation for shapes.
A guard which, in its destructor, restores the model state it found in the constructor.
Definition: UndoGuard.hxx:68
WinBits GetStyle() const
virtual short run()
#define DBG_TESTSOLARMUTEX()
#define DBG_UNHANDLED_EXCEPTION(...)
#define ENSURE_OR_RETURN_VOID(c, m)
Reference< frame::XModel > m_xModel
float u
Sequence< OUString > aServiceNames
bool m_bDisposed
Sequence< PropertyValue > aArguments
#define SAL_WARN_IF(condition, area, stream)
@ CHARTDRAW_SELECT
@ OBJECTTYPE_DATA_SERIES
@ OBJECTTYPE_DIAGRAM
@ OBJECTTYPE_DATA_ERRORS_X
@ OBJECTTYPE_DATA_ERRORS_Y
@ OBJECTTYPE_DATA_AVERAGE_LINE
@ OBJECTTYPE_DATA_ERRORS_Z
@ OBJECTTYPE_DATA_CURVE
OUString OOO_DLLPUBLIC_CHARTTOOLS SchResId(TranslateId aId)
Definition: ResId.cxx:24
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Value
QPRO_FUNC_TYPE nType
constexpr OUStringLiteral CHART_VIEW_SERVICE_NAME
constexpr OUStringLiteral CHART_CONTROLLER_SERVICE_NAME
constexpr OUStringLiteral CHART_ACCESSIBLE_TEXT_SERVICE_NAME
constexpr OUStringLiteral CHART_CONTROLLER_SERVICE_IMPLEMENTATION_NAME
bool hasValue()
Reference< XController > xController
Reference< XFrame > xFrame
Reference< XModel > xModel
OUString aCommand
OUString Name
unsigned char sal_Bool
RET_OK
RET_NO