merge the formfield patch from ooo-build
[ooovba.git] / chart2 / source / view / main / ChartView.cxx
blobb5af9db83ddb33f3c24def60a1fbfc96ab569efe
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ChartView.cxx,v $
10 * $Revision: 1.46.22.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_chart2.hxx"
35 #include "ChartView.hxx"
36 #include "chartview/DrawModelWrapper.hxx"
37 #include "ViewDefines.hxx"
38 #include "VDiagram.hxx"
39 #include "VTitle.hxx"
40 #include "ShapeFactory.hxx"
41 #include "VCoordinateSystem.hxx"
42 #include "VSeriesPlotter.hxx"
43 #include "CommonConverters.hxx"
44 #include "macros.hxx"
45 #include "TitleHelper.hxx"
46 #include "LegendHelper.hxx"
47 #include "VLegend.hxx"
48 #include "PropertyMapper.hxx"
49 #include "ChartModelHelper.hxx"
50 #include "ChartTypeHelper.hxx"
51 #include "ScaleAutomatism.hxx"
52 #include "MinimumAndMaximumSupplier.hxx"
53 #include "ObjectIdentifier.hxx"
54 #include "DiagramHelper.hxx"
55 #include "RelativePositionHelper.hxx"
56 #include "servicenames.hxx"
57 #include "AxisHelper.hxx"
58 #include "AxisIndexDefines.hxx"
59 #include "ControllerLockGuard.hxx"
60 #include "BaseGFXHelper.hxx"
61 #include "DataSeriesHelper.hxx"
63 #include <comphelper/scopeguard.hxx>
64 #include <boost/bind.hpp>
65 #include <unotools/streamwrap.hxx>
66 // header for class LocaleDataWrapper
67 #include <unotools/localedatawrapper.hxx>
68 // header for class SdrPage
69 #include <svx/svdpage.hxx>
70 // header for class SvxDrawPage
71 #include <svx/unopage.hxx>
72 // header for class SvxShape
73 #include <svx/unoshape.hxx>
74 // header for class Application
75 #include <vcl/svapp.hxx>
76 #include <vos/mutex.hxx>
78 #include <time.h>
80 #include <com/sun/star/chart/ChartAxisPosition.hpp>
81 #include <com/sun/star/chart/DataLabelPlacement.hpp>
82 #include <com/sun/star/chart/MissingValueTreatment.hpp>
83 #include <com/sun/star/chart2/ExplicitSubIncrement.hpp>
84 #include <com/sun/star/chart2/StackingDirection.hpp>
85 #include <com/sun/star/chart2/XChartDocument.hpp>
86 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
87 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
88 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
89 #include <com/sun/star/chart2/XTitled.hpp>
90 #include <com/sun/star/chart2/RelativePosition.hpp>
91 #include <com/sun/star/chart2/RelativeSize.hpp>
92 #include <com/sun/star/drawing/FillStyle.hpp>
93 #include <com/sun/star/drawing/LineStyle.hpp>
94 #include <com/sun/star/drawing/XShapeGroup.hpp>
95 #include <com/sun/star/document/XExporter.hpp>
96 #include <com/sun/star/document/XFilter.hpp>
97 #include <com/sun/star/io/XSeekable.hpp>
98 #include <com/sun/star/util/XModifiable.hpp>
99 #include <com/sun/star/util/XRefreshable.hpp>
100 #include <com/sun/star/util/NumberFormat.hpp>
102 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
103 #include <com/sun/star/text/XTextDocument.hpp>
104 #include <com/sun/star/text/WritingMode2.hpp>
105 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
106 #include <svtools/languageoptions.hxx>
107 #include <sot/clsids.hxx>
109 //.............................................................................
110 namespace chart
112 //.............................................................................
114 using namespace ::com::sun::star;
115 using namespace ::com::sun::star::chart2;
116 using ::com::sun::star::uno::Reference;
117 using ::com::sun::star::uno::Sequence;
118 using ::com::sun::star::uno::Any;
119 using rtl::OUString;
121 //static
122 const uno::Sequence<sal_Int8>& ExplicitValueProvider::getUnoTunnelId()
124 static uno::Sequence<sal_Int8> * pSeq = 0;
125 if( !pSeq )
127 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
128 if( !pSeq )
130 static uno::Sequence< sal_Int8 > aSeq( 16 );
131 rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
132 pSeq = &aSeq;
135 return *pSeq;
138 //static
139 ExplicitValueProvider* ExplicitValueProvider::getExplicitValueProvider(
140 const Reference< uno::XInterface >& xChartView )
142 ExplicitValueProvider* pExplicitValueProvider=0;
144 Reference< lang::XUnoTunnel > xTunnel( xChartView, uno::UNO_QUERY );
145 if( xTunnel.is() )
147 pExplicitValueProvider = reinterpret_cast<ExplicitValueProvider*>(xTunnel->getSomething(
148 ExplicitValueProvider::getUnoTunnelId() ));
150 return pExplicitValueProvider;
153 ChartView::ChartView(
154 uno::Reference<uno::XComponentContext> const & xContext)
155 : m_aMutex()
156 , m_xCC(xContext)
157 , m_xChartModel()
158 , m_xShapeFactory()
159 , m_xDrawPage()
160 , m_pDrawModelWrapper()
161 , m_aListenerContainer( m_aMutex )
162 , m_bViewDirty(true)
163 , m_bInViewUpdate(false)
164 , m_bViewUpdatePending(false)
165 , m_bRefreshAddIn(true)
166 , m_aPageResolution(1000,1000)
167 , m_bPointsWereSkipped(false)
168 , m_nScaleXNumerator(1)
169 , m_nScaleXDenominator(1)
170 , m_nScaleYNumerator(1)
171 , m_nScaleYDenominator(1)
172 , m_bSdrViewIsInEditMode(sal_False)
176 void ChartView::impl_setChartModel( const uno::Reference< frame::XModel >& xChartModel )
178 if( m_xChartModel != xChartModel )
180 m_xChartModel = xChartModel;
181 m_bViewDirty = true;
185 void SAL_CALL ChartView::initialize( const uno::Sequence< uno::Any >& aArguments )
186 throw ( uno::Exception, uno::RuntimeException)
188 DBG_ASSERT(aArguments.getLength() >= 1,"need 1 argument to initialize the view: xModel");
189 if( !(aArguments.getLength() >= 1) )
190 return;
192 uno::Reference< frame::XModel > xNewChartModel;
193 if( !(aArguments[0] >>= xNewChartModel) )
195 DBG_ERROR( "need a Reference to frame::XModel as first parameter for view initialization" );
197 impl_setChartModel( xNewChartModel );
199 if( !m_pDrawModelWrapper.get() )
201 // /--
202 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
203 m_pDrawModelWrapper = ::boost::shared_ptr< DrawModelWrapper >( new DrawModelWrapper( m_xCC ) );
204 m_xShapeFactory = m_pDrawModelWrapper->getShapeFactory();
205 m_xDrawPage = m_pDrawModelWrapper->getMainDrawPage();
206 StartListening( m_pDrawModelWrapper->getSdrModel(), FALSE /*bPreventDups*/ );
207 // \--
211 ChartView::~ChartView()
213 if( m_pDrawModelWrapper.get() )
214 EndListening( m_pDrawModelWrapper->getSdrModel(), FALSE /*bAllDups*/ );
215 m_xDrawPage = NULL;
216 impl_deleteCoordinateSystems();
219 void ChartView::impl_deleteCoordinateSystems()
221 //delete all coordinate systems
222 ::std::vector< VCoordinateSystem* >::const_iterator aIter = m_aVCooSysList.begin();
223 const ::std::vector< VCoordinateSystem* >::const_iterator aEnd = m_aVCooSysList.end();
224 for( ; aIter != aEnd; aIter++ )
226 delete *aIter;
228 m_aVCooSysList.clear();
232 //-----------------------------------------------------------------
233 // datatransfer::XTransferable
234 namespace
236 const rtl::OUString lcl_aGDIMetaFileMIMEType(
237 RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""));
238 const rtl::OUString lcl_aGDIMetaFileMIMETypeHighContrast(
239 RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\""));
240 } // anonymous namespace
242 void ChartView::getMetaFile( const uno::Reference< io::XOutputStream >& xOutStream
243 , bool bUseHighContrast )
245 if( !m_xDrawPage.is() )
246 return;
248 uno::Reference< lang::XMultiServiceFactory > xFactory( m_xCC->getServiceManager(), uno::UNO_QUERY );
249 if( !xFactory.is() )
250 return;
252 // creating the graphic exporter
253 uno::Reference< document::XExporter > xExporter( xFactory->createInstance(
254 C2U("com.sun.star.drawing.GraphicExportFilter")), uno::UNO_QUERY);
255 uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY );
257 if( !xExporter.is() || !xFilter.is() )
258 return;
260 uno::Sequence< beans::PropertyValue > aProps(3);
261 aProps[0].Name = C2U("FilterName");
262 aProps[0].Value <<= C2U("SVM");
264 aProps[1].Name = C2U("OutputStream");
265 aProps[1].Value <<= xOutStream;
267 uno::Sequence< beans::PropertyValue > aFilterData(4);
268 aFilterData[0].Name = C2U("ExportOnlyBackground");
269 aFilterData[0].Value <<= sal_False;
270 aFilterData[1].Name = C2U("HighContrast");
271 aFilterData[1].Value <<= bUseHighContrast;
273 aFilterData[2].Name = C2U("Version");
274 const sal_Int32 nVersion = SOFFICE_FILEFORMAT_50;
275 aFilterData[2].Value <<= nVersion;
277 aFilterData[3].Name = C2U("CurrentPage");
278 aFilterData[3].Value <<= uno::Reference< uno::XInterface >( m_xDrawPage, uno::UNO_QUERY );
280 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
282 aFilterData.realloc( aFilterData.getLength()+4 );
283 aFilterData[4].Name = C2U("ScaleXNumerator");
284 aFilterData[4].Value = uno::makeAny( m_nScaleXNumerator );
285 aFilterData[5].Name = C2U("ScaleXDenominator");
286 aFilterData[5].Value = uno::makeAny( m_nScaleXDenominator );
287 aFilterData[6].Name = C2U("ScaleYNumerator");
288 aFilterData[6].Value = uno::makeAny( m_nScaleYNumerator );
289 aFilterData[7].Name = C2U("ScaleYDenominator");
290 aFilterData[7].Value = uno::makeAny( m_nScaleYDenominator );
293 aProps[2].Name = C2U("FilterData");
294 aProps[2].Value <<= aFilterData;
296 xExporter->setSourceDocument( uno::Reference< lang::XComponent >( m_xDrawPage, uno::UNO_QUERY) );
297 if( xFilter->filter( aProps ) )
299 xOutStream->flush();
300 xOutStream->closeOutput();
301 uno::Reference< io::XSeekable > xSeekable( xOutStream, uno::UNO_QUERY );
302 if( xSeekable.is() )
303 xSeekable->seek(0);
307 uno::Any SAL_CALL ChartView::getTransferData( const datatransfer::DataFlavor& aFlavor )
308 throw (datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException)
310 bool bHighContrastMetaFile( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast));
311 uno::Any aRet;
312 if( ! (bHighContrastMetaFile || aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType)) )
313 return aRet;
315 impl_updateView();
317 SvMemoryStream aStream( 1024, 1024 );
318 utl::OStreamWrapper* pStreamWrapper = new utl::OStreamWrapper( aStream );
320 uno::Reference< io::XOutputStream > xOutStream( pStreamWrapper );
321 uno::Reference< io::XInputStream > xInStream( pStreamWrapper );
322 uno::Reference< io::XSeekable > xSeekable( pStreamWrapper );
324 if( xOutStream.is() )
326 this->getMetaFile( xOutStream, bHighContrastMetaFile );
328 if( xInStream.is() && xSeekable.is() )
330 xSeekable->seek(0);
331 sal_Int32 nBytesToRead = xInStream->available();
332 uno::Sequence< sal_Int8 > aSeq( nBytesToRead );
333 xInStream->readBytes( aSeq, nBytesToRead);
334 aRet <<= aSeq;
335 xInStream->closeInput();
339 return aRet;
341 uno::Sequence< datatransfer::DataFlavor > SAL_CALL ChartView::getTransferDataFlavors()
342 throw (uno::RuntimeException)
344 uno::Sequence< datatransfer::DataFlavor > aRet(2);
346 aRet[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMEType,
347 C2U( "GDIMetaFile" ),
348 ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
349 aRet[1] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast,
350 C2U( "GDIMetaFile" ),
351 ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
353 return aRet;
355 ::sal_Bool SAL_CALL ChartView::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
356 throw (uno::RuntimeException)
358 return ( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType) ||
359 aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast) );
362 //-----------------------------------------------------------------
363 // ____ XUnoTunnel ___
364 ::sal_Int64 SAL_CALL ChartView::getSomething( const uno::Sequence< ::sal_Int8 >& aIdentifier )
365 throw( uno::RuntimeException)
367 if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( ExplicitValueProvider::getUnoTunnelId().getConstArray(),
368 aIdentifier.getConstArray(), 16 ) )
370 ExplicitValueProvider* pProvider = this;
371 return reinterpret_cast<sal_Int64>(pProvider);
373 return 0;
376 //-----------------------------------------------------------------
377 // lang::XServiceInfo
379 APPHELPER_XSERVICEINFO_IMPL(ChartView,CHART_VIEW_SERVICE_IMPLEMENTATION_NAME)
381 uno::Sequence< rtl::OUString > ChartView
382 ::getSupportedServiceNames_Static()
384 uno::Sequence< rtl::OUString > aSNS( 1 );
385 aSNS.getArray()[ 0 ] = CHART_VIEW_SERVICE_NAME;
386 return aSNS;
389 //-----------------------------------------------------------------
390 //-----------------------------------------------------------------
392 ::basegfx::B3DHomMatrix createTransformationSceneToScreen(
393 const ::basegfx::B2IRectangle& rDiagramRectangleWithoutAxes )
395 ::basegfx::B3DHomMatrix aM;
396 aM.scale(double(rDiagramRectangleWithoutAxes.getWidth())/FIXED_SIZE_FOR_3D_CHART_VOLUME
397 , -double(rDiagramRectangleWithoutAxes.getHeight())/FIXED_SIZE_FOR_3D_CHART_VOLUME, 1.0 );
398 aM.translate(double(rDiagramRectangleWithoutAxes.getMinX())
399 , double(rDiagramRectangleWithoutAxes.getMinY()+rDiagramRectangleWithoutAxes.getHeight()-1), 0);
400 return aM;
403 VCoordinateSystem* findInCooSysList( const std::vector< VCoordinateSystem* >& rVCooSysList
404 , const uno::Reference< XCoordinateSystem >& xCooSys )
406 for( size_t nC=0; nC < rVCooSysList.size(); nC++)
408 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
409 if(pVCooSys->getModel()==xCooSys)
410 return pVCooSys;
412 return NULL;
415 VCoordinateSystem* addCooSysToList( std::vector< VCoordinateSystem* >& rVCooSysList
416 , const uno::Reference< XCoordinateSystem >& xCooSys
417 , const uno::Reference< frame::XModel >& xChartModel )
419 VCoordinateSystem* pVCooSys = findInCooSysList( rVCooSysList, xCooSys );
420 if( !pVCooSys )
422 pVCooSys = VCoordinateSystem::createCoordinateSystem(xCooSys );
423 if(pVCooSys)
425 rtl::OUString aCooSysParticle( ObjectIdentifier::createParticleForCoordinateSystem( xCooSys, xChartModel ) );
426 pVCooSys->setParticle(aCooSysParticle);
428 rVCooSysList.push_back( pVCooSys );
431 return pVCooSys;
434 VCoordinateSystem* lcl_getCooSysForPlotter( const std::vector< VCoordinateSystem* >& rVCooSysList, MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
436 if(!pMinimumAndMaximumSupplier)
437 return 0;
438 for( size_t nC=0; nC < rVCooSysList.size(); nC++)
440 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
441 if(pVCooSys->hasMinimumAndMaximumSupplier( pMinimumAndMaximumSupplier ))
442 return pVCooSys;
444 return 0;
447 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
448 typedef std::pair< VCoordinateSystem* , tFullAxisIndex > tFullCoordinateSystem;
449 typedef std::map< VCoordinateSystem*, tFullAxisIndex > tCoordinateSystemMap;
451 struct AxisUsage
453 AxisUsage();
454 ~AxisUsage();
456 void addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
457 ::std::vector< VCoordinateSystem* > getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
458 sal_Int32 getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex );
459 //tFullAxisIndex getDimensionAndIndexForCooSys( VCoordinateSystem* pCooSys );
461 ScaleAutomatism aScaleAutomatism;
463 private:
464 tCoordinateSystemMap aCoordinateSystems;
465 std::map< sal_Int32, sal_Int32 > aMaxIndexPerDimension;
468 AxisUsage::AxisUsage()
469 : aScaleAutomatism(AxisHelper::createDefaultScale())
473 AxisUsage::~AxisUsage()
475 aCoordinateSystems.clear();
479 tFullScaleIndex AxisUsage::getDimensionAndIndexForCooSys( VCoordinateSystem* pCooSys )
481 tFullScaleIndex aRet(0,0);
483 tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) );
484 if(aFound!=aCoordinateSystems.end())
485 aRet = aFound->second;
487 return aRet;
491 void AxisUsage::addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
493 if(!pCooSys)
494 return;
496 tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
497 tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) );
499 //use one scale only once for each coordinate system
500 //main axis are preferred over secondary axis
501 //value scales are preferred
502 if(aFound!=aCoordinateSystems.end())
504 sal_Int32 nFoundAxisIndex = aFound->second.second;
505 if( nFoundAxisIndex < nAxisIndex )
506 return;
507 sal_Int32 nFoundDimension = aFound->second.first;
508 if( nFoundDimension ==1 )
509 return;
510 if( nFoundDimension < nDimensionIndex )
511 return;
513 aCoordinateSystems[pCooSys] = aFullAxisIndex;
515 //set maximum scale index
516 std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex);
517 if( aIter != aMaxIndexPerDimension.end() )
519 sal_Int32 nCurrentMaxIndex = aIter->second;
520 if( nCurrentMaxIndex < nAxisIndex )
521 aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex;
523 else
524 aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex;
526 ::std::vector< VCoordinateSystem* > AxisUsage::getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
528 ::std::vector< VCoordinateSystem* > aRet;
530 tCoordinateSystemMap::const_iterator aIter;
531 for( aIter = aCoordinateSystems.begin(); aIter!=aCoordinateSystems.end();++aIter )
533 if( aIter->second.first != nDimensionIndex )
534 continue;
535 if( aIter->second.second != nAxisIndex )
536 continue;
537 aRet.push_back( aIter->first );
540 return aRet;
542 sal_Int32 AxisUsage::getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex )
544 sal_Int32 nRet = -1;
545 std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex);
546 if( aIter != aMaxIndexPerDimension.end() )
547 nRet = aIter->second;
548 return nRet;
551 //-----------------------------------------------------
553 class SeriesPlotterContainer
555 public:
556 SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList );
557 ~SeriesPlotterContainer();
559 void initializeCooSysAndSeriesPlotter( const uno::Reference< frame::XModel >& xChartModel );
560 void initAxisUsageList();
561 void doAutoScaling( const uno::Reference< frame::XModel >& xChartModel );
562 void updateScalesAndIncrementsOnAxes();
563 void setScalesFromCooSysToPlotter();
564 void setNumberFormatsFromAxes();
565 drawing::Direction3D getPreferredAspectRatio();
567 std::vector< VSeriesPlotter* >& getSeriesPlotterList() { return m_aSeriesPlotterList; }
568 std::vector< VCoordinateSystem* >& getCooSysList() { return m_rVCooSysList; }
569 std::vector< LegendEntryProvider* > getLegendEntryProviderList();
571 void AdaptScaleOfYAxisWithoutAttachedSeries( const uno::Reference< frame::XModel >& xChartModel );
573 private:
574 std::vector< VSeriesPlotter* > m_aSeriesPlotterList;
575 std::vector< VCoordinateSystem* >& m_rVCooSysList;
576 ::std::map< uno::Reference< XAxis >, AxisUsage > m_aAxisUsageList;
577 sal_Int32 m_nMaxAxisIndex;
578 bool m_bShiftXAxisTicks;
581 SeriesPlotterContainer::SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList )
582 : m_rVCooSysList( rVCooSysList )
583 , m_nMaxAxisIndex(0)
584 , m_bShiftXAxisTicks(false)
588 SeriesPlotterContainer::~SeriesPlotterContainer()
590 // - remove plotter from coordinatesystems
591 for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
592 m_rVCooSysList[nC]->clearMinimumAndMaximumSupplierList();
593 // - delete all plotter
594 ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
595 const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
596 for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
597 delete *aPlotterIter;
598 m_aSeriesPlotterList.clear();
601 std::vector< LegendEntryProvider* > SeriesPlotterContainer::getLegendEntryProviderList()
603 std::vector< LegendEntryProvider* > aRet( m_aSeriesPlotterList.size() );
604 ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
605 const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
606 sal_Int32 nN = 0;
607 for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter, nN++ )
608 aRet[nN] = *aPlotterIter;
609 return aRet;
612 void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(
613 const uno::Reference< frame::XModel >& xChartModel )
615 //------------ get model series from model
616 sal_Int32 nDiagramIndex = 0;//todo if more than one diagam is supported
617 uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
618 if( !xDiagram.is())
619 return;
621 uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartModel, uno::UNO_QUERY );
623 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
624 if(!nDimensionCount)
626 //@todo handle mixed dimension
627 nDimensionCount = 2;
630 sal_Bool bSortByXValues = sal_False;
631 sal_Bool bConnectBars = sal_False;
632 sal_Bool bGroupBarsPerAxis = sal_True;
633 sal_Bool bIncludeHiddenCells = sal_True;
634 sal_Int32 nStartingAngle = 90;
637 uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY_THROW );
638 xDiaProp->getPropertyValue( C2U( "SortByXValues" ) ) >>= bSortByXValues;
639 xDiaProp->getPropertyValue( C2U( "ConnectBars" ) ) >>= bConnectBars;
640 xDiaProp->getPropertyValue( C2U( "GroupBarsPerAxis" ) ) >>= bGroupBarsPerAxis;
641 xDiaProp->getPropertyValue( C2U( "IncludeHiddenCells" ) ) >>= bIncludeHiddenCells;
642 xDiaProp->getPropertyValue( C2U( "StartingAngle" ) ) >>= nStartingAngle;
644 catch( const uno::Exception & ex )
646 ASSERT_EXCEPTION( ex );
649 //---------------------------------------------------------------------
650 //prepare for autoscaling and shape creation
651 // - create plotter for charttypes (for each first scale group at each plotter, as they are independent)
652 // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling)
653 // - add plotter to coordinate systems
655 //iterate through all coordinate systems
656 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
657 OSL_ASSERT( xCooSysContainer.is());
658 if( !xCooSysContainer.is())
659 return;
660 uno::Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
661 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
662 sal_Int32 nGlobalSeriesIndex = 0;//for automatic symbols
663 for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
665 uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
666 VCoordinateSystem* pVCooSys = addCooSysToList(m_rVCooSysList,xCooSys,xChartModel);
668 //iterate through all chart types in the current coordinate system
669 uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
670 OSL_ASSERT( xChartTypeContainer.is());
671 if( !xChartTypeContainer.is() )
672 continue;
673 uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
674 for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
676 uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
678 if(nT==0)
679 m_bShiftXAxisTicks = ChartTypeHelper::shiftTicksAtXAxisPerDefault( xChartType );
681 VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( xChartType, nDimensionCount );
682 if( !pPlotter )
683 continue;
684 m_aSeriesPlotterList.push_back( pPlotter );
685 pPlotter->setNumberFormatsSupplier( xNumberFormatsSupplier );
686 pPlotter->setColorScheme( xColorScheme );
687 pPlotter->setExplicitCategoriesProvider( pVCooSys->getExplicitCategoriesProvider() );
688 sal_Int32 nMissingValueTreatment = DiagramHelper::getCorrectedMissingValueTreatment( xDiagram, xChartType );
690 if(pVCooSys)
691 pVCooSys->addMinimumAndMaximumSupplier(pPlotter);
693 //------------ add series to plotter and thus prepare him for providing minimum and maximum values
694 uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
695 OSL_ASSERT( xDataSeriesContainer.is());
696 if( !xDataSeriesContainer.is() )
697 continue;
698 sal_Int32 zSlot=-1;
699 sal_Int32 xSlot=-1;
700 sal_Int32 ySlot=-1;
701 uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
702 for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
704 uno::Reference< XDataSeries > xDataSeries( aSeriesList[nS], uno::UNO_QUERY );
705 if(!xDataSeries.is())
706 continue;
707 if( !bIncludeHiddenCells && !DataSeriesHelper::hasUnhiddenData(xDataSeries) )
708 continue;
710 VDataSeries* pSeries = new VDataSeries( xDataSeries );
712 pSeries->setGlobalSeriesIndex(nGlobalSeriesIndex);
713 nGlobalSeriesIndex++;
715 if( bSortByXValues )
716 pSeries->doSortByXValues();
718 pSeries->setConnectBars( bConnectBars );
719 pSeries->setGroupBarsPerAxis( bGroupBarsPerAxis );
720 pSeries->setStartingAngle( nStartingAngle );
722 pSeries->setMissingValueTreatment( nMissingValueTreatment );
724 rtl::OUString aSeriesParticle( ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCS, nT, nS ) );
725 pSeries->setParticle(aSeriesParticle);
727 OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) );
728 pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole);
730 //ignore secondary axis for charttypes that do not suppoert them
731 if( pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX &&
732 !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, 1 ) )
734 pSeries->setAttachedAxisIndex(MAIN_AXIS_INDEX);
737 StackingDirection eDirection = pSeries->getStackingDirection();
738 switch(eDirection)
740 case StackingDirection_NO_STACKING:
741 xSlot++; ySlot=-1;
742 if(zSlot<0)
743 zSlot=0;
744 break;
745 case StackingDirection_Y_STACKING:
746 ySlot++;
747 if(xSlot<0)
748 xSlot=0;
749 if(zSlot<0)
750 zSlot=0;
751 break;
752 case StackingDirection_Z_STACKING:
753 zSlot++; xSlot=-1; ySlot=-1;
754 break;
755 default:
756 // UNO enums have one additional auto-generated case
757 break;
759 pPlotter->addSeries( pSeries, zSlot, xSlot, ySlot );
764 //transport seriesnames to the coordinatesystems if needed
765 if( m_aSeriesPlotterList.size() )
767 uno::Sequence< rtl::OUString > aSeriesNames;
768 bool bSeriesNamesInitialized = false;
769 for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
771 VCoordinateSystem* pVCooSys = m_rVCooSysList[nC];
772 if(!pVCooSys)
773 continue;
774 if( pVCooSys->needSeriesNamesForAxis() )
776 if(!bSeriesNamesInitialized)
778 VSeriesPlotter* pSeriesPlotter = m_aSeriesPlotterList[0];
779 if( pSeriesPlotter )
780 aSeriesNames = pSeriesPlotter->getSeriesNames();
781 bSeriesNamesInitialized = true;
783 pVCooSys->setSeriesNamesForAxis( aSeriesNames );
789 void SeriesPlotterContainer::initAxisUsageList()
791 m_aAxisUsageList.clear();
792 size_t nC;
793 for( nC=0; nC < m_rVCooSysList.size(); nC++)
795 VCoordinateSystem* pVCooSys = m_rVCooSysList[nC];
796 for(sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
798 uno::Reference< XCoordinateSystem > xCooSys = pVCooSys->getModel();
799 if( nDimensionIndex >= xCooSys->getDimension() )
800 continue;
801 const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
802 for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
804 uno::Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
805 OSL_ASSERT( xAxis.is());
806 if( xAxis.is())
808 if(m_aAxisUsageList.find(xAxis)==m_aAxisUsageList.end())
809 m_aAxisUsageList[xAxis].aScaleAutomatism = ScaleAutomatism(xAxis->getScaleData());
810 AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis];
811 rAxisUsage.addCoordinateSystem(pVCooSys,nDimensionIndex,nAxisIndex);
817 ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
818 const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
820 //init m_nMaxAxisIndex
821 m_nMaxAxisIndex = 0;
822 for(sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
824 for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
826 sal_Int32 nLocalMax = aAxisIter->second.getMaxAxisIndexForDimension( nDimensionIndex );
827 if( m_nMaxAxisIndex < nLocalMax )
828 m_nMaxAxisIndex = nLocalMax;
833 void SeriesPlotterContainer::setScalesFromCooSysToPlotter()
835 //set scales to plotter to enable them to provide the preferred scene AspectRatio
836 ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
837 const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
838 for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
840 VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
841 VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter );
842 if(pVCooSys)
844 pSeriesPlotter->setScales( pVCooSys->getExplicitScales(0,0), pVCooSys->getPropertySwapXAndYAxis() );
845 sal_Int32 nMaxAxisIndex = pVCooSys->getMaximumAxisIndexByDimension(1);//only additional value axis are relevant for series plotter
846 for( sal_Int32 nI=1; nI<=nMaxAxisIndex; nI++ )
847 pSeriesPlotter->addSecondaryValueScale( pVCooSys->getExplicitScale(1,nI), nI );
852 void SeriesPlotterContainer::setNumberFormatsFromAxes()
854 //set numberfarmats to plotter to enable them to display the data labels in the numberfromat of teh axis
856 ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
857 const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
858 for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
860 VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
861 VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter );
862 if(pVCooSys)
864 AxesNumberFormats aAxesNumberFormats;
865 uno::Reference< XCoordinateSystem > xCooSys = pVCooSys->getModel();
866 sal_Int32 nDimensionCount = xCooSys->getDimension();
867 for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nDimensionCount; ++nDimensionIndex)
869 const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
870 for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
874 Reference< beans::XPropertySet > xAxisProp( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY );
875 if( xAxisProp.is())
877 sal_Int32 nNumberFormatKey(0);
878 if( xAxisProp->getPropertyValue( C2U( "NumberFormat" ) ) >>= nNumberFormatKey )
880 aAxesNumberFormats.setFormat( nNumberFormatKey, nDimensionIndex, nAxisIndex );
884 catch( lang::IndexOutOfBoundsException& e )
886 ASSERT_EXCEPTION( e );
890 pSeriesPlotter->setAxesNumberFormats( aAxesNumberFormats );
895 void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes()
897 for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
898 m_rVCooSysList[nC]->updateScalesAndIncrementsOnAxes();
901 void SeriesPlotterContainer::doAutoScaling( const uno::Reference< frame::XModel >& xChartModel )
903 //precondition: need a initialized m_aSeriesPlotterList
904 //precondition: need a initialized m_aAxisUsageList
906 ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
907 const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
909 //iterate over the main scales first than secondary axis
910 size_t nC;
911 sal_Int32 nAxisIndex=0;
912 for( nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ )
915 // - first do autoscale for all x and z scales (because they are treated independent)
916 for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
918 AxisUsage& rAxisUsage = (*aAxisIter).second;
919 ::std::vector< VCoordinateSystem* > aVCooSysList_X = rAxisUsage.getCoordinateSystems(0,nAxisIndex);
920 ::std::vector< VCoordinateSystem* > aVCooSysList_Z = rAxisUsage.getCoordinateSystems(2,nAxisIndex);
922 for( nC=0; nC < aVCooSysList_X.size(); nC++)
923 aVCooSysList_X[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,0,nAxisIndex);
924 for( nC=0; nC < aVCooSysList_Z.size(); nC++)
925 aVCooSysList_Z[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,2,nAxisIndex);
927 ExplicitScaleData aExplicitScale;
928 ExplicitIncrementData aExplicitIncrement;
929 rAxisUsage.aScaleAutomatism.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement );
931 for( nC=0; nC < aVCooSysList_X.size(); nC++)
933 if( m_bShiftXAxisTicks )
934 aExplicitIncrement.ShiftedPosition = true;
935 aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement );
937 for( nC=0; nC < aVCooSysList_Z.size(); nC++)
938 aVCooSysList_Z[nC]->setExplicitScaleAndIncrement( 2, nAxisIndex, aExplicitScale, aExplicitIncrement );
941 // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already )
942 for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
944 AxisUsage& rAxisUsage = (*aAxisIter).second;
945 ::std::vector< VCoordinateSystem* > aVCooSysList_X = rAxisUsage.getCoordinateSystems(0,nAxisIndex);
946 ::std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems(1,nAxisIndex);
947 ::std::vector< VCoordinateSystem* > aVCooSysList_Z = rAxisUsage.getCoordinateSystems(2,nAxisIndex);
949 if(!aVCooSysList_Y.size())
950 continue;
952 for( nC=0; nC < aVCooSysList_Y.size(); nC++)
953 aVCooSysList_Y[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,1,nAxisIndex);
955 ExplicitScaleData aExplicitScale;
956 ExplicitIncrementData aExplicitIncrement;
957 rAxisUsage.aScaleAutomatism.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement );
959 for( nC=0; nC < aVCooSysList_X.size(); nC++)
960 aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement );
961 for( nC=0; nC < aVCooSysList_Y.size(); nC++)
962 aVCooSysList_Y[nC]->setExplicitScaleAndIncrement( 1, nAxisIndex, aExplicitScale, aExplicitIncrement );
963 for( nC=0; nC < aVCooSysList_Z.size(); nC++)
964 aVCooSysList_Z[nC]->setExplicitScaleAndIncrement( 2, nAxisIndex, aExplicitScale, aExplicitIncrement );
967 AdaptScaleOfYAxisWithoutAttachedSeries( xChartModel );
970 void SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries( const uno::Reference< frame::XModel >& xChartModel )
972 //issue #i80518#
974 ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin();
975 const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
977 for( sal_Int32 nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ )
979 for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
981 AxisUsage& rAxisUsage = (*aAxisIter).second;
982 ::std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems( 1, nAxisIndex );
983 if( !aVCooSysList_Y.size() )
984 continue;
986 uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
987 if( xDiagram.is() )
989 bool bSeriesAttachedToThisAxis = false;
990 sal_Int32 nAttachedAxisIndex = -1;
992 ::std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
993 ::std::vector< Reference< XDataSeries > >::const_iterator aIter = aSeriesVector.begin();
994 for( ; aIter != aSeriesVector.end(); aIter++ )
996 sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex( *aIter );
997 if( nAxisIndex == nCurrentIndex )
999 bSeriesAttachedToThisAxis = true;
1000 break;
1002 else if( nAttachedAxisIndex<0 || nAttachedAxisIndex>nCurrentIndex )
1003 nAttachedAxisIndex=nCurrentIndex;
1007 if( !bSeriesAttachedToThisAxis && nAttachedAxisIndex >= 0 )
1009 for( size_t nC = 0; nC < aVCooSysList_Y.size(); ++nC )
1011 aVCooSysList_Y[nC]->prepareScaleAutomatismForDimensionAndIndex( rAxisUsage.aScaleAutomatism, 1, nAttachedAxisIndex );
1013 ExplicitScaleData aExplicitScaleSource = aVCooSysList_Y[nC]->getExplicitScale( 1,nAttachedAxisIndex );
1014 ExplicitIncrementData aExplicitIncrementSource = aVCooSysList_Y[nC]->getExplicitIncrement( 1,nAttachedAxisIndex );
1016 ExplicitScaleData aExplicitScaleDest = aVCooSysList_Y[nC]->getExplicitScale( 1,nAxisIndex );;
1017 ExplicitIncrementData aExplicitIncrementDest = aVCooSysList_Y[nC]->getExplicitIncrement( 1,nAxisIndex );;
1019 aExplicitScaleDest.Orientation = aExplicitScaleSource.Orientation;
1020 aExplicitScaleDest.Scaling = aExplicitScaleSource.Scaling;
1021 aExplicitScaleDest.Breaks = aExplicitScaleSource.Breaks;
1022 aExplicitScaleDest.AxisType = aExplicitScaleSource.AxisType;
1024 aExplicitIncrementDest.BaseValue = aExplicitIncrementSource.BaseValue;
1026 ScaleData aScale( rAxisUsage.aScaleAutomatism.getScale() );
1027 if( !aScale.Minimum.hasValue() )
1029 bool bNewMinOK = true;
1030 double fMax=0.0;
1031 if( aScale.Maximum >>= fMax )
1032 bNewMinOK = (aExplicitScaleSource.Minimum <= fMax);
1033 if( bNewMinOK )
1034 aExplicitScaleDest.Minimum = aExplicitScaleSource.Minimum;
1036 else
1037 aExplicitIncrementDest.BaseValue = aExplicitScaleDest.Minimum;
1039 if( !aScale.Maximum.hasValue() )
1041 bool bNewMaxOK = true;
1042 double fMin=0.0;
1043 if( aScale.Minimum >>= fMin )
1044 bNewMaxOK = (fMin <= aExplicitScaleSource.Maximum);
1045 if( bNewMaxOK )
1046 aExplicitScaleDest.Maximum = aExplicitScaleSource.Maximum;
1048 if( !aScale.Origin.hasValue() )
1049 aExplicitScaleDest.Origin = aExplicitScaleSource.Origin;
1051 if( !aScale.IncrementData.Distance.hasValue() )
1052 aExplicitIncrementDest.Distance = aExplicitIncrementSource.Distance;
1054 bool bAutoMinorInterval = true;
1055 if( aScale.IncrementData.SubIncrements.getLength() )
1056 bAutoMinorInterval = !( aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue() );
1057 if( bAutoMinorInterval )
1059 if( aExplicitIncrementDest.SubIncrements.getLength() && aExplicitIncrementSource.SubIncrements.getLength() )
1060 aExplicitIncrementDest.SubIncrements[0].IntervalCount =
1061 aExplicitIncrementSource.SubIncrements[0].IntervalCount;
1064 aVCooSysList_Y[nC]->setExplicitScaleAndIncrement( 1, nAxisIndex, aExplicitScaleDest, aExplicitIncrementDest );
1071 if( AxisHelper::isAxisPositioningEnabled() )
1073 //correct origin for y main axis (the origin is where the other main axis crosses)
1074 sal_Int32 nAxisIndex=0;
1075 sal_Int32 nDimensionIndex=1;
1076 for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
1078 AxisUsage& rAxisUsage = (*aAxisIter).second;
1079 ::std::vector< VCoordinateSystem* > aVCooSysList = rAxisUsage.getCoordinateSystems(nDimensionIndex,nAxisIndex);
1080 size_t nC;
1081 for( nC=0; nC < aVCooSysList.size(); nC++)
1083 ExplicitScaleData aExplicitScale( aVCooSysList[nC]->getExplicitScale( nDimensionIndex, nAxisIndex ) );
1084 ExplicitIncrementData aExplicitIncrement( aVCooSysList[nC]->getExplicitIncrement( nDimensionIndex, nAxisIndex ) );
1086 Reference< chart2::XCoordinateSystem > xCooSys( aVCooSysList[nC]->getModel() );
1087 Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
1088 Reference< beans::XPropertySet > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis, xCooSys ), uno::UNO_QUERY );
1090 ::com::sun::star::chart::ChartAxisPosition eCrossingMainAxisPos( ::com::sun::star::chart::ChartAxisPosition_ZERO );
1091 if( xCrossingMainAxis.is() )
1093 xCrossingMainAxis->getPropertyValue(C2U( "CrossoverPosition" )) >>= eCrossingMainAxisPos;
1094 if( ::com::sun::star::chart::ChartAxisPosition_VALUE == eCrossingMainAxisPos )
1096 double fValue = 0.0;
1097 xCrossingMainAxis->getPropertyValue(C2U( "CrossoverValue" )) >>= fValue;
1098 aExplicitScale.Origin = fValue;
1100 else if( ::com::sun::star::chart::ChartAxisPosition_ZERO == eCrossingMainAxisPos )
1101 aExplicitScale.Origin = 0.0;
1102 else if( ::com::sun::star::chart::ChartAxisPosition_START == eCrossingMainAxisPos )
1103 aExplicitScale.Origin = aExplicitScale.Minimum;
1104 else if( ::com::sun::star::chart::ChartAxisPosition_END == eCrossingMainAxisPos )
1105 aExplicitScale.Origin = aExplicitScale.Maximum;
1108 aVCooSysList[nC]->setExplicitScaleAndIncrement( nDimensionIndex, nAxisIndex, aExplicitScale, aExplicitIncrement );
1114 drawing::Direction3D SeriesPlotterContainer::getPreferredAspectRatio()
1116 drawing::Direction3D aPreferredAspectRatio(1.0,1.0,1.0);
1118 sal_Int32 nPlotterCount=0;
1119 //get a list of all preferred aspect ratios and combine them
1120 //first with special demands wins (less or equal zero <-> arbitrary)
1121 double fx, fy, fz;
1122 fx = fy = fz = -1.0;
1123 ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin();
1124 const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end();
1125 for( aPlotterIter = m_aSeriesPlotterList.begin(), nPlotterCount=0
1126 ; aPlotterIter != aPlotterEnd; aPlotterIter++, nPlotterCount++ )
1128 drawing::Direction3D aSingleRatio( (*aPlotterIter)->getPreferredDiagramAspectRatio() );
1129 if( fx<0 && aSingleRatio.DirectionX>0 )
1130 fx = aSingleRatio.DirectionX;
1132 if( fy<0 && aSingleRatio.DirectionY>0 )
1134 if( fx>0 && aSingleRatio.DirectionX>0 )
1135 fy = fx*aSingleRatio.DirectionY/aSingleRatio.DirectionX;
1136 else if( fz>0 && aSingleRatio.DirectionZ>0 )
1137 fy = fz*aSingleRatio.DirectionY/aSingleRatio.DirectionZ;
1138 else
1139 fy = aSingleRatio.DirectionY;
1142 if( fz<0 && aSingleRatio.DirectionZ>0 )
1144 if( fx>0 && aSingleRatio.DirectionX>0 )
1145 fz = fx*aSingleRatio.DirectionZ/aSingleRatio.DirectionX;
1146 else if( fy>0 && aSingleRatio.DirectionY>0 )
1147 fz = fy*aSingleRatio.DirectionZ/aSingleRatio.DirectionY;
1148 else
1149 fz = aSingleRatio.DirectionZ;
1152 if( fx>0 && fy>0 && fz>0 )
1153 break;
1155 aPreferredAspectRatio = drawing::Direction3D(fx, fy, fz);
1156 return aPreferredAspectRatio;
1159 //-----------------------------------------------------
1161 namespace
1164 bool lcl_resizeAfterCompleteCreation( const uno::Reference< XDiagram >& xDiagram )
1166 //special treatment for pie charts
1167 //the size is checked after complete creation to get the datalabels into the given space
1169 //todo: this is just a workaround at the moment for pie and donut labels
1170 return DiagramHelper::isPieOrDonutChart( xDiagram );
1173 void lcl_setDefaultWritingMode( ::boost::shared_ptr< DrawModelWrapper > pDrawModelWrapper, const Reference< frame::XModel >& xChartModel )
1175 //get writing mode from parent document:
1176 if( SvtLanguageOptions().IsCTLFontEnabled() )
1180 uno::Reference< container::XChild > xChild( xChartModel, uno::UNO_QUERY );
1181 sal_Int16 nWritingMode=-1;
1182 if ( xChild.is() )
1184 uno::Reference< beans::XPropertySet > xParentProps( xChild->getParent(), uno::UNO_QUERY );
1185 uno::Reference< style::XStyleFamiliesSupplier > xStyleFamiliesSupplier( xParentProps, uno::UNO_QUERY );
1186 if( xStyleFamiliesSupplier.is() )
1188 uno::Reference< container::XNameAccess > xStylesFamilies( xStyleFamiliesSupplier->getStyleFamilies() );
1189 if( xStylesFamilies.is() )
1191 if( !xStylesFamilies->hasByName( C2U("PageStyles") ) )
1193 //draw/impress is parent document
1194 uno::Reference< lang::XMultiServiceFactory > xFatcory( xParentProps, uno::UNO_QUERY );
1195 if( xFatcory.is() )
1197 uno::Reference< beans::XPropertySet > xDrawDefaults( xFatcory->createInstance( C2U( "com.sun.star.drawing.Defaults" ) ), uno::UNO_QUERY );
1198 if( xDrawDefaults.is() )
1199 xDrawDefaults->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
1202 else
1204 uno::Reference< container::XNameAccess > xPageStyles( xStylesFamilies->getByName( C2U("PageStyles") ), uno::UNO_QUERY );
1205 if( xPageStyles.is() )
1207 rtl::OUString aPageStyle;
1209 uno::Reference< text::XTextDocument > xTextDocument( xParentProps, uno::UNO_QUERY );
1210 if( xTextDocument.is() )
1212 //writer is parent document
1213 //retrieve the current page style from the text cursor property PageStyleName
1215 uno::Reference< text::XTextEmbeddedObjectsSupplier > xTextEmbeddedObjectsSupplier( xTextDocument, uno::UNO_QUERY );
1216 if( xTextEmbeddedObjectsSupplier.is() )
1218 uno::Reference< container::XNameAccess > xEmbeddedObjects( xTextEmbeddedObjectsSupplier->getEmbeddedObjects() );
1219 if( xEmbeddedObjects.is() )
1221 uno::Sequence< rtl::OUString > aNames( xEmbeddedObjects->getElementNames() );
1223 sal_Int32 nCount = aNames.getLength();
1224 for( sal_Int32 nN=0; nN<nCount; nN++ )
1226 uno::Reference< beans::XPropertySet > xEmbeddedProps( xEmbeddedObjects->getByName( aNames[nN] ), uno::UNO_QUERY );
1227 if( xEmbeddedProps.is() )
1229 static rtl::OUString aChartCLSID = rtl::OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName());
1230 rtl::OUString aCLSID;
1231 xEmbeddedProps->getPropertyValue( C2U("CLSID") ) >>= aCLSID;
1232 if( aCLSID.equals(aChartCLSID) )
1234 uno::Reference< frame::XModel > xModel;
1235 xEmbeddedProps->getPropertyValue( C2U("Model") ) >>= xModel;
1236 if( xModel == xChartModel )
1238 uno::Reference< text::XTextContent > xEmbeddedObject( xEmbeddedProps, uno::UNO_QUERY );
1239 if( xEmbeddedObject.is() )
1241 uno::Reference< text::XTextRange > xAnchor( xEmbeddedObject->getAnchor() );
1242 if( xAnchor.is() )
1244 uno::Reference< beans::XPropertySet > xAnchorProps( xAnchor, uno::UNO_QUERY );
1245 if( xAnchorProps.is() )
1247 xAnchorProps->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
1249 uno::Reference< text::XText > xText( xAnchor->getText() );
1250 if( xText.is() )
1252 uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
1253 if( xTextCursorProps.is() )
1254 xTextCursorProps->getPropertyValue( C2U("PageStyleName") ) >>= aPageStyle;
1258 break;
1265 if( !aPageStyle.getLength() )
1267 uno::Reference< text::XText > xText( xTextDocument->getText() );
1268 if( xText.is() )
1270 uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
1271 if( xTextCursorProps.is() )
1272 xTextCursorProps->getPropertyValue( C2U("PageStyleName") ) >>= aPageStyle;
1276 else
1278 //Calc is parent document
1279 xParentProps->getPropertyValue( C2U("PageStyle") ) >>= aPageStyle;
1280 if(!aPageStyle.getLength())
1281 aPageStyle = C2U("Default");
1283 if( nWritingMode == -1 || nWritingMode == text::WritingMode2::PAGE )
1285 uno::Reference< beans::XPropertySet > xPageStyle( xPageStyles->getByName( aPageStyle ), uno::UNO_QUERY );
1286 if( xPageStyle.is() )
1287 xPageStyle->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
1294 if( nWritingMode != -1 && nWritingMode != text::WritingMode2::PAGE )
1296 if( pDrawModelWrapper.get() )
1297 pDrawModelWrapper->GetItemPool().SetPoolDefaultItem(SfxInt32Item(EE_PARA_WRITINGDIR, nWritingMode) );
1300 catch( uno::Exception& ex )
1302 ASSERT_EXCEPTION( ex );
1307 sal_Int16 lcl_getDefaultWritingModeFromPool( ::boost::shared_ptr< DrawModelWrapper > pDrawModelWrapper )
1309 sal_Int16 nWritingMode = text::WritingMode2::LR_TB;
1310 if( pDrawModelWrapper.get() )
1312 const SfxPoolItem* pItem = &(pDrawModelWrapper->GetItemPool().GetDefaultItem( EE_PARA_WRITINGDIR ));
1313 if( pItem )
1314 nWritingMode = static_cast< sal_Int16 >((static_cast< const SfxInt32Item * >( pItem ))->GetValue());
1316 return nWritingMode;
1319 } //end anonymous namespace
1321 //------------ create complete diagram shape (inclusive axis and series)
1322 void ChartView::impl_createDiagramAndContent( SeriesPlotterContainer& rSeriesPlotterContainer
1323 , const uno::Reference< drawing::XShapes>& xDiagramPlusAxes_Shapes
1324 , const awt::Point& rAvailablePos
1325 , const awt::Size& rAvailableSize
1326 , const awt::Size& rPageSize )
1328 // sal_Int32 nDiagramIndex = 0;//todo if more than one diagam is supported
1329 uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) );
1330 if( !xDiagram.is())
1331 return;
1333 sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
1334 if(!nDimensionCount)
1336 //@todo handle mixed dimension
1337 nDimensionCount = 2;
1340 ::basegfx::B2IRectangle aAvailableOuterRect( BaseGFXHelper::makeRectangle(rAvailablePos,rAvailableSize) );
1342 const std::vector< VCoordinateSystem* >& rVCooSysList( rSeriesPlotterContainer.getCooSysList() );
1343 const std::vector< VSeriesPlotter* >& rSeriesPlotterList( rSeriesPlotterContainer.getSeriesPlotterList() );
1345 //create VAxis, so they can give necessary information for automatic scaling
1346 uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( m_xChartModel, uno::UNO_QUERY );
1347 size_t nC = 0;
1348 for( nC=0; nC < rVCooSysList.size(); nC++)
1350 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1351 if(3==nDimensionCount)
1353 uno::Reference<beans::XPropertySet> xSceneProperties( xDiagram, uno::UNO_QUERY );
1354 CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( xSceneProperties ) );
1355 CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( xSceneProperties ) );
1356 CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( xSceneProperties ) );
1357 pVCooSys->set3DWallPositions( eLeftWallPos, eBackWallPos, eBottomPos );
1359 pVCooSys->createVAxisList( xNumberFormatsSupplier
1360 , rPageSize //font reference size
1361 , BaseGFXHelper::B2IRectangleToAWTRectangle( aAvailableOuterRect ) //maximum space for labels
1366 // - prepare list of all axis and how they are used
1367 rSeriesPlotterContainer.initAxisUsageList();
1368 rSeriesPlotterContainer.doAutoScaling( m_xChartModel );
1369 rSeriesPlotterContainer.setScalesFromCooSysToPlotter();
1370 rSeriesPlotterContainer.setNumberFormatsFromAxes();
1372 //---------------------------------------------------------------------
1373 //create shapes
1375 //------------ create diagram shapes
1376 //aspect ratio
1377 drawing::Direction3D aPreferredAspectRatio(
1378 rSeriesPlotterContainer.getPreferredAspectRatio() );
1380 uno::Reference< drawing::XShapes > xSeriesTargetInFrontOfAxis(0);
1381 uno::Reference< drawing::XShapes > xSeriesTargetBehindAxis(0);
1382 VDiagram aVDiagram(xDiagram, aPreferredAspectRatio, nDimensionCount);
1383 {//create diagram
1384 aVDiagram.init(xDiagramPlusAxes_Shapes,xDiagramPlusAxes_Shapes,m_xShapeFactory);
1385 aVDiagram.createShapes(rAvailablePos,rAvailableSize);
1386 xSeriesTargetInFrontOfAxis = aVDiagram.getCoordinateRegion();
1387 aVDiagram.reduceToMimimumSize();
1390 uno::Reference< drawing::XShapes > xTextTargetShapes( ShapeFactory(m_xShapeFactory).createGroup2D(xDiagramPlusAxes_Shapes) );
1392 // - create axis and grids for all coordinate systems
1394 //init all coordinate systems
1395 for( nC=0; nC < rVCooSysList.size(); nC++)
1397 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1398 pVCooSys->initPlottingTargets(xSeriesTargetInFrontOfAxis,xTextTargetShapes,m_xShapeFactory,xSeriesTargetBehindAxis);
1400 pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1401 createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
1403 pVCooSys->initVAxisInList();
1406 //calculate resulting size respecting axis label layout and fontscaling
1408 //use first coosys only so far; todo: calculate for more than one coosys if we have more in future
1409 //todo: this is just a workaround at the moment for pie and donut labels
1410 if( !lcl_resizeAfterCompleteCreation(xDiagram) && rVCooSysList.size() > 0 )
1412 uno::Reference< drawing::XShape > xBoundingShape( xDiagramPlusAxes_Shapes, uno::UNO_QUERY );
1414 ::basegfx::B2IRectangle aFirstConsumedOuterRect( ShapeFactory::getRectangleOfShape(xBoundingShape) );
1416 VCoordinateSystem* pVCooSys = rVCooSysList[0];
1417 pVCooSys->createMaximumAxesLabels();
1419 ::basegfx::B2IRectangle aConsumedOuterRect( ShapeFactory::getRectangleOfShape(xBoundingShape) );
1420 ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.adjustInnerSize( aConsumedOuterRect ) );
1422 pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1423 createTransformationSceneToScreen( aNewInnerRect ) ));
1425 //redo autoscaling to get size and text dependent automatic main increment count
1426 rSeriesPlotterContainer.doAutoScaling( m_xChartModel );
1427 rSeriesPlotterContainer.updateScalesAndIncrementsOnAxes();
1428 rSeriesPlotterContainer.setScalesFromCooSysToPlotter();
1430 pVCooSys->createAxesLabels();
1432 bool bLessSpaceConsumedThanExpected = false;
1434 ::basegfx::B2IRectangle aOldRect( aConsumedOuterRect );
1435 aConsumedOuterRect = ShapeFactory::getRectangleOfShape(xBoundingShape);
1436 if( aConsumedOuterRect.getMinX() > aAvailableOuterRect.getMinX()
1437 || aConsumedOuterRect.getMaxX() < aAvailableOuterRect.getMaxX()
1438 || aConsumedOuterRect.getMinY() > aAvailableOuterRect.getMinY()
1439 || aConsumedOuterRect.getMinY() < aAvailableOuterRect.getMaxY() )
1440 bLessSpaceConsumedThanExpected = true;
1443 if( bLessSpaceConsumedThanExpected )
1445 aVDiagram.adjustInnerSize( aConsumedOuterRect );
1446 pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1447 createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
1448 pVCooSys->updatePositions();
1452 //create axes and grids for the final size
1453 for( nC=0; nC < rVCooSysList.size(); nC++)
1455 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1457 pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1458 createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
1460 pVCooSys->createAxesShapes();
1461 pVCooSys->createGridShapes();
1464 // - create data series for all charttypes
1465 m_bPointsWereSkipped = false;
1466 ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = rSeriesPlotterList.begin();
1467 const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = rSeriesPlotterList.end();
1468 for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
1470 //------------ set transformation to plotter / create series
1471 VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
1472 rtl::OUString aCID; //III
1473 uno::Reference< drawing::XShapes > xSeriesTarget(0);
1474 if( pSeriesPlotter->WantToPlotInFrontOfAxisLine() )
1475 xSeriesTarget = xSeriesTargetInFrontOfAxis;
1476 else
1478 xSeriesTarget = xSeriesTargetBehindAxis;
1479 DBG_ASSERT( !lcl_resizeAfterCompleteCreation(xDiagram), "not implemented yet! - during a complete recreation this shape is destroyed so no series can be created anymore" );
1481 pSeriesPlotter->initPlotter( xSeriesTarget,xTextTargetShapes,m_xShapeFactory,aCID );
1482 pSeriesPlotter->setPageReferenceSize( rPageSize );
1483 VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
1484 if(2==nDimensionCount)
1485 pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
1486 //better performance for big data
1487 awt::Size aCoordinateRegionResolution(1000,1000);
1489 //calculate resolution for coordinate system
1490 Sequence<sal_Int32> aCoordinateSystemResolution = pVCooSys->getCoordinateSystemResolution( rPageSize, m_aPageResolution );
1491 pSeriesPlotter->setCoordinateSystemResolution( aCoordinateSystemResolution );
1494 pSeriesPlotter->createShapes();
1495 m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped();
1498 //recreate with corrected sizes if requested
1499 if( lcl_resizeAfterCompleteCreation(xDiagram) )
1501 m_bPointsWereSkipped = false;
1503 uno::Reference< drawing::XShape > xBoundingShape( xDiagramPlusAxes_Shapes, uno::UNO_QUERY );
1504 ::basegfx::B2IRectangle aConsumedOuterRect( ShapeFactory::getRectangleOfShape(xBoundingShape) );
1506 ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.adjustInnerSize( aConsumedOuterRect ) );
1508 for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
1510 VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
1511 pSeriesPlotter->releaseShapes();
1514 //clear and recreate
1515 ShapeFactory::removeSubShapes( xSeriesTargetInFrontOfAxis ); //xSeriesTargetBehindAxis is a sub shape of xSeriesTargetInFrontOfAxis and will be removed here
1516 xSeriesTargetBehindAxis.clear();
1517 ShapeFactory::removeSubShapes( xTextTargetShapes );
1519 //set new transformation
1520 for( nC=0; nC < rVCooSysList.size(); nC++)
1522 VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1523 pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1524 createTransformationSceneToScreen( aNewInnerRect ) ));
1527 // - create data series for all charttypes
1528 for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
1530 //------------ set transformation to plotter / create series
1531 VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
1532 VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
1533 if(2==nDimensionCount)
1534 pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
1535 pSeriesPlotter->createShapes();
1536 m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped();
1540 uno::Reference< drawing::XShape > xDiagramPlusAxes_KeepRatio( xDiagramPlusAxes_Shapes, uno::UNO_QUERY );
1542 awt::Size aNewSize( rAvailableSize );
1543 awt::Point aNewPos( rAvailablePos );
1544 if( bKeepAspectRatio )
1546 awt::Size aCurrentSize( xDiagramPlusAxes_KeepRatio->getSize());
1548 aNewSize = ShapeFactory::calculateNewSizeRespectingAspectRatio(
1549 rAvailableSize, aCurrentSize );
1550 aNewPos = ShapeFactory::calculateTopLeftPositionToCenterObject(
1551 rAvailablePos, rAvailableSize, aNewSize );
1554 xDiagramPlusAxes_KeepRatio->setPosition( aNewPos );
1555 xDiagramPlusAxes_KeepRatio->setSize( aNewSize );
1557 for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
1559 VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
1560 pSeriesPlotter->rearrangeLabelToAvoidOverlapIfRequested( rPageSize );
1565 //-------------------------------------------------------------
1566 //-------------------------------------------------------------
1567 //-------------------------------------------------------------
1569 sal_Bool ChartView::getExplicitValuesForAxis(
1570 uno::Reference< XAxis > xAxis
1571 , ExplicitScaleData& rExplicitScale
1572 , ExplicitIncrementData& rExplicitIncrement )
1574 impl_updateView();
1576 if(!xAxis.is())
1577 return sal_False;
1579 uno::Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis(xAxis,ChartModelHelper::findDiagram( m_xChartModel ) ) );
1580 const VCoordinateSystem* pVCooSys = findInCooSysList(m_aVCooSysList,xCooSys);
1581 if(!pVCooSys)
1582 return sal_False;
1584 sal_Int32 nDimensionIndex=-1;
1585 sal_Int32 nAxisIndex=-1;
1586 if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) )
1588 rExplicitScale = pVCooSys->getExplicitScale(nDimensionIndex,nAxisIndex);
1589 rExplicitIncrement = pVCooSys->getExplicitIncrement(nDimensionIndex,nAxisIndex);
1590 return sal_True;
1592 return sal_False;
1595 SdrPage* ChartView::getSdrPage()
1597 SdrPage* pPage=0;
1598 Reference< lang::XUnoTunnel> xUnoTunnel(m_xDrawPage,uno::UNO_QUERY);
1599 if(xUnoTunnel.is())
1601 SvxDrawPage* pSvxDrawPage = reinterpret_cast<SvxDrawPage*>(xUnoTunnel->getSomething(
1602 SvxDrawPage::getUnoTunnelId() ));
1603 if(pSvxDrawPage)
1605 pPage = pSvxDrawPage->GetSdrPage();
1608 return pPage;
1611 uno::Reference< drawing::XShape > ChartView::getShapeForCID( const rtl::OUString& rObjectCID )
1613 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
1614 SdrObject* pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, this->getSdrPage() );
1615 if( pObj )
1616 return uno::Reference< drawing::XShape >( pObj->getUnoShape(), uno::UNO_QUERY);
1617 return 0;
1620 awt::Rectangle ChartView::getRectangleOfObject( const rtl::OUString& rObjectCID, bool bSnapRect )
1622 impl_updateView();
1624 awt::Rectangle aRet;
1625 uno::Reference< drawing::XShape > xShape( getShapeForCID(rObjectCID) );
1626 if(xShape.is())
1628 //special handling for axis for old api:
1629 //same special handling for diagram
1630 ObjectType eObjectType( ObjectIdentifier::getObjectType( rObjectCID ) );
1631 if( eObjectType == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_DIAGRAM )
1633 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
1634 SvxShape* pRoot = SvxShape::getImplementation( xShape );
1635 if( pRoot )
1637 SdrObject* pRootSdrObject = pRoot->GetSdrObject();
1638 if( pRootSdrObject )
1640 SdrObjList* pRootList = pRootSdrObject->GetSubList();
1641 if( pRootList )
1643 SdrObject* pShape = DrawModelWrapper::getNamedSdrObject( C2U("MarkHandles"), pRootList );
1644 if( pShape )
1645 xShape = uno::Reference< drawing::XShape >( pShape->getUnoShape(), uno::UNO_QUERY);
1651 awt::Size aSize( xShape->getSize() );
1652 awt::Point aPoint( xShape->getPosition() );
1653 aRet = awt::Rectangle( aPoint.X, aPoint.Y, aSize.Width, aSize.Height );
1654 if( bSnapRect )
1656 //for rotated objects the shape size and position differs from the visible rectangle
1657 SvxShape* pShape = SvxShape::getImplementation( xShape );
1658 if( pShape )
1660 SdrObject* pSdrObject = pShape->GetSdrObject();
1661 if( pSdrObject )
1663 Rectangle aSnapRect( pSdrObject->GetSnapRect() );
1664 aRet = awt::Rectangle(aSnapRect.Left(),aSnapRect.Top(),aSnapRect.GetWidth(),aSnapRect.GetHeight());
1669 return aRet;
1672 ::boost::shared_ptr< DrawModelWrapper > ChartView::getDrawModelWrapper()
1674 return m_pDrawModelWrapper;
1677 namespace
1679 sal_Int32 lcl_getDiagramTitleSpace()
1681 return 200; //=0,2 cm spacing
1683 bool lcl_getPropertySwapXAndYAxis( const uno::Reference< XDiagram >& xDiagram )
1685 bool bSwapXAndY = false;
1687 uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
1688 if( xCooSysContainer.is() )
1690 uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
1691 if( aCooSysList.getLength() )
1693 uno::Reference<beans::XPropertySet> xProp(aCooSysList[0], uno::UNO_QUERY );
1694 if( xProp.is()) try
1696 xProp->getPropertyValue( C2U( "SwapXAndYAxis" ) ) >>= bSwapXAndY;
1698 catch( uno::Exception& e )
1700 ASSERT_EXCEPTION( e );
1704 return bSwapXAndY;
1709 sal_Int32 lcl_getExplicitNumberFormatKeyForAxis(
1710 const Reference< chart2::XAxis >& xAxis
1711 , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
1712 , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier
1713 , bool bSearchForParallelAxisIfNothingIsFound )
1715 sal_Int32 nNumberFormatKey(0);
1716 Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
1717 if( xProp.is() && !( xProp->getPropertyValue( C2U( "NumberFormat" ) ) >>= nNumberFormatKey ) )
1719 bool bPercentFormatSet = false;
1720 //check wether we have a percent scale -> use percent format
1721 if( xNumberFormatsSupplier.is() )
1723 ScaleData aData = xAxis->getScaleData();
1724 if( aData.AxisType==AxisType::PERCENT )
1726 sal_Int32 nPercentFormat = ExplicitValueProvider::getPercentNumberFormat( xNumberFormatsSupplier );
1727 if( nPercentFormat != -1 )
1729 nNumberFormatKey = nPercentFormat;
1730 bPercentFormatSet = true;
1735 if( !bPercentFormatSet )
1737 typedef ::std::map< sal_Int32, sal_Int32 > tNumberformatFrequency;
1738 tNumberformatFrequency aKeyMap;
1740 bool bNumberFormatKeyFoundViaAttachedData = false;
1741 sal_Int32 nAxisIndex = 0;
1742 sal_Int32 nDimensionIndex = 1;
1746 Reference< XChartTypeContainer > xCTCnt( xCorrespondingCoordinateSystem, uno::UNO_QUERY_THROW );
1747 if( xCTCnt.is() )
1749 AxisHelper::getIndicesForAxis( xAxis, xCorrespondingCoordinateSystem, nDimensionIndex, nAxisIndex );
1750 ::rtl::OUString aRoleToMatch;
1751 if( nDimensionIndex == 0 )
1752 aRoleToMatch = C2U("values-x");
1753 Sequence< Reference< XChartType > > aChartTypes( xCTCnt->getChartTypes());
1754 sal_Int32 nCTCount = aChartTypes.getLength();
1755 if (nCTCount > 0)
1756 // When multiple chart types share the same axis, always
1757 // use the first chart type for automatic detection of
1758 // desired number format. This is in line with the
1759 // fact that the axis type is also determined from the
1760 // first chart type alone.
1761 nCTCount = 1;
1762 for( sal_Int32 nCTIdx=0; nCTIdx<nCTCount; ++nCTIdx )
1764 if( nDimensionIndex != 0 )
1765 aRoleToMatch = ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( aChartTypes[nCTIdx] );
1766 Reference< XDataSeriesContainer > xDSCnt( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW );
1767 Sequence< Reference< XDataSeries > > aDataSeriesSeq( xDSCnt->getDataSeries());
1768 for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aDataSeriesSeq.getLength(); ++nSeriesIdx )
1770 Reference< chart2::XDataSeries > xDataSeries(aDataSeriesSeq[nSeriesIdx]);
1771 Reference< data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY_THROW );
1773 if( nDimensionIndex == 1 )
1775 //only take those series into accoutn that are attached to this axis
1776 sal_Int32 nAttachedAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries);
1777 if( nAttachedAxisIndex != nAxisIndex )
1778 continue;
1781 Sequence< Reference< data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences());
1782 for( sal_Int32 nLSeqIdx=0; nLSeqIdx<aLabeledSeq.getLength(); ++nLSeqIdx )
1784 if(!aLabeledSeq[nLSeqIdx].is())
1785 continue;
1786 Reference< data::XDataSequence > xSeq( aLabeledSeq[nLSeqIdx]->getValues());
1787 OSL_ASSERT( xSeq.is());
1788 Reference< beans::XPropertySet > xSeqProp( xSeq, uno::UNO_QUERY );
1789 ::rtl::OUString aRole;
1790 bool bTakeIntoAccount =
1791 ( xSeqProp.is() && (aRoleToMatch.getLength() > 0) &&
1792 (xSeqProp->getPropertyValue(C2U("Role")) >>= aRole ) &&
1793 aRole.equals( aRoleToMatch ));
1795 if( bTakeIntoAccount )
1797 sal_Int32 nKey = xSeq->getNumberFormatKeyByIndex( -1 );
1798 // initialize the value
1799 if( aKeyMap.find( nKey ) == aKeyMap.end())
1800 aKeyMap[ nKey ] = 0;
1801 // increase frequency
1802 aKeyMap[ nKey ] = (aKeyMap[ nKey ] + 1);
1809 catch( const uno::Exception & ex )
1811 ASSERT_EXCEPTION( ex );
1814 if( ! aKeyMap.empty())
1816 sal_Int32 nMaxFreq = 0;
1817 // find most frequent key
1818 for( tNumberformatFrequency::const_iterator aIt = aKeyMap.begin();
1819 aIt != aKeyMap.end(); ++aIt )
1821 OSL_TRACE( "NumberFormatKey %d appears %d times", (*aIt).first, (*aIt).second );
1822 // all values must at least be 1
1823 if( (*aIt).second > nMaxFreq )
1825 nNumberFormatKey = (*aIt).first;
1826 bNumberFormatKeyFoundViaAttachedData = true;
1827 nMaxFreq = (*aIt).second;
1832 if( bSearchForParallelAxisIfNothingIsFound )
1834 //no format is set to this axis and no data is set to this axis
1835 //--> try to obtain the format from the parallel y-axis
1836 if( !bNumberFormatKeyFoundViaAttachedData && nDimensionIndex == 1 )
1838 sal_Int32 nParallelAxisIndex = (nAxisIndex==1) ?0 :1;
1839 Reference< XAxis > xParallelAxis( AxisHelper::getAxis( 1, nParallelAxisIndex, xCorrespondingCoordinateSystem ) );
1840 nNumberFormatKey = lcl_getExplicitNumberFormatKeyForAxis( xParallelAxis, xCorrespondingCoordinateSystem, xNumberFormatsSupplier, false );
1845 return nNumberFormatKey;
1848 //static
1849 sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
1850 const Reference< chart2::XAxis >& xAxis
1851 , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
1852 , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
1854 return lcl_getExplicitNumberFormatKeyForAxis( xAxis, xCorrespondingCoordinateSystem, xNumberFormatsSupplier
1855 , true /*bSearchForParallelAxisIfNothingIsFound*/ );
1858 //static
1859 sal_Int32 ExplicitValueProvider::getPercentNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
1861 sal_Int32 nRet=-1;
1862 Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() );
1863 if( xNumberFormats.is() )
1865 sal_Bool bCreate = sal_True;
1866 const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
1867 Sequence<sal_Int32> aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::PERCENT,
1868 rLocaleDataWrapper.getLocale(), bCreate );
1869 if( aKeySeq.getLength() )
1871 nRet = aKeySeq[0];
1874 return nRet;
1878 sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
1879 const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp,
1880 const uno::Reference< XDataSeries >& xSeries,
1881 sal_Int32 nPointIndex /*-1 for whole series*/,
1882 const uno::Reference< XDiagram >& xDiagram
1885 sal_Int32 nFormat=0;
1886 if( !xSeriesOrPointProp.is() )
1887 return nFormat;
1889 rtl::OUString aPropName( C2U( "NumberFormat" ) );
1890 if( !(xSeriesOrPointProp->getPropertyValue(aPropName) >>= nFormat) )
1892 uno::Reference< chart2::XChartType > xChartType( DataSeriesHelper::getChartTypeOfSeries( xSeries, xDiagram ) );
1894 bool bFormatFound = false;
1895 if( ChartTypeHelper::shouldLabelNumberFormatKeyBeDetectedFromYAxis( xChartType ) )
1897 uno::Reference< beans::XPropertySet > xAttachedAxisProps( DiagramHelper::getAttachedAxis( xSeries, xDiagram ), uno::UNO_QUERY );
1898 if( xAttachedAxisProps.is() && ( xAttachedAxisProps->getPropertyValue( aPropName ) >>= nFormat ) )
1899 bFormatFound = true;
1901 if( !bFormatFound )
1903 Reference< chart2::data::XDataSource > xSeriesSource( xSeries, uno::UNO_QUERY );
1904 OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) );
1906 Reference< data::XLabeledDataSequence > xLabeledSequence(
1907 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, aRole, false ));
1908 if( xLabeledSequence.is() )
1910 Reference< data::XDataSequence > xValues( xLabeledSequence->getValues() );
1911 if( xValues.is() )
1912 nFormat = xValues->getNumberFormatKeyByIndex( nPointIndex );
1916 if(nFormat<0)
1917 nFormat=0;
1918 return nFormat;
1921 sal_Int32 ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel(
1922 const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp,
1923 const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
1925 sal_Int32 nFormat=0;
1926 if( !xSeriesOrPointProp.is() )
1927 return nFormat;
1928 if( !(xSeriesOrPointProp->getPropertyValue(C2U( "PercentageNumberFormat" )) >>= nFormat) )
1930 nFormat = ExplicitValueProvider::getPercentNumberFormat( xNumberFormatsSupplier );
1932 if(nFormat<0)
1933 nFormat=0;
1934 return nFormat;
1937 //static
1938 awt::Rectangle ExplicitValueProvider::calculateDiagramPositionAndSizeInclusiveTitle(
1939 const Reference< frame::XModel >& xChartModel
1940 , const Reference< uno::XInterface >& xChartView
1941 , const awt::Rectangle& rExclusivePositionAndSize )
1943 awt::Rectangle aRet(rExclusivePositionAndSize);
1945 //add axis title sizes to the diagram size
1946 uno::Reference< chart2::XTitle > xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, xChartModel ) );
1947 uno::Reference< chart2::XTitle > xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, xChartModel ) );
1948 uno::Reference< chart2::XTitle > xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xChartModel ) );
1949 uno::Reference< chart2::XTitle > xSecondTitle_Width( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xChartModel ) );
1950 if( xTitle_Height.is() || xTitle_Width.is() || xSecondTitle_Height.is() || xSecondTitle_Width.is() )
1952 ExplicitValueProvider* pExplicitValueProvider = ExplicitValueProvider::getExplicitValueProvider(xChartView);
1953 if( pExplicitValueProvider )
1955 //detect wether x axis points into x direction or not
1956 if( lcl_getPropertySwapXAndYAxis( ChartModelHelper::findDiagram( xChartModel ) ) )
1958 std::swap( xTitle_Height, xTitle_Width );
1959 std::swap( xSecondTitle_Height, xSecondTitle_Width );
1962 sal_Int32 nTitleSpaceWidth = 0;
1963 sal_Int32 nTitleSpaceHeight = 0;
1964 sal_Int32 nSecondTitleSpaceWidth = 0;
1965 sal_Int32 nSecondTitleSpaceHeight = 0;
1967 if( xTitle_Height.is() )
1969 rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height, xChartModel ) );
1970 nTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
1971 if( nTitleSpaceHeight )
1972 nTitleSpaceHeight+=lcl_getDiagramTitleSpace();
1974 if( xTitle_Width.is() )
1976 rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width, xChartModel ) );
1977 nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
1978 if(nTitleSpaceWidth)
1979 nTitleSpaceWidth+=lcl_getDiagramTitleSpace();
1981 if( xSecondTitle_Height.is() )
1983 rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height, xChartModel ) );
1984 nSecondTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
1985 if( nSecondTitleSpaceHeight )
1986 nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace();
1988 if( xSecondTitle_Width.is() )
1990 rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width, xChartModel ) );
1991 nSecondTitleSpaceWidth += pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
1992 if( nSecondTitleSpaceWidth )
1993 nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace();
1996 aRet.X -= nTitleSpaceWidth;
1997 aRet.Y -= nSecondTitleSpaceHeight;
1998 aRet.Width += nTitleSpaceWidth + nSecondTitleSpaceWidth;
1999 aRet.Height += nTitleSpaceHeight + nSecondTitleSpaceHeight;
2002 return aRet;
2005 double lcl_getPageLayoutDistancePercentage()
2007 return 0.02;
2010 bool getAvailablePosAndSizeForDiagram(
2011 awt::Point& rOutPos, awt::Size& rOutAvailableDiagramSize
2012 , const awt::Rectangle& rSpaceLeft
2013 , const awt::Size & rPageSize
2014 , const uno::Reference< XDiagram > & xDiagram
2015 , VTitle* pXTitle, VTitle* pYTitle
2016 , VTitle* pSecondXTitle, VTitle* pSecondYTitle )
2018 //@todo: we need a size dependent on the axis labels
2019 awt::Rectangle aRemainingSpace(rSpaceLeft);
2021 sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
2022 sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
2023 aRemainingSpace.X+=nXDistance;
2024 aRemainingSpace.Width-=2*nXDistance;
2025 aRemainingSpace.Y+=nYDistance;
2026 aRemainingSpace.Height-=2*nYDistance;
2028 if(aRemainingSpace.Width <= 0 || aRemainingSpace.Height <= 0 )
2029 return false;
2031 uno::Reference< beans::XPropertySet > xProp(xDiagram, uno::UNO_QUERY);
2033 bool bMakeRoomForTitle = false;
2035 //size:
2036 ::com::sun::star::chart2::RelativeSize aRelativeSize;
2037 if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativeSize" ) )>>=aRelativeSize) )
2039 rOutAvailableDiagramSize.Height = static_cast<sal_Int32>(aRelativeSize.Secondary*rPageSize.Height);
2040 rOutAvailableDiagramSize.Width = static_cast<sal_Int32>(aRelativeSize.Primary*rPageSize.Width);
2041 bMakeRoomForTitle = true;
2043 else
2044 rOutAvailableDiagramSize = awt::Size(aRemainingSpace.Width,aRemainingSpace.Height);
2046 //position:
2047 chart2::RelativePosition aRelativePosition;
2048 if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativePosition" ) )>>=aRelativePosition) )
2050 //@todo decide wether x is primary or secondary
2052 //the coordinates re relative to the page
2053 double fX = aRelativePosition.Primary*rPageSize.Width;
2054 double fY = aRelativePosition.Secondary*rPageSize.Height;
2056 rOutPos = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
2057 awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY))
2058 , rOutAvailableDiagramSize, aRelativePosition.Anchor );
2059 bMakeRoomForTitle = true;
2061 else
2062 rOutPos = awt::Point(aRemainingSpace.X,aRemainingSpace.Y);
2064 //ensure that the diagram does not lap out right side or out of bottom
2066 if( rOutPos.Y + rOutAvailableDiagramSize.Height > rPageSize.Height )
2067 rOutAvailableDiagramSize.Height = rPageSize.Height - rOutPos.Y;
2068 if( rOutPos.X + rOutAvailableDiagramSize.Width > rPageSize.Width )
2069 rOutAvailableDiagramSize.Width = rPageSize.Width - rOutPos.X;
2072 if( bMakeRoomForTitle )
2074 sal_Int32 nTitleSpaceWidth = 0;
2075 sal_Int32 nTitleSpaceHeight = 0;
2076 sal_Int32 nSecondTitleSpaceWidth = 0;
2077 sal_Int32 nSecondTitleSpaceHeight = 0;
2079 //todo detect wether x axis points into x direction or not
2080 //detect wether x axis points into x direction or not
2081 if( lcl_getPropertySwapXAndYAxis( xDiagram ) )
2083 std::swap( pXTitle, pYTitle );
2084 std::swap( pSecondXTitle, pSecondYTitle );
2087 if( pXTitle )
2089 nTitleSpaceHeight = pXTitle->getFinalSize().Height;
2090 if(nTitleSpaceHeight)
2091 nTitleSpaceHeight+=lcl_getDiagramTitleSpace();
2093 if( pYTitle )
2095 nTitleSpaceWidth = pYTitle->getFinalSize().Width;
2096 if(nTitleSpaceWidth)
2097 nTitleSpaceWidth+=lcl_getDiagramTitleSpace();
2099 if( pSecondXTitle)
2101 nSecondTitleSpaceHeight += pSecondXTitle->getFinalSize().Height;
2102 if(nSecondTitleSpaceHeight)
2103 nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace();
2105 if( pSecondYTitle)
2107 nSecondTitleSpaceWidth += pSecondYTitle->getFinalSize().Width;
2108 if(nSecondTitleSpaceWidth)
2109 nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace();
2112 rOutAvailableDiagramSize.Height -= nTitleSpaceHeight + nSecondTitleSpaceHeight;
2113 rOutAvailableDiagramSize.Width -= nTitleSpaceWidth + nSecondTitleSpaceWidth;
2114 rOutPos.X += nTitleSpaceWidth;
2115 rOutPos.Y += nSecondTitleSpaceHeight;
2118 return true;
2121 enum TitleAlignment { ALIGN_LEFT, ALIGN_TOP, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_Z };
2123 void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment
2124 , awt::Rectangle& rDiagramPlusAxesRect, const awt::Size & rPageSize )
2126 if(!pVTitle)
2127 return;
2129 awt::Point aNewPosition(0,0);
2130 awt::Size aTitleSize = pVTitle->getFinalSize();
2131 sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
2132 sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
2133 switch( eAlignment )
2135 case ALIGN_TOP:
2136 aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
2137 , rDiagramPlusAxesRect.Y - aTitleSize.Height/2 - nYDistance );
2138 break;
2139 case ALIGN_BOTTOM:
2140 aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
2141 , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height + aTitleSize.Height/2 + nYDistance );
2142 break;
2143 case ALIGN_LEFT:
2144 aNewPosition = awt::Point( rDiagramPlusAxesRect.X - aTitleSize.Width/2 - nXDistance
2145 , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
2146 break;
2147 case ALIGN_RIGHT:
2148 aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
2149 , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
2150 break;
2151 case ALIGN_Z:
2152 aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
2153 , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height - aTitleSize.Height/2 );
2154 break;
2155 default:
2156 break;
2159 pVTitle->changePosition( aNewPosition );
2162 std::auto_ptr<VTitle> lcl_createTitle( const uno::Reference< XTitle >& xTitle
2163 , const uno::Reference< drawing::XShapes>& xPageShapes
2164 , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
2165 , const uno::Reference< frame::XModel >& xChartModel
2166 , awt::Rectangle& rRemainingSpace
2167 , const awt::Size & rPageSize
2168 , TitleAlignment eAlignment
2169 , bool& rbAutoPosition )
2171 std::auto_ptr<VTitle> apVTitle;
2172 if(xTitle.is())
2174 rtl::OUString aCompleteString( TitleHelper::getCompleteString( xTitle ) );
2175 if( aCompleteString.getLength()==0 )
2176 return apVTitle;//don't create empty titles as the resulting diagram position is wrong then
2178 //create title
2179 apVTitle = std::auto_ptr<VTitle>(new VTitle(xTitle));
2180 rtl::OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle, xChartModel ) );
2181 apVTitle->init(xPageShapes,xShapeFactory,aCID);
2182 apVTitle->createShapes( awt::Point(0,0), rPageSize );
2183 awt::Size aTitleUnrotatedSize = apVTitle->getUnrotatedSize();
2184 awt::Size aTitleSize = apVTitle->getFinalSize();
2186 //position
2187 rbAutoPosition=true;
2188 awt::Point aNewPosition(0,0);
2189 sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
2190 sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
2191 chart2::RelativePosition aRelativePosition;
2192 uno::Reference< beans::XPropertySet > xProp(xTitle, uno::UNO_QUERY);
2193 if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativePosition" ) )>>=aRelativePosition) )
2195 rbAutoPosition = false;
2197 //@todo decide wether x is primary or secondary
2198 double fX = aRelativePosition.Primary*rPageSize.Width;
2199 double fY = aRelativePosition.Secondary*rPageSize.Height;
2201 double fAnglePi = apVTitle->getRotationAnglePi();
2202 aNewPosition = RelativePositionHelper::getCenterOfAnchoredObject(
2203 awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY))
2204 , aTitleUnrotatedSize, aRelativePosition.Anchor, fAnglePi );
2206 else //auto position
2208 switch( eAlignment )
2210 case ALIGN_TOP:
2211 aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
2212 , rRemainingSpace.Y + aTitleSize.Height/2 + nYDistance );
2213 break;
2214 case ALIGN_BOTTOM:
2215 aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
2216 , rRemainingSpace.Y + rRemainingSpace.Height - aTitleSize.Height/2 - nYDistance );
2217 break;
2218 case ALIGN_LEFT:
2219 aNewPosition = awt::Point( rRemainingSpace.X + aTitleSize.Width/2 + nXDistance
2220 , rRemainingSpace.Y + rRemainingSpace.Height/2 );
2221 break;
2222 case ALIGN_RIGHT:
2223 aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width - aTitleSize.Width/2 - nXDistance
2224 , rRemainingSpace.Y + rRemainingSpace.Height/2 );
2225 break;
2226 default:
2227 break;
2231 apVTitle->changePosition( aNewPosition );
2233 //remaining space
2234 switch( eAlignment )
2236 case ALIGN_TOP:
2237 rRemainingSpace.Y += ( aTitleSize.Height + nYDistance );
2238 rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
2239 break;
2240 case ALIGN_BOTTOM:
2241 rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
2242 break;
2243 case ALIGN_LEFT:
2244 rRemainingSpace.X += ( aTitleSize.Width + nXDistance );
2245 rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
2246 break;
2247 case ALIGN_RIGHT:
2248 rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
2249 break;
2250 default:
2251 break;
2254 return apVTitle;
2257 bool lcl_createLegend( const uno::Reference< XLegend > & xLegend
2258 , const uno::Reference< drawing::XShapes>& xPageShapes
2259 , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
2260 , const uno::Reference< uno::XComponentContext > & xContext
2261 , awt::Rectangle & rRemainingSpace
2262 , const awt::Size & rPageSize
2263 , const uno::Reference< frame::XModel > & xModel
2264 , const std::vector< LegendEntryProvider* >& rLegendEntryProviderList
2265 , sal_Int16 nDefaultWritingMode )
2267 if( VLegend::isVisible( xLegend ))
2269 VLegend aVLegend( xLegend, xContext, rLegendEntryProviderList );
2270 aVLegend.init( xPageShapes, xShapeFactory, xModel );
2271 aVLegend.setDefaultWritingMode( nDefaultWritingMode );
2272 aVLegend.createShapes( awt::Size( rRemainingSpace.Width, rRemainingSpace.Height ),
2273 rPageSize );
2274 aVLegend.changePosition( rRemainingSpace, rPageSize );
2275 return true;
2277 return false;
2280 void formatPage(
2281 const uno::Reference< frame::XModel > & xModel
2282 , const awt::Size rPageSize
2283 , const uno::Reference< drawing::XShapes >& xTarget
2284 , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
2289 uno::Reference< XChartDocument > xChartDoc( xModel, uno::UNO_QUERY );
2290 OSL_ASSERT( xChartDoc.is());
2291 if( ! xChartDoc.is())
2292 return;
2293 uno::Reference< beans::XPropertySet > xModelPage( xChartDoc->getPageBackground());
2294 if( ! xModelPage.is())
2295 return;
2298 if( !xShapeFactory.is() )
2299 return;
2301 uno::Reference< beans::XPropertySet > xPageProp;
2302 // create a shape for the background
2304 uno::Reference< drawing::XShape > xShape(
2305 xShapeFactory->createInstance(
2306 C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
2307 if( xTarget.is() &&
2308 xShape.is())
2310 xTarget->add( xShape );
2311 xShape->setSize( rPageSize );
2312 xPageProp.set( xShape, uno::UNO_QUERY );
2313 if( xPageProp.is())
2315 xPageProp->setPropertyValue( C2U("LineStyle"), uno::makeAny( drawing::LineStyle_NONE ));
2320 //format page
2321 if( xPageProp.is())
2323 tPropertyNameValueMap aNameValueMap;
2324 PropertyMapper::getValueMap( aNameValueMap, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xModelPage );
2326 rtl::OUString aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, rtl::OUString() ) );
2327 aNameValueMap.insert( tPropertyNameValueMap::value_type( C2U("Name"), uno::makeAny( aCID ) ) ); //CID rtl::OUString
2329 tNameSequence aNames;
2330 tAnySequence aValues;
2331 PropertyMapper::getMultiPropertyListsFromValueMap( aNames, aValues, aNameValueMap );
2332 PropertyMapper::setMultiProperties( aNames, aValues, xPageProp );
2335 catch( uno::Exception & ex )
2337 ASSERT_EXCEPTION( ex );
2341 void lcl_removeEmptyGroupShapes( const Reference< drawing::XShapes>& xParent )
2343 if(!xParent.is())
2344 return;
2345 Reference< drawing::XShapeGroup > xParentGroup( xParent, uno::UNO_QUERY );
2346 if( !xParentGroup.is() )
2348 Reference< drawing::XDrawPage > xPage( xParent, uno::UNO_QUERY );
2349 if( !xPage.is() )
2350 return;
2353 //iterate from back!
2354 for( sal_Int32 nN = xParent->getCount(); nN--; )
2356 uno::Any aAny = xParent->getByIndex( nN );
2357 Reference< drawing::XShapes> xShapes(0);
2358 if( aAny >>= xShapes )
2359 lcl_removeEmptyGroupShapes( xShapes );
2360 if( xShapes.is() && xShapes->getCount()==0 )
2362 //remove empty group shape
2363 Reference< drawing::XShapeGroup > xGroup( xShapes, uno::UNO_QUERY );
2364 Reference< drawing::XShape > xShape( xShapes, uno::UNO_QUERY );
2365 if( xGroup.is() )
2366 xParent->remove( xShape );
2371 bool ChartView::impl_AddInDrawsAllByItself()
2373 bool bRet = false;
2375 uno::Reference< beans::XPropertySet > xProp( m_xChartModel, uno::UNO_QUERY );
2376 if( xProp.is()) try
2378 uno::Reference< util::XRefreshable > xAddIn;
2379 xProp->getPropertyValue( C2U( "AddIn" ) ) >>= xAddIn;
2380 if( xAddIn.is() )
2382 rtl::OUString aBaseDiagram;
2383 xProp->getPropertyValue( C2U( "BaseDiagram" ) ) >>= aBaseDiagram;
2384 if(aBaseDiagram.getLength())
2385 bRet = true;
2388 catch( uno::Exception& e )
2390 ASSERT_EXCEPTION( e );
2393 return bRet;
2396 void ChartView::impl_refreshAddIn()
2398 if( !m_bRefreshAddIn )
2399 return;
2401 uno::Reference< beans::XPropertySet > xProp( m_xChartModel, uno::UNO_QUERY );
2402 if( xProp.is()) try
2404 uno::Reference< util::XRefreshable > xAddIn;
2405 xProp->getPropertyValue( C2U( "AddIn" ) ) >>= xAddIn;
2406 if( xAddIn.is() )
2408 sal_Bool bRefreshAddInAllowed = sal_True;
2409 xProp->getPropertyValue( C2U( "RefreshAddInAllowed" ) ) >>= bRefreshAddInAllowed;
2410 if( bRefreshAddInAllowed )
2411 xAddIn->refresh();
2414 catch( uno::Exception& e )
2416 ASSERT_EXCEPTION( e );
2420 void ChartView::createShapes()
2422 #if OSL_DEBUG_LEVEL > 0
2423 clock_t nStart = clock();
2424 OSL_TRACE( "\nPPPPPPPPP>>>>>>>>>>>> chart view :: createShapes()" );
2425 #endif
2427 //make sure add-in is refreshed after creating the shapes
2428 const ::comphelper::ScopeGuard aGuard( boost::bind( &ChartView::impl_refreshAddIn, this ) );
2429 if( impl_AddInDrawsAllByItself() )
2430 return;
2432 impl_deleteCoordinateSystems();
2433 if( m_pDrawModelWrapper )
2435 // /--
2436 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
2437 m_pDrawModelWrapper->clearMainDrawPage();
2438 // \--
2441 lcl_setDefaultWritingMode( m_pDrawModelWrapper, m_xChartModel );
2443 awt::Size aPageSize = ChartModelHelper::getPageSize( m_xChartModel );
2445 uno::Reference<drawing::XShapes> xPageShapes( ShapeFactory(m_xShapeFactory)
2446 .getOrCreateChartRootShape( m_xDrawPage ) );
2448 SdrPage* pPage = ChartView::getSdrPage();
2449 if(pPage) //it is neccessary to use the implementation here as the uno page does not provide a propertyset
2450 pPage->SetSize(Size(aPageSize.Width,aPageSize.Height));
2451 else
2453 DBG_ERROR("could not set page size correctly");
2457 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
2459 //------------ apply fill properties to page
2460 // todo: it would be nicer to just pass the page m_xDrawPage and format it,
2461 // but the draw page does not support XPropertySet
2462 formatPage( m_xChartModel, aPageSize, xPageShapes, m_xShapeFactory );
2464 //sal_Int32 nYDistance = static_cast<sal_Int32>(aPageSize.Height*lcl_getPageLayoutDistancePercentage());
2465 awt::Rectangle aRemainingSpace( 0, 0, aPageSize.Width, aPageSize.Height );
2467 //create the group shape for diagram and axes first to have title and legends on top of it
2468 uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) );
2469 rtl::OUString aDiagramCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, rtl::OUString::valueOf( sal_Int32(0) ) ) );//todo: other index if more than one diagram is possible
2470 uno::Reference< drawing::XShapes > xDiagramPlusAxesPlusMarkHandlesGroup_Shapes( ShapeFactory(m_xShapeFactory).createGroup2D(xPageShapes,aDiagramCID) );
2471 uno::Reference< drawing::XShape > xDiagramPlusAxes_MarkHandles( ShapeFactory(m_xShapeFactory).createInvisibleRectangle(
2472 xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0,0) ) );
2473 ShapeFactory::setShapeName( xDiagramPlusAxes_MarkHandles, C2U("MarkHandles") );
2474 uno::Reference< drawing::XShapes > xDiagramPlusAxes_Shapes( ShapeFactory(m_xShapeFactory).createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes ) );
2476 //------------ create some titles
2477 std::auto_ptr<VTitle> apVTitle(0);
2478 bool bAutoPositionDummy = true;
2480 //------------ create main title shape
2481 lcl_createTitle( TitleHelper::getTitle( TitleHelper::MAIN_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
2482 , aRemainingSpace, aPageSize, ALIGN_TOP, bAutoPositionDummy );
2483 if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2484 return;
2486 //------------ create sub title shape
2487 lcl_createTitle( TitleHelper::getTitle( TitleHelper::SUB_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
2488 , aRemainingSpace, aPageSize, ALIGN_TOP, bAutoPositionDummy );
2489 if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2490 return;
2493 //------------ prepare series to give input to the legend (create categories and symbols etc.)
2494 SeriesPlotterContainer aSeriesPlotterContainer( m_aVCooSysList );
2495 aSeriesPlotterContainer.initializeCooSysAndSeriesPlotter( m_xChartModel );
2497 //------------ create legend
2498 lcl_createLegend( LegendHelper::getLegend( m_xChartModel ), xPageShapes, m_xShapeFactory, m_xCC
2499 , aRemainingSpace, aPageSize, m_xChartModel, aSeriesPlotterContainer.getLegendEntryProviderList()
2500 , lcl_getDefaultWritingModeFromPool( m_pDrawModelWrapper ) );
2501 if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2502 return;
2504 Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
2505 sal_Int32 nDimension = DiagramHelper::getDimension( xDiagram );
2507 //------------ create x axis title
2508 bool bAutoPosition_XTitle = true;
2509 std::auto_ptr<VTitle> apVTitle_X;
2510 if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 0 ) )
2511 apVTitle_X = lcl_createTitle( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
2512 , aRemainingSpace, aPageSize, ALIGN_BOTTOM, bAutoPosition_XTitle );
2513 if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2514 return;
2516 //------------ create y axis title
2517 bool bAutoPosition_YTitle = true;
2518 std::auto_ptr<VTitle> apVTitle_Y;
2519 if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 1 ) )
2520 apVTitle_Y = lcl_createTitle( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
2521 , aRemainingSpace, aPageSize, ALIGN_LEFT, bAutoPosition_YTitle );
2522 if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2523 return;
2525 //------------ create z axis title
2526 bool bAutoPosition_ZTitle = true;
2527 std::auto_ptr<VTitle> apVTitle_Z;
2528 if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 2 ) )
2529 apVTitle_Z = lcl_createTitle( TitleHelper::getTitle( TitleHelper::Z_AXIS_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
2530 , aRemainingSpace, aPageSize, ALIGN_RIGHT, bAutoPosition_ZTitle );
2531 if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2532 return;
2534 bool bDummy = false;
2535 bool bIsVertical = DiagramHelper::getVertical( xDiagram, bDummy, bDummy );
2537 //------------ create secondary x axis title
2538 bool bAutoPosition_SecondXTitle = true;
2539 std::auto_ptr<VTitle> apVTitle_SecondX;
2540 if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension, 0 ) )
2541 apVTitle_SecondX = lcl_createTitle( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
2542 , aRemainingSpace, aPageSize, bIsVertical? ALIGN_RIGHT : ALIGN_TOP, bAutoPosition_SecondXTitle );
2543 if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2544 return;
2546 //------------ create secondary y axis title
2547 bool bAutoPosition_SecondYTitle = true;
2548 std::auto_ptr<VTitle> apVTitle_SecondY;
2549 if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension, 1 ) )
2550 apVTitle_SecondY = lcl_createTitle( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel
2551 , aRemainingSpace, aPageSize, bIsVertical? ALIGN_TOP : ALIGN_RIGHT, bAutoPosition_SecondYTitle );
2552 if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2553 return;
2555 //------------ create complete diagram shape (inclusive axis and series)
2556 awt::Point aAvailablePosDia;
2557 awt::Size aAvailableSizeForDiagram;
2558 if( getAvailablePosAndSizeForDiagram( aAvailablePosDia, aAvailableSizeForDiagram, aRemainingSpace, aPageSize, ChartModelHelper::findDiagram( m_xChartModel )
2559 , apVTitle_X.get(), apVTitle_Y.get(), apVTitle_SecondX.get(), apVTitle_SecondY.get() ) )
2561 impl_createDiagramAndContent( aSeriesPlotterContainer
2562 , xDiagramPlusAxes_Shapes
2563 , aAvailablePosDia ,aAvailableSizeForDiagram, aPageSize );
2565 if(xDiagramPlusAxes_MarkHandles.is())
2567 xDiagramPlusAxes_MarkHandles->setPosition( aAvailablePosDia );
2568 xDiagramPlusAxes_MarkHandles->setSize( aAvailableSizeForDiagram );
2571 //correct axis title position
2572 awt::Rectangle aDiagramPlusAxesRect(aAvailablePosDia.X,aAvailablePosDia.Y,aAvailableSizeForDiagram.Width,aAvailableSizeForDiagram.Height);
2573 if(bAutoPosition_XTitle)
2574 changePositionOfAxisTitle( apVTitle_X.get(), ALIGN_BOTTOM, aDiagramPlusAxesRect, aPageSize );
2575 if(bAutoPosition_YTitle)
2576 changePositionOfAxisTitle( apVTitle_Y.get(), ALIGN_LEFT, aDiagramPlusAxesRect, aPageSize );
2577 if(bAutoPosition_ZTitle)
2578 changePositionOfAxisTitle( apVTitle_Z.get(), ALIGN_Z, aDiagramPlusAxesRect, aPageSize );
2579 if(bAutoPosition_SecondXTitle)
2580 changePositionOfAxisTitle( apVTitle_SecondX.get(), bIsVertical? ALIGN_RIGHT : ALIGN_TOP, aDiagramPlusAxesRect, aPageSize );
2581 if(bAutoPosition_SecondYTitle)
2582 changePositionOfAxisTitle( apVTitle_SecondY.get(), bIsVertical? ALIGN_TOP : ALIGN_RIGHT, aDiagramPlusAxesRect, aPageSize );
2585 //cleanup: remove all empty group shapes to avoid grey border lines:
2586 lcl_removeEmptyGroupShapes( xPageShapes );
2589 #if OSL_DEBUG_LEVEL > 0
2590 clock_t nEnd = clock();
2591 double fDuration =(double(nEnd-nStart)*1000.0)/double(CLOCKS_PER_SEC);
2593 OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< chart view :: createShapes():: needed %f msec", fDuration );
2594 #endif
2597 //-----------------------------------------------------------------
2598 // util::XEventListener (base of XCloseListener)
2599 //-----------------------------------------------------------------
2600 void SAL_CALL ChartView::disposing( const lang::EventObject& /* rSource */ )
2601 throw(uno::RuntimeException)
2603 impl_setChartModel( 0 );
2606 void ChartView::impl_updateView()
2608 if( !m_xChartModel.is() || !m_pDrawModelWrapper )
2609 return;
2611 if( m_bViewDirty && !m_bInViewUpdate )
2613 m_bInViewUpdate = true;
2614 //bool bOldRefreshAddIn = m_bRefreshAddIn;
2615 //m_bRefreshAddIn = false;
2618 impl_notifyModeChangeListener(C2U("invalid"));
2620 //prepare draw model
2622 // /--
2623 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
2624 m_pDrawModelWrapper->lockControllers();
2625 m_pDrawModelWrapper->updateTablesFromChartModel( m_xChartModel );
2626 // \--
2629 //create chart view
2632 ::vos::OGuard aGuard( Application::GetSolarMutex());
2633 while( m_bViewDirty )
2635 createShapes();
2636 m_bViewDirty = m_bViewUpdatePending;
2637 m_bViewUpdatePending = false;
2638 m_bInViewUpdate = false;
2642 m_bViewDirty = false;
2643 m_bViewUpdatePending = false;
2644 createShapes();
2646 if( m_bViewDirty )
2648 //avoid recursions due to add-in
2649 m_bRefreshAddIn = false;
2650 m_bViewDirty = false;
2651 m_bViewUpdatePending = false;
2652 //delete old chart view
2653 createShapes();
2654 m_bRefreshAddIn = true;
2658 m_bViewDirty = m_bViewUpdatePending;
2659 m_bViewUpdatePending = false;
2660 m_bInViewUpdate = false;
2662 catch( uno::Exception& ex)
2664 m_bViewDirty = m_bViewUpdatePending;
2665 m_bViewUpdatePending = false;
2666 m_bInViewUpdate = false;
2667 ASSERT_EXCEPTION( ex );
2671 // /--
2672 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
2673 m_pDrawModelWrapper->unlockControllers();
2674 // \--
2677 impl_notifyModeChangeListener(C2U("valid"));
2679 //m_bRefreshAddIn = bOldRefreshAddIn;
2683 // ____ XModifyListener ____
2684 void SAL_CALL ChartView::modified( const lang::EventObject& /* aEvent */ )
2685 throw (uno::RuntimeException)
2687 m_bViewDirty = sal_True;
2688 if( m_bInViewUpdate )
2689 m_bViewUpdatePending = true;
2691 impl_notifyModeChangeListener(C2U("dirty"));
2694 //SfxListener
2695 void ChartView::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
2697 //#i77362 change notification for changes on additional shapes are missing
2698 if( m_bInViewUpdate )
2699 return;
2700 if( m_bSdrViewIsInEditMode )
2701 return;
2703 const SdrHint* pSdrHint = dynamic_cast< const SdrHint* >(&rHint);
2704 if( !pSdrHint )
2705 return;
2707 bool bShapeChanged = false;
2708 switch( pSdrHint->GetKind() )
2710 case HINT_OBJCHG:
2711 bShapeChanged = true;
2712 break;
2713 case HINT_OBJINSERTED:
2714 bShapeChanged = true;
2715 break;
2716 case HINT_OBJREMOVED:
2717 bShapeChanged = true;
2718 break;
2719 case HINT_MODELCLEARED:
2720 bShapeChanged = true;
2721 break;
2722 default:
2723 break;
2726 if(bShapeChanged)
2728 //#i76053# do not send view modified notifications for changes on the hidden page which contains e.g. the symbols for the dialogs
2729 if( ChartView::getSdrPage() != pSdrHint->GetPage() )
2730 bShapeChanged=false;
2733 if(!bShapeChanged)
2734 return;
2736 Reference< util::XModifiable > xModifiable( m_xChartModel, uno::UNO_QUERY );
2737 if( xModifiable.is() )
2738 xModifiable->setModified( sal_True );
2741 void ChartView::impl_notifyModeChangeListener( const rtl::OUString& rNewMode )
2745 ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer
2746 .getContainer( ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0) );
2747 if( pIC )
2749 util::ModeChangeEvent aEvent( static_cast< uno::XWeak* >( this ), rNewMode );
2750 ::cppu::OInterfaceIteratorHelper aIt( *pIC );
2751 while( aIt.hasMoreElements() )
2752 (static_cast< util::XModeChangeListener*>(aIt.next()))->modeChanged( aEvent );
2755 catch( uno::Exception& ex)
2757 ASSERT_EXCEPTION( ex );
2761 // ____ XModeChangeBroadcaster ____
2763 void SAL_CALL ChartView::addModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
2764 throw (uno::RuntimeException)
2766 m_aListenerContainer.addInterface(
2767 ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0), xListener );
2769 void SAL_CALL ChartView::removeModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
2770 throw (uno::RuntimeException)
2772 m_aListenerContainer.removeInterface(
2773 ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0), xListener );
2775 void SAL_CALL ChartView::addModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
2776 throw (lang::NoSupportException, uno::RuntimeException)
2780 void SAL_CALL ChartView::removeModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
2781 throw (lang::NoSupportException, uno::RuntimeException)
2786 // ____ XUpdatable ____
2787 void SAL_CALL ChartView::update() throw (uno::RuntimeException)
2789 impl_updateView();
2792 // ____ XPropertySet ____
2793 Reference< beans::XPropertySetInfo > SAL_CALL ChartView::getPropertySetInfo()
2794 throw (uno::RuntimeException)
2796 OSL_ENSURE(false,"not implemented");
2797 return 0;
2800 void SAL_CALL ChartView::setPropertyValue( const ::rtl::OUString& rPropertyName
2801 , const Any& rValue )
2802 throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException
2803 , lang::WrappedTargetException, uno::RuntimeException)
2805 if( rPropertyName.equals(C2U("Resolution")) )
2807 awt::Size aNewResolution;
2808 if( ! (rValue >>= aNewResolution) )
2809 throw lang::IllegalArgumentException( C2U("Property 'Resolution' requires value of type awt::Size"), 0, 0 );
2811 if( m_aPageResolution.Width!=aNewResolution.Width || m_aPageResolution.Height!=aNewResolution.Height )
2813 //set modified only when the new resolution is higher and points were skipped before
2814 bool bSetModified = m_bPointsWereSkipped && (m_aPageResolution.Width<aNewResolution.Width || m_aPageResolution.Height<aNewResolution.Height);
2816 m_aPageResolution = aNewResolution;
2818 if( bSetModified )
2819 this->modified( lang::EventObject( static_cast< uno::XWeak* >( this ) ) );
2822 else if( rPropertyName.equals(C2U("ZoomFactors")) )
2824 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
2825 uno::Sequence< beans::PropertyValue > aZoomFactors;
2826 if( ! (rValue >>= aZoomFactors) )
2827 throw lang::IllegalArgumentException( C2U("Property 'ZoomFactors' requires value of type Sequence< PropertyValue >"), 0, 0 );
2829 sal_Int32 nFilterArgs = aZoomFactors.getLength();
2830 beans::PropertyValue* pDataValues = aZoomFactors.getArray();
2831 while( nFilterArgs-- )
2833 if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXNumerator" ) ) )
2834 pDataValues->Value >>= m_nScaleXNumerator;
2835 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXDenominator" ) ) )
2836 pDataValues->Value >>= m_nScaleXDenominator;
2837 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYNumerator" ) ) )
2838 pDataValues->Value >>= m_nScaleYNumerator;
2839 else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYDenominator" ) ) )
2840 pDataValues->Value >>= m_nScaleYDenominator;
2842 pDataValues++;
2845 else if( rPropertyName.equals(C2U("SdrViewIsInEditMode")) )
2847 //#i77362 change notification for changes on additional shapes are missing
2848 if( ! (rValue >>= m_bSdrViewIsInEditMode) )
2849 throw lang::IllegalArgumentException( C2U("Property 'SdrViewIsInEditMode' requires value of type sal_Bool"), 0, 0 );
2851 else
2852 throw beans::UnknownPropertyException( C2U("unknown property was tried to set to chart wizard"), 0 );
2855 Any SAL_CALL ChartView::getPropertyValue( const ::rtl::OUString& rPropertyName )
2856 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
2858 Any aRet;
2859 if( rPropertyName.equals(C2U("Resolution")) )
2861 aRet = uno::makeAny( m_aPageResolution );
2863 else
2864 throw beans::UnknownPropertyException( C2U("unknown property was tried to get from chart wizard"), 0 );
2865 return aRet;
2868 void SAL_CALL ChartView::addPropertyChangeListener(
2869 const ::rtl::OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* xListener */ )
2870 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
2872 OSL_ENSURE(false,"not implemented");
2874 void SAL_CALL ChartView::removePropertyChangeListener(
2875 const ::rtl::OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* aListener */ )
2876 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
2878 OSL_ENSURE(false,"not implemented");
2881 void SAL_CALL ChartView::addVetoableChangeListener( const ::rtl::OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
2882 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
2884 OSL_ENSURE(false,"not implemented");
2887 void SAL_CALL ChartView::removeVetoableChangeListener( const ::rtl::OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
2888 throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
2890 OSL_ENSURE(false,"not implemented");
2894 //.............................................................................
2895 } //namespace chart
2896 //.............................................................................