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