summaryrefslogtreecommitdiff
path: root/chart2/source/view/main/ChartView.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'chart2/source/view/main/ChartView.cxx')
-rw-r--r--chart2/source/view/main/ChartView.cxx2888
1 files changed, 2888 insertions, 0 deletions
diff --git a/chart2/source/view/main/ChartView.cxx b/chart2/source/view/main/ChartView.cxx
new file mode 100644
index 000000000000..fed4b52f3b5f
--- /dev/null
+++ b/chart2/source/view/main/ChartView.cxx
@@ -0,0 +1,2888 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ChartView.cxx,v $
+ * $Revision: 1.46.22.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_chart2.hxx"
+
+#include "ChartView.hxx"
+#include "chartview/DrawModelWrapper.hxx"
+#include "ViewDefines.hxx"
+#include "VDiagram.hxx"
+#include "VTitle.hxx"
+#include "ShapeFactory.hxx"
+#include "VCoordinateSystem.hxx"
+#include "VSeriesPlotter.hxx"
+#include "CommonConverters.hxx"
+#include "macros.hxx"
+#include "TitleHelper.hxx"
+#include "LegendHelper.hxx"
+#include "VLegend.hxx"
+#include "PropertyMapper.hxx"
+#include "ChartModelHelper.hxx"
+#include "ChartTypeHelper.hxx"
+#include "ScaleAutomatism.hxx"
+#include "MinimumAndMaximumSupplier.hxx"
+#include "ObjectIdentifier.hxx"
+#include "DiagramHelper.hxx"
+#include "RelativePositionHelper.hxx"
+#include "servicenames.hxx"
+#include "AxisHelper.hxx"
+#include "AxisIndexDefines.hxx"
+#include "ControllerLockGuard.hxx"
+#include "BaseGFXHelper.hxx"
+#include "DataSeriesHelper.hxx"
+
+#include <comphelper/scopeguard.hxx>
+#include <boost/bind.hpp>
+#include <unotools/streamwrap.hxx>
+// header for class LocaleDataWrapper
+#include <unotools/localedatawrapper.hxx>
+// header for class SdrPage
+#include <svx/svdpage.hxx>
+// header for class SvxDrawPage
+#include <svx/unopage.hxx>
+// header for class SvxShape
+#include <svx/unoshape.hxx>
+// header for class Application
+#include <vcl/svapp.hxx>
+#include <vos/mutex.hxx>
+
+#include <time.h>
+
+#include <com/sun/star/chart/ChartAxisPosition.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
+#include <com/sun/star/chart/MissingValueTreatment.hpp>
+#include <com/sun/star/chart2/ExplicitSubIncrement.hpp>
+#include <com/sun/star/chart2/StackingDirection.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
+#include <com/sun/star/chart2/XChartTypeContainer.hpp>
+#include <com/sun/star/chart2/XDataSeriesContainer.hpp>
+#include <com/sun/star/chart2/XTitled.hpp>
+#include <com/sun/star/chart2/RelativePosition.hpp>
+#include <com/sun/star/chart2/RelativeSize.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/XShapeGroup.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/util/XModifiable.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
+#include <svl/languageoptions.hxx>
+#include <sot/clsids.hxx>
+
+//.............................................................................
+namespace chart
+{
+//.............................................................................
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::chart2;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+using rtl::OUString;
+
+//static
+const uno::Sequence<sal_Int8>& ExplicitValueProvider::getUnoTunnelId()
+{
+ static uno::Sequence<sal_Int8> * pSeq = 0;
+ if( !pSeq )
+ {
+ osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
+ if( !pSeq )
+ {
+ static uno::Sequence< sal_Int8 > aSeq( 16 );
+ rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
+ pSeq = &aSeq;
+ }
+ }
+ return *pSeq;
+}
+
+//static
+ExplicitValueProvider* ExplicitValueProvider::getExplicitValueProvider(
+ const Reference< uno::XInterface >& xChartView )
+{
+ ExplicitValueProvider* pExplicitValueProvider=0;
+
+ Reference< lang::XUnoTunnel > xTunnel( xChartView, uno::UNO_QUERY );
+ if( xTunnel.is() )
+ {
+ pExplicitValueProvider = reinterpret_cast<ExplicitValueProvider*>(xTunnel->getSomething(
+ ExplicitValueProvider::getUnoTunnelId() ));
+ }
+ return pExplicitValueProvider;
+}
+
+ChartView::ChartView(
+ uno::Reference<uno::XComponentContext> const & xContext)
+ : m_aMutex()
+ , m_xCC(xContext)
+ , m_xChartModel()
+ , m_xShapeFactory()
+ , m_xDrawPage()
+ , m_pDrawModelWrapper()
+ , m_aListenerContainer( m_aMutex )
+ , m_bViewDirty(true)
+ , m_bInViewUpdate(false)
+ , m_bViewUpdatePending(false)
+ , m_bRefreshAddIn(true)
+ , m_aPageResolution(1000,1000)
+ , m_bPointsWereSkipped(false)
+ , m_nScaleXNumerator(1)
+ , m_nScaleXDenominator(1)
+ , m_nScaleYNumerator(1)
+ , m_nScaleYDenominator(1)
+ , m_bSdrViewIsInEditMode(sal_False)
+{
+}
+
+void ChartView::impl_setChartModel( const uno::Reference< frame::XModel >& xChartModel )
+{
+ if( m_xChartModel != xChartModel )
+ {
+ m_xChartModel = xChartModel;
+ m_bViewDirty = true;
+ }
+}
+
+void SAL_CALL ChartView::initialize( const uno::Sequence< uno::Any >& aArguments )
+ throw ( uno::Exception, uno::RuntimeException)
+{
+ DBG_ASSERT(aArguments.getLength() >= 1,"need 1 argument to initialize the view: xModel");
+ if( !(aArguments.getLength() >= 1) )
+ return;
+
+ uno::Reference< frame::XModel > xNewChartModel;
+ if( !(aArguments[0] >>= xNewChartModel) )
+ {
+ DBG_ERROR( "need a Reference to frame::XModel as first parameter for view initialization" );
+ }
+ impl_setChartModel( xNewChartModel );
+
+ if( !m_pDrawModelWrapper.get() )
+ {
+ // /--
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ m_pDrawModelWrapper = ::boost::shared_ptr< DrawModelWrapper >( new DrawModelWrapper( m_xCC ) );
+ m_xShapeFactory = m_pDrawModelWrapper->getShapeFactory();
+ m_xDrawPage = m_pDrawModelWrapper->getMainDrawPage();
+ StartListening( m_pDrawModelWrapper->getSdrModel(), FALSE /*bPreventDups*/ );
+ // \--
+ }
+}
+
+ChartView::~ChartView()
+{
+ if( m_pDrawModelWrapper.get() )
+ EndListening( m_pDrawModelWrapper->getSdrModel(), FALSE /*bAllDups*/ );
+ m_xDrawPage = NULL;
+ impl_deleteCoordinateSystems();
+}
+
+void ChartView::impl_deleteCoordinateSystems()
+{
+ //delete all coordinate systems
+ ::std::vector< VCoordinateSystem* >::const_iterator aIter = m_aVCooSysList.begin();
+ const ::std::vector< VCoordinateSystem* >::const_iterator aEnd = m_aVCooSysList.end();
+ for( ; aIter != aEnd; aIter++ )
+ {
+ delete *aIter;
+ }
+ m_aVCooSysList.clear();
+}
+
+
+//-----------------------------------------------------------------
+// datatransfer::XTransferable
+namespace
+{
+const rtl::OUString lcl_aGDIMetaFileMIMEType(
+ RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""));
+const rtl::OUString lcl_aGDIMetaFileMIMETypeHighContrast(
+ RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\""));
+} // anonymous namespace
+
+void ChartView::getMetaFile( const uno::Reference< io::XOutputStream >& xOutStream
+ , bool bUseHighContrast )
+{
+ if( !m_xDrawPage.is() )
+ return;
+
+ uno::Reference< lang::XMultiServiceFactory > xFactory( m_xCC->getServiceManager(), uno::UNO_QUERY );
+ if( !xFactory.is() )
+ return;
+
+ // creating the graphic exporter
+ uno::Reference< document::XExporter > xExporter( xFactory->createInstance(
+ C2U("com.sun.star.drawing.GraphicExportFilter")), uno::UNO_QUERY);
+ uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY );
+
+ if( !xExporter.is() || !xFilter.is() )
+ return;
+
+ uno::Sequence< beans::PropertyValue > aProps(3);
+ aProps[0].Name = C2U("FilterName");
+ aProps[0].Value <<= C2U("SVM");
+
+ aProps[1].Name = C2U("OutputStream");
+ aProps[1].Value <<= xOutStream;
+
+ uno::Sequence< beans::PropertyValue > aFilterData(4);
+ aFilterData[0].Name = C2U("ExportOnlyBackground");
+ aFilterData[0].Value <<= sal_False;
+ aFilterData[1].Name = C2U("HighContrast");
+ aFilterData[1].Value <<= bUseHighContrast;
+
+ aFilterData[2].Name = C2U("Version");
+ const sal_Int32 nVersion = SOFFICE_FILEFORMAT_50;
+ aFilterData[2].Value <<= nVersion;
+
+ aFilterData[3].Name = C2U("CurrentPage");
+ aFilterData[3].Value <<= uno::Reference< uno::XInterface >( m_xDrawPage, uno::UNO_QUERY );
+
+ //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
+ {
+ aFilterData.realloc( aFilterData.getLength()+4 );
+ aFilterData[4].Name = C2U("ScaleXNumerator");
+ aFilterData[4].Value = uno::makeAny( m_nScaleXNumerator );
+ aFilterData[5].Name = C2U("ScaleXDenominator");
+ aFilterData[5].Value = uno::makeAny( m_nScaleXDenominator );
+ aFilterData[6].Name = C2U("ScaleYNumerator");
+ aFilterData[6].Value = uno::makeAny( m_nScaleYNumerator );
+ aFilterData[7].Name = C2U("ScaleYDenominator");
+ aFilterData[7].Value = uno::makeAny( m_nScaleYDenominator );
+ }
+
+ aProps[2].Name = C2U("FilterData");
+ aProps[2].Value <<= aFilterData;
+
+ xExporter->setSourceDocument( uno::Reference< lang::XComponent >( m_xDrawPage, uno::UNO_QUERY) );
+ if( xFilter->filter( aProps ) )
+ {
+ xOutStream->flush();
+ xOutStream->closeOutput();
+ uno::Reference< io::XSeekable > xSeekable( xOutStream, uno::UNO_QUERY );
+ if( xSeekable.is() )
+ xSeekable->seek(0);
+ }
+}
+
+uno::Any SAL_CALL ChartView::getTransferData( const datatransfer::DataFlavor& aFlavor )
+ throw (datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException)
+{
+ bool bHighContrastMetaFile( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast));
+ uno::Any aRet;
+ if( ! (bHighContrastMetaFile || aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType)) )
+ return aRet;
+
+ impl_updateView();
+
+ SvMemoryStream aStream( 1024, 1024 );
+ utl::OStreamWrapper* pStreamWrapper = new utl::OStreamWrapper( aStream );
+
+ uno::Reference< io::XOutputStream > xOutStream( pStreamWrapper );
+ uno::Reference< io::XInputStream > xInStream( pStreamWrapper );
+ uno::Reference< io::XSeekable > xSeekable( pStreamWrapper );
+
+ if( xOutStream.is() )
+ {
+ this->getMetaFile( xOutStream, bHighContrastMetaFile );
+
+ if( xInStream.is() && xSeekable.is() )
+ {
+ xSeekable->seek(0);
+ sal_Int32 nBytesToRead = xInStream->available();
+ uno::Sequence< sal_Int8 > aSeq( nBytesToRead );
+ xInStream->readBytes( aSeq, nBytesToRead);
+ aRet <<= aSeq;
+ xInStream->closeInput();
+ }
+ }
+
+ return aRet;
+}
+uno::Sequence< datatransfer::DataFlavor > SAL_CALL ChartView::getTransferDataFlavors()
+ throw (uno::RuntimeException)
+{
+ uno::Sequence< datatransfer::DataFlavor > aRet(2);
+
+ aRet[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMEType,
+ C2U( "GDIMetaFile" ),
+ ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
+ aRet[1] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast,
+ C2U( "GDIMetaFile" ),
+ ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
+
+ return aRet;
+}
+::sal_Bool SAL_CALL ChartView::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
+ throw (uno::RuntimeException)
+{
+ return ( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType) ||
+ aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast) );
+}
+
+//-----------------------------------------------------------------
+// ____ XUnoTunnel ___
+::sal_Int64 SAL_CALL ChartView::getSomething( const uno::Sequence< ::sal_Int8 >& aIdentifier )
+ throw( uno::RuntimeException)
+{
+ if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( ExplicitValueProvider::getUnoTunnelId().getConstArray(),
+ aIdentifier.getConstArray(), 16 ) )
+ {
+ ExplicitValueProvider* pProvider = this;
+ return reinterpret_cast<sal_Int64>(pProvider);
+ }
+ return 0;
+}
+
+//-----------------------------------------------------------------
+// lang::XServiceInfo
+
+APPHELPER_XSERVICEINFO_IMPL(ChartView,CHART_VIEW_SERVICE_IMPLEMENTATION_NAME)
+
+ uno::Sequence< rtl::OUString > ChartView
+::getSupportedServiceNames_Static()
+{
+ uno::Sequence< rtl::OUString > aSNS( 1 );
+ aSNS.getArray()[ 0 ] = CHART_VIEW_SERVICE_NAME;
+ return aSNS;
+}
+
+//-----------------------------------------------------------------
+//-----------------------------------------------------------------
+
+::basegfx::B3DHomMatrix createTransformationSceneToScreen(
+ const ::basegfx::B2IRectangle& rDiagramRectangleWithoutAxes )
+{
+ ::basegfx::B3DHomMatrix aM;
+ aM.scale(double(rDiagramRectangleWithoutAxes.getWidth())/FIXED_SIZE_FOR_3D_CHART_VOLUME
+ , -double(rDiagramRectangleWithoutAxes.getHeight())/FIXED_SIZE_FOR_3D_CHART_VOLUME, 1.0 );
+ aM.translate(double(rDiagramRectangleWithoutAxes.getMinX())
+ , double(rDiagramRectangleWithoutAxes.getMinY()+rDiagramRectangleWithoutAxes.getHeight()-1), 0);
+ return aM;
+}
+
+VCoordinateSystem* findInCooSysList( const std::vector< VCoordinateSystem* >& rVCooSysList
+ , const uno::Reference< XCoordinateSystem >& xCooSys )
+{
+ for( size_t nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+ if(pVCooSys->getModel()==xCooSys)
+ return pVCooSys;
+ }
+ return NULL;
+}
+
+VCoordinateSystem* addCooSysToList( std::vector< VCoordinateSystem* >& rVCooSysList
+ , const uno::Reference< XCoordinateSystem >& xCooSys
+ , const uno::Reference< frame::XModel >& xChartModel )
+{
+ VCoordinateSystem* pVCooSys = findInCooSysList( rVCooSysList, xCooSys );
+ if( !pVCooSys )
+ {
+ pVCooSys = VCoordinateSystem::createCoordinateSystem(xCooSys );
+ if(pVCooSys)
+ {
+ rtl::OUString aCooSysParticle( ObjectIdentifier::createParticleForCoordinateSystem( xCooSys, xChartModel ) );
+ pVCooSys->setParticle(aCooSysParticle);
+
+ rVCooSysList.push_back( pVCooSys );
+ }
+ }
+ return pVCooSys;
+}
+
+VCoordinateSystem* lcl_getCooSysForPlotter( const std::vector< VCoordinateSystem* >& rVCooSysList, MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
+{
+ if(!pMinimumAndMaximumSupplier)
+ return 0;
+ for( size_t nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+ if(pVCooSys->hasMinimumAndMaximumSupplier( pMinimumAndMaximumSupplier ))
+ return pVCooSys;
+ }
+ return 0;
+}
+
+typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex; //first index is the dimension, second index is the axis index that indicates wether this is a main or secondary axis
+typedef std::pair< VCoordinateSystem* , tFullAxisIndex > tFullCoordinateSystem;
+typedef std::map< VCoordinateSystem*, tFullAxisIndex > tCoordinateSystemMap;
+
+struct AxisUsage
+{
+ AxisUsage();
+ ~AxisUsage();
+
+ void addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+ ::std::vector< VCoordinateSystem* > getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
+ sal_Int32 getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex );
+ //tFullAxisIndex getDimensionAndIndexForCooSys( VCoordinateSystem* pCooSys );
+
+ ScaleAutomatism aScaleAutomatism;
+
+private:
+ tCoordinateSystemMap aCoordinateSystems;
+ std::map< sal_Int32, sal_Int32 > aMaxIndexPerDimension;
+};
+
+AxisUsage::AxisUsage()
+ : aScaleAutomatism(AxisHelper::createDefaultScale())
+{
+}
+
+AxisUsage::~AxisUsage()
+{
+ aCoordinateSystems.clear();
+}
+
+/*
+tFullScaleIndex AxisUsage::getDimensionAndIndexForCooSys( VCoordinateSystem* pCooSys )
+{
+ tFullScaleIndex aRet(0,0);
+
+ tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) );
+ if(aFound!=aCoordinateSystems.end())
+ aRet = aFound->second;
+
+ return aRet;
+}
+*/
+
+void AxisUsage::addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ if(!pCooSys)
+ return;
+
+ tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
+ tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) );
+
+ //use one scale only once for each coordinate system
+ //main axis are preferred over secondary axis
+ //value scales are preferred
+ if(aFound!=aCoordinateSystems.end())
+ {
+ sal_Int32 nFoundAxisIndex = aFound->second.second;
+ if( nFoundAxisIndex < nAxisIndex )
+ return;
+ sal_Int32 nFoundDimension = aFound->second.first;
+ if( nFoundDimension ==1 )
+ return;
+ if( nFoundDimension < nDimensionIndex )
+ return;
+ }
+ aCoordinateSystems[pCooSys] = aFullAxisIndex;
+
+ //set maximum scale index
+ std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex);
+ if( aIter != aMaxIndexPerDimension.end() )
+ {
+ sal_Int32 nCurrentMaxIndex = aIter->second;
+ if( nCurrentMaxIndex < nAxisIndex )
+ aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex;
+ }
+ else
+ aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex;
+}
+::std::vector< VCoordinateSystem* > AxisUsage::getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
+{
+ ::std::vector< VCoordinateSystem* > aRet;
+
+ tCoordinateSystemMap::const_iterator aIter;
+ for( aIter = aCoordinateSystems.begin(); aIter!=aCoordinateSystems.end();++aIter )
+ {
+ if( aIter->second.first != nDimensionIndex )
+ continue;
+ if( aIter->second.second != nAxisIndex )
+ continue;
+ aRet.push_back( aIter->first );
+ }
+
+ return aRet;
+}
+sal_Int32 AxisUsage::getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex )
+{
+ sal_Int32 nRet = -1;
+ std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex);
+ if( aIter != aMaxIndexPerDimension.end() )
+ nRet = aIter->second;
+ return nRet;
+}
+
+//-----------------------------------------------------
+
+class SeriesPlotterContainer
+{
+public:
+ SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList );
+ ~SeriesPlotterContainer();
+
+ void initializeCooSysAndSeriesPlotter( const uno::Reference< frame::XModel >& xChartModel );
+ void initAxisUsageList();
+ void doAutoScaling( const uno::Reference< frame::XModel >& xChartModel );
+ void updateScalesAndIncrementsOnAxes();
+ void setScalesFromCooSysToPlotter();
+ void setNumberFormatsFromAxes();
+ drawing::Direction3D getPreferredAspectRatio();
+
+ std::vector< VSeriesPlotter* >& getSeriesPlotterList() { return m_aSeriesPlotterList; }
+ std::vector< VCoordinateSystem* >& getCooSysList() { return m_rVCooSysList; }
+ std::vector< LegendEntryProvider* > getLegendEntryProviderList();
+
+ void AdaptScaleOfYAxisWithoutAttachedSeries( const uno::Reference< frame::XModel >& xChartModel );
+
+private:
+ std::vector< VSeriesPlotter* > m_aSeriesPlotterList;
+ std::vector< VCoordinateSystem* >& m_rVCooSysList;
+ ::std::map< uno::Reference< XAxis >, AxisUsage > m_aAxisUsageList;
+ sal_Int32 m_nMaxAxisIndex;
+ bool m_bShiftXAxisTicks;
+};
+
+SeriesPlotterContainer::SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList )
+ : m_rVCooSysList( rVCooSysList )
+ , m_nMaxAxisIndex(0)
+ , m_bShiftXAxisTicks(false)
+{
+}
+
+SeriesPlotterContainer::~SeriesPlotterContainer()
+{
+ // - remove plotter from coordinatesystems
+ for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
+ m_rVCooSysList[nC]->clearMinimumAndMaximumSupplierList();
+ // - delete all plotter
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
+ for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ delete *aPlotterIter;
+ m_aSeriesPlotterList.clear();
+}
+
+std::vector< LegendEntryProvider* > SeriesPlotterContainer::getLegendEntryProviderList()
+{
+ std::vector< LegendEntryProvider* > aRet( m_aSeriesPlotterList.size() );
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
+ sal_Int32 nN = 0;
+ for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter, nN++ )
+ aRet[nN] = *aPlotterIter;
+ return aRet;
+}
+
+void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(
+ const uno::Reference< frame::XModel >& xChartModel )
+{
+ //------------ get model series from model
+ sal_Int32 nDiagramIndex = 0;//todo if more than one diagam is supported
+ uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
+ if( !xDiagram.is())
+ return;
+
+ uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartModel, uno::UNO_QUERY );
+
+ sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
+ if(!nDimensionCount)
+ {
+ //@todo handle mixed dimension
+ nDimensionCount = 2;
+ }
+
+ sal_Bool bSortByXValues = sal_False;
+ sal_Bool bConnectBars = sal_False;
+ sal_Bool bGroupBarsPerAxis = sal_True;
+ sal_Bool bIncludeHiddenCells = sal_True;
+ sal_Int32 nStartingAngle = 90;
+ try
+ {
+ uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY_THROW );
+ xDiaProp->getPropertyValue( C2U( "SortByXValues" ) ) >>= bSortByXValues;
+ xDiaProp->getPropertyValue( C2U( "ConnectBars" ) ) >>= bConnectBars;
+ xDiaProp->getPropertyValue( C2U( "GroupBarsPerAxis" ) ) >>= bGroupBarsPerAxis;
+ xDiaProp->getPropertyValue( C2U( "IncludeHiddenCells" ) ) >>= bIncludeHiddenCells;
+ xDiaProp->getPropertyValue( C2U( "StartingAngle" ) ) >>= nStartingAngle;
+ }
+ catch( const uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+
+ //---------------------------------------------------------------------
+ //prepare for autoscaling and shape creation
+ // - create plotter for charttypes (for each first scale group at each plotter, as they are independent)
+ // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling)
+ // - add plotter to coordinate systems
+
+ //iterate through all coordinate systems
+ uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
+ OSL_ASSERT( xCooSysContainer.is());
+ if( !xCooSysContainer.is())
+ return;
+ uno::Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
+ uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
+ sal_Int32 nGlobalSeriesIndex = 0;//for automatic symbols
+ for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
+ {
+ uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
+ VCoordinateSystem* pVCooSys = addCooSysToList(m_rVCooSysList,xCooSys,xChartModel);
+
+ //iterate through all chart types in the current coordinate system
+ uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
+ OSL_ASSERT( xChartTypeContainer.is());
+ if( !xChartTypeContainer.is() )
+ continue;
+ uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
+ for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
+ {
+ uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
+
+ if(nT==0)
+ m_bShiftXAxisTicks = ChartTypeHelper::shiftTicksAtXAxisPerDefault( xChartType );
+
+ VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( xChartType, nDimensionCount );
+ if( !pPlotter )
+ continue;
+ m_aSeriesPlotterList.push_back( pPlotter );
+ pPlotter->setNumberFormatsSupplier( xNumberFormatsSupplier );
+ pPlotter->setColorScheme( xColorScheme );
+ pPlotter->setExplicitCategoriesProvider( pVCooSys->getExplicitCategoriesProvider() );
+ sal_Int32 nMissingValueTreatment = DiagramHelper::getCorrectedMissingValueTreatment( xDiagram, xChartType );
+
+ if(pVCooSys)
+ pVCooSys->addMinimumAndMaximumSupplier(pPlotter);
+
+ //------------ add series to plotter and thus prepare him for providing minimum and maximum values
+ uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
+ OSL_ASSERT( xDataSeriesContainer.is());
+ if( !xDataSeriesContainer.is() )
+ continue;
+ sal_Int32 zSlot=-1;
+ sal_Int32 xSlot=-1;
+ sal_Int32 ySlot=-1;
+ uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
+ for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
+ {
+ uno::Reference< XDataSeries > xDataSeries( aSeriesList[nS], uno::UNO_QUERY );
+ if(!xDataSeries.is())
+ continue;
+ if( !bIncludeHiddenCells && !DataSeriesHelper::hasUnhiddenData(xDataSeries) )
+ continue;
+
+ VDataSeries* pSeries = new VDataSeries( xDataSeries );
+
+ pSeries->setGlobalSeriesIndex(nGlobalSeriesIndex);
+ nGlobalSeriesIndex++;
+
+ if( bSortByXValues )
+ pSeries->doSortByXValues();
+
+ pSeries->setConnectBars( bConnectBars );
+ pSeries->setGroupBarsPerAxis( bGroupBarsPerAxis );
+ pSeries->setStartingAngle( nStartingAngle );
+
+ pSeries->setMissingValueTreatment( nMissingValueTreatment );
+
+ rtl::OUString aSeriesParticle( ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCS, nT, nS ) );
+ pSeries->setParticle(aSeriesParticle);
+
+ OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) );
+ pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole);
+
+ //ignore secondary axis for charttypes that do not suppoert them
+ if( pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX &&
+ !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, 1 ) )
+ {
+ pSeries->setAttachedAxisIndex(MAIN_AXIS_INDEX);
+ }
+
+ StackingDirection eDirection = pSeries->getStackingDirection();
+ switch(eDirection)
+ {
+ case StackingDirection_NO_STACKING:
+ xSlot++; ySlot=-1;
+ if(zSlot<0)
+ zSlot=0;
+ break;
+ case StackingDirection_Y_STACKING:
+ ySlot++;
+ if(xSlot<0)
+ xSlot=0;
+ if(zSlot<0)
+ zSlot=0;
+ break;
+ case StackingDirection_Z_STACKING:
+ zSlot++; xSlot=-1; ySlot=-1;
+ break;
+ default:
+ // UNO enums have one additional auto-generated case
+ break;
+ }
+ pPlotter->addSeries( pSeries, zSlot, xSlot, ySlot );
+ }
+ }
+ }
+
+ //transport seriesnames to the coordinatesystems if needed
+ if( m_aSeriesPlotterList.size() )
+ {
+ uno::Sequence< rtl::OUString > aSeriesNames;
+ bool bSeriesNamesInitialized = false;
+ for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = m_rVCooSysList[nC];
+ if(!pVCooSys)
+ continue;
+ if( pVCooSys->needSeriesNamesForAxis() )
+ {
+ if(!bSeriesNamesInitialized)
+ {
+ VSeriesPlotter* pSeriesPlotter = m_aSeriesPlotterList[0];
+ if( pSeriesPlotter )
+ aSeriesNames = pSeriesPlotter->getSeriesNames();
+ bSeriesNamesInitialized = true;
+ }
+ pVCooSys->setSeriesNamesForAxis( aSeriesNames );
+ }
+ }
+ }
+}
+
+void SeriesPlotterContainer::initAxisUsageList()
+{
+ m_aAxisUsageList.clear();
+ size_t nC;
+ for( nC=0; nC < m_rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = m_rVCooSysList[nC];
+ for(sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
+ {
+ uno::Reference< XCoordinateSystem > xCooSys = pVCooSys->getModel();
+ if( nDimensionIndex >= xCooSys->getDimension() )
+ continue;
+ const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
+ {
+ uno::Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
+ OSL_ASSERT( xAxis.is());
+ if( xAxis.is())
+ {
+ if(m_aAxisUsageList.find(xAxis)==m_aAxisUsageList.end())
+ m_aAxisUsageList[xAxis].aScaleAutomatism = ScaleAutomatism(xAxis->getScaleData());
+ AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis];
+ rAxisUsage.addCoordinateSystem(pVCooSys,nDimensionIndex,nAxisIndex);
+ }
+ }
+ }
+ }
+
+ ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
+ const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
+
+ //init m_nMaxAxisIndex
+ m_nMaxAxisIndex = 0;
+ for(sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
+ {
+ for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
+ {
+ sal_Int32 nLocalMax = aAxisIter->second.getMaxAxisIndexForDimension( nDimensionIndex );
+ if( m_nMaxAxisIndex < nLocalMax )
+ m_nMaxAxisIndex = nLocalMax;
+ }
+ }
+}
+
+void SeriesPlotterContainer::setScalesFromCooSysToPlotter()
+{
+ //set scales to plotter to enable them to provide the preferred scene AspectRatio
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
+ for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter );
+ if(pVCooSys)
+ {
+ pSeriesPlotter->setScales( pVCooSys->getExplicitScales(0,0), pVCooSys->getPropertySwapXAndYAxis() );
+ sal_Int32 nMaxAxisIndex = pVCooSys->getMaximumAxisIndexByDimension(1);//only additional value axis are relevant for series plotter
+ for( sal_Int32 nI=1; nI<=nMaxAxisIndex; nI++ )
+ pSeriesPlotter->addSecondaryValueScale( pVCooSys->getExplicitScale(1,nI), nI );
+ }
+ }
+}
+
+void SeriesPlotterContainer::setNumberFormatsFromAxes()
+{
+ //set numberfarmats to plotter to enable them to display the data labels in the numberfromat of teh axis
+
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
+ for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter );
+ if(pVCooSys)
+ {
+ AxesNumberFormats aAxesNumberFormats;
+ uno::Reference< XCoordinateSystem > xCooSys = pVCooSys->getModel();
+ sal_Int32 nDimensionCount = xCooSys->getDimension();
+ for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nDimensionCount; ++nDimensionIndex)
+ {
+ const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
+ for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
+ {
+ try
+ {
+ Reference< beans::XPropertySet > xAxisProp( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY );
+ if( xAxisProp.is())
+ {
+ sal_Int32 nNumberFormatKey(0);
+ if( xAxisProp->getPropertyValue( C2U( "NumberFormat" ) ) >>= nNumberFormatKey )
+ {
+ aAxesNumberFormats.setFormat( nNumberFormatKey, nDimensionIndex, nAxisIndex );
+ }
+ }
+ }
+ catch( lang::IndexOutOfBoundsException& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ }
+ pSeriesPlotter->setAxesNumberFormats( aAxesNumberFormats );
+ }
+ }
+}
+
+void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes()
+{
+ for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
+ m_rVCooSysList[nC]->updateScalesAndIncrementsOnAxes();
+}
+
+void SeriesPlotterContainer::doAutoScaling( const uno::Reference< frame::XModel >& xChartModel )
+{
+ //precondition: need a initialized m_aSeriesPlotterList
+ //precondition: need a initialized m_aAxisUsageList
+
+ ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
+ const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
+
+ //iterate over the main scales first than secondary axis
+ size_t nC;
+ sal_Int32 nAxisIndex=0;
+ for( nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ )
+ {
+
+ // - first do autoscale for all x and z scales (because they are treated independent)
+ for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
+ {
+ AxisUsage& rAxisUsage = (*aAxisIter).second;
+ ::std::vector< VCoordinateSystem* > aVCooSysList_X = rAxisUsage.getCoordinateSystems(0,nAxisIndex);
+ ::std::vector< VCoordinateSystem* > aVCooSysList_Z = rAxisUsage.getCoordinateSystems(2,nAxisIndex);
+
+ for( nC=0; nC < aVCooSysList_X.size(); nC++)
+ aVCooSysList_X[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,0,nAxisIndex);
+ for( nC=0; nC < aVCooSysList_Z.size(); nC++)
+ aVCooSysList_Z[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,2,nAxisIndex);
+
+ ExplicitScaleData aExplicitScale;
+ ExplicitIncrementData aExplicitIncrement;
+ rAxisUsage.aScaleAutomatism.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement );
+
+ for( nC=0; nC < aVCooSysList_X.size(); nC++)
+ {
+ if( m_bShiftXAxisTicks )
+ aExplicitIncrement.ShiftedPosition = true;
+ aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ }
+ for( nC=0; nC < aVCooSysList_Z.size(); nC++)
+ aVCooSysList_Z[nC]->setExplicitScaleAndIncrement( 2, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ }
+
+ // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already )
+ for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
+ {
+ AxisUsage& rAxisUsage = (*aAxisIter).second;
+ ::std::vector< VCoordinateSystem* > aVCooSysList_X = rAxisUsage.getCoordinateSystems(0,nAxisIndex);
+ ::std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems(1,nAxisIndex);
+ ::std::vector< VCoordinateSystem* > aVCooSysList_Z = rAxisUsage.getCoordinateSystems(2,nAxisIndex);
+
+ if(!aVCooSysList_Y.size())
+ continue;
+
+ for( nC=0; nC < aVCooSysList_Y.size(); nC++)
+ aVCooSysList_Y[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,1,nAxisIndex);
+
+ ExplicitScaleData aExplicitScale;
+ ExplicitIncrementData aExplicitIncrement;
+ rAxisUsage.aScaleAutomatism.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement );
+
+ for( nC=0; nC < aVCooSysList_X.size(); nC++)
+ aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ for( nC=0; nC < aVCooSysList_Y.size(); nC++)
+ aVCooSysList_Y[nC]->setExplicitScaleAndIncrement( 1, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ for( nC=0; nC < aVCooSysList_Z.size(); nC++)
+ aVCooSysList_Z[nC]->setExplicitScaleAndIncrement( 2, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ }
+ }
+ AdaptScaleOfYAxisWithoutAttachedSeries( xChartModel );
+}
+
+void SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries( const uno::Reference< frame::XModel >& xChartModel )
+{
+ //issue #i80518#
+
+ ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
+ const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
+
+ for( sal_Int32 nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ )
+ {
+ for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
+ {
+ AxisUsage& rAxisUsage = (*aAxisIter).second;
+ ::std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems( 1, nAxisIndex );
+ if( !aVCooSysList_Y.size() )
+ continue;
+
+ uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
+ if( xDiagram.is() )
+ {
+ bool bSeriesAttachedToThisAxis = false;
+ sal_Int32 nAttachedAxisIndex = -1;
+ {
+ ::std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
+ ::std::vector< Reference< XDataSeries > >::const_iterator aIter = aSeriesVector.begin();
+ for( ; aIter != aSeriesVector.end(); aIter++ )
+ {
+ sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex( *aIter );
+ if( nAxisIndex == nCurrentIndex )
+ {
+ bSeriesAttachedToThisAxis = true;
+ break;
+ }
+ else if( nAttachedAxisIndex<0 || nAttachedAxisIndex>nCurrentIndex )
+ nAttachedAxisIndex=nCurrentIndex;
+ }
+ }
+
+ if( !bSeriesAttachedToThisAxis && nAttachedAxisIndex >= 0 )
+ {
+ for( size_t nC = 0; nC < aVCooSysList_Y.size(); ++nC )
+ {
+ aVCooSysList_Y[nC]->prepareScaleAutomatismForDimensionAndIndex( rAxisUsage.aScaleAutomatism, 1, nAttachedAxisIndex );
+
+ ExplicitScaleData aExplicitScaleSource = aVCooSysList_Y[nC]->getExplicitScale( 1,nAttachedAxisIndex );
+ ExplicitIncrementData aExplicitIncrementSource = aVCooSysList_Y[nC]->getExplicitIncrement( 1,nAttachedAxisIndex );
+
+ ExplicitScaleData aExplicitScaleDest = aVCooSysList_Y[nC]->getExplicitScale( 1,nAxisIndex );;
+ ExplicitIncrementData aExplicitIncrementDest = aVCooSysList_Y[nC]->getExplicitIncrement( 1,nAxisIndex );;
+
+ aExplicitScaleDest.Orientation = aExplicitScaleSource.Orientation;
+ aExplicitScaleDest.Scaling = aExplicitScaleSource.Scaling;
+ aExplicitScaleDest.Breaks = aExplicitScaleSource.Breaks;
+ aExplicitScaleDest.AxisType = aExplicitScaleSource.AxisType;
+
+ aExplicitIncrementDest.BaseValue = aExplicitIncrementSource.BaseValue;
+
+ ScaleData aScale( rAxisUsage.aScaleAutomatism.getScale() );
+ if( !aScale.Minimum.hasValue() )
+ {
+ bool bNewMinOK = true;
+ double fMax=0.0;
+ if( aScale.Maximum >>= fMax )
+ bNewMinOK = (aExplicitScaleSource.Minimum <= fMax);
+ if( bNewMinOK )
+ aExplicitScaleDest.Minimum = aExplicitScaleSource.Minimum;
+ }
+ else
+ aExplicitIncrementDest.BaseValue = aExplicitScaleDest.Minimum;
+
+ if( !aScale.Maximum.hasValue() )
+ {
+ bool bNewMaxOK = true;
+ double fMin=0.0;
+ if( aScale.Minimum >>= fMin )
+ bNewMaxOK = (fMin <= aExplicitScaleSource.Maximum);
+ if( bNewMaxOK )
+ aExplicitScaleDest.Maximum = aExplicitScaleSource.Maximum;
+ }
+ if( !aScale.Origin.hasValue() )
+ aExplicitScaleDest.Origin = aExplicitScaleSource.Origin;
+
+ if( !aScale.IncrementData.Distance.hasValue() )
+ aExplicitIncrementDest.Distance = aExplicitIncrementSource.Distance;
+
+ bool bAutoMinorInterval = true;
+ if( aScale.IncrementData.SubIncrements.getLength() )
+ bAutoMinorInterval = !( aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue() );
+ if( bAutoMinorInterval )
+ {
+ if( aExplicitIncrementDest.SubIncrements.getLength() && aExplicitIncrementSource.SubIncrements.getLength() )
+ aExplicitIncrementDest.SubIncrements[0].IntervalCount =
+ aExplicitIncrementSource.SubIncrements[0].IntervalCount;
+ }
+
+ aVCooSysList_Y[nC]->setExplicitScaleAndIncrement( 1, nAxisIndex, aExplicitScaleDest, aExplicitIncrementDest );
+ }
+ }
+ }
+ }
+ }
+
+ if( AxisHelper::isAxisPositioningEnabled() )
+ {
+ //correct origin for y main axis (the origin is where the other main axis crosses)
+ sal_Int32 nAxisIndex=0;
+ sal_Int32 nDimensionIndex=1;
+ for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
+ {
+ AxisUsage& rAxisUsage = (*aAxisIter).second;
+ ::std::vector< VCoordinateSystem* > aVCooSysList = rAxisUsage.getCoordinateSystems(nDimensionIndex,nAxisIndex);
+ size_t nC;
+ for( nC=0; nC < aVCooSysList.size(); nC++)
+ {
+ ExplicitScaleData aExplicitScale( aVCooSysList[nC]->getExplicitScale( nDimensionIndex, nAxisIndex ) );
+ ExplicitIncrementData aExplicitIncrement( aVCooSysList[nC]->getExplicitIncrement( nDimensionIndex, nAxisIndex ) );
+
+ Reference< chart2::XCoordinateSystem > xCooSys( aVCooSysList[nC]->getModel() );
+ Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
+ Reference< beans::XPropertySet > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis, xCooSys ), uno::UNO_QUERY );
+
+ ::com::sun::star::chart::ChartAxisPosition eCrossingMainAxisPos( ::com::sun::star::chart::ChartAxisPosition_ZERO );
+ if( xCrossingMainAxis.is() )
+ {
+ xCrossingMainAxis->getPropertyValue(C2U( "CrossoverPosition" )) >>= eCrossingMainAxisPos;
+ if( ::com::sun::star::chart::ChartAxisPosition_VALUE == eCrossingMainAxisPos )
+ {
+ double fValue = 0.0;
+ xCrossingMainAxis->getPropertyValue(C2U( "CrossoverValue" )) >>= fValue;
+ aExplicitScale.Origin = fValue;
+ }
+ else if( ::com::sun::star::chart::ChartAxisPosition_ZERO == eCrossingMainAxisPos )
+ aExplicitScale.Origin = 0.0;
+ else if( ::com::sun::star::chart::ChartAxisPosition_START == eCrossingMainAxisPos )
+ aExplicitScale.Origin = aExplicitScale.Minimum;
+ else if( ::com::sun::star::chart::ChartAxisPosition_END == eCrossingMainAxisPos )
+ aExplicitScale.Origin = aExplicitScale.Maximum;
+ }
+
+ aVCooSysList[nC]->setExplicitScaleAndIncrement( nDimensionIndex, nAxisIndex, aExplicitScale, aExplicitIncrement );
+ }
+ }
+ }
+}
+
+drawing::Direction3D SeriesPlotterContainer::getPreferredAspectRatio()
+{
+ drawing::Direction3D aPreferredAspectRatio(1.0,1.0,1.0);
+
+ sal_Int32 nPlotterCount=0;
+ //get a list of all preferred aspect ratios and combine them
+ //first with special demands wins (less or equal zero <-> arbitrary)
+ double fx, fy, fz;
+ fx = fy = fz = -1.0;
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
+ for( aPlotterIter = m_aSeriesPlotterList.begin(), nPlotterCount=0
+ ; aPlotterIter != aPlotterEnd; aPlotterIter++, nPlotterCount++ )
+ {
+ drawing::Direction3D aSingleRatio( (*aPlotterIter)->getPreferredDiagramAspectRatio() );
+ if( fx<0 && aSingleRatio.DirectionX>0 )
+ fx = aSingleRatio.DirectionX;
+
+ if( fy<0 && aSingleRatio.DirectionY>0 )
+ {
+ if( fx>0 && aSingleRatio.DirectionX>0 )
+ fy = fx*aSingleRatio.DirectionY/aSingleRatio.DirectionX;
+ else if( fz>0 && aSingleRatio.DirectionZ>0 )
+ fy = fz*aSingleRatio.DirectionY/aSingleRatio.DirectionZ;
+ else
+ fy = aSingleRatio.DirectionY;
+ }
+
+ if( fz<0 && aSingleRatio.DirectionZ>0 )
+ {
+ if( fx>0 && aSingleRatio.DirectionX>0 )
+ fz = fx*aSingleRatio.DirectionZ/aSingleRatio.DirectionX;
+ else if( fy>0 && aSingleRatio.DirectionY>0 )
+ fz = fy*aSingleRatio.DirectionZ/aSingleRatio.DirectionY;
+ else
+ fz = aSingleRatio.DirectionZ;
+ }
+
+ if( fx>0 && fy>0 && fz>0 )
+ break;
+ }
+ aPreferredAspectRatio = drawing::Direction3D(fx, fy, fz);
+ return aPreferredAspectRatio;
+}
+
+//-----------------------------------------------------
+
+namespace
+{
+
+bool lcl_resizeAfterCompleteCreation( const uno::Reference< XDiagram >& xDiagram )
+{
+ //special treatment for pie charts
+ //the size is checked after complete creation to get the datalabels into the given space
+
+ //todo: this is just a workaround at the moment for pie and donut labels
+ return DiagramHelper::isPieOrDonutChart( xDiagram );
+}
+
+void lcl_setDefaultWritingMode( ::boost::shared_ptr< DrawModelWrapper > pDrawModelWrapper, const Reference< frame::XModel >& xChartModel )
+{
+ //get writing mode from parent document:
+ if( SvtLanguageOptions().IsCTLFontEnabled() )
+ {
+ try
+ {
+ uno::Reference< container::XChild > xChild( xChartModel, uno::UNO_QUERY );
+ sal_Int16 nWritingMode=-1;
+ if ( xChild.is() )
+ {
+ uno::Reference< beans::XPropertySet > xParentProps( xChild->getParent(), uno::UNO_QUERY );
+ uno::Reference< style::XStyleFamiliesSupplier > xStyleFamiliesSupplier( xParentProps, uno::UNO_QUERY );
+ if( xStyleFamiliesSupplier.is() )
+ {
+ uno::Reference< container::XNameAccess > xStylesFamilies( xStyleFamiliesSupplier->getStyleFamilies() );
+ if( xStylesFamilies.is() )
+ {
+ if( !xStylesFamilies->hasByName( C2U("PageStyles") ) )
+ {
+ //draw/impress is parent document
+ uno::Reference< lang::XMultiServiceFactory > xFatcory( xParentProps, uno::UNO_QUERY );
+ if( xFatcory.is() )
+ {
+ uno::Reference< beans::XPropertySet > xDrawDefaults( xFatcory->createInstance( C2U( "com.sun.star.drawing.Defaults" ) ), uno::UNO_QUERY );
+ if( xDrawDefaults.is() )
+ xDrawDefaults->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
+ }
+ }
+ else
+ {
+ uno::Reference< container::XNameAccess > xPageStyles( xStylesFamilies->getByName( C2U("PageStyles") ), uno::UNO_QUERY );
+ if( xPageStyles.is() )
+ {
+ rtl::OUString aPageStyle;
+
+ uno::Reference< text::XTextDocument > xTextDocument( xParentProps, uno::UNO_QUERY );
+ if( xTextDocument.is() )
+ {
+ //writer is parent document
+ //retrieve the current page style from the text cursor property PageStyleName
+
+ uno::Reference< text::XTextEmbeddedObjectsSupplier > xTextEmbeddedObjectsSupplier( xTextDocument, uno::UNO_QUERY );
+ if( xTextEmbeddedObjectsSupplier.is() )
+ {
+ uno::Reference< container::XNameAccess > xEmbeddedObjects( xTextEmbeddedObjectsSupplier->getEmbeddedObjects() );
+ if( xEmbeddedObjects.is() )
+ {
+ uno::Sequence< rtl::OUString > aNames( xEmbeddedObjects->getElementNames() );
+
+ sal_Int32 nCount = aNames.getLength();
+ for( sal_Int32 nN=0; nN<nCount; nN++ )
+ {
+ uno::Reference< beans::XPropertySet > xEmbeddedProps( xEmbeddedObjects->getByName( aNames[nN] ), uno::UNO_QUERY );
+ if( xEmbeddedProps.is() )
+ {
+ static rtl::OUString aChartCLSID = rtl::OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName());
+ rtl::OUString aCLSID;
+ xEmbeddedProps->getPropertyValue( C2U("CLSID") ) >>= aCLSID;
+ if( aCLSID.equals(aChartCLSID) )
+ {
+ uno::Reference< frame::XModel > xModel;
+ xEmbeddedProps->getPropertyValue( C2U("Model") ) >>= xModel;
+ if( xModel == xChartModel )
+ {
+ uno::Reference< text::XTextContent > xEmbeddedObject( xEmbeddedProps, uno::UNO_QUERY );
+ if( xEmbeddedObject.is() )
+ {
+ uno::Reference< text::XTextRange > xAnchor( xEmbeddedObject->getAnchor() );
+ if( xAnchor.is() )
+ {
+ uno::Reference< beans::XPropertySet > xAnchorProps( xAnchor, uno::UNO_QUERY );
+ if( xAnchorProps.is() )
+ {
+ xAnchorProps->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
+ }
+ uno::Reference< text::XText > xText( xAnchor->getText() );
+ if( xText.is() )
+ {
+ uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
+ if( xTextCursorProps.is() )
+ xTextCursorProps->getPropertyValue( C2U("PageStyleName") ) >>= aPageStyle;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ if( !aPageStyle.getLength() )
+ {
+ uno::Reference< text::XText > xText( xTextDocument->getText() );
+ if( xText.is() )
+ {
+ uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
+ if( xTextCursorProps.is() )
+ xTextCursorProps->getPropertyValue( C2U("PageStyleName") ) >>= aPageStyle;
+ }
+ }
+ }
+ else
+ {
+ //Calc is parent document
+ xParentProps->getPropertyValue( C2U("PageStyle") ) >>= aPageStyle;
+ if(!aPageStyle.getLength())
+ aPageStyle = C2U("Default");
+ }
+ if( nWritingMode == -1 || nWritingMode == text::WritingMode2::PAGE )
+ {
+ uno::Reference< beans::XPropertySet > xPageStyle( xPageStyles->getByName( aPageStyle ), uno::UNO_QUERY );
+ if( xPageStyle.is() )
+ xPageStyle->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
+ }
+ }
+ }
+ }
+ }
+ }
+ if( nWritingMode != -1 && nWritingMode != text::WritingMode2::PAGE )
+ {
+ if( pDrawModelWrapper.get() )
+ pDrawModelWrapper->GetItemPool().SetPoolDefaultItem(SfxInt32Item(EE_PARA_WRITINGDIR, nWritingMode) );
+ }
+ }
+ catch( uno::Exception& ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+ }
+}
+
+sal_Int16 lcl_getDefaultWritingModeFromPool( ::boost::shared_ptr< DrawModelWrapper > pDrawModelWrapper )
+{
+ sal_Int16 nWritingMode = text::WritingMode2::LR_TB;
+ if( pDrawModelWrapper.get() )
+ {
+ const SfxPoolItem* pItem = &(pDrawModelWrapper->GetItemPool().GetDefaultItem( EE_PARA_WRITINGDIR ));
+ if( pItem )
+ nWritingMode = static_cast< sal_Int16 >((static_cast< const SfxInt32Item * >( pItem ))->GetValue());
+ }
+ return nWritingMode;
+}
+
+} //end anonymous namespace
+
+//------------ create complete diagram shape (inclusive axis and series)
+void ChartView::impl_createDiagramAndContent( SeriesPlotterContainer& rSeriesPlotterContainer
+ , const uno::Reference< drawing::XShapes>& xDiagramPlusAxes_Shapes
+ , const awt::Point& rAvailablePos
+ , const awt::Size& rAvailableSize
+ , const awt::Size& rPageSize )
+{
+// sal_Int32 nDiagramIndex = 0;//todo if more than one diagam is supported
+ uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) );
+ if( !xDiagram.is())
+ return;
+
+ sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
+ if(!nDimensionCount)
+ {
+ //@todo handle mixed dimension
+ nDimensionCount = 2;
+ }
+
+ ::basegfx::B2IRectangle aAvailableOuterRect( BaseGFXHelper::makeRectangle(rAvailablePos,rAvailableSize) );
+
+ const std::vector< VCoordinateSystem* >& rVCooSysList( rSeriesPlotterContainer.getCooSysList() );
+ const std::vector< VSeriesPlotter* >& rSeriesPlotterList( rSeriesPlotterContainer.getSeriesPlotterList() );
+
+ //create VAxis, so they can give necessary information for automatic scaling
+ uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( m_xChartModel, uno::UNO_QUERY );
+ size_t nC = 0;
+ for( nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+ if(3==nDimensionCount)
+ {
+ uno::Reference<beans::XPropertySet> xSceneProperties( xDiagram, uno::UNO_QUERY );
+ CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( xSceneProperties ) );
+ CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( xSceneProperties ) );
+ CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( xSceneProperties ) );
+ pVCooSys->set3DWallPositions( eLeftWallPos, eBackWallPos, eBottomPos );
+ }
+ pVCooSys->createVAxisList( xNumberFormatsSupplier
+ , rPageSize //font reference size
+ , BaseGFXHelper::B2IRectangleToAWTRectangle( aAvailableOuterRect ) //maximum space for labels
+ );
+ }
+
+
+ // - prepare list of all axis and how they are used
+ rSeriesPlotterContainer.initAxisUsageList();
+ rSeriesPlotterContainer.doAutoScaling( m_xChartModel );
+ rSeriesPlotterContainer.setScalesFromCooSysToPlotter();
+ rSeriesPlotterContainer.setNumberFormatsFromAxes();
+
+ //---------------------------------------------------------------------
+ //create shapes
+
+ //------------ create diagram shapes
+ //aspect ratio
+ drawing::Direction3D aPreferredAspectRatio(
+ rSeriesPlotterContainer.getPreferredAspectRatio() );
+
+ uno::Reference< drawing::XShapes > xSeriesTargetInFrontOfAxis(0);
+ uno::Reference< drawing::XShapes > xSeriesTargetBehindAxis(0);
+ VDiagram aVDiagram(xDiagram, aPreferredAspectRatio, nDimensionCount);
+ {//create diagram
+ aVDiagram.init(xDiagramPlusAxes_Shapes,xDiagramPlusAxes_Shapes,m_xShapeFactory);
+ aVDiagram.createShapes(rAvailablePos,rAvailableSize);
+ xSeriesTargetInFrontOfAxis = aVDiagram.getCoordinateRegion();
+ aVDiagram.reduceToMimimumSize();
+ }
+
+ uno::Reference< drawing::XShapes > xTextTargetShapes( ShapeFactory(m_xShapeFactory).createGroup2D(xDiagramPlusAxes_Shapes) );
+
+ // - create axis and grids for all coordinate systems
+
+ //init all coordinate systems
+ for( nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+ pVCooSys->initPlottingTargets(xSeriesTargetInFrontOfAxis,xTextTargetShapes,m_xShapeFactory,xSeriesTargetBehindAxis);
+
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
+
+ pVCooSys->initVAxisInList();
+ }
+
+ //calculate resulting size respecting axis label layout and fontscaling
+
+ //use first coosys only so far; todo: calculate for more than one coosys if we have more in future
+ //todo: this is just a workaround at the moment for pie and donut labels
+ if( !lcl_resizeAfterCompleteCreation(xDiagram) && rVCooSysList.size() > 0 )
+ {
+ uno::Reference< drawing::XShape > xBoundingShape( xDiagramPlusAxes_Shapes, uno::UNO_QUERY );
+
+ ::basegfx::B2IRectangle aFirstConsumedOuterRect( ShapeFactory::getRectangleOfShape(xBoundingShape) );
+
+ VCoordinateSystem* pVCooSys = rVCooSysList[0];
+ pVCooSys->createMaximumAxesLabels();
+
+ ::basegfx::B2IRectangle aConsumedOuterRect( ShapeFactory::getRectangleOfShape(xBoundingShape) );
+ ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.adjustInnerSize( aConsumedOuterRect ) );
+
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aNewInnerRect ) ));
+
+ //redo autoscaling to get size and text dependent automatic main increment count
+ rSeriesPlotterContainer.doAutoScaling( m_xChartModel );
+ rSeriesPlotterContainer.updateScalesAndIncrementsOnAxes();
+ rSeriesPlotterContainer.setScalesFromCooSysToPlotter();
+
+ pVCooSys->createAxesLabels();
+
+ bool bLessSpaceConsumedThanExpected = false;
+ {
+ ::basegfx::B2IRectangle aOldRect( aConsumedOuterRect );
+ aConsumedOuterRect = ShapeFactory::getRectangleOfShape(xBoundingShape);
+ if( aConsumedOuterRect.getMinX() > aAvailableOuterRect.getMinX()
+ || aConsumedOuterRect.getMaxX() < aAvailableOuterRect.getMaxX()
+ || aConsumedOuterRect.getMinY() > aAvailableOuterRect.getMinY()
+ || aConsumedOuterRect.getMinY() < aAvailableOuterRect.getMaxY() )
+ bLessSpaceConsumedThanExpected = true;
+ }
+
+ if( bLessSpaceConsumedThanExpected )
+ {
+ aVDiagram.adjustInnerSize( aConsumedOuterRect );
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
+ pVCooSys->updatePositions();
+ }
+ }
+
+ //create axes and grids for the final size
+ for( nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
+
+ pVCooSys->createAxesShapes();
+ pVCooSys->createGridShapes();
+ }
+
+ // - create data series for all charttypes
+ m_bPointsWereSkipped = false;
+ ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = rSeriesPlotterList.begin();
+ const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = rSeriesPlotterList.end();
+ for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ //------------ set transformation to plotter / create series
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ rtl::OUString aCID; //III
+ uno::Reference< drawing::XShapes > xSeriesTarget(0);
+ if( pSeriesPlotter->WantToPlotInFrontOfAxisLine() )
+ xSeriesTarget = xSeriesTargetInFrontOfAxis;
+ else
+ {
+ xSeriesTarget = xSeriesTargetBehindAxis;
+ DBG_ASSERT( !lcl_resizeAfterCompleteCreation(xDiagram), "not implemented yet! - during a complete recreation this shape is destroyed so no series can be created anymore" );
+ }
+ pSeriesPlotter->initPlotter( xSeriesTarget,xTextTargetShapes,m_xShapeFactory,aCID );
+ pSeriesPlotter->setPageReferenceSize( rPageSize );
+ VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
+ if(2==nDimensionCount)
+ pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
+ //better performance for big data
+ awt::Size aCoordinateRegionResolution(1000,1000);
+ {
+ //calculate resolution for coordinate system
+ Sequence<sal_Int32> aCoordinateSystemResolution = pVCooSys->getCoordinateSystemResolution( rPageSize, m_aPageResolution );
+ pSeriesPlotter->setCoordinateSystemResolution( aCoordinateSystemResolution );
+ }
+ //
+ pSeriesPlotter->createShapes();
+ m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped();
+ }
+
+ //recreate with corrected sizes if requested
+ if( lcl_resizeAfterCompleteCreation(xDiagram) )
+ {
+ m_bPointsWereSkipped = false;
+
+ uno::Reference< drawing::XShape > xBoundingShape( xDiagramPlusAxes_Shapes, uno::UNO_QUERY );
+ ::basegfx::B2IRectangle aConsumedOuterRect( ShapeFactory::getRectangleOfShape(xBoundingShape) );
+
+ ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.adjustInnerSize( aConsumedOuterRect ) );
+
+ for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ pSeriesPlotter->releaseShapes();
+ }
+
+ //clear and recreate
+ ShapeFactory::removeSubShapes( xSeriesTargetInFrontOfAxis ); //xSeriesTargetBehindAxis is a sub shape of xSeriesTargetInFrontOfAxis and will be removed here
+ xSeriesTargetBehindAxis.clear();
+ ShapeFactory::removeSubShapes( xTextTargetShapes );
+
+ //set new transformation
+ for( nC=0; nC < rVCooSysList.size(); nC++)
+ {
+ VCoordinateSystem* pVCooSys = rVCooSysList[nC];
+ pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
+ createTransformationSceneToScreen( aNewInnerRect ) ));
+ }
+
+ // - create data series for all charttypes
+ for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ //------------ set transformation to plotter / create series
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
+ if(2==nDimensionCount)
+ pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
+ pSeriesPlotter->createShapes();
+ m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped();
+ }
+
+ /*
+ uno::Reference< drawing::XShape > xDiagramPlusAxes_KeepRatio( xDiagramPlusAxes_Shapes, uno::UNO_QUERY );
+
+ awt::Size aNewSize( rAvailableSize );
+ awt::Point aNewPos( rAvailablePos );
+ if( bKeepAspectRatio )
+ {
+ awt::Size aCurrentSize( xDiagramPlusAxes_KeepRatio->getSize());
+
+ aNewSize = ShapeFactory::calculateNewSizeRespectingAspectRatio(
+ rAvailableSize, aCurrentSize );
+ aNewPos = ShapeFactory::calculateTopLeftPositionToCenterObject(
+ rAvailablePos, rAvailableSize, aNewSize );
+ }
+
+ xDiagramPlusAxes_KeepRatio->setPosition( aNewPos );
+ xDiagramPlusAxes_KeepRatio->setSize( aNewSize );
+ */
+ for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
+ {
+ VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
+ pSeriesPlotter->rearrangeLabelToAvoidOverlapIfRequested( rPageSize );
+ }
+ }
+}
+
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+
+sal_Bool ChartView::getExplicitValuesForAxis(
+ uno::Reference< XAxis > xAxis
+ , ExplicitScaleData& rExplicitScale
+ , ExplicitIncrementData& rExplicitIncrement )
+{
+ impl_updateView();
+
+ if(!xAxis.is())
+ return sal_False;
+
+ uno::Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis(xAxis,ChartModelHelper::findDiagram( m_xChartModel ) ) );
+ const VCoordinateSystem* pVCooSys = findInCooSysList(m_aVCooSysList,xCooSys);
+ if(!pVCooSys)
+ return sal_False;
+
+ sal_Int32 nDimensionIndex=-1;
+ sal_Int32 nAxisIndex=-1;
+ if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) )
+ {
+ rExplicitScale = pVCooSys->getExplicitScale(nDimensionIndex,nAxisIndex);
+ rExplicitIncrement = pVCooSys->getExplicitIncrement(nDimensionIndex,nAxisIndex);
+ return sal_True;
+ }
+ return sal_False;
+}
+
+SdrPage* ChartView::getSdrPage()
+{
+ SdrPage* pPage=0;
+ Reference< lang::XUnoTunnel> xUnoTunnel(m_xDrawPage,uno::UNO_QUERY);
+ if(xUnoTunnel.is())
+ {
+ SvxDrawPage* pSvxDrawPage = reinterpret_cast<SvxDrawPage*>(xUnoTunnel->getSomething(
+ SvxDrawPage::getUnoTunnelId() ));
+ if(pSvxDrawPage)
+ {
+ pPage = pSvxDrawPage->GetSdrPage();
+ }
+ }
+ return pPage;
+}
+
+uno::Reference< drawing::XShape > ChartView::getShapeForCID( const rtl::OUString& rObjectCID )
+{
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ SdrObject* pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, this->getSdrPage() );
+ if( pObj )
+ return uno::Reference< drawing::XShape >( pObj->getUnoShape(), uno::UNO_QUERY);
+ return 0;
+}
+
+awt::Rectangle ChartView::getRectangleOfObject( const rtl::OUString& rObjectCID, bool bSnapRect )
+{
+ impl_updateView();
+
+ awt::Rectangle aRet;
+ uno::Reference< drawing::XShape > xShape( getShapeForCID(rObjectCID) );
+ if(xShape.is())
+ {
+ //special handling for axis for old api:
+ //same special handling for diagram
+ ObjectType eObjectType( ObjectIdentifier::getObjectType( rObjectCID ) );
+ if( eObjectType == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_DIAGRAM )
+ {
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ SvxShape* pRoot = SvxShape::getImplementation( xShape );
+ if( pRoot )
+ {
+ SdrObject* pRootSdrObject = pRoot->GetSdrObject();
+ if( pRootSdrObject )
+ {
+ SdrObjList* pRootList = pRootSdrObject->GetSubList();
+ if( pRootList )
+ {
+ SdrObject* pShape = DrawModelWrapper::getNamedSdrObject( C2U("MarkHandles"), pRootList );
+ if( pShape )
+ xShape = uno::Reference< drawing::XShape >( pShape->getUnoShape(), uno::UNO_QUERY);
+ }
+ }
+ }
+ }
+
+ awt::Size aSize( xShape->getSize() );
+ awt::Point aPoint( xShape->getPosition() );
+ aRet = awt::Rectangle( aPoint.X, aPoint.Y, aSize.Width, aSize.Height );
+ if( bSnapRect )
+ {
+ //for rotated objects the shape size and position differs from the visible rectangle
+ SvxShape* pShape = SvxShape::getImplementation( xShape );
+ if( pShape )
+ {
+ SdrObject* pSdrObject = pShape->GetSdrObject();
+ if( pSdrObject )
+ {
+ Rectangle aSnapRect( pSdrObject->GetSnapRect() );
+ aRet = awt::Rectangle(aSnapRect.Left(),aSnapRect.Top(),aSnapRect.GetWidth(),aSnapRect.GetHeight());
+ }
+ }
+ }
+ }
+ return aRet;
+}
+
+::boost::shared_ptr< DrawModelWrapper > ChartView::getDrawModelWrapper()
+{
+ return m_pDrawModelWrapper;
+}
+
+namespace
+{
+sal_Int32 lcl_getDiagramTitleSpace()
+{
+ return 200; //=0,2 cm spacing
+}
+bool lcl_getPropertySwapXAndYAxis( const uno::Reference< XDiagram >& xDiagram )
+{
+ bool bSwapXAndY = false;
+
+ uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
+ if( xCooSysContainer.is() )
+ {
+ uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
+ if( aCooSysList.getLength() )
+ {
+ uno::Reference<beans::XPropertySet> xProp(aCooSysList[0], uno::UNO_QUERY );
+ if( xProp.is()) try
+ {
+ xProp->getPropertyValue( C2U( "SwapXAndYAxis" ) ) >>= bSwapXAndY;
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ }
+ }
+ return bSwapXAndY;
+}
+
+}
+
+sal_Int32 lcl_getExplicitNumberFormatKeyForAxis(
+ const Reference< chart2::XAxis >& xAxis
+ , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
+ , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
+ , bool bSearchForParallelAxisIfNothingIsFound )
+{
+ sal_Int32 nNumberFormatKey(0);
+ Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
+ if( xProp.is() && !( xProp->getPropertyValue( C2U( "NumberFormat" ) ) >>= nNumberFormatKey ) )
+ {
+ bool bPercentFormatSet = false;
+ //check wether we have a percent scale -> use percent format
+ if( xNumberFormatsSupplier.is() )
+ {
+ ScaleData aData = xAxis->getScaleData();
+ if( aData.AxisType==AxisType::PERCENT )
+ {
+ sal_Int32 nPercentFormat = ExplicitValueProvider::getPercentNumberFormat( xNumberFormatsSupplier );
+ if( nPercentFormat != -1 )
+ {
+ nNumberFormatKey = nPercentFormat;
+ bPercentFormatSet = true;
+ }
+ }
+ }
+
+ if( !bPercentFormatSet )
+ {
+ typedef ::std::map< sal_Int32, sal_Int32 > tNumberformatFrequency;
+ tNumberformatFrequency aKeyMap;
+
+ bool bNumberFormatKeyFoundViaAttachedData = false;
+ sal_Int32 nAxisIndex = 0;
+ sal_Int32 nDimensionIndex = 1;
+
+ try
+ {
+ Reference< XChartTypeContainer > xCTCnt( xCorrespondingCoordinateSystem, uno::UNO_QUERY_THROW );
+ if( xCTCnt.is() )
+ {
+ AxisHelper::getIndicesForAxis( xAxis, xCorrespondingCoordinateSystem, nDimensionIndex, nAxisIndex );
+ ::rtl::OUString aRoleToMatch;
+ if( nDimensionIndex == 0 )
+ aRoleToMatch = C2U("values-x");
+ Sequence< Reference< XChartType > > aChartTypes( xCTCnt->getChartTypes());
+ for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx )
+ {
+ if( nDimensionIndex != 0 )
+ aRoleToMatch = ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( aChartTypes[nCTIdx] );
+ Reference< XDataSeriesContainer > xDSCnt( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
+ Sequence< Reference< XDataSeries > > aDataSeriesSeq( xDSCnt->getDataSeries());
+ for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aDataSeriesSeq.getLength(); ++nSeriesIdx )
+ {
+ Reference< chart2::XDataSeries > xDataSeries(aDataSeriesSeq[nSeriesIdx]);
+ Reference< data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY_THROW );
+
+ if( nDimensionIndex == 1 )
+ {
+ //only take those series into accoutn that are attached to this axis
+ sal_Int32 nAttachedAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
+ if( nAttachedAxisIndex != nAxisIndex )
+ continue;
+ }
+
+ Sequence< Reference< data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences());
+ for( sal_Int32 nLSeqIdx=0; nLSeqIdx<aLabeledSeq.getLength(); ++nLSeqIdx )
+ {
+ if(!aLabeledSeq[nLSeqIdx].is())
+ continue;
+ Reference< data::XDataSequence > xSeq( aLabeledSeq[nLSeqIdx]->getValues());
+ OSL_ASSERT( xSeq.is());
+ Reference< beans::XPropertySet > xSeqProp( xSeq, uno::UNO_QUERY );
+ ::rtl::OUString aRole;
+ bool bTakeIntoAccount =
+ ( xSeqProp.is() && (aRoleToMatch.getLength() > 0) &&
+ (xSeqProp->getPropertyValue(C2U("Role")) >>= aRole ) &&
+ aRole.equals( aRoleToMatch ));
+
+ if( bTakeIntoAccount )
+ {
+ sal_Int32 nKey = xSeq->getNumberFormatKeyByIndex( -1 );
+ // initialize the value
+ if( aKeyMap.find( nKey ) == aKeyMap.end())
+ aKeyMap[ nKey ] = 0;
+ // increase frequency
+ aKeyMap[ nKey ] = (aKeyMap[ nKey ] + 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+
+ if( ! aKeyMap.empty())
+ {
+ sal_Int32 nMaxFreq = 0;
+ // find most frequent key
+ for( tNumberformatFrequency::const_iterator aIt = aKeyMap.begin();
+ aIt != aKeyMap.end(); ++aIt )
+ {
+ OSL_TRACE( "NumberFormatKey %d appears %d times", (*aIt).first, (*aIt).second );
+ // all values must at least be 1
+ if( (*aIt).second > nMaxFreq )
+ {
+ nNumberFormatKey = (*aIt).first;
+ bNumberFormatKeyFoundViaAttachedData = true;
+ nMaxFreq = (*aIt).second;
+ }
+ }
+ }
+
+ if( bSearchForParallelAxisIfNothingIsFound )
+ {
+ //no format is set to this axis and no data is set to this axis
+ //--> try to obtain the format from the parallel y-axis
+ if( !bNumberFormatKeyFoundViaAttachedData && nDimensionIndex == 1 )
+ {
+ sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
+ Reference< XAxis > xParallelAxis( AxisHelper::getAxis( 1, nParallelAxisIndex, xCorrespondingCoordinateSystem ) );
+ nNumberFormatKey = lcl_getExplicitNumberFormatKeyForAxis( xParallelAxis, xCorrespondingCoordinateSystem, xNumberFormatsSupplier, false );
+ }
+ }
+ }
+ }
+ return nNumberFormatKey;
+}
+
+//static
+sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
+ const Reference< chart2::XAxis >& xAxis
+ , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
+ , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
+{
+ return lcl_getExplicitNumberFormatKeyForAxis( xAxis, xCorrespondingCoordinateSystem, xNumberFormatsSupplier
+ , true /*bSearchForParallelAxisIfNothingIsFound*/ );
+}
+
+//static
+sal_Int32 ExplicitValueProvider::getPercentNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
+{
+ sal_Int32 nRet=-1;
+ Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() );
+ if( xNumberFormats.is() )
+ {
+ sal_Bool bCreate = sal_True;
+ const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
+ Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::PERCENT,
+ rLocaleDataWrapper.getLocale(), bCreate );
+ if( aKeySeq.getLength() )
+ {
+ nRet = aKeySeq[0];
+ }
+ }
+ return nRet;
+}
+
+
+sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
+ const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp,
+ const uno::Reference< XDataSeries >& xSeries,
+ sal_Int32 nPointIndex /*-1 for whole series*/,
+ const uno::Reference< XDiagram >& xDiagram
+ )
+{
+ sal_Int32 nFormat=0;
+ if( !xSeriesOrPointProp.is() )
+ return nFormat;
+
+ rtl::OUString aPropName( C2U( "NumberFormat" ) );
+ if( !(xSeriesOrPointProp->getPropertyValue(aPropName) >>= nFormat) )
+ {
+ uno::Reference< chart2::XChartType > xChartType( DataSeriesHelper::getChartTypeOfSeries( xSeries, xDiagram ) );
+
+ bool bFormatFound = false;
+ if( ChartTypeHelper::shouldLabelNumberFormatKeyBeDetectedFromYAxis( xChartType ) )
+ {
+ uno::Reference< beans::XPropertySet > xAttachedAxisProps( DiagramHelper::getAttachedAxis( xSeries, xDiagram ), uno::UNO_QUERY );
+ if( xAttachedAxisProps.is() && ( xAttachedAxisProps->getPropertyValue( aPropName ) >>= nFormat ) )
+ bFormatFound = true;
+ }
+ if( !bFormatFound )
+ {
+ Reference< chart2::data::XDataSource > xSeriesSource( xSeries, uno::UNO_QUERY );
+ OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) );
+
+ Reference< data::XLabeledDataSequence > xLabeledSequence(
+ DataSeriesHelper::getDataSequenceByRole( xSeriesSource, aRole, false ));
+ if( xLabeledSequence.is() )
+ {
+ Reference< data::XDataSequence > xValues( xLabeledSequence->getValues() );
+ if( xValues.is() )
+ nFormat = xValues->getNumberFormatKeyByIndex( nPointIndex );
+ }
+ }
+ }
+ if(nFormat<0)
+ nFormat=0;
+ return nFormat;
+}
+
+sal_Int32 ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel(
+ const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp,
+ const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
+{
+ sal_Int32 nFormat=0;
+ if( !xSeriesOrPointProp.is() )
+ return nFormat;
+ if( !(xSeriesOrPointProp->getPropertyValue(C2U( "PercentageNumberFormat" )) >>= nFormat) )
+ {
+ nFormat = ExplicitValueProvider::getPercentNumberFormat( xNumberFormatsSupplier );
+ }
+ if(nFormat<0)
+ nFormat=0;
+ return nFormat;
+}
+
+//static
+awt::Rectangle ExplicitValueProvider::calculateDiagramPositionAndSizeInclusiveTitle(
+ const Reference< frame::XModel >& xChartModel
+ , const Reference< uno::XInterface >& xChartView
+ , const awt::Rectangle& rExclusivePositionAndSize )
+{
+ awt::Rectangle aRet(rExclusivePositionAndSize);
+
+ //add axis title sizes to the diagram size
+ uno::Reference< chart2::XTitle > xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, xChartModel ) );
+ uno::Reference< chart2::XTitle > xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, xChartModel ) );
+ uno::Reference< chart2::XTitle > xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xChartModel ) );
+ uno::Reference< chart2::XTitle > xSecondTitle_Width( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xChartModel ) );
+ if( xTitle_Height.is() || xTitle_Width.is() || xSecondTitle_Height.is() || xSecondTitle_Width.is() )
+ {
+ ExplicitValueProvider* pExplicitValueProvider = ExplicitValueProvider::getExplicitValueProvider(xChartView);
+ if( pExplicitValueProvider )
+ {
+ //detect wether x axis points into x direction or not
+ if( lcl_getPropertySwapXAndYAxis( ChartModelHelper::findDiagram( xChartModel ) ) )
+ {
+ std::swap( xTitle_Height, xTitle_Width );
+ std::swap( xSecondTitle_Height, xSecondTitle_Width );
+ }
+
+ sal_Int32 nTitleSpaceWidth = 0;
+ sal_Int32 nTitleSpaceHeight = 0;
+ sal_Int32 nSecondTitleSpaceWidth = 0;
+ sal_Int32 nSecondTitleSpaceHeight = 0;
+
+ if( xTitle_Height.is() )
+ {
+ rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height, xChartModel ) );
+ nTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
+ if( nTitleSpaceHeight )
+ nTitleSpaceHeight+=lcl_getDiagramTitleSpace();
+ }
+ if( xTitle_Width.is() )
+ {
+ rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width, xChartModel ) );
+ nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
+ if(nTitleSpaceWidth)
+ nTitleSpaceWidth+=lcl_getDiagramTitleSpace();
+ }
+ if( xSecondTitle_Height.is() )
+ {
+ rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height, xChartModel ) );
+ nSecondTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
+ if( nSecondTitleSpaceHeight )
+ nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace();
+ }
+ if( xSecondTitle_Width.is() )
+ {
+ rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width, xChartModel ) );
+ nSecondTitleSpaceWidth += pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
+ if( nSecondTitleSpaceWidth )
+ nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace();
+ }
+
+ aRet.X -= nTitleSpaceWidth;
+ aRet.Y -= nSecondTitleSpaceHeight;
+ aRet.Width += nTitleSpaceWidth + nSecondTitleSpaceWidth;
+ aRet.Height += nTitleSpaceHeight + nSecondTitleSpaceHeight;
+ }
+ }
+ return aRet;
+}
+
+double lcl_getPageLayoutDistancePercentage()
+{
+ return 0.02;
+}
+
+bool getAvailablePosAndSizeForDiagram(
+ awt::Point& rOutPos, awt::Size& rOutAvailableDiagramSize
+ , const awt::Rectangle& rSpaceLeft
+ , const awt::Size & rPageSize
+ , const uno::Reference< XDiagram > & xDiagram
+ , VTitle* pXTitle, VTitle* pYTitle
+ , VTitle* pSecondXTitle, VTitle* pSecondYTitle )
+{
+ //@todo: we need a size dependent on the axis labels
+ awt::Rectangle aRemainingSpace(rSpaceLeft);
+ {
+ sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
+ sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
+ aRemainingSpace.X+=nXDistance;
+ aRemainingSpace.Width-=2*nXDistance;
+ aRemainingSpace.Y+=nYDistance;
+ aRemainingSpace.Height-=2*nYDistance;
+ }
+ if(aRemainingSpace.Width <= 0 || aRemainingSpace.Height <= 0 )
+ return false;
+
+ uno::Reference< beans::XPropertySet > xProp(xDiagram, uno::UNO_QUERY);
+
+ bool bMakeRoomForTitle = false;
+
+ //size:
+ ::com::sun::star::chart2::RelativeSize aRelativeSize;
+ if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativeSize" ) )>>=aRelativeSize) )
+ {
+ rOutAvailableDiagramSize.Height = static_cast<sal_Int32>(aRelativeSize.Secondary*rPageSize.Height);
+ rOutAvailableDiagramSize.Width = static_cast<sal_Int32>(aRelativeSize.Primary*rPageSize.Width);
+ bMakeRoomForTitle = true;
+ }
+ else
+ rOutAvailableDiagramSize = awt::Size(aRemainingSpace.Width,aRemainingSpace.Height);
+
+ //position:
+ chart2::RelativePosition aRelativePosition;
+ if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativePosition" ) )>>=aRelativePosition) )
+ {
+ //@todo decide wether x is primary or secondary
+
+ //the coordinates re relative to the page
+ double fX = aRelativePosition.Primary*rPageSize.Width;
+ double fY = aRelativePosition.Secondary*rPageSize.Height;
+
+ rOutPos = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
+ awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY))
+ , rOutAvailableDiagramSize, aRelativePosition.Anchor );
+ bMakeRoomForTitle = true;
+ }
+ else
+ rOutPos = awt::Point(aRemainingSpace.X,aRemainingSpace.Y);
+
+ //ensure that the diagram does not lap out right side or out of bottom
+ {
+ if( rOutPos.Y + rOutAvailableDiagramSize.Height > rPageSize.Height )
+ rOutAvailableDiagramSize.Height = rPageSize.Height - rOutPos.Y;
+ if( rOutPos.X + rOutAvailableDiagramSize.Width > rPageSize.Width )
+ rOutAvailableDiagramSize.Width = rPageSize.Width - rOutPos.X;
+ }
+
+ if( bMakeRoomForTitle )
+ {
+ sal_Int32 nTitleSpaceWidth = 0;
+ sal_Int32 nTitleSpaceHeight = 0;
+ sal_Int32 nSecondTitleSpaceWidth = 0;
+ sal_Int32 nSecondTitleSpaceHeight = 0;
+ {
+ //todo detect wether x axis points into x direction or not
+ //detect wether x axis points into x direction or not
+ if( lcl_getPropertySwapXAndYAxis( xDiagram ) )
+ {
+ std::swap( pXTitle, pYTitle );
+ std::swap( pSecondXTitle, pSecondYTitle );
+ }
+
+ if( pXTitle )
+ {
+ nTitleSpaceHeight = pXTitle->getFinalSize().Height;
+ if(nTitleSpaceHeight)
+ nTitleSpaceHeight+=lcl_getDiagramTitleSpace();
+ }
+ if( pYTitle )
+ {
+ nTitleSpaceWidth = pYTitle->getFinalSize().Width;
+ if(nTitleSpaceWidth)
+ nTitleSpaceWidth+=lcl_getDiagramTitleSpace();
+ }
+ if( pSecondXTitle)
+ {
+ nSecondTitleSpaceHeight += pSecondXTitle->getFinalSize().Height;
+ if(nSecondTitleSpaceHeight)
+ nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace();
+ }
+ if( pSecondYTitle)
+ {
+ nSecondTitleSpaceWidth += pSecondYTitle->getFinalSize().Width;
+ if(nSecondTitleSpaceWidth)
+ nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace();
+ }
+ }
+ rOutAvailableDiagramSize.Height -= nTitleSpaceHeight + nSecondTitleSpaceHeight;
+ rOutAvailableDiagramSize.Width -= nTitleSpaceWidth + nSecondTitleSpaceWidth;
+ rOutPos.X += nTitleSpaceWidth;
+ rOutPos.Y += nSecondTitleSpaceHeight;
+ }
+
+ return true;
+}
+
+enum TitleAlignment { ALIGN_LEFT, ALIGN_TOP, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_Z };
+
+void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment
+ , awt::Rectangle& rDiagramPlusAxesRect, const awt::Size & rPageSize )
+{
+ if(!pVTitle)
+ return;
+
+ awt::Point aNewPosition(0,0);
+ awt::Size aTitleSize = pVTitle->getFinalSize();
+ sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
+ sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
+ switch( eAlignment )
+ {
+ case ALIGN_TOP:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
+ , rDiagramPlusAxesRect.Y - aTitleSize.Height/2 - nYDistance );
+ break;
+ case ALIGN_BOTTOM:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height + aTitleSize.Height/2 + nYDistance );
+ break;
+ case ALIGN_LEFT:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X - aTitleSize.Width/2 - nXDistance
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
+ break;
+ case ALIGN_RIGHT:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
+ break;
+ case ALIGN_Z:
+ aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
+ , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height - aTitleSize.Height/2 );
+ break;
+ default:
+ break;
+ }
+
+ pVTitle->changePosition( aNewPosition );
+}
+
+std::auto_ptr<VTitle> lcl_createTitle( const uno::Reference< XTitle >& xTitle
+ , const uno::Reference< drawing::XShapes>& xPageShapes
+ , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
+ , const uno::Reference< frame::XModel >& xChartModel
+ , awt::Rectangle& rRemainingSpace
+ , const awt::Size & rPageSize
+ , TitleAlignment eAlignment
+ , bool& rbAutoPosition )
+{
+ std::auto_ptr<VTitle> apVTitle;
+ if(xTitle.is())
+ {
+ rtl::OUString aCompleteString( TitleHelper::getCompleteString( xTitle ) );
+ if( aCompleteString.getLength()==0 )
+ return apVTitle;//don't create empty titles as the resulting diagram position is wrong then
+
+ //create title
+ apVTitle = std::auto_ptr<VTitle>(new VTitle(xTitle));
+ rtl::OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle, xChartModel ) );
+ apVTitle->init(xPageShapes,xShapeFactory,aCID);
+ apVTitle->createShapes( awt::Point(0,0), rPageSize );
+ awt::Size aTitleUnrotatedSize = apVTitle->getUnrotatedSize();
+ awt::Size aTitleSize = apVTitle->getFinalSize();
+
+ //position
+ rbAutoPosition=true;
+ awt::Point aNewPosition(0,0);
+ sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
+ sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
+ chart2::RelativePosition aRelativePosition;
+ uno::Reference< beans::XPropertySet > xProp(xTitle, uno::UNO_QUERY);
+ if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativePosition" ) )>>=aRelativePosition) )
+ {
+ rbAutoPosition = false;
+
+ //@todo decide wether x is primary or secondary
+ double fX = aRelativePosition.Primary*rPageSize.Width;
+ double fY = aRelativePosition.Secondary*rPageSize.Height;
+
+ double fAnglePi = apVTitle->getRotationAnglePi();
+ aNewPosition = RelativePositionHelper::getCenterOfAnchoredObject(
+ awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY))
+ , aTitleUnrotatedSize, aRelativePosition.Anchor, fAnglePi );
+ }
+ else //auto position
+ {
+ switch( eAlignment )
+ {
+ case ALIGN_TOP:
+ aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
+ , rRemainingSpace.Y + aTitleSize.Height/2 + nYDistance );
+ break;
+ case ALIGN_BOTTOM:
+ aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
+ , rRemainingSpace.Y + rRemainingSpace.Height - aTitleSize.Height/2 - nYDistance );
+ break;
+ case ALIGN_LEFT:
+ aNewPosition = awt::Point( rRemainingSpace.X + aTitleSize.Width/2 + nXDistance
+ , rRemainingSpace.Y + rRemainingSpace.Height/2 );
+ break;
+ case ALIGN_RIGHT:
+ aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width - aTitleSize.Width/2 - nXDistance
+ , rRemainingSpace.Y + rRemainingSpace.Height/2 );
+ break;
+ default:
+ break;
+
+ }
+ }
+ apVTitle->changePosition( aNewPosition );
+
+ //remaining space
+ switch( eAlignment )
+ {
+ case ALIGN_TOP:
+ rRemainingSpace.Y += ( aTitleSize.Height + nYDistance );
+ rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
+ break;
+ case ALIGN_BOTTOM:
+ rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
+ break;
+ case ALIGN_LEFT:
+ rRemainingSpace.X += ( aTitleSize.Width + nXDistance );
+ rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
+ break;
+ case ALIGN_RIGHT:
+ rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
+ break;
+ default:
+ break;
+ }
+ }
+ return apVTitle;
+}
+
+bool lcl_createLegend( const uno::Reference< XLegend > & xLegend
+ , const uno::Reference< drawing::XShapes>& xPageShapes
+ , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
+ , const uno::Reference< uno::XComponentContext > & xContext
+ , awt::Rectangle & rRemainingSpace
+ , const awt::Size & rPageSize
+ , const uno::Reference< frame::XModel > & xModel
+ , const std::vector< LegendEntryProvider* >& rLegendEntryProviderList
+ , sal_Int16 nDefaultWritingMode )
+{
+ if( VLegend::isVisible( xLegend ))
+ {
+ VLegend aVLegend( xLegend, xContext, rLegendEntryProviderList );
+ aVLegend.init( xPageShapes, xShapeFactory, xModel );
+ aVLegend.setDefaultWritingMode( nDefaultWritingMode );
+ aVLegend.createShapes( awt::Size( rRemainingSpace.Width, rRemainingSpace.Height ),
+ rPageSize );
+ aVLegend.changePosition( rRemainingSpace, rPageSize );
+ return true;
+ }
+ return false;
+}
+
+void formatPage(
+ const uno::Reference< frame::XModel > & xModel
+ , const awt::Size rPageSize
+ , const uno::Reference< drawing::XShapes >& xTarget
+ , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
+ )
+{
+ try
+ {
+ uno::Reference< XChartDocument > xChartDoc( xModel, uno::UNO_QUERY );
+ OSL_ASSERT( xChartDoc.is());
+ if( ! xChartDoc.is())
+ return;
+ uno::Reference< beans::XPropertySet > xModelPage( xChartDoc->getPageBackground());
+ if( ! xModelPage.is())
+ return;
+
+
+ if( !xShapeFactory.is() )
+ return;
+
+ uno::Reference< beans::XPropertySet > xPageProp;
+ // create a shape for the background
+ {
+ uno::Reference< drawing::XShape > xShape(
+ xShapeFactory->createInstance(
+ C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
+ if( xTarget.is() &&
+ xShape.is())
+ {
+ xTarget->add( xShape );
+ xShape->setSize( rPageSize );
+ xPageProp.set( xShape, uno::UNO_QUERY );
+ if( xPageProp.is())
+ {
+ xPageProp->setPropertyValue( C2U("LineStyle"), uno::makeAny( drawing::LineStyle_NONE ));
+ }
+ }
+ }
+
+ //format page
+ if( xPageProp.is())
+ {
+ tPropertyNameValueMap aNameValueMap;
+ PropertyMapper::getValueMap( aNameValueMap, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xModelPage );
+
+ rtl::OUString aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, rtl::OUString() ) );
+ aNameValueMap.insert( tPropertyNameValueMap::value_type( C2U("Name"), uno::makeAny( aCID ) ) ); //CID rtl::OUString
+
+ tNameSequence aNames;
+ tAnySequence aValues;
+ PropertyMapper::getMultiPropertyListsFromValueMap( aNames, aValues, aNameValueMap );
+ PropertyMapper::setMultiProperties( aNames, aValues, xPageProp );
+ }
+ }
+ catch( uno::Exception & ex )
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+}
+
+void lcl_removeEmptyGroupShapes( const Reference< drawing::XShapes>& xParent )
+{
+ if(!xParent.is())
+ return;
+ Reference< drawing::XShapeGroup > xParentGroup( xParent, uno::UNO_QUERY );
+ if( !xParentGroup.is() )
+ {
+ Reference< drawing::XDrawPage > xPage( xParent, uno::UNO_QUERY );
+ if( !xPage.is() )
+ return;
+ }
+
+ //iterate from back!
+ for( sal_Int32 nN = xParent->getCount(); nN--; )
+ {
+ uno::Any aAny = xParent->getByIndex( nN );
+ Reference< drawing::XShapes> xShapes(0);
+ if( aAny >>= xShapes )
+ lcl_removeEmptyGroupShapes( xShapes );
+ if( xShapes.is() && xShapes->getCount()==0 )
+ {
+ //remove empty group shape
+ Reference< drawing::XShapeGroup > xGroup( xShapes, uno::UNO_QUERY );
+ Reference< drawing::XShape > xShape( xShapes, uno::UNO_QUERY );
+ if( xGroup.is() )
+ xParent->remove( xShape );
+ }
+ }
+}
+
+bool ChartView::impl_AddInDrawsAllByItself()
+{
+ bool bRet = false;
+ /*
+ uno::Reference< beans::XPropertySet > xProp( m_xChartModel, uno::UNO_QUERY );
+ if( xProp.is()) try
+ {
+ uno::Reference< util::XRefreshable > xAddIn;
+ xProp->getPropertyValue( C2U( "AddIn" ) ) >>= xAddIn;
+ if( xAddIn.is() )
+ {
+ rtl::OUString aBaseDiagram;
+ xProp->getPropertyValue( C2U( "BaseDiagram" ) ) >>= aBaseDiagram;
+ if(aBaseDiagram.getLength())
+ bRet = true;
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+ */
+ return bRet;
+}
+
+void ChartView::impl_refreshAddIn()
+{
+ if( !m_bRefreshAddIn )
+ return;
+
+ uno::Reference< beans::XPropertySet > xProp( m_xChartModel, uno::UNO_QUERY );
+ if( xProp.is()) try
+ {
+ uno::Reference< util::XRefreshable > xAddIn;
+ xProp->getPropertyValue( C2U( "AddIn" ) ) >>= xAddIn;
+ if( xAddIn.is() )
+ {
+ sal_Bool bRefreshAddInAllowed = sal_True;
+ xProp->getPropertyValue( C2U( "RefreshAddInAllowed" ) ) >>= bRefreshAddInAllowed;
+ if( bRefreshAddInAllowed )
+ xAddIn->refresh();
+ }
+ }
+ catch( uno::Exception& e )
+ {
+ ASSERT_EXCEPTION( e );
+ }
+}
+
+void ChartView::createShapes()
+{
+#if OSL_DEBUG_LEVEL > 0
+ clock_t nStart = clock();
+ OSL_TRACE( "\nPPPPPPPPP>>>>>>>>>>>> chart view :: createShapes()" );
+#endif
+
+ //make sure add-in is refreshed after creating the shapes
+ const ::comphelper::ScopeGuard aGuard( boost::bind( &ChartView::impl_refreshAddIn, this ) );
+ if( impl_AddInDrawsAllByItself() )
+ return;
+
+ impl_deleteCoordinateSystems();
+ if( m_pDrawModelWrapper )
+ {
+ // /--
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ m_pDrawModelWrapper->clearMainDrawPage();
+ // \--
+ }
+
+ lcl_setDefaultWritingMode( m_pDrawModelWrapper, m_xChartModel );
+
+ awt::Size aPageSize = ChartModelHelper::getPageSize( m_xChartModel );
+
+ uno::Reference<drawing::XShapes> xPageShapes( ShapeFactory(m_xShapeFactory)
+ .getOrCreateChartRootShape( m_xDrawPage ) );
+
+ SdrPage* pPage = ChartView::getSdrPage();
+ if(pPage) //it is neccessary to use the implementation here as the uno page does not provide a propertyset
+ pPage->SetSize(Size(aPageSize.Width,aPageSize.Height));
+ else
+ {
+ DBG_ERROR("could not set page size correctly");
+ }
+
+ {
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+
+ //------------ apply fill properties to page
+ // todo: it would be nicer to just pass the page m_xDrawPage and format it,
+ // but the draw page does not support XPropertySet
+ formatPage( m_xChartModel, aPageSize, xPageShapes, m_xShapeFactory );
+
+ //sal_Int32 nYDistance = static_cast<sal_Int32>(aPageSize.Height*lcl_getPageLayoutDistancePercentage());
+ awt::Rectangle aRemainingSpace( 0, 0, aPageSize.Width, aPageSize.Height );
+
+ //create the group shape for diagram and axes first to have title and legends on top of it
+ uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) );
+ rtl::OUString aDiagramCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, rtl::OUString::valueOf( sal_Int32(0) ) ) );//todo: other index if more than one diagram is possible
+ uno::Reference< drawing::XShapes > xDiagramPlusAxesPlusMarkHandlesGroup_Shapes( ShapeFactory(m_xShapeFactory).createGroup2D(xPageShapes,aDiagramCID) );
+ uno::Reference< drawing::XShape > xDiagramPlusAxes_MarkHandles( ShapeFactory(m_xShapeFactory).createInvisibleRectangle(
+ xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0,0) ) );
+ ShapeFactory::setShapeName( xDiagramPlusAxes_MarkHandles, C2U("MarkHandles") );
+ uno::Reference< drawing::XShapes > xDiagramPlusAxes_Shapes( ShapeFactory(m_xShapeFactory).createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes ) );
+
+ //------------ create some titles
+ std::auto_ptr<VTitle> apVTitle(0);
+ bool bAutoPositionDummy = true;
+
+ //------------ create main title shape
+ lcl_createTitle( TitleHelper::getTitle( TitleHelper::MAIN_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, ALIGN_TOP, bAutoPositionDummy );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ //------------ create sub title shape
+ lcl_createTitle( TitleHelper::getTitle( TitleHelper::SUB_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, ALIGN_TOP, bAutoPositionDummy );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+
+ //------------ prepare series to give input to the legend (create categories and symbols etc.)
+ SeriesPlotterContainer aSeriesPlotterContainer( m_aVCooSysList );
+ aSeriesPlotterContainer.initializeCooSysAndSeriesPlotter( m_xChartModel );
+
+ //------------ create legend
+ lcl_createLegend( LegendHelper::getLegend( m_xChartModel ), xPageShapes, m_xShapeFactory, m_xCC
+ , aRemainingSpace, aPageSize, m_xChartModel, aSeriesPlotterContainer.getLegendEntryProviderList()
+ , lcl_getDefaultWritingModeFromPool( m_pDrawModelWrapper ) );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
+ sal_Int32 nDimension = DiagramHelper::getDimension( xDiagram );
+
+ //------------ create x axis title
+ bool bAutoPosition_XTitle = true;
+ std::auto_ptr<VTitle> apVTitle_X;
+ if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 0 ) )
+ apVTitle_X = lcl_createTitle( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, ALIGN_BOTTOM, bAutoPosition_XTitle );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ //------------ create y axis title
+ bool bAutoPosition_YTitle = true;
+ std::auto_ptr<VTitle> apVTitle_Y;
+ if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 1 ) )
+ apVTitle_Y = lcl_createTitle( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, ALIGN_LEFT, bAutoPosition_YTitle );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ //------------ create z axis title
+ bool bAutoPosition_ZTitle = true;
+ std::auto_ptr<VTitle> apVTitle_Z;
+ if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 2 ) )
+ apVTitle_Z = lcl_createTitle( TitleHelper::getTitle( TitleHelper::Z_AXIS_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, ALIGN_RIGHT, bAutoPosition_ZTitle );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ bool bDummy = false;
+ bool bIsVertical = DiagramHelper::getVertical( xDiagram, bDummy, bDummy );
+
+ //------------ create secondary x axis title
+ bool bAutoPosition_SecondXTitle = true;
+ std::auto_ptr<VTitle> apVTitle_SecondX;
+ if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension, 0 ) )
+ apVTitle_SecondX = lcl_createTitle( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, bIsVertical? ALIGN_RIGHT : ALIGN_TOP, bAutoPosition_SecondXTitle );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ //------------ create secondary y axis title
+ bool bAutoPosition_SecondYTitle = true;
+ std::auto_ptr<VTitle> apVTitle_SecondY;
+ if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension, 1 ) )
+ apVTitle_SecondY = lcl_createTitle( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
+ , aRemainingSpace, aPageSize, bIsVertical? ALIGN_TOP : ALIGN_RIGHT, bAutoPosition_SecondYTitle );
+ if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
+ return;
+
+ //------------ create complete diagram shape (inclusive axis and series)
+ awt::Point aAvailablePosDia;
+ awt::Size aAvailableSizeForDiagram;
+ if( getAvailablePosAndSizeForDiagram( aAvailablePosDia, aAvailableSizeForDiagram, aRemainingSpace, aPageSize, ChartModelHelper::findDiagram( m_xChartModel )
+ , apVTitle_X.get(), apVTitle_Y.get(), apVTitle_SecondX.get(), apVTitle_SecondY.get() ) )
+ {
+ impl_createDiagramAndContent( aSeriesPlotterContainer
+ , xDiagramPlusAxes_Shapes
+ , aAvailablePosDia ,aAvailableSizeForDiagram, aPageSize );
+
+ if(xDiagramPlusAxes_MarkHandles.is())
+ {
+ xDiagramPlusAxes_MarkHandles->setPosition( aAvailablePosDia );
+ xDiagramPlusAxes_MarkHandles->setSize( aAvailableSizeForDiagram );
+ }
+
+ //correct axis title position
+ awt::Rectangle aDiagramPlusAxesRect(aAvailablePosDia.X,aAvailablePosDia.Y,aAvailableSizeForDiagram.Width,aAvailableSizeForDiagram.Height);
+ if(bAutoPosition_XTitle)
+ changePositionOfAxisTitle( apVTitle_X.get(), ALIGN_BOTTOM, aDiagramPlusAxesRect, aPageSize );
+ if(bAutoPosition_YTitle)
+ changePositionOfAxisTitle( apVTitle_Y.get(), ALIGN_LEFT, aDiagramPlusAxesRect, aPageSize );
+ if(bAutoPosition_ZTitle)
+ changePositionOfAxisTitle( apVTitle_Z.get(), ALIGN_Z, aDiagramPlusAxesRect, aPageSize );
+ if(bAutoPosition_SecondXTitle)
+ changePositionOfAxisTitle( apVTitle_SecondX.get(), bIsVertical? ALIGN_RIGHT : ALIGN_TOP, aDiagramPlusAxesRect, aPageSize );
+ if(bAutoPosition_SecondYTitle)
+ changePositionOfAxisTitle( apVTitle_SecondY.get(), bIsVertical? ALIGN_TOP : ALIGN_RIGHT, aDiagramPlusAxesRect, aPageSize );
+ }
+
+ //cleanup: remove all empty group shapes to avoid grey border lines:
+ lcl_removeEmptyGroupShapes( xPageShapes );
+ }
+
+#if OSL_DEBUG_LEVEL > 0
+ clock_t nEnd = clock();
+ double fDuration =(double(nEnd-nStart)*1000.0)/double(CLOCKS_PER_SEC);
+
+ OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< chart view :: createShapes():: needed %f msec", fDuration );
+#endif
+}
+
+//-----------------------------------------------------------------
+// util::XEventListener (base of XCloseListener)
+//-----------------------------------------------------------------
+void SAL_CALL ChartView::disposing( const lang::EventObject& /* rSource */ )
+ throw(uno::RuntimeException)
+{
+ impl_setChartModel( 0 );
+}
+
+void ChartView::impl_updateView()
+{
+ if( !m_xChartModel.is() || !m_pDrawModelWrapper )
+ return;
+
+ if( m_bViewDirty && !m_bInViewUpdate )
+ {
+ m_bInViewUpdate = true;
+ //bool bOldRefreshAddIn = m_bRefreshAddIn;
+ //m_bRefreshAddIn = false;
+ try
+ {
+ impl_notifyModeChangeListener(C2U("invalid"));
+
+ //prepare draw model
+ {
+ // /--
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ m_pDrawModelWrapper->lockControllers();
+ m_pDrawModelWrapper->updateTablesFromChartModel( m_xChartModel );
+ // \--
+ }
+
+ //create chart view
+ {
+ /*
+ ::vos::OGuard aGuard( Application::GetSolarMutex());
+ while( m_bViewDirty )
+ {
+ createShapes();
+ m_bViewDirty = m_bViewUpdatePending;
+ m_bViewUpdatePending = false;
+ m_bInViewUpdate = false;
+ }
+ */
+
+ m_bViewDirty = false;
+ m_bViewUpdatePending = false;
+ createShapes();
+
+ if( m_bViewDirty )
+ {
+ //avoid recursions due to add-in
+ m_bRefreshAddIn = false;
+ m_bViewDirty = false;
+ m_bViewUpdatePending = false;
+ //delete old chart view
+ createShapes();
+ m_bRefreshAddIn = true;
+ }
+ }
+
+ m_bViewDirty = m_bViewUpdatePending;
+ m_bViewUpdatePending = false;
+ m_bInViewUpdate = false;
+ }
+ catch( uno::Exception& ex)
+ {
+ m_bViewDirty = m_bViewUpdatePending;
+ m_bViewUpdatePending = false;
+ m_bInViewUpdate = false;
+ ASSERT_EXCEPTION( ex );
+ }
+
+ {
+ // /--
+ ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
+ m_pDrawModelWrapper->unlockControllers();
+ // \--
+ }
+
+ impl_notifyModeChangeListener(C2U("valid"));
+
+ //m_bRefreshAddIn = bOldRefreshAddIn;
+ }
+}
+
+// ____ XModifyListener ____
+void SAL_CALL ChartView::modified( const lang::EventObject& /* aEvent */ )
+ throw (uno::RuntimeException)
+{
+ m_bViewDirty = sal_True;
+ if( m_bInViewUpdate )
+ m_bViewUpdatePending = true;
+
+ impl_notifyModeChangeListener(C2U("dirty"));
+}
+
+//SfxListener
+void ChartView::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
+{
+ //#i77362 change notification for changes on additional shapes are missing
+ if( m_bInViewUpdate )
+ return;
+ if( m_bSdrViewIsInEditMode )
+ return;
+
+ const SdrHint* pSdrHint = dynamic_cast< const SdrHint* >(&rHint);
+ if( !pSdrHint )
+ return;
+
+ bool bShapeChanged = false;
+ switch( pSdrHint->GetKind() )
+ {
+ case HINT_OBJCHG:
+ bShapeChanged = true;
+ break;
+ case HINT_OBJINSERTED:
+ bShapeChanged = true;
+ break;
+ case HINT_OBJREMOVED:
+ bShapeChanged = true;
+ break;
+ case HINT_MODELCLEARED:
+ bShapeChanged = true;
+ break;
+ default:
+ break;
+ }
+
+ if(bShapeChanged)
+ {
+ //#i76053# do not send view modified notifications for changes on the hidden page which contains e.g. the symbols for the dialogs
+ if( ChartView::getSdrPage() != pSdrHint->GetPage() )
+ bShapeChanged=false;
+ }
+
+ if(!bShapeChanged)
+ return;
+
+ Reference< util::XModifiable > xModifiable( m_xChartModel, uno::UNO_QUERY );
+ if( xModifiable.is() )
+ xModifiable->setModified( sal_True );
+}
+
+void ChartView::impl_notifyModeChangeListener( const rtl::OUString& rNewMode )
+{
+ try
+ {
+ ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer
+ .getContainer( ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0) );
+ if( pIC )
+ {
+ util::ModeChangeEvent aEvent( static_cast< uno::XWeak* >( this ), rNewMode );
+ ::cppu::OInterfaceIteratorHelper aIt( *pIC );
+ while( aIt.hasMoreElements() )
+ (static_cast< util::XModeChangeListener*>(aIt.next()))->modeChanged( aEvent );
+ }
+ }
+ catch( uno::Exception& ex)
+ {
+ ASSERT_EXCEPTION( ex );
+ }
+}
+
+// ____ XModeChangeBroadcaster ____
+
+void SAL_CALL ChartView::addModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
+ throw (uno::RuntimeException)
+{
+ m_aListenerContainer.addInterface(
+ ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0), xListener );
+}
+void SAL_CALL ChartView::removeModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
+ throw (uno::RuntimeException)
+{
+ m_aListenerContainer.removeInterface(
+ ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0), xListener );
+}
+void SAL_CALL ChartView::addModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
+ throw (lang::NoSupportException, uno::RuntimeException)
+{
+
+}
+void SAL_CALL ChartView::removeModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
+ throw (lang::NoSupportException, uno::RuntimeException)
+{
+
+}
+
+// ____ XUpdatable ____
+void SAL_CALL ChartView::update() throw (uno::RuntimeException)
+{
+ impl_updateView();
+}
+
+// ____ XPropertySet ____
+Reference< beans::XPropertySetInfo > SAL_CALL ChartView::getPropertySetInfo()
+ throw (uno::RuntimeException)
+{
+ OSL_ENSURE(false,"not implemented");
+ return 0;
+}
+
+void SAL_CALL ChartView::setPropertyValue( const ::rtl::OUString& rPropertyName
+ , const Any& rValue )
+ throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException
+ , lang::WrappedTargetException, uno::RuntimeException)
+{
+ if( rPropertyName.equals(C2U("Resolution")) )
+ {
+ awt::Size aNewResolution;
+ if( ! (rValue >>= aNewResolution) )
+ throw lang::IllegalArgumentException( C2U("Property 'Resolution' requires value of type awt::Size"), 0, 0 );
+
+ if( m_aPageResolution.Width!=aNewResolution.Width || m_aPageResolution.Height!=aNewResolution.Height )
+ {
+ //set modified only when the new resolution is higher and points were skipped before
+ bool bSetModified = m_bPointsWereSkipped && (m_aPageResolution.Width<aNewResolution.Width || m_aPageResolution.Height<aNewResolution.Height);
+
+ m_aPageResolution = aNewResolution;
+
+ if( bSetModified )
+ this->modified( lang::EventObject( static_cast< uno::XWeak* >( this ) ) );
+ }
+ }
+ else if( rPropertyName.equals(C2U("ZoomFactors")) )
+ {
+ //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
+ uno::Sequence< beans::PropertyValue > aZoomFactors;
+ if( ! (rValue >>= aZoomFactors) )
+ throw lang::IllegalArgumentException( C2U("Property 'ZoomFactors' requires value of type Sequence< PropertyValue >"), 0, 0 );
+
+ sal_Int32 nFilterArgs = aZoomFactors.getLength();
+ beans::PropertyValue* pDataValues = aZoomFactors.getArray();
+ while( nFilterArgs-- )
+ {
+ if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXNumerator" ) ) )
+ pDataValues->Value >>= m_nScaleXNumerator;
+ else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXDenominator" ) ) )
+ pDataValues->Value >>= m_nScaleXDenominator;
+ else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYNumerator" ) ) )
+ pDataValues->Value >>= m_nScaleYNumerator;
+ else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYDenominator" ) ) )
+ pDataValues->Value >>= m_nScaleYDenominator;
+
+ pDataValues++;
+ }
+ }
+ else if( rPropertyName.equals(C2U("SdrViewIsInEditMode")) )
+ {
+ //#i77362 change notification for changes on additional shapes are missing
+ if( ! (rValue >>= m_bSdrViewIsInEditMode) )
+ throw lang::IllegalArgumentException( C2U("Property 'SdrViewIsInEditMode' requires value of type sal_Bool"), 0, 0 );
+ }
+ else
+ throw beans::UnknownPropertyException( C2U("unknown property was tried to set to chart wizard"), 0 );
+}
+
+Any SAL_CALL ChartView::getPropertyValue( const ::rtl::OUString& rPropertyName )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ Any aRet;
+ if( rPropertyName.equals(C2U("Resolution")) )
+ {
+ aRet = uno::makeAny( m_aPageResolution );
+ }
+ else
+ throw beans::UnknownPropertyException( C2U("unknown property was tried to get from chart wizard"), 0 );
+ return aRet;
+}
+
+void SAL_CALL ChartView::addPropertyChangeListener(
+ const ::rtl::OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* xListener */ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_ENSURE(false,"not implemented");
+}
+void SAL_CALL ChartView::removePropertyChangeListener(
+ const ::rtl::OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* aListener */ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_ENSURE(false,"not implemented");
+}
+
+void SAL_CALL ChartView::addVetoableChangeListener( const ::rtl::OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_ENSURE(false,"not implemented");
+}
+
+void SAL_CALL ChartView::removeVetoableChangeListener( const ::rtl::OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
+ throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ OSL_ENSURE(false,"not implemented");
+}
+
+
+//.............................................................................
+} //namespace chart
+//.............................................................................