/* -*- 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 <ChartController.hxx>
#include <ChartWindow.hxx>
#include <ChartModel.hxx>
#include <ChartModelHelper.hxx>
#include <TitleHelper.hxx>
#include <ThreeDHelper.hxx>
#include <DataSeriesHelper.hxx>
#include "UndoGuard.hxx"
#include <ControllerLockGuard.hxx>
#include <ResId.hxx>
#include <strings.hrc>
#include <ObjectIdentifier.hxx>
#include <ReferenceSizeProvider.hxx>
#include <chartview/ExplicitValueProvider.hxx>
#include <chartview/DrawModelWrapper.hxx>
#include "ChartTransferable.hxx"
#include <DrawViewWrapper.hxx>
#include <LegendHelper.hxx>
#include <AxisHelper.hxx>
#include <RegressionCurveHelper.hxx>
#include "ShapeController.hxx"
#include <DiagramHelper.hxx>
#include <ObjectNameProvider.hxx>
#include <unonames.hxx>
 
#include <com/sun/star/chart2/DataPointLabel.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/drawing/CameraGeometry.hpp>
#include <com/sun/star/graphic/XGraphic.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
#include <com/sun/star/chart/ErrorBarStyle.hpp>
#include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
 
#include <editeng/editview.hxx>
#include <editeng/outliner.hxx>
#include <svx/ActionDescriptionProvider.hxx>
#include <svtools/transfer.hxx>
#include <sot/storage.hxx>
#include <vcl/graph.hxx>
#include <svx/unomodel.hxx>
#include <svx/svdmodel.hxx>
#include <unotools/streamwrap.hxx>
#include <vcl/svapp.hxx>
#include <svx/dialmgr.hxx>
#include <svx/dialogs.hrc>
#include <svx/strings.hrc>
#include <svx/svditer.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdundo.hxx>
#include <svx/unoapi.hxx>
#include <svx/unopage.hxx>
#include <o3tl/make_unique.hxx>
 
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <tools/diagnose_ex.h>
 
#include <memory>
 
using namespace ::com::sun::star;
 
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
 
namespace chart
{
 
namespace
{
 
bool lcl_deleteDataSeries(
    const OUString & rCID,
    const Reference< frame::XModel > & xModel,
    const Reference< document::XUndoManager > & xUndoManager )
{
    bool bResult = false;
    uno::Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rCID, xModel ));
    uno::Reference< chart2::XChartDocument > xChartDoc( xModel, uno::UNO_QUERY );
    if( xSeries.is() && xChartDoc.is())
    {
        uno::Reference< chart2::XChartType > xChartType(
            DataSeriesHelper::getChartTypeOfSeries( xSeries, xChartDoc->getFirstDiagram()));
        if( xChartType.is())
        {
            UndoGuard aUndoGuard(
                ActionDescriptionProvider::createDescription(
                    ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_DATASERIES )),
                xUndoManager );
 
            Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel ) );
            uno::Reference< chart2::XAxis > xAxis( DiagramHelper::getAttachedAxis( xSeries, xDiagram ) );
 
            DataSeriesHelper::deleteSeries( xSeries, xChartType );
 
            AxisHelper::hideAxisIfNoDataIsAttached( xAxis, xDiagram );
 
            bResult = true;
            aUndoGuard.commit();
        }
    }
    return bResult;
}
 
bool lcl_deleteDataCurve(
    const OUString & rCID,
    const Reference< frame::XModel > & xModel,
    const Reference< document::XUndoManager > & xUndoManager )
{
    bool bResult = false;
 
    uno::Reference< beans::XPropertySet > xProperties(
        ObjectIdentifier::getObjectPropertySet( rCID, xModel));
 
    uno::Reference< chart2::XRegressionCurve > xRegressionCurve( xProperties, uno::UNO_QUERY );
 
    if( xRegressionCurve.is())
    {
        uno::Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer(
            ObjectIdentifier::getObjectPropertySet(
                ObjectIdentifier::getFullParentParticle( rCID ), xModel), uno::UNO_QUERY );
 
        if( xRegressionCurveContainer.is())
        {
            UndoGuard aUndoGuard(
                ActionDescriptionProvider::createDescription(
                    ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_CURVE )),
                xUndoManager );
 
            xRegressionCurveContainer->removeRegressionCurve( xRegressionCurve );
 
            bResult = true;
            aUndoGuard.commit();
        }
    }
    return bResult;
}
 
} // anonymous namespace
 
std::unique_ptr<ReferenceSizeProvider> ChartController::impl_createReferenceSizeProvider()
{
    awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) );
 
    return o3tl::make_unique<ReferenceSizeProvider>(
        aPageSize, Reference<chart2::XChartDocument>(getModel(), uno::UNO_QUERY));
}
 
void ChartController::impl_adaptDataSeriesAutoResize()
{
    std::unique_ptr<ReferenceSizeProvider> pRefSizeProvider(impl_createReferenceSizeProvider());
    if (pRefSizeProvider)
        pRefSizeProvider->setValuesAtAllDataSeries();
}
 
void ChartController::executeDispatch_NewArrangement()
{
    // remove manual positions at titles, legend and the diagram, remove manual
    // size at the diagram
 
    try
    {
        Reference< frame::XModel > xModel( getModel() );
        Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel ));
        if( xDiagram.is())
        {
            UndoGuard aUndoGuard(
                SchResId( STR_ACTION_REARRANGE_CHART ),
                m_xUndoManager );
            ControllerLockGuardUNO aCtlLockGuard( xModel );
 
            // diagram
            Reference< beans::XPropertyState > xState( xDiagram, uno::UNO_QUERY_THROW );
            xState->setPropertyToDefault( "RelativeSize");
            xState->setPropertyToDefault( "RelativePosition");
            xState->setPropertyToDefault( "PosSizeExcludeAxes");
 
            // 3d rotation
            ThreeDHelper::set3DSettingsToDefault( uno::Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY ) );
 
            // legend
            Reference< beans::XPropertyState > xLegendState( xDiagram->getLegend(), uno::UNO_QUERY );
            if( xLegendState.is())
            {
                xLegendState->setPropertyToDefault( "RelativePosition");
                xLegendState->setPropertyToDefault( "RelativeSize");
                xLegendState->setPropertyToDefault( "AnchorPosition");
            }
 
            // titles
            for( sal_Int32 eType = TitleHelper::TITLE_BEGIN;
                 eType < TitleHelper::NORMAL_TITLE_END;
                 ++eType )
            {
                Reference< beans::XPropertyState > xTitleState(
                    TitleHelper::getTitle(
                        static_cast< TitleHelper::eTitleType >( eType ), xModel ), uno::UNO_QUERY );
                if( xTitleState.is())
                    xTitleState->setPropertyToDefault( "RelativePosition");
            }
 
            // regression curve equations
            std::vector< Reference< chart2::XRegressionCurve > > aRegressionCurves(
                RegressionCurveHelper::getAllRegressionCurvesNotMeanValueLine( xDiagram ));
 
            // reset equation position
            for( const auto& xCurve : aRegressionCurves )
                RegressionCurveHelper::resetEquationPosition( xCurve );
 
            aUndoGuard.commit();
        }
    }
    catch( const uno::RuntimeException & )
    {
        DBG_UNHANDLED_EXCEPTION("chart2");
    }
}
 
void ChartController::executeDispatch_ScaleText()
{
    SolarMutexGuard aSolarGuard;
    UndoGuard aUndoGuard(
        SchResId( STR_ACTION_SCALE_TEXT ),
        m_xUndoManager );
    ControllerLockGuardUNO aCtlLockGuard( getModel() );
 
    std::unique_ptr<ReferenceSizeProvider> pRefSizeProv(impl_createReferenceSizeProvider());
    OSL_ASSERT( pRefSizeProv.get());
    if (pRefSizeProv)
        pRefSizeProv->toggleAutoResizeState();
 
    aUndoGuard.commit();
}
 
void ChartController::executeDispatch_Paste()
{
    SolarMutexGuard aGuard;
    auto pChartWindow(GetChartWindow());
    if( pChartWindow )
    {
        Graphic aGraphic;
        // paste location: center of window
        Point aPos;
        aPos = pChartWindow->PixelToLogic( tools::Rectangle( aPos, pChartWindow->GetSizePixel()).Center());
 
        // handle different formats
        TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pChartWindow ));
        if( aDataHelper.GetTransferable().is())
        {
            if ( aDataHelper.HasFormat( SotClipboardFormatId::DRAWING ) )
            {
                tools::SvRef<SotStorageStream> xStm;
                if ( aDataHelper.GetSotStorageStream( SotClipboardFormatId::DRAWING, xStm ) )
                {
                    xStm->Seek( 0 );
                    Reference< io::XInputStream > xInputStream( new utl::OInputStreamWrapper( *xStm ) );
 
                    std::unique_ptr< SdrModel > spModel(
                        new SdrModel());
 
                    if ( SvxDrawingLayerImport( spModel.get(), xInputStream ) )
                    {
                        impl_PasteShapes( spModel.get() );
                    }
                }
            }
            else if ( aDataHelper.HasFormat( SotClipboardFormatId::SVXB ) )
            {
                // graphic exchange format (graphic manager bitmap format?)
                tools::SvRef<SotStorageStream> xStm;
                if( aDataHelper.GetSotStorageStream( SotClipboardFormatId::SVXB, xStm ))
                    ReadGraphic( *xStm, aGraphic );
            }
            else if( aDataHelper.HasFormat( SotClipboardFormatId::GDIMETAFILE ))
            {
                // meta file
                GDIMetaFile aMetafile;
                if( aDataHelper.GetGDIMetaFile( SotClipboardFormatId::GDIMETAFILE, aMetafile ))
                    aGraphic = Graphic( aMetafile );
            }
            else if( aDataHelper.HasFormat( SotClipboardFormatId::BITMAP ))
            {
                // bitmap (non-graphic-manager)
                BitmapEx aBmpEx;
                if( aDataHelper.GetBitmapEx( SotClipboardFormatId::BITMAP, aBmpEx ))
                    aGraphic = Graphic( aBmpEx );
            }
            else if( aDataHelper.HasFormat( SotClipboardFormatId::STRING ))
            {
                OUString aString;
                if( aDataHelper.GetString( SotClipboardFormatId::STRING, aString ) && m_pDrawModelWrapper )
                {
                    if( m_pDrawViewWrapper )
                    {
                        OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView();
                        if( pOutlinerView )//in case of edit mode insert into edited string
                            pOutlinerView->InsertText( aString );
                        else
                        {
                            impl_PasteStringAsTextShape( aString, awt::Point( 0, 0 ) );
                        }
                    }
                }
            }
        }
 
        if( aGraphic.GetType() != GraphicType::NONE )
        {
            Reference< graphic::XGraphic > xGraphic( aGraphic.GetXGraphic());
            if( xGraphic.is())
                impl_PasteGraphic( xGraphic, aPos );
        }
    }
}
 
// note: aPosition is ignored for now. The object is always pasted centered to
// the page
void ChartController::impl_PasteGraphic(
    uno::Reference< graphic::XGraphic > const & xGraphic,
    const ::Point & /* aPosition */ )
{
    DBG_TESTSOLARMUTEX();
    // note: the XPropertySet of the model is the old API. Also the property
    // "AdditionalShapes" that is used there.
    uno::Reference< beans::XPropertySet > xModelProp( getModel(), uno::UNO_QUERY );
    DrawModelWrapper * pDrawModelWrapper( GetDrawModelWrapper());
    if( ! (xGraphic.is() && xModelProp.is()))
        return;
    uno::Reference< lang::XMultiServiceFactory > xFact( pDrawModelWrapper->getShapeFactory());
    uno::Reference< drawing::XShape > xGraphicShape(
        xFact->createInstance( "com.sun.star.drawing.GraphicObjectShape" ), uno::UNO_QUERY );
    uno::Reference< beans::XPropertySet > xGraphicShapeProp( xGraphicShape, uno::UNO_QUERY );
    if( xGraphicShapeProp.is() && xGraphicShape.is())
    {
        uno::Reference< drawing::XShapes > xPage( pDrawModelWrapper->getMainDrawPage(), uno::UNO_QUERY );
        if( xPage.is())
        {
            xPage->add( xGraphicShape );
            //need to change the model state manually
            {
                uno::Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY );
                if( xModifiable.is() )
                    xModifiable->setModified( true );
            }
            //select new shape
            m_aSelection.setSelection( xGraphicShape );
            m_aSelection.applySelection( m_pDrawViewWrapper.get() );
        }
        xGraphicShapeProp->setPropertyValue( "Graphic", uno::Any( xGraphic ));
        uno::Reference< beans::XPropertySet > xGraphicProp( xGraphic, uno::UNO_QUERY );
 
        awt::Size aGraphicSize( 1000, 1000 );
        auto pChartWindow(GetChartWindow());
        // first try size in 100th mm, then pixel size
        if( ! ( xGraphicProp->getPropertyValue( "Size100thMM") >>= aGraphicSize ) &&
            ( ( xGraphicProp->getPropertyValue( "SizePixel") >>= aGraphicSize ) && pChartWindow ))
        {
            ::Size aVCLSize( pChartWindow->PixelToLogic( Size( aGraphicSize.Width, aGraphicSize.Height )));
            aGraphicSize.Width = aVCLSize.getWidth();
            aGraphicSize.Height = aVCLSize.getHeight();
        }
        xGraphicShape->setSize( aGraphicSize );
        xGraphicShape->setPosition( awt::Point( 0, 0 ) );
    }
}
 
void ChartController::impl_PasteShapes( SdrModel* pModel )
{
    DrawModelWrapper* pDrawModelWrapper( GetDrawModelWrapper() );
    if ( pDrawModelWrapper && m_pDrawViewWrapper )
    {
        Reference< drawing::XDrawPage > xDestPage( pDrawModelWrapper->getMainDrawPage() );
        SdrPage* pDestPage = GetSdrPageFromXDrawPage( xDestPage );
        if ( pDestPage )
        {
            Reference< drawing::XShape > xSelShape;
            m_pDrawViewWrapper->BegUndo( SvxResId( RID_SVX_3D_UNDO_EXCHANGE_PASTE ) );
            sal_uInt16 nCount = pModel->GetPageCount();
            for ( sal_uInt16 i = 0; i < nCount; ++i )
            {
                const SdrPage* pPage = pModel->GetPage( i );
                SdrObjListIter aIter( pPage, SdrIterMode::DeepNoGroups );
                while ( aIter.IsMore() )
                {
                    SdrObject* pObj(aIter.Next());
                    // Clone to new SdrModel
                    SdrObject* pNewObj(pObj ? pObj->CloneSdrObject(pDrawModelWrapper->getSdrModel()) : nullptr);
 
                    if ( pNewObj )
                    {
                        // set position
                        Reference< drawing::XShape > xShape( pNewObj->getUnoShape(), uno::UNO_QUERY );
                        if ( xShape.is() )
                        {
                            xShape->setPosition( awt::Point( 0, 0 ) );
                        }
 
                        pDestPage->InsertObject( pNewObj );
                        m_pDrawViewWrapper->AddUndo( new SdrUndoInsertObj( *pNewObj ) );
                        xSelShape = xShape;
                    }
                }
            }
 
            Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY );
            if ( xModifiable.is() )
            {
                xModifiable->setModified( true );
            }
 
            // select last inserted shape
            m_aSelection.setSelection( xSelShape );
            m_aSelection.applySelection( m_pDrawViewWrapper.get() );
 
            m_pDrawViewWrapper->EndUndo();
 
            impl_switchDiagramPositioningToExcludingPositioning();
        }
    }
}
 
void ChartController::impl_PasteStringAsTextShape( const OUString& rString, const awt::Point& rPosition )
{
    DrawModelWrapper* pDrawModelWrapper( GetDrawModelWrapper() );
    if ( pDrawModelWrapper && m_pDrawViewWrapper )
    {
        const Reference< lang::XMultiServiceFactory >& xShapeFactory( pDrawModelWrapper->getShapeFactory() );
        const Reference< drawing::XDrawPage >& xDrawPage( pDrawModelWrapper->getMainDrawPage() );
        OSL_ASSERT( xShapeFactory.is() && xDrawPage.is() );
 
        if ( xShapeFactory.is() && xDrawPage.is() )
        {
            try
            {
                Reference< drawing::XShape > xTextShape(
                    xShapeFactory->createInstance( "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY_THROW );
                xDrawPage->add( xTextShape );
 
                Reference< text::XTextRange > xRange( xTextShape, uno::UNO_QUERY_THROW );
                xRange->setString( rString );
 
                float fCharHeight = 10.0;
                Reference< beans::XPropertySet > xProperties( xTextShape, uno::UNO_QUERY_THROW );
                xProperties->setPropertyValue( "TextAutoGrowHeight", uno::Any( true ) );
                xProperties->setPropertyValue( "TextAutoGrowWidth", uno::Any( true ) );
                xProperties->setPropertyValue( "CharHeight", uno::Any( fCharHeight ) );
                xProperties->setPropertyValue( "CharHeightAsian", uno::Any( fCharHeight ) );
                xProperties->setPropertyValue( "CharHeightComplex", uno::Any( fCharHeight ) );
                xProperties->setPropertyValue( "TextVerticalAdjust", uno::Any( drawing::TextVerticalAdjust_CENTER ) );
                xProperties->setPropertyValue( "TextHorizontalAdjust", uno::Any( drawing::TextHorizontalAdjust_CENTER ) );
                xProperties->setPropertyValue( "CharFontName", uno::Any( OUString("Albany") ) );
 
                xTextShape->setPosition( rPosition );
 
                m_aSelection.setSelection( xTextShape );
                m_aSelection.applySelection( m_pDrawViewWrapper.get() );
 
                SdrObject* pObj = DrawViewWrapper::getSdrObject( xTextShape );
                if ( pObj )
                {
                    m_pDrawViewWrapper->BegUndo( SvxResId( RID_SVX_3D_UNDO_EXCHANGE_PASTE ) );
                    m_pDrawViewWrapper->AddUndo( new SdrUndoInsertObj( *pObj ) );
                    m_pDrawViewWrapper->EndUndo();
 
                    impl_switchDiagramPositioningToExcludingPositioning();
                }
            }
            catch ( const uno::Exception& )
            {
                DBG_UNHANDLED_EXCEPTION("chart2");
            }
        }
    }
}
 
void ChartController::executeDispatch_Copy()
{
    if ( m_pDrawViewWrapper )
    {
        OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView();
        if ( pOutlinerView )
        {
            pOutlinerView->Copy();
        }
        else
        {
            Reference< datatransfer::XTransferable > xTransferable;
            {
                SolarMutexGuard aSolarGuard;
                if ( m_pDrawModelWrapper )
                {
                    SdrObject* pSelectedObj = nullptr;
                    ObjectIdentifier aSelOID( m_aSelection.getSelectedOID() );
                    if ( aSelOID.isAutoGeneratedObject() )
                    {
                        pSelectedObj = m_pDrawModelWrapper->getNamedSdrObject( aSelOID.getObjectCID() );
                    }
                    else if ( aSelOID.isAdditionalShape() )
                    {
                        pSelectedObj = DrawViewWrapper::getSdrObject( aSelOID.getAdditionalShape() );
                    }
                    if ( pSelectedObj )
                    {
                        xTransferable.set( new ChartTransferable(
                                m_pDrawModelWrapper->getSdrModel(),
                                pSelectedObj,
                                aSelOID.isAdditionalShape() ) );
                    }
                }
            }
            if ( xTransferable.is() )
            {
                SolarMutexGuard aSolarGuard;
                Reference<datatransfer::clipboard::XClipboard> xClipboard(GetChartWindow()->GetClipboard());
                if ( xClipboard.is() )
                {
                    xClipboard->setContents( xTransferable, Reference< datatransfer::clipboard::XClipboardOwner >() );
                }
            }
        }
    }
}
 
void ChartController::executeDispatch_Cut()
{
    executeDispatch_Copy();
    executeDispatch_Delete();
}
 
bool ChartController::isObjectDeleteable( const uno::Any& rSelection )
{
    ObjectIdentifier aSelOID( rSelection );
    if ( aSelOID.isAutoGeneratedObject() )
    {
        OUString aSelObjCID( aSelOID.getObjectCID() );
        ObjectType aObjectType(ObjectIdentifier::getObjectType( aSelObjCID ));
 
        switch(aObjectType)
        {
        case OBJECTTYPE_TITLE:
        case OBJECTTYPE_LEGEND:
        case OBJECTTYPE_DATA_SERIES:
        case OBJECTTYPE_LEGEND_ENTRY:
        case OBJECTTYPE_DATA_CURVE_EQUATION:
        case OBJECTTYPE_DATA_CURVE:
        case OBJECTTYPE_DATA_AVERAGE_LINE:
        case OBJECTTYPE_DATA_ERRORS_X:
        case OBJECTTYPE_DATA_ERRORS_Y:
        case OBJECTTYPE_DATA_ERRORS_Z:
        case OBJECTTYPE_DATA_LABELS:
        case OBJECTTYPE_DATA_LABEL:
        case OBJECTTYPE_AXIS:
        case OBJECTTYPE_GRID:
        case OBJECTTYPE_SUBGRID:
            return true;
        default:
            break;
        }
    }
    else if ( aSelOID.isAdditionalShape() )
    {
        return true;
    }
 
    return false;
}
 
bool ChartController::isShapeContext() const
{
    return m_aSelection.isAdditionalShapeSelected() ||
         ( m_pDrawViewWrapper && m_pDrawViewWrapper->AreObjectsMarked() &&
           ( m_pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_TEXT ) );
}
 
void ChartController::impl_ClearSelection()
{
    if( m_aSelection.hasSelection())
    {
        m_aSelection.clearSelection();
        impl_notifySelectionChangeListeners();
    }
}
 
bool ChartController::executeDispatch_Delete()
{
    bool bReturn = false;
 
    // remove the selected object
    OUString aCID( m_aSelection.getSelectedCID() );
    if( !aCID.isEmpty() )
    {
        if( !isObjectDeleteable( uno::Any( aCID ) ) )
            return false;
 
        //remove chart object
        uno::Reference< chart2::XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY );
        if( !xChartDoc.is() )
            return false;
 
        ObjectType aObjectType( ObjectIdentifier::getObjectType( aCID ));
        switch( aObjectType )
        {
            case OBJECTTYPE_TITLE:
            {
                UndoGuard aUndoGuard(
                    ActionDescriptionProvider::createDescription(
                        ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_TITLE )),
                    m_xUndoManager );
                TitleHelper::removeTitle(
                    ObjectIdentifier::getTitleTypeForCID( aCID ), getModel() );
                bReturn = true;
                aUndoGuard.commit();
                break;
            }
            case OBJECTTYPE_LEGEND:
            {
                uno::Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
                if( xDiagram.is())
                {
                    uno::Reference< beans::XPropertySet > xLegendProp( xDiagram->getLegend(), uno::UNO_QUERY );
                    if( xLegendProp.is())
                    {
                        UndoGuard aUndoGuard(
                            ActionDescriptionProvider::createDescription(
                                ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_LEGEND )),
                            m_xUndoManager );
                        xLegendProp->setPropertyValue( "Show", uno::Any( false ));
                        bReturn = true;
                        aUndoGuard.commit();
                    }
                }
                break;
            }
 
            case OBJECTTYPE_DATA_SERIES:
                bReturn = lcl_deleteDataSeries( aCID, getModel(), m_xUndoManager );
                break;
 
            case OBJECTTYPE_LEGEND_ENTRY:
            {
                ObjectType eParentObjectType = ObjectIdentifier::getObjectType(
                    ObjectIdentifier::getFullParentParticle( aCID ));
                if( eParentObjectType == OBJECTTYPE_DATA_SERIES )
                {
                    bReturn = lcl_deleteDataSeries( aCID, getModel(), m_xUndoManager );
                }
                else if( eParentObjectType == OBJECTTYPE_DATA_CURVE )
                {
                    sal_Int32 nEndPos = aCID.lastIndexOf(':');
                    OUString aParentCID = aCID.copy(0, nEndPos);
 
                    bReturn = lcl_deleteDataCurve(aParentCID, getModel(), m_xUndoManager );
                }
                else if( eParentObjectType == OBJECTTYPE_DATA_AVERAGE_LINE )
                {
                    executeDispatch_DeleteMeanValue();
                    bReturn = true;
                }
                break;
            }
 
            case OBJECTTYPE_DATA_AVERAGE_LINE:
            {
                uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt(
                    ObjectIdentifier::getObjectPropertySet(
                        ObjectIdentifier::getFullParentParticle( aCID ), getModel()), uno::UNO_QUERY );
                if( xRegCurveCnt.is())
                {
                    UndoGuard aUndoGuard(
                        ActionDescriptionProvider::createDescription(
                            ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_AVERAGE_LINE )),
                        m_xUndoManager );
                    RegressionCurveHelper::removeMeanValueLine( xRegCurveCnt );
                    bReturn = true;
                    aUndoGuard.commit();
                }
            }
            break;
 
            case OBJECTTYPE_DATA_CURVE:
            {
                bReturn = lcl_deleteDataCurve( aCID, getModel(), m_xUndoManager );
            }
            break;
 
            case OBJECTTYPE_DATA_CURVE_EQUATION:
            {
                uno::Reference< beans::XPropertySet > xEqProp(
                    ObjectIdentifier::getObjectPropertySet( aCID, getModel()));
 
                if( xEqProp.is())
                {
                    uno::Reference< frame::XModel > xModel( getModel() );
                    UndoGuard aUndoGuard(
                        ActionDescriptionProvider::createDescription(
                            ActionDescriptionProvider::ActionType::Delete, SchResId( STR_OBJECT_CURVE_EQUATION )),
                        m_xUndoManager );
                    {
                        ControllerLockGuardUNO aCtlLockGuard( xModel );
                        xEqProp->setPropertyValue( "ShowEquation", uno::Any( false ));
                        xEqProp->setPropertyValue( "XName", uno::Any( OUString("x") ));
                        xEqProp->setPropertyValue( "YName", uno::Any( OUString("f(x)") ));
                        xEqProp->setPropertyValue( "ShowCorrelationCoefficient", uno::Any( false ));
                    }
                    bReturn = true;
                    aUndoGuard.commit();
                }
            }
            break;
 
            case OBJECTTYPE_DATA_ERRORS_X:
            case OBJECTTYPE_DATA_ERRORS_Y:
            case OBJECTTYPE_DATA_ERRORS_Z:
            {
                uno::Reference< beans::XPropertySet > xErrorBarProp(
                    ObjectIdentifier::getObjectPropertySet( aCID, getModel() ));
                if( xErrorBarProp.is())
                {
                    const char* pId;
 
                    if ( aObjectType == OBJECTTYPE_DATA_ERRORS_X )
                        pId = STR_OBJECT_ERROR_BARS_X;
                    else if ( aObjectType == OBJECTTYPE_DATA_ERRORS_Y )
                        pId = STR_OBJECT_ERROR_BARS_Y;
                    else
                        pId = STR_OBJECT_ERROR_BARS_Z;
 
                    uno::Reference< frame::XModel > xModel( getModel() );
                    UndoGuard aUndoGuard(
                        ActionDescriptionProvider::createDescription(
                            ActionDescriptionProvider::ActionType::Delete, SchResId(pId)),
                        m_xUndoManager);
                    {
                        ControllerLockGuardUNO aCtlLockGuard( xModel );
                        xErrorBarProp->setPropertyValue(
                            "ErrorBarStyle",
                            uno::Any( css::chart::ErrorBarStyle::NONE ));
                    }
                    bReturn = true;
                    aUndoGuard.commit();
                }
                break;
            }
 
            case OBJECTTYPE_DATA_LABELS:
            case OBJECTTYPE_DATA_LABEL:
            {
                uno::Reference< beans::XPropertySet > xObjectProperties =
                    ObjectIdentifier::getObjectPropertySet( aCID, getModel() );
                if( xObjectProperties.is() )
                {
                    UndoGuard aUndoGuard(
                        ActionDescriptionProvider::createDescription(
                        ActionDescriptionProvider::ActionType::Delete,
                            SchResId( aObjectType == OBJECTTYPE_DATA_LABEL ? STR_OBJECT_LABEL : STR_OBJECT_DATALABELS )),
                                m_xUndoManager );
                    chart2::DataPointLabel aLabel;
                    xObjectProperties->getPropertyValue(CHART_UNONAME_LABEL) >>= aLabel;
                    aLabel.ShowNumber = false;
                    aLabel.ShowNumberInPercent = false;
                    aLabel.ShowCategoryName = false;
                    aLabel.ShowLegendSymbol = false;
                    if( aObjectType == OBJECTTYPE_DATA_LABELS )
                    {
                        uno::Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( aCID, getModel() ));
                        ::chart::DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, CHART_UNONAME_LABEL, uno::Any(aLabel) );
                    }
                    else
                        xObjectProperties->setPropertyValue( CHART_UNONAME_LABEL, uno::Any(aLabel) );
                    bReturn = true;
                    aUndoGuard.commit();
                }
                break;
            }
            case OBJECTTYPE_AXIS:
            {
                executeDispatch_DeleteAxis();
                bReturn = true;
                break;
            }
            case OBJECTTYPE_GRID:
            {
                executeDispatch_DeleteMajorGrid();
                bReturn = true;
                break;
            }
            case OBJECTTYPE_SUBGRID:
            {
                executeDispatch_DeleteMinorGrid();
                bReturn = true;
                break;
            }
 
            default:
            {
                break;
            }
        }
    }
    else
    {
        //remove additional shape
        impl_ClearSelection();
        {
            SolarMutexGuard aSolarGuard;
            if ( m_pDrawViewWrapper )
            {
                m_pDrawViewWrapper->DeleteMarked();
                bReturn = true;
            }
        }
    }
    return bReturn;
}
 
void ChartController::executeDispatch_ToggleLegend()
{
    Reference< frame::XModel > xModel( getModel() );
    UndoGuard aUndoGuard(
        SchResId( STR_ACTION_TOGGLE_LEGEND ), m_xUndoManager );
    ChartModel& rModel = dynamic_cast<ChartModel&>(*xModel.get());
    Reference< beans::XPropertySet > xLegendProp( LegendHelper::getLegend(rModel), uno::UNO_QUERY );
    bool bChanged = false;
    if( xLegendProp.is())
    {
        try
        {
            bool bShow = false;
            if( xLegendProp->getPropertyValue( "Show") >>= bShow )
            {
                xLegendProp->setPropertyValue( "Show", uno::Any( ! bShow ));
                bChanged = true;
            }
        }
        catch( const uno::Exception & )
        {
            DBG_UNHANDLED_EXCEPTION("chart2");
        }
    }
    else
    {
        xLegendProp.set( LegendHelper::getLegend(rModel, m_xCC, true), uno::UNO_QUERY );
        if( xLegendProp.is())
            bChanged = true;
    }
 
    if( bChanged )
        aUndoGuard.commit();
}
 
void ChartController::executeDispatch_ToggleGridHorizontal()
{
    UndoGuard aUndoGuard(
        SchResId( STR_ACTION_TOGGLE_GRID_HORZ ), m_xUndoManager );
    Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( getModel() ));
    if( xDiagram.is())
    {
        sal_Int32 nDimensionIndex = 1;
        sal_Int32 nCooSysIndex = 0;
 
        bool bHasMajorYGrid = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, true,  xDiagram );
        bool bHasMinorYGrid = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, false, xDiagram );
 
        if( bHasMajorYGrid )
        {
            if ( bHasMinorYGrid )
            {
                AxisHelper::hideGrid( nDimensionIndex, nCooSysIndex, true,  xDiagram );
                AxisHelper::hideGrid( nDimensionIndex, nCooSysIndex, false, xDiagram );
            }
            else
            {
                AxisHelper::showGrid( nDimensionIndex, nCooSysIndex, false, xDiagram );
            }
        }
        else
        {
            AxisHelper::showGrid( nDimensionIndex, nCooSysIndex, true, xDiagram );
        }
        aUndoGuard.commit();
    }
}
 
void ChartController::executeDispatch_ToggleGridVertical()
{
    UndoGuard aUndoGuard(
        SchResId( STR_ACTION_TOGGLE_GRID_VERTICAL ), m_xUndoManager );
    Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( getModel() ));
    if( xDiagram.is())
    {
        sal_Int32 nDimensionIndex = 0;
        sal_Int32 nCooSysIndex = 0;
 
        bool bHasMajorXGrid = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, true,  xDiagram );
        bool bHasMinorXGrid = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, false, xDiagram );
        if( bHasMajorXGrid )
        {
            if (bHasMinorXGrid)
            {
                AxisHelper::hideGrid( nDimensionIndex, nCooSysIndex, true,  xDiagram );
                AxisHelper::hideGrid( nDimensionIndex, nCooSysIndex, false, xDiagram );
            }
            else
            {
                AxisHelper::showGrid( nDimensionIndex, nCooSysIndex, false, xDiagram );
            }
        }
        else
        {
            AxisHelper::showGrid( nDimensionIndex, nCooSysIndex, true, xDiagram );
        }
 
        aUndoGuard.commit();
    }
}
 
void ChartController::executeDispatch_LOKSetTextSelection(int nType, int nX, int nY)
{
    if (m_pDrawViewWrapper)
    {
        if (m_pDrawViewWrapper->IsTextEdit())
        {
            OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView();
            if (pOutlinerView)
            {
                EditView& rEditView = pOutlinerView->GetEditView();
                Point aPoint(convertTwipToMm100(nX), convertTwipToMm100(nY));
                switch (nType)
                {
                    case LOK_SETTEXTSELECTION_START:
                        rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/false, /*bClearMark=*/false);
                        break;
                    case LOK_SETTEXTSELECTION_END:
                        rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/false);
                        break;
                    case LOK_SETTEXTSELECTION_RESET:
                        rEditView.SetCursorLogicPosition(aPoint, /*bPoint=*/true, /*bClearMark=*/true);
                        break;
                    default:
                        assert(false);
                        break;
                }
            }
        }
    }
}
 
void ChartController::impl_ShapeControllerDispatch( const util::URL& rURL, const Sequence< beans::PropertyValue >& rArgs )
{
    Reference< frame::XDispatch > xDispatch( m_aDispatchContainer.getShapeController() );
    if ( xDispatch.is() )
    {
        xDispatch->dispatch( rURL, rArgs );
    }
}
 
void ChartController::impl_switchDiagramPositioningToExcludingPositioning()
{
    UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription(
        ActionDescriptionProvider::ActionType::PosSize,
        ObjectNameProvider::getName( OBJECTTYPE_DIAGRAM)),
        m_xUndoManager );
    ChartModel& rModel = dynamic_cast<ChartModel&>(*m_aModel->getModel().get());
    if (DiagramHelper::switchDiagramPositioningToExcludingPositioning(rModel, true, true))
        aUndoGuard.commit();
}
 
} //  namespace chart
 
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

V1019 Compound assignment expression is used inside condition.