diff options
Diffstat (limited to 'chart2/source/controller/main/ControllerCommandDispatch.cxx')
-rw-r--r-- | chart2/source/controller/main/ControllerCommandDispatch.cxx | 837 |
1 files changed, 837 insertions, 0 deletions
diff --git a/chart2/source/controller/main/ControllerCommandDispatch.cxx b/chart2/source/controller/main/ControllerCommandDispatch.cxx new file mode 100644 index 000000000..aa21b77fb --- /dev/null +++ b/chart2/source/controller/main/ControllerCommandDispatch.cxx @@ -0,0 +1,837 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "ControllerCommandDispatch.hxx" +#include <ChartModelHelper.hxx> +#include <ChartModel.hxx> +#include <DiagramHelper.hxx> +#include <AxisHelper.hxx> +#include <TitleHelper.hxx> +#include <LegendHelper.hxx> +#include <ObjectIdentifier.hxx> +#include <ChartTypeHelper.hxx> +#include <ChartController.hxx> +#include <RegressionCurveHelper.hxx> +#include <DataSeriesHelper.hxx> +#include <StatisticsHelper.hxx> +#include <ReferenceSizeProvider.hxx> +#include "ShapeController.hxx" + +#include <vcl/svapp.hxx> +#include <sal/log.hxx> +#include <tools/diagnose_ex.h> +#include <comphelper/lok.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/objsh.hxx> + +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XRegressionCurve.hpp> +#include <com/sun/star/chart2/XRegressionCurveContainer.hpp> +#include <com/sun/star/chart2/XDataProviderAccess.hpp> + +// only needed until #i68864# is fixed +#include <com/sun/star/frame/XLayoutManager.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ +bool lcl_isStatusBarVisible( const Reference< frame::XController > & xController ) +{ + bool bIsStatusBarVisible = false; + // Status-Bar visible, workaround: this should not be necessary. @todo: + // remove when Issue #i68864# is fixed + if( xController.is()) + { + Reference< beans::XPropertySet > xPropSet( xController->getFrame(), uno::UNO_QUERY ); + if( xPropSet.is() ) + { + uno::Reference< css::frame::XLayoutManager > xLayoutManager; + xPropSet->getPropertyValue( "LayoutManager" ) >>= xLayoutManager; + if ( xLayoutManager.is() ) + bIsStatusBarVisible = xLayoutManager->isElementVisible( "private:resource/statusbar/statusbar" ); + } + } + return bIsStatusBarVisible; +} + +} // anonymous namespace + +namespace chart +{ + +namespace impl +{ + +/// Constants for moving the series. +namespace { + static bool const MOVE_SERIES_FORWARD = true; + static bool const MOVE_SERIES_BACKWARD = false; +} + +/** Represents the current state of the controller (needed for issue 63017). + + You can set the state by calling update(). After this call the state is + preserved in this class until the next call to update(). + + This is useful, not to say necessary, for enabling and disabling of menu + entries (e.g. format>arrangement). As the status requests are sent very + frequently it would be impossible, from a performance point of view, to + query the current status every time directly at the model. So this class + serves as a cache for the state. +*/ +struct ControllerState +{ + ControllerState(); + + void update( const Reference< frame::XController > & xController, + const Reference< frame::XModel > & xModel ); + + // -- State variables ------- + bool bHasSelectedObject; + bool bIsPositionableObject; + bool bIsTextObject; + bool bIsDeleteableObjectSelected; + bool bIsFormateableObjectSelected; + + // May the selected series be moved forward or backward (cf + // format>arrangement). + bool bMayMoveSeriesForward; + bool bMayMoveSeriesBackward; + + // trendlines + bool bMayAddMenuTrendline; + bool bMayAddTrendline; + bool bMayAddTrendlineEquation; + bool bMayAddR2Value; + bool bMayAddMeanValue; + bool bMayAddXErrorBars; + bool bMayAddYErrorBars; + + bool bMayDeleteTrendline; + bool bMayDeleteTrendlineEquation; + bool bMayDeleteR2Value; + bool bMayDeleteMeanValue; + bool bMayDeleteXErrorBars; + bool bMayDeleteYErrorBars; + + bool bMayFormatTrendline; + bool bMayFormatTrendlineEquation; + bool bMayFormatMeanValue; + bool bMayFormatXErrorBars; + bool bMayFormatYErrorBars; +}; + +ControllerState::ControllerState() : + bHasSelectedObject( false ), + bIsPositionableObject( false ), + bIsTextObject(false), + bIsDeleteableObjectSelected(false), + bIsFormateableObjectSelected(false), + bMayMoveSeriesForward( false ), + bMayMoveSeriesBackward( false ), + bMayAddMenuTrendline( false ), + bMayAddTrendline( false ), + bMayAddTrendlineEquation( false ), + bMayAddR2Value( false ), + bMayAddMeanValue( false ), + bMayAddXErrorBars( false ), + bMayAddYErrorBars( false ), + bMayDeleteTrendline( false ), + bMayDeleteTrendlineEquation( false ), + bMayDeleteR2Value( false ), + bMayDeleteMeanValue( false ), + bMayDeleteXErrorBars( false ), + bMayDeleteYErrorBars( false ), + bMayFormatTrendline( false ), + bMayFormatTrendlineEquation( false ), + bMayFormatMeanValue( false ), + bMayFormatXErrorBars( false ), + bMayFormatYErrorBars( false ) +{} + +void ControllerState::update( + const Reference< frame::XController > & xController, + const Reference< frame::XModel > & xModel ) +{ + Reference< view::XSelectionSupplier > xSelectionSupplier( + xController, uno::UNO_QUERY ); + + // Update ControllerState variables. + if( !xSelectionSupplier.is()) + return; + + uno::Any aSelObj( xSelectionSupplier->getSelection() ); + ObjectIdentifier aSelOID( aSelObj ); + OUString aSelObjCID( aSelOID.getObjectCID() ); + + bHasSelectedObject = aSelOID.isValid(); + + ObjectType aObjectType(ObjectIdentifier::getObjectType( aSelObjCID )); + + bIsPositionableObject = (aObjectType != OBJECTTYPE_DATA_POINT) && aSelOID.isDragableObject(); + bIsTextObject = aObjectType == OBJECTTYPE_TITLE; + + uno::Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel )); + bIsFormateableObjectSelected = bHasSelectedObject && aSelOID.isAutoGeneratedObject(); + if( aObjectType==OBJECTTYPE_DIAGRAM || aObjectType==OBJECTTYPE_DIAGRAM_WALL || aObjectType==OBJECTTYPE_DIAGRAM_FLOOR ) + bIsFormateableObjectSelected = DiagramHelper::isSupportingFloorAndWall( xDiagram ); + + uno::Reference< chart2::XDataSeries > xGivenDataSeries( + ObjectIdentifier::getDataSeriesForCID( + aSelObjCID, xModel ) ); + + bIsDeleteableObjectSelected = ChartController::isObjectDeleteable( aSelObj ); + + bMayMoveSeriesForward = (aObjectType!=OBJECTTYPE_DATA_POINT) && DiagramHelper::isSeriesMoveable( + ChartModelHelper::findDiagram( xModel ), + xGivenDataSeries, + MOVE_SERIES_FORWARD ); + + bMayMoveSeriesBackward = (aObjectType!=OBJECTTYPE_DATA_POINT) && DiagramHelper::isSeriesMoveable( + ChartModelHelper::findDiagram( xModel ), + xGivenDataSeries, + MOVE_SERIES_BACKWARD ); + + bMayAddMenuTrendline = false; + bMayAddTrendline = false; + bMayAddTrendlineEquation = false; + bMayAddR2Value = false; + bMayAddMeanValue = false; + bMayAddXErrorBars = false; + bMayAddYErrorBars = false; + bMayDeleteTrendline = false; + bMayDeleteTrendlineEquation = false; + bMayDeleteR2Value = false; + bMayDeleteMeanValue = false; + bMayDeleteXErrorBars = false; + bMayDeleteYErrorBars = false; + bMayFormatTrendline = false; + bMayFormatTrendlineEquation = false; + bMayFormatMeanValue = false; + bMayFormatXErrorBars = false; + bMayFormatYErrorBars = false; + if( !bHasSelectedObject ) + return; + + if( xGivenDataSeries.is()) + { + bMayAddMenuTrendline = true; + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + uno::Reference< chart2::XChartType > xFirstChartType( + DataSeriesHelper::getChartTypeOfSeries( xGivenDataSeries, xDiagram )); + + // trend lines/mean value line + if( (aObjectType == OBJECTTYPE_DATA_SERIES || aObjectType == OBJECTTYPE_DATA_POINT) + && ChartTypeHelper::isSupportingRegressionProperties( xFirstChartType, nDimensionCount )) + { + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( xGivenDataSeries, uno::UNO_QUERY ); + if( xRegCurveCnt.is()) + { + // Trendline + bMayAddTrendline = true; + + // Mean Value + bMayFormatMeanValue = bMayDeleteMeanValue = RegressionCurveHelper::hasMeanValueLine( xRegCurveCnt ); + bMayAddMeanValue = ! bMayDeleteMeanValue; + } + } + + // error bars + if( (aObjectType == OBJECTTYPE_DATA_SERIES || aObjectType == OBJECTTYPE_DATA_POINT) + && ChartTypeHelper::isSupportingStatisticProperties( xFirstChartType, nDimensionCount )) + { + bMayFormatXErrorBars = bMayDeleteXErrorBars = StatisticsHelper::hasErrorBars( xGivenDataSeries, false ); + bMayAddXErrorBars = ! bMayDeleteXErrorBars; + + bMayFormatYErrorBars = bMayDeleteYErrorBars = StatisticsHelper::hasErrorBars( xGivenDataSeries ); + bMayAddYErrorBars = ! bMayDeleteYErrorBars; + } + } + + if( aObjectType == OBJECTTYPE_DATA_AVERAGE_LINE ) + bMayFormatMeanValue = true; + + if( aObjectType == OBJECTTYPE_DATA_ERRORS_X) + bMayFormatXErrorBars = true; + + if( aObjectType == OBJECTTYPE_DATA_ERRORS_Y ) + bMayFormatYErrorBars = true; + + if( aObjectType == OBJECTTYPE_DATA_CURVE ) + { + bMayFormatTrendline = true; + bMayDeleteTrendline = true; + uno::Reference< chart2::XRegressionCurve > xRegCurve( + ObjectIdentifier::getObjectPropertySet( aSelObjCID, xModel ), uno::UNO_QUERY ); + + // Trendline Equation + bMayFormatTrendlineEquation = bMayDeleteTrendlineEquation = RegressionCurveHelper::hasEquation( xRegCurve ); + bMayAddTrendlineEquation = !bMayDeleteTrendlineEquation; + } + else if( aObjectType == OBJECTTYPE_DATA_CURVE_EQUATION ) + { + bMayFormatTrendlineEquation = true; + bool bHasR2Value = false; + try + { + uno::Reference< beans::XPropertySet > xEquationProperties = + ObjectIdentifier::getObjectPropertySet( aSelObjCID, xModel ); + if( xEquationProperties.is() ) + xEquationProperties->getPropertyValue( "ShowCorrelationCoefficient" ) >>= bHasR2Value; + } + catch(const uno::RuntimeException&) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + bMayAddR2Value = !bHasR2Value; + bMayDeleteR2Value = bHasR2Value; + } +} + +/** Represents the current state of the model. + + You can set the state by calling update(). After this call the state is + preserved in this class until the next call to update(). + + This is useful, not to say necessary, for enabling and disabling of menu + entries and toolbar icons. As the status requests are sent very frequently + it would be impossible, from a performance point of view, to query the + current status every time directly at the model. So this class serves as a + cache for the state. + */ +struct ModelState +{ + ModelState(); + + void update( const Reference< frame::XModel > & xModel ); + + bool HasAnyAxis() const; + bool HasAnyGrid() const; + bool HasAnyTitle() const; + + bool bIsReadOnly; + bool bIsThreeD; + bool bHasOwnData; + bool bHasDataFromPivotTable; + + bool bHasMainTitle; + bool bHasSubTitle; + bool bHasXAxisTitle; + bool bHasYAxisTitle; + bool bHasZAxisTitle; + bool bHasSecondaryXAxisTitle; + bool bHasSecondaryYAxisTitle; + + bool bHasXAxis; + bool bHasYAxis; + bool bHasZAxis; + bool bHasAAxis; + bool bHasBAxis; + + bool bHasMainXGrid; + bool bHasMainYGrid; + bool bHasMainZGrid; + bool bHasHelpXGrid; + bool bHasHelpYGrid; + bool bHasHelpZGrid; + + bool bHasAutoScaledText; + bool bHasLegend; + bool bHasWall; + bool bHasFloor; + + bool bSupportsStatistics; + bool bSupportsAxes; +}; + +ModelState::ModelState() : + bIsReadOnly(true), + bIsThreeD(false), + bHasOwnData(false), + bHasDataFromPivotTable(false), + bHasMainTitle(false), + bHasSubTitle(false), + bHasXAxisTitle(false), + bHasYAxisTitle(false), + bHasZAxisTitle(false), + bHasSecondaryXAxisTitle(false), + bHasSecondaryYAxisTitle(false), + bHasXAxis(false), + bHasYAxis(false), + bHasZAxis(false), + bHasAAxis(false), + bHasBAxis(false), + bHasMainXGrid(false), + bHasMainYGrid(false), + bHasMainZGrid(false), + bHasHelpXGrid(false), + bHasHelpYGrid(false), + bHasHelpZGrid(false), + bHasAutoScaledText(false), + bHasLegend(false), + bHasWall(false), + bHasFloor(false), + bSupportsStatistics(false), + bSupportsAxes(false) +{} + +void ModelState::update( const Reference< frame::XModel > & xModel ) +{ + Reference< chart2::XChartDocument > xChartDoc( xModel, uno::UNO_QUERY ); + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel )); + + bIsReadOnly = true; + Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY ); + if( xStorable.is()) + bIsReadOnly = xStorable->isReadonly(); + + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + + uno::Reference< chart2::XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + bSupportsStatistics = ChartTypeHelper::isSupportingStatisticProperties( xFirstChartType, nDimensionCount ); + bSupportsAxes = ChartTypeHelper::isSupportingMainAxis( xFirstChartType, nDimensionCount, 0 ); + + bIsThreeD = (nDimensionCount == 3); + if (xChartDoc.is()) + { + ChartModel& rModel = dynamic_cast<ChartModel&>(*xChartDoc); + bHasOwnData = rModel.hasInternalDataProvider(); + bHasDataFromPivotTable = !bHasOwnData && rModel.isDataFromPivotTable(); + } + + bHasMainTitle = TitleHelper::getTitle( TitleHelper::MAIN_TITLE, xModel ).is(); + bHasSubTitle = TitleHelper::getTitle( TitleHelper::SUB_TITLE, xModel ).is(); + bHasXAxisTitle = TitleHelper::getTitle( TitleHelper::X_AXIS_TITLE, xModel ).is(); + bHasYAxisTitle = TitleHelper::getTitle( TitleHelper::Y_AXIS_TITLE, xModel ).is(); + bHasZAxisTitle = TitleHelper::getTitle( TitleHelper::Z_AXIS_TITLE, xModel ).is(); + bHasSecondaryXAxisTitle = TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xModel ).is(); + bHasSecondaryYAxisTitle = TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xModel ).is(); + + bHasXAxis = bSupportsAxes && AxisHelper::getAxis( 0, true, xDiagram ).is(); + bHasYAxis = bSupportsAxes && AxisHelper::getAxis( 1, true, xDiagram ).is(); + bHasZAxis = bSupportsAxes && AxisHelper::getAxis( 2, true, xDiagram ).is(); + bHasAAxis = bSupportsAxes && AxisHelper::getAxis( 0, false, xDiagram ).is(); + bHasBAxis = bSupportsAxes && AxisHelper::getAxis( 1, false, xDiagram ).is(); + + bHasMainXGrid = bSupportsAxes && AxisHelper::isGridShown( 0, 0, true, xDiagram ); + bHasMainYGrid = bSupportsAxes && AxisHelper::isGridShown( 1, 0, true, xDiagram ); + bHasMainZGrid = bSupportsAxes && AxisHelper::isGridShown( 2, 0, true, xDiagram ); + bHasHelpXGrid = bSupportsAxes && AxisHelper::isGridShown( 0, 0, false, xDiagram ); + bHasHelpYGrid = bSupportsAxes && AxisHelper::isGridShown( 1, 0, false, xDiagram ); + bHasHelpZGrid = bSupportsAxes && AxisHelper::isGridShown( 2, 0, false, xDiagram ); + + bHasAutoScaledText = + (ReferenceSizeProvider::getAutoResizeState( xChartDoc ) == + ReferenceSizeProvider::AUTO_RESIZE_YES); + + bHasLegend = LegendHelper::hasLegend( xDiagram ); + bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram ); + bHasFloor = bHasWall && bIsThreeD; +} + +bool ModelState::HasAnyAxis() const +{ + return bHasXAxis || bHasYAxis || bHasZAxis || bHasAAxis || bHasBAxis; +} + +bool ModelState::HasAnyGrid() const +{ + return bHasMainXGrid || bHasMainYGrid || bHasMainZGrid || + bHasHelpXGrid || bHasHelpYGrid || bHasHelpZGrid; +} + +bool ModelState::HasAnyTitle() const +{ + return bHasMainTitle || bHasSubTitle || bHasXAxisTitle || bHasYAxisTitle || bHasZAxisTitle || bHasSecondaryXAxisTitle || bHasSecondaryYAxisTitle; +} + +} // namespace impl + +ControllerCommandDispatch::ControllerCommandDispatch( + const Reference< uno::XComponentContext > & xContext, + ChartController* pController, CommandDispatchContainer* pContainer ) : + impl::ControllerCommandDispatch_Base( xContext ), + m_xChartController( pController ), + m_xSelectionSupplier( Reference< view::XSelectionSupplier >( pController ) ), + m_xDispatch( Reference< frame::XDispatch >( pController ) ), + m_apModelState( new impl::ModelState() ), + m_apControllerState( new impl::ControllerState() ), + m_pDispatchContainer( pContainer ) +{ +} + +ControllerCommandDispatch::~ControllerCommandDispatch() +{ +} + +void ControllerCommandDispatch::initialize() +{ + if( !m_xChartController.is()) + return; + + Reference< frame::XModel > xModel( m_xChartController->getModel()); + Reference< util::XModifyBroadcaster > xModifyBroadcaster( xModel, uno::UNO_QUERY ); + OSL_ASSERT( xModifyBroadcaster.is()); + if( xModifyBroadcaster.is()) + xModifyBroadcaster->addModifyListener( this ); + + // Listen selection modifications (Arrangement feature - issue 63017). + if( m_xSelectionSupplier.is() ) + m_xSelectionSupplier->addSelectionChangeListener( this ); + + if( m_apModelState && xModel.is()) + m_apModelState->update( xModel ); + + if( m_apControllerState && xModel.is()) + m_apControllerState->update( m_xChartController.get(), xModel ); + + updateCommandAvailability(); +} + +void ControllerCommandDispatch::fireStatusEventForURLImpl( + const OUString & rURL, + const Reference< frame::XStatusListener > & xSingleListener ) +{ + std::map< OUString, uno::Any >::const_iterator aArgIt( m_aCommandArguments.find( rURL )); + if( aArgIt != m_aCommandArguments.end()) + fireStatusEventForURL( rURL, aArgIt->second, commandAvailable( rURL ), xSingleListener ); + else + fireStatusEventForURL( rURL, uno::Any(), commandAvailable( rURL ), xSingleListener ); +} + +void ControllerCommandDispatch::updateCommandAvailability() +{ + bool bModelStateIsValid = (m_apModelState != nullptr); + bool bControllerStateIsValid = (m_apControllerState != nullptr); + // Model and controller states exist. + OSL_ASSERT( bModelStateIsValid ); + OSL_ASSERT( bControllerStateIsValid ); + + // read-only + bool bIsWritable = bModelStateIsValid && (! m_apModelState->bIsReadOnly); + bool bShapeContext = m_xChartController.is() && m_xChartController->isShapeContext(); + + bool bEnableDataTableDialog = false; + bool bCanCreateDataProvider = false; + + if ( m_xChartController.is() ) + { + Reference< beans::XPropertySet > xProps( m_xChartController->getModel(), uno::UNO_QUERY ); + if ( xProps.is() ) + { + try + { + xProps->getPropertyValue("EnableDataTableDialog") >>= bEnableDataTableDialog; + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + + Reference< chart2::XChartDocument > xChartDoc(m_xChartController->getModel(), uno::UNO_QUERY); + OSL_ENSURE(xChartDoc.is(), "Invalid XChartDocument"); + if ( xChartDoc.is() ) + { + ChartModel& rModel = dynamic_cast<ChartModel&>(*xChartDoc); + css::uno::Reference< com::sun::star::chart2::XDataProviderAccess > xCreatorDoc(rModel.getParent(), uno::UNO_QUERY); + bCanCreateDataProvider = xCreatorDoc.is(); + } + } + + // edit commands + m_aCommandAvailability[ ".uno:Cut" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bIsDeleteableObjectSelected; + m_aCommandAvailability[ ".uno:Copy" ] = bControllerStateIsValid && m_apControllerState->bHasSelectedObject; + m_aCommandAvailability[ ".uno:Paste" ] = bIsWritable; + + // toolbar commands + m_aCommandAvailability[ ".uno:ToggleGridHorizontal" ] = bIsWritable; + m_aCommandArguments[ ".uno:ToggleGridHorizontal" ] <<= m_apModelState->bHasMainYGrid; + m_aCommandAvailability[ ".uno:ToggleGridVertical" ] = bIsWritable; + m_aCommandArguments[ ".uno:ToggleGridVertical" ] <<= m_apModelState->bHasMainXGrid; + + m_aCommandAvailability[ ".uno:ToggleLegend" ] = bIsWritable; + m_aCommandArguments[ ".uno:ToggleLegend" ] <<= m_apModelState->bHasLegend; + + m_aCommandAvailability[ ".uno:NewArrangement" ] = bIsWritable; + m_aCommandAvailability[ ".uno:Update" ] = bIsWritable; + m_aCommandAvailability[ ".uno:DefaultColors" ] = bIsWritable; + m_aCommandAvailability[ ".uno:BarWidth" ] = bIsWritable; + m_aCommandAvailability[ ".uno:NumberOfLines" ] = bIsWritable; + m_aCommandAvailability[ ".uno:ArrangeRow" ] = + bShapeContext || ( bIsWritable && bControllerStateIsValid && ( m_apControllerState->bMayMoveSeriesForward || m_apControllerState->bMayMoveSeriesBackward ) ); + + // insert objects + m_aCommandAvailability[ ".uno:InsertTitles" ] = m_aCommandAvailability[ ".uno:InsertMenuTitles" ] = bIsWritable; + m_aCommandAvailability[ ".uno:InsertLegend" ] = m_aCommandAvailability[ ".uno:InsertMenuLegend" ] = bIsWritable; + m_aCommandAvailability[ ".uno:DeleteLegend" ] = bIsWritable; + m_aCommandAvailability[ ".uno:InsertMenuDataLabels" ] = bIsWritable; + m_aCommandAvailability[ ".uno:InsertRemoveAxes" ] = m_aCommandAvailability[ ".uno:InsertMenuAxes" ] = bIsWritable && m_apModelState->bSupportsAxes; + m_aCommandAvailability[ ".uno:InsertMenuGrids" ] = bIsWritable && m_apModelState->bSupportsAxes; + m_aCommandAvailability[ ".uno:InsertMenuTrendlines" ] = bIsWritable && m_apModelState->bSupportsStatistics && m_apControllerState->bMayAddMenuTrendline; + m_aCommandAvailability[ ".uno:InsertMenuMeanValues" ] = bIsWritable && m_apModelState->bSupportsStatistics; + m_aCommandAvailability[ ".uno:InsertMenuXErrorBars" ] = bIsWritable && m_apModelState->bSupportsStatistics; + m_aCommandAvailability[ ".uno:InsertMenuYErrorBars" ] = bIsWritable && m_apModelState->bSupportsStatistics; + m_aCommandAvailability[ ".uno:InsertSymbol" ] = bIsWritable && m_apControllerState->bIsTextObject; + + // format objects + bool bFormatObjectAvailable = bIsWritable && bControllerStateIsValid && m_apControllerState->bIsFormateableObjectSelected; + m_aCommandAvailability[ ".uno:FormatSelection" ] = bFormatObjectAvailable; + m_aCommandAvailability[ ".uno:FormatAxis" ] = bFormatObjectAvailable; + m_aCommandAvailability[ ".uno:FormatTitle" ] = bFormatObjectAvailable; + m_aCommandAvailability[ ".uno:FormatDataSeries" ] = bFormatObjectAvailable; + m_aCommandAvailability[ ".uno:FormatDataPoint" ] = bFormatObjectAvailable; + m_aCommandAvailability[ ".uno:FormatDataLabels" ] = bFormatObjectAvailable; + m_aCommandAvailability[ ".uno:FormatDataLabel" ] = bFormatObjectAvailable; + m_aCommandAvailability[ ".uno:FormatXErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatXErrorBars; + m_aCommandAvailability[ ".uno:FormatYErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatYErrorBars; + m_aCommandAvailability[ ".uno:FormatMeanValue" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatMeanValue; + m_aCommandAvailability[ ".uno:FormatTrendline" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatTrendline; + m_aCommandAvailability[ ".uno:FormatTrendlineEquation" ] = bFormatObjectAvailable && bControllerStateIsValid && m_apControllerState->bMayFormatTrendlineEquation; + m_aCommandAvailability[ ".uno:FormatStockLoss" ] = bFormatObjectAvailable; + m_aCommandAvailability[ ".uno:FormatStockGain" ] = bFormatObjectAvailable; + + m_aCommandAvailability[ ".uno:DiagramType" ] = bIsWritable; + m_aCommandAvailability[ ".uno:Legend" ] = bIsWritable && m_apModelState->bHasLegend; + m_aCommandAvailability[ ".uno:DiagramWall" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasWall; + m_aCommandAvailability[ ".uno:DiagramArea" ] = bIsWritable; + + m_aCommandAvailability[ ".uno:TransformDialog" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bHasSelectedObject && m_apControllerState->bIsPositionableObject; + + // 3d commands + m_aCommandAvailability[ ".uno:View3D" ] = bIsWritable && bModelStateIsValid && m_apModelState->bIsThreeD; + m_aCommandAvailability[ ".uno:DiagramFloor" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasFloor; + + //some more format commands with different ui text + m_aCommandAvailability[ ".uno:FormatWall" ] = m_aCommandAvailability[ ".uno:DiagramWall" ]; + m_aCommandAvailability[ ".uno:FormatFloor" ] = m_aCommandAvailability[ ".uno:DiagramFloor" ]; + m_aCommandAvailability[ ".uno:FormatChartArea" ] = m_aCommandAvailability[ ".uno:DiagramArea" ]; + m_aCommandAvailability[ ".uno:FormatLegend" ] = m_aCommandAvailability[ ".uno:Legend" ]; + + // depending on own data and ability to create new data provider + m_aCommandAvailability[".uno:DataRanges"] = bIsWritable && bModelStateIsValid && !m_apModelState->bHasDataFromPivotTable + && ((m_apModelState->bHasOwnData && bCanCreateDataProvider) || !m_apModelState->bHasOwnData); + m_aCommandAvailability[ ".uno:DiagramData" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasOwnData && bEnableDataTableDialog; + + // titles + m_aCommandAvailability[ ".uno:MainTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainTitle; + m_aCommandAvailability[ ".uno:SubTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSubTitle; + m_aCommandAvailability[ ".uno:XTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasXAxisTitle; + m_aCommandAvailability[ ".uno:YTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasYAxisTitle; + m_aCommandAvailability[ ".uno:ZTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasZAxisTitle; + m_aCommandAvailability[ ".uno:SecondaryXTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSecondaryXAxisTitle; + m_aCommandAvailability[ ".uno:SecondaryYTitle" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSecondaryYAxisTitle; + m_aCommandAvailability[ ".uno:AllTitles" ] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyTitle(); + + // text + m_aCommandAvailability[ ".uno:ScaleText" ] = bIsWritable && bModelStateIsValid ; + m_aCommandArguments[ ".uno:ScaleText" ] <<= m_apModelState->bHasAutoScaledText; + + // axes + m_aCommandAvailability[ ".uno:DiagramAxisX" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasXAxis; + m_aCommandAvailability[ ".uno:DiagramAxisY" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasYAxis; + m_aCommandAvailability[ ".uno:DiagramAxisZ" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasZAxis; + m_aCommandAvailability[ ".uno:DiagramAxisA" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasAAxis; + m_aCommandAvailability[ ".uno:DiagramAxisB" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasBAxis; + m_aCommandAvailability[ ".uno:DiagramAxisAll" ] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyAxis(); + + // grids + // note: x and y are swapped in the commands! + m_aCommandAvailability[ ".uno:DiagramGridYMain" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainXGrid; + m_aCommandAvailability[ ".uno:DiagramGridXMain" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainYGrid; + m_aCommandAvailability[ ".uno:DiagramGridZMain" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainZGrid; + m_aCommandAvailability[ ".uno:DiagramGridYHelp" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpXGrid; + m_aCommandAvailability[ ".uno:DiagramGridXHelp" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpYGrid; + m_aCommandAvailability[ ".uno:DiagramGridZHelp" ] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpZGrid; + m_aCommandAvailability[ ".uno:DiagramGridAll" ] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyGrid(); + + // series arrangement + m_aCommandAvailability[ ".uno:Forward" ] = ( bShapeContext ? isShapeControllerCommandAvailable( ".uno:Forward" ) : + ( bIsWritable && bControllerStateIsValid && m_apControllerState->bMayMoveSeriesForward && bEnableDataTableDialog ) ); + m_aCommandAvailability[ ".uno:Backward" ] = ( bShapeContext ? isShapeControllerCommandAvailable( ".uno:Backward" ) : + ( bIsWritable && bControllerStateIsValid && m_apControllerState->bMayMoveSeriesBackward && bEnableDataTableDialog ) ); + + m_aCommandAvailability[ ".uno:InsertDataLabels" ] = bIsWritable; + m_aCommandAvailability[ ".uno:InsertDataLabel" ] = bIsWritable; + m_aCommandAvailability[ ".uno:InsertMeanValue" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddMeanValue; + m_aCommandAvailability[ ".uno:InsertTrendline" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddTrendline; + m_aCommandAvailability[ ".uno:InsertTrendlineEquation" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddTrendlineEquation; + m_aCommandAvailability[ ".uno:InsertTrendlineEquationAndR2" ] = m_aCommandAvailability[ ".uno:InsertTrendlineEquation" ]; + m_aCommandAvailability[ ".uno:InsertR2Value" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddR2Value; + m_aCommandAvailability[ ".uno:DeleteR2Value" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteR2Value; + + m_aCommandAvailability[ ".uno:InsertXErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddXErrorBars; + m_aCommandAvailability[ ".uno:InsertYErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddYErrorBars; + + m_aCommandAvailability[ ".uno:DeleteDataLabels" ] = bIsWritable; + m_aCommandAvailability[ ".uno:DeleteDataLabel" ] = bIsWritable; + m_aCommandAvailability[ ".uno:DeleteTrendline" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteTrendline; + m_aCommandAvailability[ ".uno:DeleteTrendlineEquation" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteTrendlineEquation; + m_aCommandAvailability[ ".uno:DeleteMeanValue" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteMeanValue; + m_aCommandAvailability[ ".uno:DeleteXErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteXErrorBars; + m_aCommandAvailability[ ".uno:DeleteYErrorBars" ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteYErrorBars; + + m_aCommandAvailability[ ".uno:ResetDataPoint" ] = bIsWritable; + m_aCommandAvailability[ ".uno:ResetAllDataPoints" ] = bIsWritable; + + m_aCommandAvailability[ ".uno:InsertAxis" ] = bIsWritable; + m_aCommandAvailability[ ".uno:DeleteAxis" ] = bIsWritable; + m_aCommandAvailability[ ".uno:InsertAxisTitle" ] = bIsWritable; + m_aCommandAvailability[ ".uno:FormatMajorGrid" ] = bIsWritable; + m_aCommandAvailability[ ".uno:InsertMajorGrid" ] = bIsWritable; + m_aCommandAvailability[ ".uno:DeleteMajorGrid" ] = bIsWritable; + m_aCommandAvailability[ ".uno:FormatMinorGrid" ] = bIsWritable; + m_aCommandAvailability[ ".uno:InsertMinorGrid" ] = bIsWritable; + m_aCommandAvailability[ ".uno:DeleteMinorGrid" ] = bIsWritable; +} + +bool ControllerCommandDispatch::commandAvailable( const OUString & rCommand ) +{ + std::map< OUString, bool >::const_iterator aIt( m_aCommandAvailability.find( rCommand )); + if( aIt != m_aCommandAvailability.end()) + return aIt->second; + SAL_WARN("chart2", "commandAvailable: command not in availability map:" << rCommand); + return false; +} + +bool ControllerCommandDispatch::isShapeControllerCommandAvailable( const OUString& rCommand ) +{ + ShapeController* pShapeController(nullptr); + { + SolarMutexGuard g; + if (m_pDispatchContainer) + pShapeController = m_pDispatchContainer->getShapeController(); + } + if ( pShapeController ) + { + FeatureState aState( pShapeController->getState( rCommand ) ); + return aState.bEnabled; + } + return false; +} + +void ControllerCommandDispatch::fireStatusEvent( + const OUString & rURL, + const Reference< frame::XStatusListener > & xSingleListener /* = 0 */ ) +{ + bool bIsChartSelectorURL = rURL == ".uno:ChartElementSelector"; + if( rURL.isEmpty() || bIsChartSelectorURL ) + { + uno::Any aArg; + aArg <<= Reference< frame::XController >(m_xChartController.get()); + fireStatusEventForURL( ".uno:ChartElementSelector", aArg, true, xSingleListener ); + } + + if( rURL.isEmpty() ) + { + for (auto const& elem : m_aCommandAvailability) + fireStatusEventForURLImpl( elem.first, xSingleListener ); + } + else if( !bIsChartSelectorURL ) + fireStatusEventForURLImpl( rURL, xSingleListener ); + + // statusbar. Should be handled by base implementation + // @todo: remove if Issue 68864 is fixed + if( rURL.isEmpty() || rURL == ".uno:StatusBarVisible" ) + { + bool bIsStatusBarVisible( lcl_isStatusBarVisible( m_xChartController.get() )); + fireStatusEventForURL( ".uno:StatusBarVisible", uno::Any( bIsStatusBarVisible ), true, xSingleListener ); + } +} + +// ____ XDispatch ____ +void SAL_CALL ControllerCommandDispatch::dispatch( + const util::URL& URL, + const Sequence< beans::PropertyValue >& Arguments ) +{ + if( commandAvailable( URL.Complete )) + m_xDispatch->dispatch( URL, Arguments ); +} + +// ____ WeakComponentImplHelperBase ____ +/// is called when this is disposed +void SAL_CALL ControllerCommandDispatch::disposing() +{ + m_xChartController.clear(); + m_xDispatch.clear(); + m_xSelectionSupplier.clear(); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL ControllerCommandDispatch::disposing( const lang::EventObject& /* Source */ ) +{ + m_xChartController.clear(); + m_xDispatch.clear(); + m_xSelectionSupplier.clear(); +} + +// ____ XModifyListener ____ +void SAL_CALL ControllerCommandDispatch::modified( const lang::EventObject& aEvent ) +{ + bool bUpdateCommandAvailability = false; + + // Update the "ModelState" Struct. + if( m_apModelState && m_xChartController.is()) + { + m_apModelState->update( m_xChartController->getModel()); + bUpdateCommandAvailability = true; + } + + // Update the "ControllerState" Struct. + if( m_apControllerState && m_xChartController.is()) + { + m_apControllerState->update( m_xChartController.get(), m_xChartController->getModel()); + bUpdateCommandAvailability = true; + } + + if( bUpdateCommandAvailability ) + updateCommandAvailability(); + + if (comphelper::LibreOfficeKit::isActive()) + { + if (SfxViewShell* pViewShell = SfxViewShell::Current()) + if (SfxObjectShell* pObjSh = pViewShell->GetObjectShell()) + pObjSh->SetModified(); + } + + CommandDispatch::modified( aEvent ); +} + +// ____ XSelectionChangeListener ____ +void SAL_CALL ControllerCommandDispatch::selectionChanged( const lang::EventObject& aEvent ) +{ + // Update the "ControllerState" Struct. + if( m_apControllerState && m_xChartController.is()) + { + m_apControllerState->update( m_xChartController.get(), m_xChartController->getModel()); + updateCommandAvailability(); + } + + CommandDispatch::modified( aEvent ); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |