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 "ControllerCommandDispatch.hxx"
21 #include <ChartModelHelper.hxx>
22 #include <ChartModel.hxx>
23 #include <DiagramHelper.hxx>
24 #include <AxisHelper.hxx>
25 #include <TitleHelper.hxx>
26 #include <LegendHelper.hxx>
27 #include <ObjectIdentifier.hxx>
28 #include <ChartTypeHelper.hxx>
29 #include <ChartController.hxx>
30 #include <RegressionCurveHelper.hxx>
31 #include <DataSeriesHelper.hxx>
32 #include <StatisticsHelper.hxx>
33 #include <ReferenceSizeProvider.hxx>
34 #include "ShapeController.hxx"
35 
36 #include <vcl/svapp.hxx>
37 #include <sal/log.hxx>
38 #include <tools/diagnose_ex.h>
39 
40 #include <com/sun/star/util/XModifyBroadcaster.hpp>
41 #include <com/sun/star/frame/XStorable.hpp>
42 #include <com/sun/star/chart2/XChartDocument.hpp>
43 #include <com/sun/star/chart2/XRegressionCurve.hpp>
44 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
45 #include <com/sun/star/chart2/XDataProviderAccess.hpp>
46 
47 // only needed until #i68864# is fixed
48 #include <com/sun/star/frame/XLayoutManager.hpp>
49 
50 using namespace ::com::sun::star;
51 
52 using ::com::sun::star::uno::Reference;
53 using ::com::sun::star::uno::Sequence;
54 
55 namespace
56 {
lcl_isStatusBarVisible(const Reference<frame::XController> & xController)57 bool lcl_isStatusBarVisible( const Reference< frame::XController > & xController )
58 {
59     bool bIsStatusBarVisible = false;
60     // Status-Bar visible, workaround: this should not be necessary. @todo:
61     // remove when Issue #i68864# is fixed
62     if( xController.is())
63     {
64         Reference< beans::XPropertySet > xPropSet( xController->getFrame(), uno::UNO_QUERY );
65         if( xPropSet.is() )
66         {
67             uno::Reference< css::frame::XLayoutManager > xLayoutManager;
68             xPropSet->getPropertyValue( "LayoutManager" ) >>= xLayoutManager;
69             if ( xLayoutManager.is() )
70                 bIsStatusBarVisible = xLayoutManager->isElementVisible( "private:resource/statusbar/statusbar" );
71         }
72     }
73     return bIsStatusBarVisible;
74 }
75 
76 } // anonymous namespace
77 
78 namespace chart
79 {
80 
81 namespace impl
82 {
83 
84 /// Constants for moving the series.
85 namespace {
86     static bool const MOVE_SERIES_FORWARD = true;
87     static bool const MOVE_SERIES_BACKWARD = false;
88 }
89 
90 /** Represents the current state of the controller (needed for issue 63017).
91 
92     You can set the state by calling update().  After this call the state is
93     preserved in this class until the next call to update().
94 
95     This is useful, not to say necessary, for enabling and disabling of menu
96     entries (e.g. format>arrangement). As the status requests are sent very
97     frequently it would be impossible, from a performance point of view, to
98     query the current status every time directly at the model.  So this class
99     serves as a cache for the state.
100 */
101 struct ControllerState
102 {
103     ControllerState();
104 
105     void update( const Reference< frame::XController > & xController,
106                  const Reference< frame::XModel > & xModel );
107 
108     // -- State variables -------
109     bool bHasSelectedObject;
110     bool bIsPositionableObject;
111     bool bIsTextObject;
112     bool bIsDeleteableObjectSelected;
113     bool bIsFormateableObjectSelected;
114 
115     // May the selected series be moved forward or backward (cf
116     // format>arrangement).
117     bool bMayMoveSeriesForward;
118     bool bMayMoveSeriesBackward;
119 
120     // trendlines
121     bool bMayAddMenuTrendline;
122     bool bMayAddTrendline;
123     bool bMayAddTrendlineEquation;
124     bool bMayAddR2Value;
125     bool bMayAddMeanValue;
126     bool bMayAddXErrorBars;
127     bool bMayAddYErrorBars;
128 
129     bool bMayDeleteTrendline;
130     bool bMayDeleteTrendlineEquation;
131     bool bMayDeleteR2Value;
132     bool bMayDeleteMeanValue;
133     bool bMayDeleteXErrorBars;
134     bool bMayDeleteYErrorBars;
135 
136     bool bMayFormatTrendline;
137     bool bMayFormatTrendlineEquation;
138     bool bMayFormatMeanValue;
139     bool bMayFormatXErrorBars;
140     bool bMayFormatYErrorBars;
141 };
142 
ControllerState()143 ControllerState::ControllerState() :
144         bHasSelectedObject( false ),
145         bIsPositionableObject( false ),
146         bIsTextObject(false),
147         bIsDeleteableObjectSelected(false),
148         bIsFormateableObjectSelected(false),
149         bMayMoveSeriesForward( false ),
150         bMayMoveSeriesBackward( false ),
151         bMayAddMenuTrendline( false ),
152         bMayAddTrendline( false ),
153         bMayAddTrendlineEquation( false ),
154         bMayAddR2Value( false ),
155         bMayAddMeanValue( false ),
156         bMayAddXErrorBars( false ),
157         bMayAddYErrorBars( false ),
158         bMayDeleteTrendline( false ),
159         bMayDeleteTrendlineEquation( false ),
160         bMayDeleteR2Value( false ),
161         bMayDeleteMeanValue( false ),
162         bMayDeleteXErrorBars( false ),
163         bMayDeleteYErrorBars( false ),
164         bMayFormatTrendline( false ),
165         bMayFormatTrendlineEquation( false ),
166         bMayFormatMeanValue( false ),
167         bMayFormatXErrorBars( false ),
168         bMayFormatYErrorBars( false )
169 {}
170 
update(const Reference<frame::XController> & xController,const Reference<frame::XModel> & xModel)171 void ControllerState::update(
172     const Reference< frame::XController > & xController,
173     const Reference< frame::XModel > & xModel )
174 {
175     Reference< view::XSelectionSupplier > xSelectionSupplier(
176         xController, uno::UNO_QUERY );
177 
178     // Update ControllerState variables.
179     if( xSelectionSupplier.is())
180     {
181         uno::Any aSelObj( xSelectionSupplier->getSelection() );
182         ObjectIdentifier aSelOID( aSelObj );
183         OUString aSelObjCID( aSelOID.getObjectCID() );
184 
185         bHasSelectedObject = aSelOID.isValid();
186 
187         ObjectType aObjectType(ObjectIdentifier::getObjectType( aSelObjCID ));
188 
189         bIsPositionableObject = (aObjectType != OBJECTTYPE_DATA_POINT) && aSelOID.isDragableObject();
190         bIsTextObject = aObjectType == OBJECTTYPE_TITLE;
191 
192         uno::Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel ));
193         bIsFormateableObjectSelected = bHasSelectedObject && aSelOID.isAutoGeneratedObject();
194         if( aObjectType==OBJECTTYPE_DIAGRAM || aObjectType==OBJECTTYPE_DIAGRAM_WALL || aObjectType==OBJECTTYPE_DIAGRAM_FLOOR )
195             bIsFormateableObjectSelected = DiagramHelper::isSupportingFloorAndWall( xDiagram );
196 
197         uno::Reference< chart2::XDataSeries > xGivenDataSeries(
198             ObjectIdentifier::getDataSeriesForCID(
199                 aSelObjCID, xModel ) );
200 
201         bIsDeleteableObjectSelected = ChartController::isObjectDeleteable( aSelObj );
202 
203         bMayMoveSeriesForward = (aObjectType!=OBJECTTYPE_DATA_POINT) && DiagramHelper::isSeriesMoveable(
204             ChartModelHelper::findDiagram( xModel ),
205             xGivenDataSeries,
206             MOVE_SERIES_FORWARD );
207 
208         bMayMoveSeriesBackward = (aObjectType!=OBJECTTYPE_DATA_POINT) && DiagramHelper::isSeriesMoveable(
209             ChartModelHelper::findDiagram( xModel ),
210             xGivenDataSeries,
211             MOVE_SERIES_BACKWARD );
212 
213         bMayAddMenuTrendline = false;
214         bMayAddTrendline = false;
215         bMayAddTrendlineEquation = false;
216         bMayAddR2Value = false;
217         bMayAddMeanValue = false;
218         bMayAddXErrorBars = false;
219         bMayAddYErrorBars = false;
220         bMayDeleteTrendline = false;
221         bMayDeleteTrendlineEquation = false;
222         bMayDeleteR2Value = false;
223         bMayDeleteMeanValue = false;
224         bMayDeleteXErrorBars = false;
225         bMayDeleteYErrorBars = false;
226         bMayFormatTrendline = false;
227         bMayFormatTrendlineEquation = false;
228         bMayFormatMeanValue = false;
229         bMayFormatXErrorBars = false;
230         bMayFormatYErrorBars = false;
231         if( bHasSelectedObject )
232         {
233             if( xGivenDataSeries.is())
234             {
235                 bMayAddMenuTrendline = true;
236                 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
237                 uno::Reference< chart2::XChartType > xFirstChartType(
238                     DataSeriesHelper::getChartTypeOfSeries( xGivenDataSeries, xDiagram ));
239 
240                 // trend lines/mean value line
241                 if( (aObjectType == OBJECTTYPE_DATA_SERIES || aObjectType == OBJECTTYPE_DATA_POINT)
242                     && ChartTypeHelper::isSupportingRegressionProperties( xFirstChartType, nDimensionCount ))
243                 {
244                     uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( xGivenDataSeries, uno::UNO_QUERY );
245                     if( xRegCurveCnt.is())
246                     {
247                         // Trendline
248                         bMayAddTrendline = true;
249 
250                         // Mean Value
251                         bMayFormatMeanValue = bMayDeleteMeanValue = RegressionCurveHelper::hasMeanValueLine( xRegCurveCnt );
252                         bMayAddMeanValue = ! bMayDeleteMeanValue;
253                     }
254                 }
255 
256                 // error bars
257                 if( (aObjectType == OBJECTTYPE_DATA_SERIES || aObjectType == OBJECTTYPE_DATA_POINT)
258                     && ChartTypeHelper::isSupportingStatisticProperties( xFirstChartType, nDimensionCount ))
259                 {
260                     bMayFormatXErrorBars = bMayDeleteXErrorBars = StatisticsHelper::hasErrorBars( xGivenDataSeries, false );
261                     bMayAddXErrorBars = ! bMayDeleteXErrorBars;
262 
263                     bMayFormatYErrorBars = bMayDeleteYErrorBars = StatisticsHelper::hasErrorBars( xGivenDataSeries );
264                     bMayAddYErrorBars = ! bMayDeleteYErrorBars;
265                 }
266             }
267 
268             if( aObjectType == OBJECTTYPE_DATA_AVERAGE_LINE )
269                 bMayFormatMeanValue = true;
270 
271             if( aObjectType == OBJECTTYPE_DATA_ERRORS_X)
272                 bMayFormatXErrorBars = true;
273 
274             if( aObjectType == OBJECTTYPE_DATA_ERRORS_Y )
275                 bMayFormatYErrorBars = true;
276 
277             if( aObjectType == OBJECTTYPE_DATA_CURVE )
278             {
279                 bMayFormatTrendline = true;
280                 bMayDeleteTrendline = true;
281                 uno::Reference< chart2::XRegressionCurve > xRegCurve(
282                     ObjectIdentifier::getObjectPropertySet( aSelObjCID, xModel ), uno::UNO_QUERY );
283 
284                 // Trendline Equation
285                 bMayFormatTrendlineEquation = bMayDeleteTrendlineEquation = RegressionCurveHelper::hasEquation( xRegCurve );
286                 bMayAddTrendlineEquation = !bMayDeleteTrendlineEquation;
287             }
288             else if( aObjectType == OBJECTTYPE_DATA_CURVE_EQUATION )
289             {
290                 bMayFormatTrendlineEquation = true;
291                 bool bHasR2Value = false;
292                 try
293                 {
294                     uno::Reference< beans::XPropertySet > xEquationProperties =
295                         ObjectIdentifier::getObjectPropertySet( aSelObjCID, xModel );
296                     if( xEquationProperties.is() )
297                         xEquationProperties->getPropertyValue( "ShowCorrelationCoefficient" ) >>= bHasR2Value;
298                 }
299                 catch(const uno::RuntimeException&)
300                 {
301                     TOOLS_WARN_EXCEPTION("chart2", "" );
302                 }
303                 bMayAddR2Value = !bHasR2Value;
304                 bMayDeleteR2Value = bHasR2Value;
305             }
306         }
307     }
308 }
309 
310 /** Represents the current state of the model.
311 
312     You can set the state by calling update().  After this call the state is
313     preserved in this class until the next call to update().
314 
315     This is useful, not to say necessary, for enabling and disabling of menu
316     entries and toolbar icons.  As the status requests are sent very frequently
317     it would be impossible, from a performance point of view, to query the
318     current status every time directly at the model.  So this class serves as a
319     cache for the state.
320  */
321 struct ModelState
322 {
323     ModelState();
324 
325     void update( const Reference< frame::XModel > & xModel );
326 
327     bool HasAnyAxis() const;
328     bool HasAnyGrid() const;
329     bool HasAnyTitle() const;
330 
331     bool bIsReadOnly;
332     bool bIsThreeD;
333     bool bHasOwnData;
334     bool bHasDataFromPivotTable;
335 
336     bool bHasMainTitle;
337     bool bHasSubTitle;
338     bool bHasXAxisTitle;
339     bool bHasYAxisTitle;
340     bool bHasZAxisTitle;
341     bool bHasSecondaryXAxisTitle;
342     bool bHasSecondaryYAxisTitle;
343 
344     bool bHasXAxis;
345     bool bHasYAxis;
346     bool bHasZAxis;
347     bool bHasAAxis;
348     bool bHasBAxis;
349 
350     bool bHasMainXGrid;
351     bool bHasMainYGrid;
352     bool bHasMainZGrid;
353     bool bHasHelpXGrid;
354     bool bHasHelpYGrid;
355     bool bHasHelpZGrid;
356 
357     bool bHasAutoScaledText;
358     bool bHasLegend;
359     bool bHasWall;
360     bool bHasFloor;
361 
362     bool bSupportsStatistics;
363     bool bSupportsAxes;
364 };
365 
ModelState()366 ModelState::ModelState() :
367         bIsReadOnly(true),
368         bIsThreeD(false),
369         bHasOwnData(false),
370         bHasDataFromPivotTable(false),
371         bHasMainTitle(false),
372         bHasSubTitle(false),
373         bHasXAxisTitle(false),
374         bHasYAxisTitle(false),
375         bHasZAxisTitle(false),
376         bHasSecondaryXAxisTitle(false),
377         bHasSecondaryYAxisTitle(false),
378         bHasXAxis(false),
379         bHasYAxis(false),
380         bHasZAxis(false),
381         bHasAAxis(false),
382         bHasBAxis(false),
383         bHasMainXGrid(false),
384         bHasMainYGrid(false),
385         bHasMainZGrid(false),
386         bHasHelpXGrid(false),
387         bHasHelpYGrid(false),
388         bHasHelpZGrid(false),
389         bHasAutoScaledText(false),
390         bHasLegend(false),
391         bHasWall(false),
392         bHasFloor(false),
393         bSupportsStatistics(false),
394         bSupportsAxes(false)
395 {}
396 
update(const Reference<frame::XModel> & xModel)397 void ModelState::update( const Reference< frame::XModel > & xModel )
398 {
399     Reference< chart2::XChartDocument > xChartDoc( xModel, uno::UNO_QUERY );
400     Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel ));
401 
402     bIsReadOnly = true;
403     Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY );
404     if( xStorable.is())
405         bIsReadOnly = xStorable->isReadonly();
406 
407     sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
408 
409     uno::Reference< chart2::XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
410     bSupportsStatistics = ChartTypeHelper::isSupportingStatisticProperties( xFirstChartType, nDimensionCount );
411     bSupportsAxes = ChartTypeHelper::isSupportingMainAxis( xFirstChartType, nDimensionCount, 0 );
412 
413     bIsThreeD = (nDimensionCount == 3);
414     if (xChartDoc.is())
415     {
416         ChartModel& rModel = dynamic_cast<ChartModel&>(*xChartDoc);
417         bHasOwnData = rModel.hasInternalDataProvider();
418         bHasDataFromPivotTable = !bHasOwnData && rModel.isDataFromPivotTable();
419     }
420 
421     bHasMainTitle =  TitleHelper::getTitle( TitleHelper::MAIN_TITLE, xModel ).is();
422     bHasSubTitle =   TitleHelper::getTitle( TitleHelper::SUB_TITLE, xModel ).is();
423     bHasXAxisTitle = TitleHelper::getTitle( TitleHelper::X_AXIS_TITLE, xModel ).is();
424     bHasYAxisTitle = TitleHelper::getTitle( TitleHelper::Y_AXIS_TITLE, xModel ).is();
425     bHasZAxisTitle = TitleHelper::getTitle( TitleHelper::Z_AXIS_TITLE, xModel ).is();
426     bHasSecondaryXAxisTitle = TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xModel ).is();
427     bHasSecondaryYAxisTitle = TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xModel ).is();
428 
429     bHasXAxis = bSupportsAxes && AxisHelper::getAxis( 0, true, xDiagram ).is();
430     bHasYAxis = bSupportsAxes && AxisHelper::getAxis( 1, true, xDiagram ).is();
431     bHasZAxis = bSupportsAxes && AxisHelper::getAxis( 2, true, xDiagram ).is();
432     bHasAAxis = bSupportsAxes && AxisHelper::getAxis( 0, false, xDiagram ).is();
433     bHasBAxis = bSupportsAxes && AxisHelper::getAxis( 1, false, xDiagram ).is();
434 
435     bHasMainXGrid = bSupportsAxes && AxisHelper::isGridShown( 0, 0, true, xDiagram );
436     bHasMainYGrid = bSupportsAxes && AxisHelper::isGridShown( 1, 0, true, xDiagram );
437     bHasMainZGrid = bSupportsAxes && AxisHelper::isGridShown( 2, 0, true, xDiagram );
438     bHasHelpXGrid = bSupportsAxes && AxisHelper::isGridShown( 0, 0, false, xDiagram );
439     bHasHelpYGrid = bSupportsAxes && AxisHelper::isGridShown( 1, 0, false, xDiagram );
440     bHasHelpZGrid = bSupportsAxes && AxisHelper::isGridShown( 2, 0, false, xDiagram );
441 
442     bHasAutoScaledText =
443         (ReferenceSizeProvider::getAutoResizeState( xChartDoc ) ==
444          ReferenceSizeProvider::AUTO_RESIZE_YES);
445 
446     bHasLegend = LegendHelper::hasLegend( xDiagram );
447     bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram );
448     bHasFloor = bHasWall && bIsThreeD;
449 }
450 
HasAnyAxis() const451 bool ModelState::HasAnyAxis() const
452 {
453     return bHasXAxis || bHasYAxis || bHasZAxis || bHasAAxis || bHasBAxis;
454 }
455 
HasAnyGrid() const456 bool ModelState::HasAnyGrid() const
457 {
458     return bHasMainXGrid || bHasMainYGrid || bHasMainZGrid ||
459         bHasHelpXGrid || bHasHelpYGrid || bHasHelpZGrid;
460 }
461 
HasAnyTitle() const462 bool ModelState::HasAnyTitle() const
463 {
464     return bHasMainTitle || bHasSubTitle || bHasXAxisTitle || bHasYAxisTitle || bHasZAxisTitle || bHasSecondaryXAxisTitle || bHasSecondaryYAxisTitle;
465 }
466 
467 } // namespace impl
468 
ControllerCommandDispatch(const Reference<uno::XComponentContext> & xContext,ChartController * pController,CommandDispatchContainer * pContainer)469 ControllerCommandDispatch::ControllerCommandDispatch(
470     const Reference< uno::XComponentContext > & xContext,
471     ChartController* pController, CommandDispatchContainer* pContainer ) :
472         impl::ControllerCommandDispatch_Base( xContext ),
473         m_xChartController( pController ),
474         m_xSelectionSupplier( Reference< view::XSelectionSupplier >( pController ) ),
475         m_xDispatch( Reference< frame::XDispatch >( pController ) ),
476         m_apModelState( new impl::ModelState() ),
477         m_apControllerState( new impl::ControllerState() ),
478         m_pDispatchContainer( pContainer )
479 {
480 }
481 
~ControllerCommandDispatch()482 ControllerCommandDispatch::~ControllerCommandDispatch()
483 {
484 }
485 
initialize()486 void ControllerCommandDispatch::initialize()
487 {
488     if( m_xChartController.is())
489     {
490         Reference< frame::XModel > xModel( m_xChartController->getModel());
491         Reference< util::XModifyBroadcaster > xModifyBroadcaster( xModel, uno::UNO_QUERY );
492         OSL_ASSERT( xModifyBroadcaster.is());
493         if( xModifyBroadcaster.is())
494             xModifyBroadcaster->addModifyListener( this );
495 
496         // Listen selection modifications (Arrangement feature - issue 63017).
497         if( m_xSelectionSupplier.is() )
498             m_xSelectionSupplier->addSelectionChangeListener( this );
499 
500         if( m_apModelState.get() && xModel.is())
501             m_apModelState->update( xModel );
502 
503         if( m_apControllerState.get() && xModel.is())
504             m_apControllerState->update( m_xChartController.get(), xModel );
505 
506         updateCommandAvailability();
507     }
508 }
509 
fireStatusEventForURLImpl(const OUString & rURL,const Reference<frame::XStatusListener> & xSingleListener)510 void ControllerCommandDispatch::fireStatusEventForURLImpl(
511     const OUString & rURL,
512     const Reference< frame::XStatusListener > & xSingleListener )
513 {
514     std::map< OUString, uno::Any >::const_iterator aArgIt( m_aCommandArguments.find( rURL ));
515     if( aArgIt != m_aCommandArguments.end())
516         fireStatusEventForURL( rURL, aArgIt->second, commandAvailable( rURL ), xSingleListener );
517     else
518         fireStatusEventForURL( rURL, uno::Any(), commandAvailable( rURL ), xSingleListener );
519 }
520 
updateCommandAvailability()521 void ControllerCommandDispatch::updateCommandAvailability()
522 {
523     bool bModelStateIsValid = (m_apModelState != nullptr);
524     bool bControllerStateIsValid = (m_apControllerState != nullptr);
525     // Model and controller states exist.
526     OSL_ASSERT( bModelStateIsValid );
527     OSL_ASSERT( bControllerStateIsValid );
528 
529     // read-only
530     bool bIsWritable = bModelStateIsValid && (! m_apModelState->bIsReadOnly);
531     bool bShapeContext = m_xChartController.is() && m_xChartController->isShapeContext();
532 
533     bool bEnableDataTableDialog = false;
534     bool bCanCreateDataProvider = false;
535 
536     if ( m_xChartController.is() )
537     {
538         Reference< beans::XPropertySet > xProps( m_xChartController->getModel(), uno::UNO_QUERY );
539         if ( xProps.is() )
540         {
541             try
542             {
543                 xProps->getPropertyValue("EnableDataTableDialog") >>= bEnableDataTableDialog;
544             }
545             catch( const uno::Exception& )
546             {
547                 TOOLS_WARN_EXCEPTION("chart2", "" );
548             }
549         }
550 
551         Reference< chart2::XChartDocument > xChartDoc(m_xChartController->getModel(), uno::UNO_QUERY);
552         OSL_ENSURE(xChartDoc.is(), "Invalid XChartDocument");
553         if ( xChartDoc.is() )
554         {
555             ChartModel& rModel = dynamic_cast<ChartModel&>(*xChartDoc);
556             css::uno::Reference< com::sun::star::chart2::XDataProviderAccess > xCreatorDoc(rModel.getParent(), uno::UNO_QUERY);
557             bCanCreateDataProvider = xCreatorDoc.is();
558         }
559     }
560 
561     // edit commands
562     m_aCommandAvailability[ ".uno:Cut" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bIsDeleteableObjectSelected;
563     m_aCommandAvailability[ ".uno:Copy" ] = bControllerStateIsValid && m_apControllerState->bHasSelectedObject;
564     m_aCommandAvailability[ ".uno:Paste" ] = bIsWritable;
565 
566     // toolbar commands
567     m_aCommandAvailability[ ".uno:ToggleGridHorizontal" ] = bIsWritable;
568     m_aCommandArguments[ ".uno:ToggleGridHorizontal" ] <<= m_apModelState->bHasMainYGrid;
569     m_aCommandAvailability[ ".uno:ToggleGridVertical" ] = bIsWritable;
570     m_aCommandArguments[ ".uno:ToggleGridVertical" ] <<= m_apModelState->bHasMainXGrid;
571 
572     m_aCommandAvailability[ ".uno:ToggleLegend" ] = bIsWritable;
573     m_aCommandArguments[ ".uno:ToggleLegend" ] <<= m_apModelState->bHasLegend;
574 
575     m_aCommandAvailability[ ".uno:NewArrangement" ] = bIsWritable;
576     m_aCommandAvailability[ ".uno:Update" ] = bIsWritable;
577     m_aCommandAvailability[ ".uno:DefaultColors" ] = bIsWritable;
578     m_aCommandAvailability[ ".uno:BarWidth" ] = bIsWritable;
579     m_aCommandAvailability[ ".uno:NumberOfLines" ] = bIsWritable;
580     m_aCommandAvailability[ ".uno:ArrangeRow" ] =
581         bShapeContext || ( bIsWritable && bControllerStateIsValid && ( m_apControllerState->bMayMoveSeriesForward || m_apControllerState->bMayMoveSeriesBackward ) );
582 
583     // insert objects
584     m_aCommandAvailability[ ".uno:InsertTitles" ] = m_aCommandAvailability[ ".uno:InsertMenuTitles" ] = bIsWritable;
585     m_aCommandAvailability[ ".uno:InsertLegend" ] = m_aCommandAvailability[ ".uno:InsertMenuLegend" ] = bIsWritable;
586     m_aCommandAvailability[ ".uno:DeleteLegend" ] = bIsWritable;
587     m_aCommandAvailability[ ".uno:InsertMenuDataLabels" ] = bIsWritable;
588     m_aCommandAvailability[ ".uno:InsertRemoveAxes" ] = m_aCommandAvailability[ ".uno:InsertMenuAxes" ] = bIsWritable && m_apModelState->bSupportsAxes;
589     m_aCommandAvailability[ ".uno:InsertMenuGrids" ] = bIsWritable && m_apModelState->bSupportsAxes;
590     m_aCommandAvailability[ ".uno:InsertMenuTrendlines" ] = bIsWritable && m_apModelState->bSupportsStatistics && m_apControllerState->bMayAddMenuTrendline;
591     m_aCommandAvailability[ ".uno:InsertMenuMeanValues" ] = bIsWritable && m_apModelState->bSupportsStatistics;
592     m_aCommandAvailability[ ".uno:InsertMenuXErrorBars" ] = bIsWritable && m_apModelState->bSupportsStatistics;
593     m_aCommandAvailability[ ".uno:InsertMenuYErrorBars" ] = bIsWritable && m_apModelState->bSupportsStatistics;
594     m_aCommandAvailability[ ".uno:InsertSymbol" ] = bIsWritable && m_apControllerState->bIsTextObject;
595 
596     // format objects
597     bool bFormatObjectAvailable = bIsWritable && bControllerStateIsValid && m_apControllerState->bIsFormateableObjectSelected;
598     m_aCommandAvailability[ ".uno:FormatSelection" ] = bFormatObjectAvailable;
599     m_aCommandAvailability[ ".uno:FormatAxis" ] = bFormatObjectAvailable;
600     m_aCommandAvailability[ ".uno:FormatTitle" ] = bFormatObjectAvailable;
601     m_aCommandAvailability[ ".uno:FormatDataSeries" ] = bFormatObjectAvailable;
602     m_aCommandAvailability[ ".uno:FormatDataPoint" ] = bFormatObjectAvailable;
603     m_aCommandAvailability[ ".uno:FormatDataLabels" ] = bFormatObjectAvailable;
604     m_aCommandAvailability[ ".uno:FormatDataLabel" ] = bFormatObjectAvailable;
605     m_aCommandAvailability[ ".uno:FormatXErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatXErrorBars;
606     m_aCommandAvailability[ ".uno:FormatYErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatYErrorBars;
607     m_aCommandAvailability[ ".uno:FormatMeanValue" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatMeanValue;
608     m_aCommandAvailability[ ".uno:FormatTrendline" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatTrendline;
609     m_aCommandAvailability[ ".uno:FormatTrendlineEquation" ] = bFormatObjectAvailable && bControllerStateIsValid && m_apControllerState->bMayFormatTrendlineEquation;
610     m_aCommandAvailability[ ".uno:FormatStockLoss" ] = bFormatObjectAvailable;
611     m_aCommandAvailability[ ".uno:FormatStockGain" ] = bFormatObjectAvailable;
612 
613     m_aCommandAvailability[ ".uno:DiagramType" ] = bIsWritable;
614     m_aCommandAvailability[ ".uno:Legend" ] = bIsWritable && m_apModelState->bHasLegend;
615     m_aCommandAvailability[ ".uno:DiagramWall" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasWall;
616     m_aCommandAvailability[ ".uno:DiagramArea" ] = bIsWritable;
617 
618     m_aCommandAvailability[ ".uno:TransformDialog" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bHasSelectedObject && m_apControllerState->bIsPositionableObject;
619 
620     // 3d commands
621     m_aCommandAvailability[ ".uno:View3D" ] = bIsWritable && bModelStateIsValid && m_apModelState->bIsThreeD;
622     m_aCommandAvailability[ ".uno:DiagramFloor" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasFloor;
623 
624     //some more format commands with different ui text
625     m_aCommandAvailability[ ".uno:FormatWall" ] = m_aCommandAvailability[ ".uno:DiagramWall" ];
626     m_aCommandAvailability[ ".uno:FormatFloor" ] = m_aCommandAvailability[ ".uno:DiagramFloor" ];
627     m_aCommandAvailability[ ".uno:FormatChartArea" ] = m_aCommandAvailability[ ".uno:DiagramArea" ];
628     m_aCommandAvailability[ ".uno:FormatLegend" ] = m_aCommandAvailability[ ".uno:Legend" ];
629 
630     // depending on own data and ability to create new data provider
631     m_aCommandAvailability[".uno:DataRanges"] = bIsWritable && bModelStateIsValid && !m_apModelState->bHasDataFromPivotTable
632         && ((m_apModelState->bHasOwnData && bCanCreateDataProvider) || !m_apModelState->bHasOwnData);
633     m_aCommandAvailability[ ".uno:DiagramData" ] = bIsWritable && bModelStateIsValid &&  m_apModelState->bHasOwnData && bEnableDataTableDialog;
634 
635     // titles
636     m_aCommandAvailability[ ".uno:MainTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainTitle;
637     m_aCommandAvailability[ ".uno:SubTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSubTitle;
638     m_aCommandAvailability[ ".uno:XTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasXAxisTitle;
639     m_aCommandAvailability[ ".uno:YTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasYAxisTitle;
640     m_aCommandAvailability[ ".uno:ZTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasZAxisTitle;
641     m_aCommandAvailability[ ".uno:SecondaryXTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSecondaryXAxisTitle;
642     m_aCommandAvailability[ ".uno:SecondaryYTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSecondaryYAxisTitle;
643     m_aCommandAvailability[ ".uno:AllTitles" ] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyTitle();
644 
645     // text
646     m_aCommandAvailability[ ".uno:ScaleText" ] = bIsWritable && bModelStateIsValid ;
647     m_aCommandArguments[ ".uno:ScaleText" ] <<= m_apModelState->bHasAutoScaledText;
648 
649     // axes
650     m_aCommandAvailability[ ".uno:DiagramAxisX" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasXAxis;
651     m_aCommandAvailability[ ".uno:DiagramAxisY" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasYAxis;
652     m_aCommandAvailability[ ".uno:DiagramAxisZ" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasZAxis;
653     m_aCommandAvailability[ ".uno:DiagramAxisA" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasAAxis;
654     m_aCommandAvailability[ ".uno:DiagramAxisB" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasBAxis;
655     m_aCommandAvailability[ ".uno:DiagramAxisAll" ] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyAxis();
656 
657     // grids
658     // note: x and y are swapped in the commands!
659     m_aCommandAvailability[ ".uno:DiagramGridYMain" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainXGrid;
660     m_aCommandAvailability[ ".uno:DiagramGridXMain" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainYGrid;
661     m_aCommandAvailability[ ".uno:DiagramGridZMain" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainZGrid;
662     m_aCommandAvailability[ ".uno:DiagramGridYHelp" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpXGrid;
663     m_aCommandAvailability[ ".uno:DiagramGridXHelp" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpYGrid;
664     m_aCommandAvailability[ ".uno:DiagramGridZHelp" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpZGrid;
665     m_aCommandAvailability[ ".uno:DiagramGridAll" ] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyGrid();
666 
667     // series arrangement
668     m_aCommandAvailability[ ".uno:Forward" ] = ( bShapeContext ? isShapeControllerCommandAvailable( ".uno:Forward" ) :
669         ( bIsWritable && bControllerStateIsValid && m_apControllerState->bMayMoveSeriesForward && bEnableDataTableDialog ) );
670     m_aCommandAvailability[ ".uno:Backward" ] = ( bShapeContext ? isShapeControllerCommandAvailable( ".uno:Backward" ) :
671         ( bIsWritable && bControllerStateIsValid && m_apControllerState->bMayMoveSeriesBackward && bEnableDataTableDialog ) );
672 
673     m_aCommandAvailability[ ".uno:InsertDataLabels" ] = bIsWritable;
674     m_aCommandAvailability[ ".uno:InsertDataLabel" ] = bIsWritable;
675     m_aCommandAvailability[ ".uno:InsertMeanValue" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddMeanValue;
676     m_aCommandAvailability[ ".uno:InsertTrendline" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddTrendline;
677     m_aCommandAvailability[ ".uno:InsertTrendlineEquation" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddTrendlineEquation;
678     m_aCommandAvailability[ ".uno:InsertTrendlineEquationAndR2" ] = m_aCommandAvailability[ ".uno:InsertTrendlineEquation" ];
679     m_aCommandAvailability[ ".uno:InsertR2Value" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddR2Value;
680     m_aCommandAvailability[ ".uno:DeleteR2Value" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteR2Value;
681 
682     m_aCommandAvailability[ ".uno:InsertXErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddXErrorBars;
683     m_aCommandAvailability[ ".uno:InsertYErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddYErrorBars;
684 
685     m_aCommandAvailability[ ".uno:DeleteDataLabels" ] = bIsWritable;
686     m_aCommandAvailability[ ".uno:DeleteDataLabel" ] = bIsWritable;
687     m_aCommandAvailability[ ".uno:DeleteTrendline" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteTrendline;
688     m_aCommandAvailability[ ".uno:DeleteTrendlineEquation" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteTrendlineEquation;
689     m_aCommandAvailability[ ".uno:DeleteMeanValue" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteMeanValue;
690     m_aCommandAvailability[ ".uno:DeleteXErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteXErrorBars;
691     m_aCommandAvailability[ ".uno:DeleteYErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteYErrorBars;
692 
693     m_aCommandAvailability[ ".uno:ResetDataPoint" ] = bIsWritable;
694     m_aCommandAvailability[ ".uno:ResetAllDataPoints" ] = bIsWritable;
695 
696     m_aCommandAvailability[ ".uno:InsertAxis" ] = bIsWritable;
697     m_aCommandAvailability[ ".uno:DeleteAxis" ] = bIsWritable;
698     m_aCommandAvailability[ ".uno:InsertAxisTitle" ] = bIsWritable;
699     m_aCommandAvailability[ ".uno:FormatMajorGrid" ] = bIsWritable;
700     m_aCommandAvailability[ ".uno:InsertMajorGrid" ] = bIsWritable;
701     m_aCommandAvailability[ ".uno:DeleteMajorGrid" ] = bIsWritable;
702     m_aCommandAvailability[ ".uno:FormatMinorGrid" ] = bIsWritable;
703     m_aCommandAvailability[ ".uno:InsertMinorGrid" ] = bIsWritable;
704     m_aCommandAvailability[ ".uno:DeleteMinorGrid" ] = bIsWritable;
705 }
706 
commandAvailable(const OUString & rCommand)707 bool ControllerCommandDispatch::commandAvailable( const OUString & rCommand )
708 {
709     std::map< OUString, bool >::const_iterator aIt( m_aCommandAvailability.find( rCommand ));
710     if( aIt != m_aCommandAvailability.end())
711         return aIt->second;
712     SAL_WARN("chart2", "commandAvailable: command not in availability map:" << rCommand);
713     return false;
714 }
715 
isShapeControllerCommandAvailable(const OUString & rCommand)716 bool ControllerCommandDispatch::isShapeControllerCommandAvailable( const OUString& rCommand )
717 {
718     ShapeController* pShapeController(nullptr);
719     {
720         SolarMutexGuard g;
721         if (m_pDispatchContainer)
722             pShapeController = m_pDispatchContainer->getShapeController();
723     }
724     if ( pShapeController )
725     {
726         FeatureState aState( pShapeController->getState( rCommand ) );
727         return aState.bEnabled;
728     }
729     return false;
730 }
731 
fireStatusEvent(const OUString & rURL,const Reference<frame::XStatusListener> & xSingleListener)732 void ControllerCommandDispatch::fireStatusEvent(
733     const OUString & rURL,
734     const Reference< frame::XStatusListener > & xSingleListener /* = 0 */ )
735 {
736     bool bIsChartSelectorURL = rURL == ".uno:ChartElementSelector";
737     if( rURL.isEmpty() || bIsChartSelectorURL )
738     {
739         uno::Any aArg;
740         aArg <<= Reference< frame::XController >(m_xChartController.get());
741         fireStatusEventForURL( ".uno:ChartElementSelector", aArg, true, xSingleListener );
742     }
743 
744     if( rURL.isEmpty() )
745     {
746         for (auto const& elem : m_aCommandAvailability)
747             fireStatusEventForURLImpl( elem.first, xSingleListener );
748     }
749     else if( !bIsChartSelectorURL )
750         fireStatusEventForURLImpl( rURL, xSingleListener );
751 
752     // statusbar. Should be handled by base implementation
753     // @todo: remove if Issue 68864 is fixed
754     if( rURL.isEmpty() || rURL == ".uno:StatusBarVisible" )
755     {
756         bool bIsStatusBarVisible( lcl_isStatusBarVisible( m_xChartController.get() ));
757         fireStatusEventForURL( ".uno:StatusBarVisible", uno::Any( bIsStatusBarVisible ), true, xSingleListener );
758     }
759 }
760 
761 // ____ XDispatch ____
dispatch(const util::URL & URL,const Sequence<beans::PropertyValue> & Arguments)762 void SAL_CALL ControllerCommandDispatch::dispatch(
763     const util::URL& URL,
764     const Sequence< beans::PropertyValue >& Arguments )
765 {
766     if( commandAvailable( URL.Complete ))
767         m_xDispatch->dispatch( URL, Arguments );
768 }
769 
770 // ____ WeakComponentImplHelperBase ____
771 /// is called when this is disposed
disposing()772 void SAL_CALL ControllerCommandDispatch::disposing()
773 {
774     m_xChartController.clear();
775     m_xDispatch.clear();
776     m_xSelectionSupplier.clear();
777 }
778 
779 // ____ XEventListener (base of XModifyListener) ____
disposing(const lang::EventObject &)780 void SAL_CALL ControllerCommandDispatch::disposing( const lang::EventObject& /* Source */ )
781 {
782     m_xChartController.clear();
783     m_xDispatch.clear();
784     m_xSelectionSupplier.clear();
785 }
786 
787 // ____ XModifyListener ____
modified(const lang::EventObject & aEvent)788 void SAL_CALL ControllerCommandDispatch::modified( const lang::EventObject& aEvent )
789 {
790     bool bUpdateCommandAvailability = false;
791 
792     // Update the "ModelState" Struct.
793     if( m_apModelState.get() && m_xChartController.is())
794     {
795         m_apModelState->update( m_xChartController->getModel());
796         bUpdateCommandAvailability = true;
797     }
798 
799     // Update the "ControllerState" Struct.
800     if( m_apControllerState.get() && m_xChartController.is())
801     {
802         m_apControllerState->update( m_xChartController.get(), m_xChartController->getModel());
803         bUpdateCommandAvailability = true;
804     }
805 
806     if( bUpdateCommandAvailability )
807         updateCommandAvailability();
808 
809     CommandDispatch::modified( aEvent );
810 }
811 
812 // ____ XSelectionChangeListener ____
selectionChanged(const lang::EventObject & aEvent)813 void SAL_CALL ControllerCommandDispatch::selectionChanged( const lang::EventObject& aEvent )
814 {
815     // Update the "ControllerState" Struct.
816     if( m_apControllerState.get() && m_xChartController.is())
817     {
818         m_apControllerState->update( m_xChartController.get(), m_xChartController->getModel());
819         updateCommandAvailability();
820     }
821 
822     CommandDispatch::modified( aEvent );
823 }
824 
825 } //  namespace chart
826 
827 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
828