xref: /trunk/main/chart2/source/view/main/ChartView.cxx (revision 74cbd1f1)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 
25 // MARKER(update_precomp.py): autogen include statement, do not remove
26 #include "precompiled_chart2.hxx"
27 
28 #include "ChartView.hxx"
29 #include "chartview/DrawModelWrapper.hxx"
30 #include "NumberFormatterWrapper.hxx"
31 #include "ViewDefines.hxx"
32 #include "VDiagram.hxx"
33 #include "VTitle.hxx"
34 #include "ShapeFactory.hxx"
35 #include "VCoordinateSystem.hxx"
36 #include "VSeriesPlotter.hxx"
37 #include "CommonConverters.hxx"
38 #include "macros.hxx"
39 #include "TitleHelper.hxx"
40 #include "LegendHelper.hxx"
41 #include "VLegend.hxx"
42 #include "PropertyMapper.hxx"
43 #include "ChartModelHelper.hxx"
44 #include "ChartTypeHelper.hxx"
45 #include "ScaleAutomatism.hxx"
46 #include "MinimumAndMaximumSupplier.hxx"
47 #include "ObjectIdentifier.hxx"
48 #include "DiagramHelper.hxx"
49 #include "RelativePositionHelper.hxx"
50 #include "servicenames.hxx"
51 #include "AxisHelper.hxx"
52 #include "AxisIndexDefines.hxx"
53 #include "ControllerLockGuard.hxx"
54 #include "BaseGFXHelper.hxx"
55 #include "DataSeriesHelper.hxx"
56 #include "DateHelper.hxx"
57 
58 #include <rtl/uuid.h>
59 #include <comphelper/scopeguard.hxx>
60 #include <boost/bind.hpp>
61 #include <unotools/streamwrap.hxx>
62 // header for class LocaleDataWrapper
63 #include <unotools/localedatawrapper.hxx>
64 // header for class SdrPage
65 #include <svx/svdpage.hxx>
66 // header for class SvxDrawPage
67 #include <svx/unopage.hxx>
68 // header for class SvxShape
69 #include <svx/unoshape.hxx>
70 // header for class Application
71 #include <vcl/svapp.hxx>
72 #include <vos/mutex.hxx>
73 #include <svx/unofill.hxx>
74 
75 #include <time.h>
76 
77 #include <com/sun/star/chart/ChartAxisPosition.hpp>
78 #include <com/sun/star/chart/DataLabelPlacement.hpp>
79 #include <com/sun/star/chart/MissingValueTreatment.hpp>
80 #include <com/sun/star/chart2/StackingDirection.hpp>
81 #include <com/sun/star/chart2/XChartDocument.hpp>
82 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
83 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
84 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
85 #include <com/sun/star/chart2/XTitled.hpp>
86 #include <com/sun/star/chart2/RelativePosition.hpp>
87 #include <com/sun/star/chart2/RelativeSize.hpp>
88 #include <com/sun/star/drawing/FillStyle.hpp>
89 #include <com/sun/star/drawing/LineStyle.hpp>
90 #include <com/sun/star/drawing/XShapeGroup.hpp>
91 #include <com/sun/star/document/XExporter.hpp>
92 #include <com/sun/star/document/XFilter.hpp>
93 #include <com/sun/star/io/XSeekable.hpp>
94 #include <com/sun/star/util/XModifiable.hpp>
95 #include <com/sun/star/util/XRefreshable.hpp>
96 #include <com/sun/star/util/NumberFormat.hpp>
97 
98 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
99 #include <com/sun/star/text/XTextDocument.hpp>
100 #include <com/sun/star/text/WritingMode2.hpp>
101 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
102 #include <com/sun/star/view/XSelectionSupplier.hpp>
103 #include <svl/languageoptions.hxx>
104 #include <sot/clsids.hxx>
105 #include "servicenames_charttypes.hxx"
106 
107 //.............................................................................
108 namespace chart
109 {
110 //.............................................................................
111 
112 using namespace ::com::sun::star;
113 using namespace ::com::sun::star::chart2;
114 using ::com::sun::star::uno::Reference;
115 using ::com::sun::star::uno::Sequence;
116 using ::com::sun::star::uno::Any;
117 using rtl::OUString;
118 
getUnoTunnelId()119 const uno::Sequence<sal_Int8>& ExplicitValueProvider::getUnoTunnelId()
120 {
121     static uno::Sequence<sal_Int8> * pSeq = 0;
122 	if( !pSeq )
123 	{
124 		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
125 		if( !pSeq )
126 		{
127 			static uno::Sequence< sal_Int8 > aSeq( 16 );
128 			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
129 			pSeq = &aSeq;
130 		}
131 	}
132 	return *pSeq;
133 }
134 
getExplicitValueProvider(const Reference<uno::XInterface> & xChartView)135 ExplicitValueProvider* ExplicitValueProvider::getExplicitValueProvider(
136         const Reference< uno::XInterface >& xChartView )
137 {
138     ExplicitValueProvider* pExplicitValueProvider=0;
139 
140     Reference< lang::XUnoTunnel > xTunnel( xChartView, uno::UNO_QUERY );
141     if( xTunnel.is() )
142     {
143         pExplicitValueProvider = reinterpret_cast<ExplicitValueProvider*>(xTunnel->getSomething(
144             ExplicitValueProvider::getUnoTunnelId() ));
145     }
146     return pExplicitValueProvider;
147 }
148 
ChartView(uno::Reference<uno::XComponentContext> const & xContext)149 ChartView::ChartView(
150 		uno::Reference<uno::XComponentContext> const & xContext)
151     : m_aMutex()
152     , m_xCC(xContext)
153     , m_xChartModel()
154 	, m_xShapeFactory()
155 	, m_xDrawPage()
156     , m_pDrawModelWrapper()
157     , m_aListenerContainer( m_aMutex )
158     , m_bViewDirty(true)
159     , m_bInViewUpdate(false)
160     , m_bViewUpdatePending(false)
161     , m_bRefreshAddIn(true)
162     , m_aPageResolution(1000,1000)
163     , m_bPointsWereSkipped(false)
164     , m_nScaleXNumerator(1)
165     , m_nScaleXDenominator(1)
166     , m_nScaleYNumerator(1)
167     , m_nScaleYDenominator(1)
168     , m_bSdrViewIsInEditMode(sal_False)
169     , m_aResultingDiagramRectangleExcludingAxes(0,0,0,0)
170 {
171 }
172 
impl_setChartModel(const uno::Reference<frame::XModel> & xChartModel)173 void ChartView::impl_setChartModel( const uno::Reference< frame::XModel >& xChartModel )
174 {
175     if( m_xChartModel != xChartModel )
176     {
177         m_xChartModel = xChartModel;
178         m_bViewDirty = true;
179     }
180 }
181 
initialize(const uno::Sequence<uno::Any> & aArguments)182 void SAL_CALL ChartView::initialize( const uno::Sequence< uno::Any >& aArguments )
183                 throw ( uno::Exception, uno::RuntimeException)
184 {
185     DBG_ASSERT(aArguments.getLength() >= 1,"need 1 argument to initialize the view: xModel");
186     if( !(aArguments.getLength() >= 1) )
187         return;
188 
189     uno::Reference< frame::XModel > xNewChartModel;
190     if( !(aArguments[0] >>= xNewChartModel) )
191     {
192         DBG_ERROR( "need a Reference to frame::XModel as first parameter for view initialization" );
193     }
194     impl_setChartModel( xNewChartModel );
195 
196     if( !m_pDrawModelWrapper.get() )
197     {
198         // /--
199         ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
200         m_pDrawModelWrapper = ::boost::shared_ptr< DrawModelWrapper >( new DrawModelWrapper( m_xCC ) );
201         m_xShapeFactory = m_pDrawModelWrapper->getShapeFactory();
202         m_xDrawPage = m_pDrawModelWrapper->getMainDrawPage();
203         StartListening( m_pDrawModelWrapper->getSdrModel(), sal_False /*bPreventDups*/ );
204         // \--
205     }
206 }
207 
~ChartView()208 ChartView::~ChartView()
209 {
210     // #i120831#. In ChartView::initialize(), m_xShapeFactory is created from SdrModel::getUnoModel() and indirectly
211     //   from SfxBaseModel, it needs call dispose() to make sure SfxBaseModel object is freed correctly.
212     uno::Reference< lang::XComponent > xComp( m_xShapeFactory, uno::UNO_QUERY);
213     if ( xComp.is() )
214         xComp->dispose();
215 
216     if( m_pDrawModelWrapper.get() )
217     {
218         EndListening( m_pDrawModelWrapper->getSdrModel(), sal_False /*bAllDups*/ );
219         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
220         m_pDrawModelWrapper.reset();
221     }
222     m_xDrawPage = NULL;
223     impl_deleteCoordinateSystems();
224 }
225 
impl_deleteCoordinateSystems()226 void ChartView::impl_deleteCoordinateSystems()
227 {
228     //delete all coordinate systems
229     ::std::vector< VCoordinateSystem* > aVectorToDeleteObjects;
230     ::std::swap( aVectorToDeleteObjects, m_aVCooSysList );//#i109770#
231     ::std::vector< VCoordinateSystem* >::const_iterator       aIter = aVectorToDeleteObjects.begin();
232     const ::std::vector< VCoordinateSystem* >::const_iterator aEnd  = aVectorToDeleteObjects.end();
233 	for( ; aIter != aEnd; aIter++ )
234     {
235         delete *aIter;
236     }
237     aVectorToDeleteObjects.clear();
238 }
239 
240 
241 //-----------------------------------------------------------------
242 // datatransfer::XTransferable
243 namespace
244 {
245 const rtl::OUString lcl_aGDIMetaFileMIMEType(
246     RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""));
247 const rtl::OUString lcl_aGDIMetaFileMIMETypeHighContrast(
248     RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\""));
249 } // anonymous namespace
250 
getMetaFile(const uno::Reference<io::XOutputStream> & xOutStream,bool bUseHighContrast)251 void ChartView::getMetaFile( const uno::Reference< io::XOutputStream >& xOutStream
252                            , bool bUseHighContrast )
253 {
254     if( !m_xDrawPage.is() )
255         return;
256 
257     uno::Reference< lang::XMultiServiceFactory > xFactory( m_xCC->getServiceManager(), uno::UNO_QUERY );
258     if( !xFactory.is() )
259         return;
260 
261     // creating the graphic exporter
262     uno::Reference< document::XExporter > xExporter( xFactory->createInstance(
263             C2U("com.sun.star.drawing.GraphicExportFilter")), uno::UNO_QUERY);
264     uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY );
265 
266     if( !xExporter.is() || !xFilter.is() )
267         return;
268 
269     uno::Sequence< beans::PropertyValue > aProps(3);
270     aProps[0].Name = C2U("FilterName");
271     aProps[0].Value <<= C2U("SVM");
272 
273     aProps[1].Name = C2U("OutputStream");
274     aProps[1].Value <<= xOutStream;
275 
276     uno::Sequence< beans::PropertyValue > aFilterData(4);
277     aFilterData[0].Name = C2U("ExportOnlyBackground");
278     aFilterData[0].Value <<= sal_False;
279     aFilterData[1].Name = C2U("HighContrast");
280     aFilterData[1].Value <<= bUseHighContrast;
281 
282     aFilterData[2].Name = C2U("Version");
283     const sal_Int32 nVersion = SOFFICE_FILEFORMAT_50;
284     aFilterData[2].Value <<= nVersion;
285 
286     aFilterData[3].Name = C2U("CurrentPage");
287     aFilterData[3].Value <<= uno::Reference< uno::XInterface >( m_xDrawPage, uno::UNO_QUERY );
288 
289     //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
290     {
291         aFilterData.realloc( aFilterData.getLength()+4 );
292         aFilterData[4].Name = C2U("ScaleXNumerator");
293         aFilterData[4].Value = uno::makeAny( m_nScaleXNumerator );
294         aFilterData[5].Name = C2U("ScaleXDenominator");
295         aFilterData[5].Value = uno::makeAny( m_nScaleXDenominator );
296         aFilterData[6].Name = C2U("ScaleYNumerator");
297         aFilterData[6].Value = uno::makeAny( m_nScaleYNumerator );
298         aFilterData[7].Name = C2U("ScaleYDenominator");
299         aFilterData[7].Value = uno::makeAny( m_nScaleYDenominator );
300     }
301 
302     aProps[2].Name = C2U("FilterData");
303     aProps[2].Value <<= aFilterData;
304 
305     xExporter->setSourceDocument( uno::Reference< lang::XComponent >( m_xDrawPage, uno::UNO_QUERY) );
306     if( xFilter->filter( aProps ) )
307     {
308         xOutStream->flush();
309         xOutStream->closeOutput();
310         uno::Reference< io::XSeekable > xSeekable( xOutStream, uno::UNO_QUERY );
311         if( xSeekable.is() )
312             xSeekable->seek(0);
313     }
314 }
315 
getTransferData(const datatransfer::DataFlavor & aFlavor)316 uno::Any SAL_CALL ChartView::getTransferData( const datatransfer::DataFlavor& aFlavor )
317                 throw (datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException)
318 {
319     bool bHighContrastMetaFile( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast));
320     uno::Any aRet;
321     if( ! (bHighContrastMetaFile || aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType)) )
322         return aRet;
323 
324     update();
325 
326     SvMemoryStream aStream( 1024, 1024 );
327     utl::OStreamWrapper* pStreamWrapper = new utl::OStreamWrapper( aStream );
328 
329     uno::Reference< io::XOutputStream > xOutStream( pStreamWrapper );
330     uno::Reference< io::XInputStream > xInStream( pStreamWrapper );
331     uno::Reference< io::XSeekable > xSeekable( pStreamWrapper );
332 
333     if( xOutStream.is() )
334     {
335         this->getMetaFile( xOutStream, bHighContrastMetaFile );
336 
337         if( xInStream.is() && xSeekable.is() )
338         {
339             xSeekable->seek(0);
340             sal_Int32 nBytesToRead = xInStream->available();
341             uno::Sequence< sal_Int8 > aSeq( nBytesToRead );
342             xInStream->readBytes( aSeq, nBytesToRead);
343             aRet <<= aSeq;
344             xInStream->closeInput();
345         }
346     }
347 
348     return aRet;
349 }
getTransferDataFlavors()350 uno::Sequence< datatransfer::DataFlavor > SAL_CALL ChartView::getTransferDataFlavors()
351                 throw (uno::RuntimeException)
352 {
353     uno::Sequence< datatransfer::DataFlavor > aRet(2);
354 
355     aRet[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMEType,
356         C2U( "GDIMetaFile" ),
357 		::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
358     aRet[1] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast,
359         C2U( "GDIMetaFile" ),
360 		::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) );
361 
362 	return aRet;
363 }
isDataFlavorSupported(const datatransfer::DataFlavor & aFlavor)364 ::sal_Bool SAL_CALL ChartView::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
365                 throw (uno::RuntimeException)
366 {
367     return ( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType) ||
368              aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast) );
369 }
370 
371 //-----------------------------------------------------------------
372 // ____ XUnoTunnel ___
getSomething(const uno::Sequence<::sal_Int8> & aIdentifier)373 ::sal_Int64 SAL_CALL ChartView::getSomething( const uno::Sequence< ::sal_Int8 >& aIdentifier )
374         throw( uno::RuntimeException)
375 {
376     if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( ExplicitValueProvider::getUnoTunnelId().getConstArray(),
377 														 aIdentifier.getConstArray(), 16 ) )
378 	{
379         ExplicitValueProvider* pProvider = this;
380         return reinterpret_cast<sal_Int64>(pProvider);
381 	}
382 	return 0;
383 }
384 
385 //-----------------------------------------------------------------
386 // lang::XServiceInfo
387 
APPHELPER_XSERVICEINFO_IMPL(ChartView,CHART_VIEW_SERVICE_IMPLEMENTATION_NAME)388 APPHELPER_XSERVICEINFO_IMPL(ChartView,CHART_VIEW_SERVICE_IMPLEMENTATION_NAME)
389 
390 	uno::Sequence< rtl::OUString > ChartView
391 ::getSupportedServiceNames_Static()
392 {
393 	uno::Sequence< rtl::OUString > aSNS( 1 );
394 	aSNS.getArray()[ 0 ] = CHART_VIEW_SERVICE_NAME;
395 	return aSNS;
396 }
397 
398 //-----------------------------------------------------------------
399 //-----------------------------------------------------------------
400 
createTransformationSceneToScreen(const::basegfx::B2IRectangle & rDiagramRectangleWithoutAxes)401 ::basegfx::B3DHomMatrix createTransformationSceneToScreen(
402     const ::basegfx::B2IRectangle& rDiagramRectangleWithoutAxes )
403 {
404     ::basegfx::B3DHomMatrix aM;
405     aM.scale(double(rDiagramRectangleWithoutAxes.getWidth())/FIXED_SIZE_FOR_3D_CHART_VOLUME
406             , -double(rDiagramRectangleWithoutAxes.getHeight())/FIXED_SIZE_FOR_3D_CHART_VOLUME, 1.0 );
407     aM.translate(double(rDiagramRectangleWithoutAxes.getMinX())
408         , double(rDiagramRectangleWithoutAxes.getMinY()+rDiagramRectangleWithoutAxes.getHeight()-1), 0);
409     return aM;
410 }
411 
findInCooSysList(const std::vector<VCoordinateSystem * > & rVCooSysList,const uno::Reference<XCoordinateSystem> & xCooSys)412 VCoordinateSystem* findInCooSysList( const std::vector< VCoordinateSystem* >& rVCooSysList
413                                     , const uno::Reference< XCoordinateSystem >& xCooSys )
414 {
415     for( size_t nC=0; nC < rVCooSysList.size(); nC++)
416     {
417         VCoordinateSystem* pVCooSys = rVCooSysList[nC];
418         if(pVCooSys->getModel()==xCooSys)
419             return pVCooSys;
420     }
421     return NULL;
422 }
423 
addCooSysToList(std::vector<VCoordinateSystem * > & rVCooSysList,const uno::Reference<XCoordinateSystem> & xCooSys,const uno::Reference<frame::XModel> & xChartModel)424 VCoordinateSystem* addCooSysToList( std::vector< VCoordinateSystem* >& rVCooSysList
425             , const uno::Reference< XCoordinateSystem >& xCooSys
426             , const uno::Reference< frame::XModel >& xChartModel )
427 {
428 	VCoordinateSystem* pVCooSys = findInCooSysList( rVCooSysList, xCooSys );
429     if( !pVCooSys )
430     {
431         pVCooSys = VCoordinateSystem::createCoordinateSystem(xCooSys );
432         if(pVCooSys)
433         {
434             rtl::OUString aCooSysParticle( ObjectIdentifier::createParticleForCoordinateSystem( xCooSys, xChartModel ) );
435             pVCooSys->setParticle(aCooSysParticle);
436 
437             pVCooSys->setExplicitCategoriesProvider( new ExplicitCategoriesProvider(xCooSys,xChartModel) );
438 
439             rVCooSysList.push_back( pVCooSys );
440         }
441     }
442     return pVCooSys;
443 }
444 
lcl_getCooSysForPlotter(const std::vector<VCoordinateSystem * > & rVCooSysList,MinimumAndMaximumSupplier * pMinimumAndMaximumSupplier)445 VCoordinateSystem* lcl_getCooSysForPlotter( const std::vector< VCoordinateSystem* >& rVCooSysList, MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier )
446 {
447     if(!pMinimumAndMaximumSupplier)
448         return 0;
449     for( size_t nC=0; nC < rVCooSysList.size(); nC++)
450     {
451         VCoordinateSystem* pVCooSys = rVCooSysList[nC];
452         if(pVCooSys->hasMinimumAndMaximumSupplier( pMinimumAndMaximumSupplier ))
453             return pVCooSys;
454     }
455     return 0;
456 }
457 
458 typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex; //first index is the dimension, second index is the axis index that indicates whether this is a main or secondary axis
459 typedef std::pair< VCoordinateSystem* , tFullAxisIndex > tFullCoordinateSystem;
460 typedef std::map< VCoordinateSystem*, tFullAxisIndex > tCoordinateSystemMap;
461 
462 struct AxisUsage
463 {
464     AxisUsage();
465     ~AxisUsage();
466 
467     void addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
468     ::std::vector< VCoordinateSystem* > getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex );
469     sal_Int32 getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex );
470     //tFullAxisIndex getDimensionAndIndexForCooSys( VCoordinateSystem* pCooSys );
471 
472     ScaleAutomatism         aScaleAutomatism;
473 
474 private:
475     tCoordinateSystemMap    aCoordinateSystems;
476     std::map< sal_Int32, sal_Int32 > aMaxIndexPerDimension;
477 };
478 
AxisUsage()479 AxisUsage::AxisUsage()
480     : aScaleAutomatism(AxisHelper::createDefaultScale(),Date())
481 {
482 }
483 
~AxisUsage()484 AxisUsage::~AxisUsage()
485 {
486     aCoordinateSystems.clear();
487 }
488 
489 /*
490 tFullScaleIndex AxisUsage::getDimensionAndIndexForCooSys( VCoordinateSystem* pCooSys )
491 {
492     tFullScaleIndex aRet(0,0);
493 
494     tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) );
495     if(aFound!=aCoordinateSystems.end())
496         aRet = aFound->second;
497 
498     return aRet;
499 }
500 */
501 
addCoordinateSystem(VCoordinateSystem * pCooSys,sal_Int32 nDimensionIndex,sal_Int32 nAxisIndex)502 void AxisUsage::addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
503 {
504     if(!pCooSys)
505         return;
506 
507     tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex );
508     tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) );
509 
510     //use one scale only once for each coordinate system
511     //main axis are preferred over secondary axis
512     //value scales are preferred
513     if(aFound!=aCoordinateSystems.end())
514     {
515         sal_Int32 nFoundAxisIndex = aFound->second.second;
516         if( nFoundAxisIndex < nAxisIndex )
517             return;
518         sal_Int32 nFoundDimension = aFound->second.first;
519         if( nFoundDimension ==1 )
520             return;
521         if( nFoundDimension < nDimensionIndex )
522             return;
523     }
524     aCoordinateSystems[pCooSys] = aFullAxisIndex;
525 
526     //set maximum scale index
527     std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex);
528     if( aIter != aMaxIndexPerDimension.end() )
529     {
530         sal_Int32 nCurrentMaxIndex = aIter->second;
531         if( nCurrentMaxIndex < nAxisIndex )
532             aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex;
533     }
534     else
535         aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex;
536 }
getCoordinateSystems(sal_Int32 nDimensionIndex,sal_Int32 nAxisIndex)537 ::std::vector< VCoordinateSystem* > AxisUsage::getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex )
538 {
539     ::std::vector< VCoordinateSystem* > aRet;
540 
541     tCoordinateSystemMap::const_iterator aIter;
542     for( aIter = aCoordinateSystems.begin(); aIter!=aCoordinateSystems.end();++aIter )
543     {
544         if( aIter->second.first != nDimensionIndex )
545             continue;
546         if( aIter->second.second != nAxisIndex )
547             continue;
548         aRet.push_back( aIter->first );
549     }
550 
551     return aRet;
552 }
getMaxAxisIndexForDimension(sal_Int32 nDimensionIndex)553 sal_Int32 AxisUsage::getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex )
554 {
555     sal_Int32 nRet = -1;
556     std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex);
557     if( aIter != aMaxIndexPerDimension.end() )
558         nRet = aIter->second;
559     return nRet;
560 }
561 
562 //-----------------------------------------------------
563 
564 class SeriesPlotterContainer
565 {
566 public:
567     SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList );
568     ~SeriesPlotterContainer();
569 
570     void initializeCooSysAndSeriesPlotter( const uno::Reference< frame::XModel >& xChartModel );
571     void initAxisUsageList(const Date& rNullDate);
572     void doAutoScaling( const uno::Reference< frame::XModel >& xChartModel );
573     void updateScalesAndIncrementsOnAxes();
574     void setScalesFromCooSysToPlotter();
575     void setNumberFormatsFromAxes();
576     drawing::Direction3D getPreferredAspectRatio();
577 
getSeriesPlotterList()578     std::vector< VSeriesPlotter* >& getSeriesPlotterList() { return m_aSeriesPlotterList; }
getCooSysList()579     std::vector< VCoordinateSystem* >& getCooSysList() { return m_rVCooSysList; }
580     std::vector< LegendEntryProvider* > getLegendEntryProviderList();
581 
582     void AdaptScaleOfYAxisWithoutAttachedSeries( const uno::Reference< frame::XModel >& xChartModel );
583 
584 private:
585     std::vector< VSeriesPlotter* > m_aSeriesPlotterList;
586     std::vector< VCoordinateSystem* >& m_rVCooSysList;
587     ::std::map< uno::Reference< XAxis >, AxisUsage > m_aAxisUsageList;
588     sal_Int32 m_nMaxAxisIndex;
589     bool m_bChartTypeUsesShiftedCategoryPositionPerDefault;
590     sal_Int32 m_nDefaultDateNumberFormat;
591 };
592 
SeriesPlotterContainer(std::vector<VCoordinateSystem * > & rVCooSysList)593 SeriesPlotterContainer::SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList )
594         : m_rVCooSysList( rVCooSysList )
595         , m_nMaxAxisIndex(0)
596         , m_bChartTypeUsesShiftedCategoryPositionPerDefault(false)
597         , m_nDefaultDateNumberFormat(0)
598 {
599 }
600 
~SeriesPlotterContainer()601 SeriesPlotterContainer::~SeriesPlotterContainer()
602 {
603     // - remove plotter from coordinatesystems
604     for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
605         m_rVCooSysList[nC]->clearMinimumAndMaximumSupplierList();
606     // - delete all plotter
607     ::std::vector< VSeriesPlotter* >::const_iterator       aPlotterIter = m_aSeriesPlotterList.begin();
608     const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd  = m_aSeriesPlotterList.end();
609     for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
610         delete *aPlotterIter;
611     m_aSeriesPlotterList.clear();
612 }
613 
getLegendEntryProviderList()614 std::vector< LegendEntryProvider* > SeriesPlotterContainer::getLegendEntryProviderList()
615 {
616     std::vector< LegendEntryProvider* > aRet( m_aSeriesPlotterList.size() );
617     ::std::vector< VSeriesPlotter* >::const_iterator       aPlotterIter = m_aSeriesPlotterList.begin();
618     const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd  = m_aSeriesPlotterList.end();
619     sal_Int32 nN = 0;
620     for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter, nN++ )
621         aRet[nN] = *aPlotterIter;
622     return aRet;
623 }
624 
initializeCooSysAndSeriesPlotter(const uno::Reference<frame::XModel> & xChartModel)625 void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(
626               const uno::Reference< frame::XModel >& xChartModel )
627 {
628     //------------ get model series from model
629     sal_Int32 nDiagramIndex = 0;//todo if more than one diagam is supported
630     uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
631     if( !xDiagram.is())
632         return;
633 
634     uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartModel, uno::UNO_QUERY );
635     uno::Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY );
636     if( xChartDoc.is() && xChartDoc->hasInternalDataProvider()
637         && DiagramHelper::isSupportingDateAxis( xDiagram ) )
638             m_nDefaultDateNumberFormat=DiagramHelper::getDateNumberFormat( xNumberFormatsSupplier );
639 
640     sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
641     if(!nDimensionCount)
642     {
643         //@todo handle mixed dimension
644         nDimensionCount = 2;
645     }
646 
647     sal_Bool bSortByXValues = sal_False;
648     sal_Bool bConnectBars = sal_False;
649     sal_Bool bGroupBarsPerAxis = sal_True;
650     sal_Bool bIncludeHiddenCells = sal_True;
651     sal_Int32 nStartingAngle = 90;
652     sal_Int32 n3DRelativeHeight = 100;
653     try
654     {
655         uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY_THROW );
656         xDiaProp->getPropertyValue( C2U( "SortByXValues" ) ) >>= bSortByXValues;
657         xDiaProp->getPropertyValue( C2U( "ConnectBars" ) ) >>= bConnectBars;
658         xDiaProp->getPropertyValue( C2U( "GroupBarsPerAxis" ) ) >>= bGroupBarsPerAxis;
659         xDiaProp->getPropertyValue( C2U( "IncludeHiddenCells" ) ) >>= bIncludeHiddenCells;
660         xDiaProp->getPropertyValue( C2U( "StartingAngle" ) ) >>= nStartingAngle;
661 
662         if (nDimensionCount == 3)
663         {
664              xDiaProp->getPropertyValue( C2U( "3DRelativeHeight" ) ) >>= n3DRelativeHeight;
665         }
666     }
667     catch( const uno::Exception & ex )
668     {
669         ASSERT_EXCEPTION( ex );
670     }
671 
672     //---------------------------------------------------------------------
673     //prepare for autoscaling and shape creation
674     // - create plotter for charttypes (for each first scale group at each plotter, as they are independent)
675     // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling)
676     // - add plotter to coordinate systems
677 
678     //iterate through all coordinate systems
679     uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
680     OSL_ASSERT( xCooSysContainer.is());
681     if( !xCooSysContainer.is())
682         return;
683     uno::Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
684     uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
685     sal_Int32 nGlobalSeriesIndex = 0;//for automatic symbols
686     for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS )
687     {
688         uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] );
689         VCoordinateSystem* pVCooSys = addCooSysToList(m_rVCooSysList,xCooSys,xChartModel);
690 
691         //iterate through all chart types in the current coordinate system
692         uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY );
693         OSL_ASSERT( xChartTypeContainer.is());
694         if( !xChartTypeContainer.is() )
695             continue;
696         uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() );
697         for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT )
698         {
699             uno::Reference< XChartType > xChartType( aChartTypeList[nT] );
700             if(3 == nDimensionCount && xChartType->getChartType().equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE))
701             {
702                 uno::Reference< beans::XPropertySet > xPropertySet( xChartType, uno::UNO_QUERY );
703                 if (xPropertySet.is())
704                 {
705                     try
706                     {
707                         sal_Int32 n3DRelativeHeightOldValue(100);
708                         uno::Any aAny = xPropertySet->getPropertyValue( C2U("3DRelativeHeight") );
709                         aAny >>= n3DRelativeHeightOldValue;
710                         if (n3DRelativeHeightOldValue != n3DRelativeHeight)
711                             xPropertySet->setPropertyValue( C2U("3DRelativeHeight"), uno::makeAny(n3DRelativeHeight) );
712                     }
713                     catch(const uno::Exception& e){}
714                 }
715             }
716 
717             if(nT==0)
718                 m_bChartTypeUsesShiftedCategoryPositionPerDefault = ChartTypeHelper::shiftCategoryPosAtXAxisPerDefault( xChartType );
719 
720             bool bExcludingPositioning = DiagramPositioningMode_EXCLUDING == DiagramHelper::getDiagramPositioningMode( xDiagram );
721             VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( xChartType, nDimensionCount, bExcludingPositioning );
722             if( !pPlotter )
723                 continue;
724             m_aSeriesPlotterList.push_back( pPlotter );
725             pPlotter->setNumberFormatsSupplier( xNumberFormatsSupplier );
726             pPlotter->setColorScheme( xColorScheme );
727             pPlotter->setExplicitCategoriesProvider( pVCooSys->getExplicitCategoriesProvider() );
728             sal_Int32 nMissingValueTreatment = DiagramHelper::getCorrectedMissingValueTreatment( xDiagram, xChartType );
729 
730             if(pVCooSys)
731                 pVCooSys->addMinimumAndMaximumSupplier(pPlotter);
732 
733             //------------ add series to plotter and thus prepare him for providing minimum and maximum values
734             uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY );
735             OSL_ASSERT( xDataSeriesContainer.is());
736             if( !xDataSeriesContainer.is() )
737                 continue;
738             sal_Int32 zSlot=-1;
739             sal_Int32 xSlot=-1;
740             sal_Int32 ySlot=-1;
741             uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() );
742             for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS )
743             {
744                 uno::Reference< XDataSeries > xDataSeries( aSeriesList[nS], uno::UNO_QUERY );
745 		        if(!xDataSeries.is())
746 			        continue;
747                 if( !bIncludeHiddenCells && !DataSeriesHelper::hasUnhiddenData(xDataSeries) )
748                     continue;
749 
750 		        VDataSeries* pSeries = new VDataSeries( xDataSeries );
751 
752                 pSeries->setGlobalSeriesIndex(nGlobalSeriesIndex);
753                 nGlobalSeriesIndex++;
754 
755                 if( bSortByXValues )
756                     pSeries->doSortByXValues();
757 
758                 pSeries->setConnectBars( bConnectBars );
759                 pSeries->setGroupBarsPerAxis( bGroupBarsPerAxis );
760                 pSeries->setStartingAngle( nStartingAngle );
761 
762                 pSeries->setMissingValueTreatment( nMissingValueTreatment );
763 
764                 rtl::OUString aSeriesParticle( ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCS, nT, nS ) );
765                 pSeries->setParticle(aSeriesParticle);
766 
767                 OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) );
768                 pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole);
769 
770                 //ignore secondary axis for charttypes that do not suppoert them
771                 if( pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX &&
772                     !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, 1 ) )
773                 {
774                     pSeries->setAttachedAxisIndex(MAIN_AXIS_INDEX);
775                 }
776 
777                 StackingDirection eDirection = pSeries->getStackingDirection();
778                 switch(eDirection)
779                 {
780                     case StackingDirection_NO_STACKING:
781                         xSlot++; ySlot=-1;
782                         if(zSlot<0)
783                             zSlot=0;
784                         break;
785                     case StackingDirection_Y_STACKING:
786                         ySlot++;
787                         if(xSlot<0)
788                             xSlot=0;
789                         if(zSlot<0)
790                             zSlot=0;
791                         break;
792                     case StackingDirection_Z_STACKING:
793                         zSlot++; xSlot=-1; ySlot=-1;
794                         break;
795                     default:
796                         // UNO enums have one additional auto-generated case
797                         break;
798                 }
799                 pPlotter->addSeries( pSeries, zSlot, xSlot, ySlot );
800             }
801         }
802     }
803 
804     //transport seriesnames to the coordinatesystems if needed
805     if( m_aSeriesPlotterList.size() )
806     {
807         uno::Sequence< rtl::OUString > aSeriesNames;
808         bool bSeriesNamesInitialized = false;
809         for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
810         {
811             VCoordinateSystem* pVCooSys = m_rVCooSysList[nC];
812             if(!pVCooSys)
813                 continue;
814             if( pVCooSys->needSeriesNamesForAxis() )
815             {
816                 if(!bSeriesNamesInitialized)
817                 {
818                     VSeriesPlotter* pSeriesPlotter = m_aSeriesPlotterList[0];
819                     if( pSeriesPlotter )
820                         aSeriesNames = pSeriesPlotter->getSeriesNames();
821                     bSeriesNamesInitialized = true;
822                 }
823                 pVCooSys->setSeriesNamesForAxis( aSeriesNames );
824             }
825         }
826     }
827 }
828 
initAxisUsageList(const Date & rNullDate)829 void SeriesPlotterContainer::initAxisUsageList(const Date& rNullDate)
830 {
831     m_aAxisUsageList.clear();
832     size_t nC;
833     for( nC=0; nC < m_rVCooSysList.size(); nC++)
834     {
835         VCoordinateSystem* pVCooSys = m_rVCooSysList[nC];
836         for(sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
837         {
838             uno::Reference< XCoordinateSystem > xCooSys = pVCooSys->getModel();
839             sal_Int32 nDimensionCount = xCooSys->getDimension();
840             if( nDimensionIndex >= nDimensionCount )
841                 continue;
842             bool bChartTypeAllowsDateAxis = ChartTypeHelper::isSupportingDateAxis(  AxisHelper::getChartTypeByIndex( xCooSys, 0 ), nDimensionCount, nDimensionIndex );
843             const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
844             for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
845             {
846                 uno::Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
847                 OSL_ASSERT( xAxis.is());
848                 if( xAxis.is())
849                 {
850                     if(m_aAxisUsageList.find(xAxis)==m_aAxisUsageList.end())
851                     {
852                         chart2::ScaleData aSourceScale = xAxis->getScaleData();
853                         ExplicitCategoriesProvider* pExplicitCategoriesProvider = pVCooSys->getExplicitCategoriesProvider();
854                         if( nDimensionIndex==0 )
855                             AxisHelper::checkDateAxis( aSourceScale, pExplicitCategoriesProvider, bChartTypeAllowsDateAxis );
856                         if( (aSourceScale.AxisType == AxisType::CATEGORY && m_bChartTypeUsesShiftedCategoryPositionPerDefault)
857                             || (aSourceScale.AxisType==AxisType::CATEGORY && pExplicitCategoriesProvider && pExplicitCategoriesProvider->hasComplexCategories() )
858                             || aSourceScale.AxisType == AxisType::DATE
859                             || aSourceScale.AxisType == AxisType::SERIES )
860                             aSourceScale.ShiftedCategoryPosition = true;
861                         else
862                             aSourceScale.ShiftedCategoryPosition = false;
863                         m_aAxisUsageList[xAxis].aScaleAutomatism = ScaleAutomatism(aSourceScale,rNullDate);
864                     }
865                     AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis];
866                     rAxisUsage.addCoordinateSystem(pVCooSys,nDimensionIndex,nAxisIndex);
867                 }
868             }
869         }
870     }
871 
872     ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator             aAxisIter    = m_aAxisUsageList.begin();
873     const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
874 
875     //init m_nMaxAxisIndex
876     m_nMaxAxisIndex = 0;
877     for(sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++)
878     {
879         for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
880         {
881             sal_Int32 nLocalMax = aAxisIter->second.getMaxAxisIndexForDimension( nDimensionIndex );
882             if( m_nMaxAxisIndex < nLocalMax )
883                 m_nMaxAxisIndex = nLocalMax;
884         }
885     }
886 }
887 
setScalesFromCooSysToPlotter()888 void SeriesPlotterContainer::setScalesFromCooSysToPlotter()
889 {
890     //set scales to plotter to enable them to provide the preferred scene AspectRatio
891     ::std::vector< VSeriesPlotter* >::const_iterator       aPlotterIter = m_aSeriesPlotterList.begin();
892     const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd  = m_aSeriesPlotterList.end();
893 	for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
894     {
895         VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
896         VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter );
897         if(pVCooSys)
898         {
899             pSeriesPlotter->setScales( pVCooSys->getExplicitScales(0,0), pVCooSys->getPropertySwapXAndYAxis() );
900             sal_Int32 nMaxAxisIndex = pVCooSys->getMaximumAxisIndexByDimension(1);//only additional value axis are relevant for series plotter
901             for( sal_Int32 nI=1; nI<=nMaxAxisIndex; nI++ )
902                 pSeriesPlotter->addSecondaryValueScale( pVCooSys->getExplicitScale(1,nI), nI );
903         }
904     }
905 }
906 
setNumberFormatsFromAxes()907 void SeriesPlotterContainer::setNumberFormatsFromAxes()
908 {
909     //set numberfarmats to plotter to enable them to display the data labels in the numberfromat of the axis
910 
911     ::std::vector< VSeriesPlotter* >::const_iterator       aPlotterIter = m_aSeriesPlotterList.begin();
912     const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd  = m_aSeriesPlotterList.end();
913 	for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
914     {
915         VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
916         VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter );
917         if(pVCooSys)
918         {
919             AxesNumberFormats aAxesNumberFormats;
920             uno::Reference< XCoordinateSystem > xCooSys = pVCooSys->getModel();
921             sal_Int32 nDimensionCount = xCooSys->getDimension();
922             for(sal_Int32 nDimensionIndex=0; nDimensionIndex<nDimensionCount; ++nDimensionIndex)
923             {
924                 const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex);
925                 for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex)
926                 {
927                     try
928                     {
929                         Reference< beans::XPropertySet > xAxisProp( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY );
930                         if( xAxisProp.is())
931                         {
932                             sal_Int32 nNumberFormatKey(0);
933                             if( xAxisProp->getPropertyValue( C2U( "NumberFormat" ) ) >>= nNumberFormatKey )
934                             {
935                                 aAxesNumberFormats.setFormat( nNumberFormatKey, nDimensionIndex, nAxisIndex );
936                             }
937                             else if( nDimensionIndex==0 )
938                             {
939                                 //provide a default date format for date axis with own data
940                                 aAxesNumberFormats.setFormat( m_nDefaultDateNumberFormat, nDimensionIndex, nAxisIndex );
941                             }
942                         }
943                     }
944                     catch( lang::IndexOutOfBoundsException& e )
945                     {
946                         ASSERT_EXCEPTION( e );
947                     }
948                 }
949             }
950             pSeriesPlotter->setAxesNumberFormats( aAxesNumberFormats );
951         }
952     }
953 }
954 
updateScalesAndIncrementsOnAxes()955 void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes()
956 {
957     for( size_t nC=0; nC < m_rVCooSysList.size(); nC++)
958         m_rVCooSysList[nC]->updateScalesAndIncrementsOnAxes();
959 }
960 
doAutoScaling(const uno::Reference<frame::XModel> & xChartModel)961 void SeriesPlotterContainer::doAutoScaling( const uno::Reference< frame::XModel >& xChartModel )
962 {
963     //precondition: need a initialized m_aSeriesPlotterList
964     //precondition: need a initialized m_aAxisUsageList
965 
966     ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator             aAxisIter    = m_aAxisUsageList.begin();
967     const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
968 
969     //iterate over the main scales first than secondary axis
970     size_t nC;
971     sal_Int32 nAxisIndex=0;
972     for( nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ )
973     {
974 
975         // - first do autoscale for all x and z scales (because they are treated independent)
976         for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
977         {
978             AxisUsage& rAxisUsage = (*aAxisIter).second;
979             ::std::vector< VCoordinateSystem* > aVCooSysList_X = rAxisUsage.getCoordinateSystems(0,nAxisIndex);
980             ::std::vector< VCoordinateSystem* > aVCooSysList_Z = rAxisUsage.getCoordinateSystems(2,nAxisIndex);
981 
982             for( nC=0; nC < aVCooSysList_X.size(); nC++)
983                 aVCooSysList_X[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,0,nAxisIndex);
984             for( nC=0; nC < aVCooSysList_Z.size(); nC++)
985                 aVCooSysList_Z[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,2,nAxisIndex);
986 
987             ExplicitScaleData       aExplicitScale;
988             ExplicitIncrementData   aExplicitIncrement;
989             rAxisUsage.aScaleAutomatism.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement );
990 
991             for( nC=0; nC < aVCooSysList_X.size(); nC++)
992                 aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement );
993             for( nC=0; nC < aVCooSysList_Z.size(); nC++)
994                 aVCooSysList_Z[nC]->setExplicitScaleAndIncrement( 2, nAxisIndex, aExplicitScale, aExplicitIncrement );
995         }
996 
997         // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already )
998         for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
999         {
1000             AxisUsage& rAxisUsage = (*aAxisIter).second;
1001             ::std::vector< VCoordinateSystem* > aVCooSysList_X = rAxisUsage.getCoordinateSystems(0,nAxisIndex);
1002             ::std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems(1,nAxisIndex);
1003             ::std::vector< VCoordinateSystem* > aVCooSysList_Z = rAxisUsage.getCoordinateSystems(2,nAxisIndex);
1004 
1005             if(!aVCooSysList_Y.size())
1006                 continue;
1007 
1008             for( nC=0; nC < aVCooSysList_Y.size(); nC++)
1009                 aVCooSysList_Y[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,1,nAxisIndex);
1010 
1011             ExplicitScaleData       aExplicitScale;
1012             ExplicitIncrementData   aExplicitIncrement;
1013             rAxisUsage.aScaleAutomatism.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement );
1014 
1015             for( nC=0; nC < aVCooSysList_X.size(); nC++)
1016                 aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement );
1017             for( nC=0; nC < aVCooSysList_Y.size(); nC++)
1018                 aVCooSysList_Y[nC]->setExplicitScaleAndIncrement( 1, nAxisIndex, aExplicitScale, aExplicitIncrement );
1019             for( nC=0; nC < aVCooSysList_Z.size(); nC++)
1020                 aVCooSysList_Z[nC]->setExplicitScaleAndIncrement( 2, nAxisIndex, aExplicitScale, aExplicitIncrement );
1021         }
1022     }
1023     AdaptScaleOfYAxisWithoutAttachedSeries( xChartModel );
1024 }
1025 
AdaptScaleOfYAxisWithoutAttachedSeries(const uno::Reference<frame::XModel> & xChartModel)1026 void SeriesPlotterContainer::AdaptScaleOfYAxisWithoutAttachedSeries( const uno::Reference< frame::XModel >& xChartModel )
1027 {
1028     //issue #i80518#
1029 
1030     ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator             aAxisIter    = m_aAxisUsageList.begin();
1031     const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end();
1032 
1033     for( sal_Int32 nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ )
1034     {
1035         for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
1036         {
1037             AxisUsage& rAxisUsage = (*aAxisIter).second;
1038             ::std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems( 1, nAxisIndex );
1039             if( !aVCooSysList_Y.size() )
1040                 continue;
1041 
1042             uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) );
1043             if( xDiagram.is() )
1044             {
1045                 bool bSeriesAttachedToThisAxis = false;
1046                 sal_Int32 nAttachedAxisIndex = -1;
1047                 {
1048                     ::std::vector< Reference< XDataSeries > > aSeriesVector( DiagramHelper::getDataSeriesFromDiagram( xDiagram ) );
1049                     ::std::vector< Reference< XDataSeries > >::const_iterator aIter = aSeriesVector.begin();
1050                     for( ; aIter != aSeriesVector.end(); aIter++ )
1051                     {
1052                         sal_Int32 nCurrentIndex = DataSeriesHelper::getAttachedAxisIndex( *aIter );
1053                         if( nAxisIndex == nCurrentIndex )
1054                         {
1055                             bSeriesAttachedToThisAxis = true;
1056                             break;
1057                         }
1058                         else if( nAttachedAxisIndex<0 || nAttachedAxisIndex>nCurrentIndex )
1059                             nAttachedAxisIndex=nCurrentIndex;
1060                     }
1061                 }
1062 
1063                 if( !bSeriesAttachedToThisAxis && nAttachedAxisIndex >= 0 )
1064                 {
1065                     for( size_t nC = 0; nC < aVCooSysList_Y.size(); ++nC )
1066                     {
1067                         aVCooSysList_Y[nC]->prepareScaleAutomatismForDimensionAndIndex( rAxisUsage.aScaleAutomatism, 1, nAttachedAxisIndex );
1068 
1069                         ExplicitScaleData aExplicitScaleSource = aVCooSysList_Y[nC]->getExplicitScale( 1,nAttachedAxisIndex );
1070                         ExplicitIncrementData aExplicitIncrementSource = aVCooSysList_Y[nC]->getExplicitIncrement( 1,nAttachedAxisIndex );
1071 
1072                         ExplicitScaleData aExplicitScaleDest = aVCooSysList_Y[nC]->getExplicitScale( 1,nAxisIndex );;
1073                         ExplicitIncrementData aExplicitIncrementDest = aVCooSysList_Y[nC]->getExplicitIncrement( 1,nAxisIndex );;
1074 
1075                         aExplicitScaleDest.Orientation = aExplicitScaleSource.Orientation;
1076                         aExplicitScaleDest.Scaling = aExplicitScaleSource.Scaling;
1077                         aExplicitScaleDest.AxisType = aExplicitScaleSource.AxisType;
1078 
1079                         aExplicitIncrementDest.BaseValue = aExplicitIncrementSource.BaseValue;
1080 
1081                         ScaleData aScale( rAxisUsage.aScaleAutomatism.getScale() );
1082                         if( !aScale.Minimum.hasValue() )
1083                         {
1084                             bool bNewMinOK = true;
1085                             double fMax=0.0;
1086                             if( aScale.Maximum >>= fMax )
1087                                 bNewMinOK = (aExplicitScaleSource.Minimum <= fMax);
1088                             if( bNewMinOK )
1089                                 aExplicitScaleDest.Minimum = aExplicitScaleSource.Minimum;
1090                         }
1091                         else
1092                             aExplicitIncrementDest.BaseValue = aExplicitScaleDest.Minimum;
1093 
1094                         if( !aScale.Maximum.hasValue() )
1095                         {
1096                             bool bNewMaxOK = true;
1097                             double fMin=0.0;
1098                             if( aScale.Minimum >>= fMin )
1099                                 bNewMaxOK = (fMin <= aExplicitScaleSource.Maximum);
1100                             if( bNewMaxOK )
1101                                 aExplicitScaleDest.Maximum = aExplicitScaleSource.Maximum;
1102                         }
1103                         if( !aScale.Origin.hasValue() )
1104                             aExplicitScaleDest.Origin = aExplicitScaleSource.Origin;
1105 
1106                         if( !aScale.IncrementData.Distance.hasValue() )
1107                             aExplicitIncrementDest.Distance = aExplicitIncrementSource.Distance;
1108 
1109                         bool bAutoMinorInterval = true;
1110                         if( aScale.IncrementData.SubIncrements.getLength() )
1111                             bAutoMinorInterval = !( aScale.IncrementData.SubIncrements[0].IntervalCount.hasValue() );
1112                         if( bAutoMinorInterval )
1113                         {
1114                             if( !aExplicitIncrementDest.SubIncrements.empty() && !aExplicitIncrementSource.SubIncrements.empty() )
1115                                 aExplicitIncrementDest.SubIncrements[0].IntervalCount =
1116                                     aExplicitIncrementSource.SubIncrements[0].IntervalCount;
1117                         }
1118 
1119                         aVCooSysList_Y[nC]->setExplicitScaleAndIncrement( 1, nAxisIndex, aExplicitScaleDest, aExplicitIncrementDest );
1120                     }
1121                 }
1122             }
1123         }
1124     }
1125 
1126     if( AxisHelper::isAxisPositioningEnabled() )
1127     {
1128         //correct origin for y main axis (the origin is where the other main axis crosses)
1129         sal_Int32 nAxisIndex=0;
1130         sal_Int32 nDimensionIndex=1;
1131         for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ )
1132         {
1133             AxisUsage& rAxisUsage = (*aAxisIter).second;
1134             ::std::vector< VCoordinateSystem* > aVCooSysList = rAxisUsage.getCoordinateSystems(nDimensionIndex,nAxisIndex);
1135             size_t nC;
1136             for( nC=0; nC < aVCooSysList.size(); nC++)
1137             {
1138                 ExplicitScaleData aExplicitScale( aVCooSysList[nC]->getExplicitScale( nDimensionIndex, nAxisIndex ) );
1139                 ExplicitIncrementData aExplicitIncrement( aVCooSysList[nC]->getExplicitIncrement( nDimensionIndex, nAxisIndex ) );
1140 
1141                 Reference< chart2::XCoordinateSystem > xCooSys( aVCooSysList[nC]->getModel() );
1142                 Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) );
1143                 Reference< beans::XPropertySet > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis, xCooSys ), uno::UNO_QUERY );
1144 
1145                 ::com::sun::star::chart::ChartAxisPosition eCrossingMainAxisPos( ::com::sun::star::chart::ChartAxisPosition_ZERO );
1146                 if( xCrossingMainAxis.is() )
1147                 {
1148                     xCrossingMainAxis->getPropertyValue(C2U( "CrossoverPosition" )) >>= eCrossingMainAxisPos;
1149                     if( ::com::sun::star::chart::ChartAxisPosition_VALUE == eCrossingMainAxisPos )
1150                     {
1151                         double fValue = 0.0;
1152                         xCrossingMainAxis->getPropertyValue(C2U( "CrossoverValue" )) >>= fValue;
1153                         aExplicitScale.Origin = fValue;
1154                     }
1155                     else if( ::com::sun::star::chart::ChartAxisPosition_ZERO == eCrossingMainAxisPos )
1156                         aExplicitScale.Origin = 0.0;
1157                     else  if( ::com::sun::star::chart::ChartAxisPosition_START == eCrossingMainAxisPos )
1158                         aExplicitScale.Origin = aExplicitScale.Minimum;
1159                     else  if( ::com::sun::star::chart::ChartAxisPosition_END == eCrossingMainAxisPos )
1160                         aExplicitScale.Origin = aExplicitScale.Maximum;
1161                 }
1162 
1163                 aVCooSysList[nC]->setExplicitScaleAndIncrement( nDimensionIndex, nAxisIndex, aExplicitScale, aExplicitIncrement );
1164             }
1165         }
1166     }
1167 }
1168 
getPreferredAspectRatio()1169 drawing::Direction3D SeriesPlotterContainer::getPreferredAspectRatio()
1170 {
1171     drawing::Direction3D aPreferredAspectRatio(1.0,1.0,1.0);
1172 
1173     sal_Int32 nPlotterCount=0;
1174     //get a list of all preferred aspect ratios and combine them
1175     //first with special demands wins (less or equal zero <-> arbitrary)
1176     double fx, fy, fz;
1177     fx = fy = fz = -1.0;
1178     ::std::vector< VSeriesPlotter* >::const_iterator       aPlotterIter = m_aSeriesPlotterList.begin();
1179     const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd  = m_aSeriesPlotterList.end();
1180     for( aPlotterIter = m_aSeriesPlotterList.begin(), nPlotterCount=0
1181         ; aPlotterIter != aPlotterEnd; aPlotterIter++, nPlotterCount++ )
1182     {
1183         drawing::Direction3D aSingleRatio( (*aPlotterIter)->getPreferredDiagramAspectRatio() );
1184         if( fx<0 && aSingleRatio.DirectionX>0 )
1185             fx = aSingleRatio.DirectionX;
1186 
1187         if( fy<0 && aSingleRatio.DirectionY>0 )
1188         {
1189             if( fx>0 && aSingleRatio.DirectionX>0 )
1190                 fy = fx*aSingleRatio.DirectionY/aSingleRatio.DirectionX;
1191             else if( fz>0 && aSingleRatio.DirectionZ>0 )
1192                 fy = fz*aSingleRatio.DirectionY/aSingleRatio.DirectionZ;
1193             else
1194                 fy = aSingleRatio.DirectionY;
1195         }
1196 
1197         if( fz<0 && aSingleRatio.DirectionZ>0 )
1198         {
1199             if( fx>0 && aSingleRatio.DirectionX>0 )
1200                 fz = fx*aSingleRatio.DirectionZ/aSingleRatio.DirectionX;
1201             else if( fy>0 && aSingleRatio.DirectionY>0 )
1202                 fz = fy*aSingleRatio.DirectionZ/aSingleRatio.DirectionY;
1203             else
1204                 fz = aSingleRatio.DirectionZ;
1205         }
1206 
1207         if( fx>0 && fy>0 && fz>0 )
1208             break;
1209     }
1210     aPreferredAspectRatio = drawing::Direction3D(fx, fy, fz);
1211     return aPreferredAspectRatio;
1212 }
1213 
1214 //-----------------------------------------------------
1215 
1216 namespace
1217 {
1218 
lcl_IsPieOrDonut(const uno::Reference<XDiagram> & xDiagram)1219 bool lcl_IsPieOrDonut( const uno::Reference< XDiagram >& xDiagram )
1220 {
1221     //special treatment for pie charts
1222     //the size is checked after complete creation to get the datalabels into the given space
1223 
1224     //todo: this is just a workaround at the moment for pie and donut labels
1225     return DiagramHelper::isPieOrDonutChart( xDiagram );
1226 }
1227 
lcl_setDefaultWritingMode(::boost::shared_ptr<DrawModelWrapper> pDrawModelWrapper,const Reference<frame::XModel> & xChartModel)1228 void lcl_setDefaultWritingMode( ::boost::shared_ptr< DrawModelWrapper > pDrawModelWrapper, const Reference< frame::XModel >& xChartModel )
1229 {
1230     //get writing mode from parent document:
1231     if( SvtLanguageOptions().IsCTLFontEnabled() )
1232     {
1233         try
1234         {
1235             uno::Reference< container::XChild > xChild( xChartModel, uno::UNO_QUERY );
1236             sal_Int16 nWritingMode=-1;
1237             if ( xChild.is() )
1238             {
1239                 uno::Reference< beans::XPropertySet > xParentProps( xChild->getParent(), uno::UNO_QUERY );
1240                 uno::Reference< style::XStyleFamiliesSupplier > xStyleFamiliesSupplier( xParentProps, uno::UNO_QUERY );
1241                 if( xStyleFamiliesSupplier.is() )
1242                 {
1243                     uno::Reference< container::XNameAccess > xStylesFamilies( xStyleFamiliesSupplier->getStyleFamilies() );
1244 		            if( xStylesFamilies.is() )
1245 		            {
1246                         if( !xStylesFamilies->hasByName( C2U("PageStyles") ) )
1247                         {
1248                             //draw/impress is parent document
1249                             uno::Reference< lang::XMultiServiceFactory > xFatcory( xParentProps, uno::UNO_QUERY );
1250                             if( xFatcory.is() )
1251                             {
1252                                 uno::Reference< beans::XPropertySet > xDrawDefaults( xFatcory->createInstance( C2U( "com.sun.star.drawing.Defaults" ) ), uno::UNO_QUERY );
1253                                 if( xDrawDefaults.is() )
1254                                     xDrawDefaults->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
1255                             }
1256                         }
1257                         else
1258                         {
1259                             uno::Reference< container::XNameAccess > xPageStyles( xStylesFamilies->getByName( C2U("PageStyles") ), uno::UNO_QUERY );
1260                             if( xPageStyles.is() )
1261                             {
1262                                 rtl::OUString aPageStyle;
1263 
1264                                 uno::Reference< text::XTextDocument > xTextDocument( xParentProps, uno::UNO_QUERY );
1265                                 if( xTextDocument.is() )
1266                                 {
1267                                     //writer is parent document
1268                                     //retrieve the current page style from the text cursor property PageStyleName
1269 
1270                                     uno::Reference< text::XTextEmbeddedObjectsSupplier > xTextEmbeddedObjectsSupplier( xTextDocument, uno::UNO_QUERY );
1271                                     if( xTextEmbeddedObjectsSupplier.is() )
1272                                     {
1273                                         uno::Reference< container::XNameAccess > xEmbeddedObjects( xTextEmbeddedObjectsSupplier->getEmbeddedObjects() );
1274                                         if( xEmbeddedObjects.is() )
1275                                         {
1276                                             uno::Sequence< rtl::OUString > aNames( xEmbeddedObjects->getElementNames() );
1277 
1278                                             sal_Int32 nCount = aNames.getLength();
1279                                             for( sal_Int32 nN=0; nN<nCount; nN++ )
1280                                             {
1281                                                 uno::Reference< beans::XPropertySet > xEmbeddedProps( xEmbeddedObjects->getByName( aNames[nN] ), uno::UNO_QUERY );
1282                                                 if( xEmbeddedProps.is() )
1283                                                 {
1284                                                     static rtl::OUString aChartCLSID = rtl::OUString( SvGlobalName( SO3_SCH_CLASSID ).GetHexName());
1285                                                     rtl::OUString aCLSID;
1286                                                     xEmbeddedProps->getPropertyValue( C2U("CLSID") ) >>= aCLSID;
1287                                                     if( aCLSID.equals(aChartCLSID) )
1288                                                     {
1289                                                         uno::Reference< frame::XModel > xModel;
1290                                                         xEmbeddedProps->getPropertyValue( C2U("Model") ) >>= xModel;
1291                                                         if( xModel == xChartModel )
1292                                                         {
1293                                                             uno::Reference< text::XTextContent > xEmbeddedObject( xEmbeddedProps, uno::UNO_QUERY );
1294                                                             if( xEmbeddedObject.is() )
1295                                                             {
1296                                                                 uno::Reference< text::XTextRange > xAnchor( xEmbeddedObject->getAnchor() );
1297                                                                 if( xAnchor.is() )
1298                                                                 {
1299                                                                     uno::Reference< beans::XPropertySet > xAnchorProps( xAnchor, uno::UNO_QUERY );
1300                                                                     if( xAnchorProps.is() )
1301                                                                     {
1302                                                                         xAnchorProps->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
1303                                                                     }
1304                                                                     uno::Reference< text::XText > xText( xAnchor->getText() );
1305                                                                     if( xText.is() )
1306                                                                     {
1307                                                                         uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
1308                                                                         if( xTextCursorProps.is() )
1309                                                                             xTextCursorProps->getPropertyValue( C2U("PageStyleName") ) >>= aPageStyle;
1310                                                                     }
1311                                                                 }
1312                                                             }
1313                                                             break;
1314                                                         }
1315                                                     }
1316                                                 }
1317                                             }
1318                                         }
1319                                     }
1320                                     if( aPageStyle.isEmpty() )
1321                                     {
1322                                         uno::Reference< text::XText > xText( xTextDocument->getText() );
1323                                         if( xText.is() )
1324                                         {
1325                                             uno::Reference< beans::XPropertySet > xTextCursorProps( xText->createTextCursor(), uno::UNO_QUERY );
1326                                             if( xTextCursorProps.is() )
1327                                                 xTextCursorProps->getPropertyValue( C2U("PageStyleName") ) >>= aPageStyle;
1328                                         }
1329                                     }
1330                                 }
1331                                 else
1332                                 {
1333                                     //Calc is parent document
1334                                     xParentProps->getPropertyValue( C2U("PageStyle") ) >>= aPageStyle;
1335                                     if( aPageStyle.isEmpty() )
1336                                         aPageStyle = C2U("Default");
1337                                 }
1338                                 if( nWritingMode == -1 || nWritingMode == text::WritingMode2::PAGE )
1339                                 {
1340                                     uno::Reference< beans::XPropertySet > xPageStyle( xPageStyles->getByName( aPageStyle ), uno::UNO_QUERY );
1341                                     if( xPageStyle.is() )
1342                                         xPageStyle->getPropertyValue( C2U("WritingMode") ) >>= nWritingMode;
1343                                 }
1344                             }
1345                         }
1346                     }
1347                 }
1348             }
1349             if( nWritingMode != -1 && nWritingMode != text::WritingMode2::PAGE )
1350             {
1351                 if( pDrawModelWrapper.get() )
1352                     pDrawModelWrapper->GetItemPool().SetPoolDefaultItem(SfxInt32Item(EE_PARA_WRITINGDIR, nWritingMode) );
1353             }
1354         }
1355         catch( uno::Exception& ex )
1356         {
1357             ASSERT_EXCEPTION( ex );
1358         }
1359     }
1360 }
1361 
lcl_getDefaultWritingModeFromPool(::boost::shared_ptr<DrawModelWrapper> pDrawModelWrapper)1362 sal_Int16 lcl_getDefaultWritingModeFromPool( ::boost::shared_ptr< DrawModelWrapper > pDrawModelWrapper )
1363 {
1364     sal_Int16 nWritingMode = text::WritingMode2::LR_TB;
1365     if( pDrawModelWrapper.get() )
1366     {
1367         const SfxPoolItem* pItem = &(pDrawModelWrapper->GetItemPool().GetDefaultItem( EE_PARA_WRITINGDIR ));
1368         if( pItem )
1369             nWritingMode = static_cast< sal_Int16 >((static_cast< const SfxInt32Item * >( pItem ))->GetValue());
1370     }
1371     return nWritingMode;
1372 }
1373 
1374 } //end anonymous namespace
1375 
1376 //------------ create complete diagram shape (inclusive axis and series)
1377 
impl_createDiagramAndContent(SeriesPlotterContainer & rSeriesPlotterContainer,const uno::Reference<drawing::XShapes> & xDiagramPlusAxes_Shapes,const awt::Point & rAvailablePos,const awt::Size & rAvailableSize,const awt::Size & rPageSize,bool bUseFixedInnerSize,const uno::Reference<drawing::XShape> & xDiagram_MarkHandles)1378 awt::Rectangle ChartView::impl_createDiagramAndContent( SeriesPlotterContainer& rSeriesPlotterContainer
1379             , const uno::Reference< drawing::XShapes>& xDiagramPlusAxes_Shapes
1380             , const awt::Point& rAvailablePos
1381             , const awt::Size& rAvailableSize
1382             , const awt::Size& rPageSize
1383             , bool bUseFixedInnerSize
1384             , const uno::Reference< drawing::XShape>& xDiagram_MarkHandles /*needs to be resized to fit the result*/
1385             )
1386 {
1387     //return the used rectangle
1388     awt::Rectangle aUsedOuterRect( rAvailablePos.X, rAvailablePos.Y, 0, 0 );
1389 
1390 //     sal_Int32 nDiagramIndex = 0;//todo if more than one diagam is supported
1391     uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) );
1392     if( !xDiagram.is())
1393         return aUsedOuterRect;
1394 
1395     sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram );
1396     if(!nDimensionCount)
1397     {
1398         //@todo handle mixed dimension
1399         nDimensionCount = 2;
1400     }
1401 
1402     ::basegfx::B2IRectangle aAvailableOuterRect( BaseGFXHelper::makeRectangle(rAvailablePos,rAvailableSize) );
1403 
1404     const std::vector< VCoordinateSystem* >& rVCooSysList( rSeriesPlotterContainer.getCooSysList() );
1405     const std::vector< VSeriesPlotter* >& rSeriesPlotterList( rSeriesPlotterContainer.getSeriesPlotterList() );
1406 
1407     //create VAxis, so they can give necessary information for automatic scaling
1408     uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( m_xChartModel, uno::UNO_QUERY );
1409     size_t nC = 0;
1410     for( nC=0; nC < rVCooSysList.size(); nC++)
1411     {
1412         VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1413         if(3==nDimensionCount)
1414         {
1415             uno::Reference<beans::XPropertySet> xSceneProperties( xDiagram, uno::UNO_QUERY );
1416             CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( xSceneProperties ) );
1417             CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( xSceneProperties ) );
1418             CuboidPlanePosition eBottomPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBottom( xSceneProperties ) );
1419             pVCooSys->set3DWallPositions( eLeftWallPos, eBackWallPos, eBottomPos );
1420         }
1421         pVCooSys->createVAxisList( xNumberFormatsSupplier
1422                                         , rPageSize //font reference size
1423                                         , BaseGFXHelper::B2IRectangleToAWTRectangle( aAvailableOuterRect ) //maximum space for labels
1424                                         );
1425     }
1426 
1427 
1428     // - prepare list of all axis and how they are used
1429     Date aNullDate = NumberFormatterWrapper( uno::Reference< util::XNumberFormatsSupplier >( m_xChartModel, uno::UNO_QUERY ) ).getNullDate();
1430     rSeriesPlotterContainer.initAxisUsageList(aNullDate);
1431     rSeriesPlotterContainer.doAutoScaling( m_xChartModel );
1432     rSeriesPlotterContainer.setScalesFromCooSysToPlotter();
1433     rSeriesPlotterContainer.setNumberFormatsFromAxes();
1434 
1435     //---------------------------------------------------------------------
1436     //create shapes
1437 
1438     //------------ create diagram shapes
1439     //aspect ratio
1440     drawing::Direction3D aPreferredAspectRatio(
1441         rSeriesPlotterContainer.getPreferredAspectRatio() );
1442 
1443     uno::Reference< drawing::XShapes > xSeriesTargetInFrontOfAxis(0);
1444     uno::Reference< drawing::XShapes > xSeriesTargetBehindAxis(0);
1445     VDiagram aVDiagram(xDiagram, aPreferredAspectRatio, nDimensionCount);
1446     {//create diagram
1447         aVDiagram.init(xDiagramPlusAxes_Shapes,xDiagramPlusAxes_Shapes,m_xShapeFactory);
1448         aVDiagram.createShapes(rAvailablePos,rAvailableSize);
1449         xSeriesTargetInFrontOfAxis = aVDiagram.getCoordinateRegion();
1450         if( !bUseFixedInnerSize )
1451             aVDiagram.reduceToMimimumSize();
1452     }
1453 
1454     uno::Reference< drawing::XShapes > xTextTargetShapes( ShapeFactory(m_xShapeFactory).createGroup2D(xDiagramPlusAxes_Shapes) );
1455 
1456     // - create axis and grids for all coordinate systems
1457 
1458     //init all coordinate systems
1459     for( nC=0; nC < rVCooSysList.size(); nC++)
1460     {
1461         VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1462         pVCooSys->initPlottingTargets(xSeriesTargetInFrontOfAxis,xTextTargetShapes,m_xShapeFactory,xSeriesTargetBehindAxis);
1463 
1464         pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1465             createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
1466 
1467         pVCooSys->initVAxisInList();
1468     }
1469 
1470     //calculate resulting size respecting axis label layout and fontscaling
1471 
1472     uno::Reference< drawing::XShape > xBoundingShape( xDiagramPlusAxes_Shapes, uno::UNO_QUERY );
1473     ::basegfx::B2IRectangle aConsumedOuterRect;
1474 
1475     //use first coosys only so far; todo: calculate for more than one coosys if we have more in future
1476     //todo: this is just a workaround at the moment for pie and donut labels
1477     bool bIsPieOrDonut = lcl_IsPieOrDonut(xDiagram);
1478     if( !bIsPieOrDonut && rVCooSysList.size() > 0 )
1479     {
1480         VCoordinateSystem* pVCooSys = rVCooSysList[0];
1481         pVCooSys->createMaximumAxesLabels();
1482 
1483         aConsumedOuterRect = ::basegfx::B2IRectangle( ShapeFactory::getRectangleOfShape(xBoundingShape) );
1484         ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.getCurrentRectangle() );
1485         if( !bUseFixedInnerSize )
1486             aNewInnerRect = aVDiagram.adjustInnerSize( aConsumedOuterRect );
1487 
1488         pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1489             createTransformationSceneToScreen( aNewInnerRect ) ));
1490 
1491         //redo autoscaling to get size and text dependent automatic main increment count
1492         rSeriesPlotterContainer.doAutoScaling( m_xChartModel );
1493         rSeriesPlotterContainer.updateScalesAndIncrementsOnAxes();
1494         rSeriesPlotterContainer.setScalesFromCooSysToPlotter();
1495 
1496         pVCooSys->createAxesLabels();
1497 
1498         bool bLessSpaceConsumedThanExpected = false;
1499         {
1500             ::basegfx::B2IRectangle aOldRect( aConsumedOuterRect );
1501             aConsumedOuterRect = ShapeFactory::getRectangleOfShape(xBoundingShape);
1502             if( aConsumedOuterRect.getMinX() > aAvailableOuterRect.getMinX()
1503                 || aConsumedOuterRect.getMaxX() < aAvailableOuterRect.getMaxX()
1504                 || aConsumedOuterRect.getMinY() > aAvailableOuterRect.getMinY()
1505                 || aConsumedOuterRect.getMinY() < aAvailableOuterRect.getMaxY() )
1506                 bLessSpaceConsumedThanExpected = true;
1507         }
1508 
1509         if( bLessSpaceConsumedThanExpected && !bUseFixedInnerSize )
1510         {
1511             aVDiagram.adjustInnerSize( aConsumedOuterRect );
1512             pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1513                 createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
1514         }
1515         pVCooSys->updatePositions();//todo: logically this belongs to the condition above, but it seems also to be necessary to give the axes group shapes the right bounding rects for hit test -  probably caused by bug i106183 -> check again if fixed
1516     }
1517 
1518     //create axes and grids for the final size
1519     for( nC=0; nC < rVCooSysList.size(); nC++)
1520     {
1521         VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1522 
1523         pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1524             createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) ));
1525 
1526         pVCooSys->createAxesShapes();
1527         pVCooSys->createGridShapes();
1528     }
1529 
1530     // - create data series for all charttypes
1531     m_bPointsWereSkipped = false;
1532     ::std::vector< VSeriesPlotter* >::const_iterator       aPlotterIter = rSeriesPlotterList.begin();
1533     const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd  = rSeriesPlotterList.end();
1534 	for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
1535     {
1536         //------------ set transformation to plotter / create series
1537         VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
1538         rtl::OUString aCID; //III
1539         uno::Reference< drawing::XShapes > xSeriesTarget(0);
1540         if( pSeriesPlotter->WantToPlotInFrontOfAxisLine() )
1541             xSeriesTarget = xSeriesTargetInFrontOfAxis;
1542         else
1543         {
1544             xSeriesTarget = xSeriesTargetBehindAxis;
1545             DBG_ASSERT( !bIsPieOrDonut, "not implemented yet! - during a complete recreation this shape is destroyed so no series can be created anymore" );
1546         }
1547         pSeriesPlotter->initPlotter( xSeriesTarget,xTextTargetShapes,m_xShapeFactory,aCID );
1548         pSeriesPlotter->setPageReferenceSize( rPageSize );
1549         VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
1550         if(2==nDimensionCount)
1551             pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
1552         //better performance for big data
1553         awt::Size aCoordinateRegionResolution(1000,1000);
1554         {
1555             //calculate resolution for coordinate system
1556             Sequence<sal_Int32> aCoordinateSystemResolution = pVCooSys->getCoordinateSystemResolution( rPageSize, m_aPageResolution );
1557             pSeriesPlotter->setCoordinateSystemResolution( aCoordinateSystemResolution );
1558         }
1559         //
1560         pSeriesPlotter->createShapes();
1561         m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped();
1562     }
1563 
1564     //recreate all with corrected sizes if requested
1565     if( bIsPieOrDonut )
1566     {
1567         m_bPointsWereSkipped = false;
1568 
1569         aConsumedOuterRect = ::basegfx::B2IRectangle( ShapeFactory::getRectangleOfShape(xBoundingShape) );
1570         ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.getCurrentRectangle() );
1571         if( !bUseFixedInnerSize )
1572             aNewInnerRect = aVDiagram.adjustInnerSize( aConsumedOuterRect );
1573 
1574         for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
1575         {
1576             VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
1577             pSeriesPlotter->releaseShapes();
1578         }
1579 
1580         //clear and recreate
1581         ShapeFactory::removeSubShapes( xSeriesTargetInFrontOfAxis ); //xSeriesTargetBehindAxis is a sub shape of xSeriesTargetInFrontOfAxis and will be removed here
1582         xSeriesTargetBehindAxis.clear();
1583         ShapeFactory::removeSubShapes( xTextTargetShapes );
1584 
1585         //set new transformation
1586         for( nC=0; nC < rVCooSysList.size(); nC++)
1587         {
1588             VCoordinateSystem* pVCooSys = rVCooSysList[nC];
1589             pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix(
1590                 createTransformationSceneToScreen( aNewInnerRect ) ));
1591         }
1592 
1593         // - create data series for all charttypes
1594         for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
1595         {
1596             //------------ set transformation to plotter / create series
1597             VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
1598             VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter );
1599             if(2==nDimensionCount)
1600                 pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() );
1601             pSeriesPlotter->createShapes();
1602             m_bPointsWereSkipped = m_bPointsWereSkipped || pSeriesPlotter->PointsWereSkipped();
1603         }
1604 
1605         /*
1606         uno::Reference< drawing::XShape > xDiagramPlusAxes_KeepRatio( xDiagramPlusAxes_Shapes, uno::UNO_QUERY );
1607 
1608         awt::Size aNewSize( rAvailableSize );
1609         awt::Point aNewPos( rAvailablePos );
1610         if( bKeepAspectRatio )
1611         {
1612             awt::Size aCurrentSize( xDiagramPlusAxes_KeepRatio->getSize());
1613 
1614             aNewSize = ShapeFactory::calculateNewSizeRespectingAspectRatio(
1615                             rAvailableSize, aCurrentSize );
1616             aNewPos = ShapeFactory::calculateTopLeftPositionToCenterObject(
1617                     rAvailablePos, rAvailableSize, aNewSize );
1618         }
1619 
1620         xDiagramPlusAxes_KeepRatio->setPosition( aNewPos );
1621         xDiagramPlusAxes_KeepRatio->setSize( aNewSize );
1622         */
1623         for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
1624         {
1625             VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
1626             pSeriesPlotter->rearrangeLabelToAvoidOverlapIfRequested( rPageSize );
1627         }
1628     }
1629 
1630     if( bUseFixedInnerSize )
1631     {
1632         //if( !bIsPieOrDonut )
1633         //    aConsumedOuterRect = ::basegfx::B2IRectangle( ShapeFactory::getRectangleOfShape(xBoundingShape) );
1634         aUsedOuterRect = awt::Rectangle( aConsumedOuterRect.getMinX(), aConsumedOuterRect.getMinY(), aConsumedOuterRect.getWidth(), aConsumedOuterRect.getHeight() );
1635     }
1636     else
1637         aUsedOuterRect = awt::Rectangle( rAvailablePos.X, rAvailablePos.Y, rAvailableSize.Width, rAvailableSize.Height );
1638 
1639     bool bSnapRectToUsedArea = false;
1640     for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ )
1641     {
1642         VSeriesPlotter* pSeriesPlotter = *aPlotterIter;
1643         bSnapRectToUsedArea = pSeriesPlotter->shouldSnapRectToUsedArea();
1644         if(bSnapRectToUsedArea)
1645             break;
1646     }
1647     if(bSnapRectToUsedArea)
1648     {
1649         if( bUseFixedInnerSize )
1650             m_aResultingDiagramRectangleExcludingAxes = getRectangleOfObject( C2U("PlotAreaExcludingAxes") );
1651         else
1652         {
1653             ::basegfx::B2IRectangle aConsumedInnerRect = aVDiagram.getCurrentRectangle();
1654             m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle( aConsumedInnerRect.getMinX(), aConsumedInnerRect.getMinY(), aConsumedInnerRect.getWidth(), aConsumedInnerRect.getHeight() );
1655         }
1656     }
1657     else
1658     {
1659         if( bUseFixedInnerSize )
1660             m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle( rAvailablePos.X, rAvailablePos.Y, rAvailableSize.Width, rAvailableSize.Height );
1661         else
1662         {
1663             ::basegfx::B2IRectangle aConsumedInnerRect = aVDiagram.getCurrentRectangle();
1664             m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle( aConsumedInnerRect.getMinX(), aConsumedInnerRect.getMinY(), aConsumedInnerRect.getWidth(), aConsumedInnerRect.getHeight() );
1665         }
1666     }
1667 
1668     if( xDiagram_MarkHandles.is() )
1669     {
1670         awt::Point aPos(rAvailablePos);
1671         awt::Size  aSize(rAvailableSize);
1672         bool bPosSizeExcludeAxesProperty = true;
1673         uno::Reference< beans::XPropertySet > xDiaProps( xDiagram, uno::UNO_QUERY_THROW );
1674         if( xDiaProps.is() )
1675             xDiaProps->getPropertyValue(C2U("PosSizeExcludeAxes")) >>= bPosSizeExcludeAxesProperty;
1676         if( bUseFixedInnerSize || bPosSizeExcludeAxesProperty )
1677         {
1678             aPos = awt::Point( m_aResultingDiagramRectangleExcludingAxes.X, m_aResultingDiagramRectangleExcludingAxes.Y );
1679             aSize = awt::Size( m_aResultingDiagramRectangleExcludingAxes.Width, m_aResultingDiagramRectangleExcludingAxes.Height );
1680         }
1681         xDiagram_MarkHandles->setPosition( aPos );
1682         xDiagram_MarkHandles->setSize( aSize );
1683     }
1684 
1685     return aUsedOuterRect;
1686 }
1687 
1688 //-------------------------------------------------------------
1689 //-------------------------------------------------------------
1690 //-------------------------------------------------------------
1691 
getExplicitValuesForAxis(uno::Reference<XAxis> xAxis,ExplicitScaleData & rExplicitScale,ExplicitIncrementData & rExplicitIncrement)1692 sal_Bool ChartView::getExplicitValuesForAxis(
1693                      uno::Reference< XAxis > xAxis
1694                      , ExplicitScaleData&  rExplicitScale
1695                      , ExplicitIncrementData& rExplicitIncrement )
1696 {
1697     impl_updateView();
1698 
1699     if(!xAxis.is())
1700         return sal_False;
1701 
1702     uno::Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis(xAxis,ChartModelHelper::findDiagram( m_xChartModel )  ) );
1703     const VCoordinateSystem* pVCooSys = findInCooSysList(m_aVCooSysList,xCooSys);
1704     if(!pVCooSys)
1705         return sal_False;
1706 
1707     sal_Int32 nDimensionIndex=-1;
1708     sal_Int32 nAxisIndex=-1;
1709     if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) )
1710     {
1711         rExplicitScale = pVCooSys->getExplicitScale(nDimensionIndex,nAxisIndex);
1712         rExplicitIncrement = pVCooSys->getExplicitIncrement(nDimensionIndex,nAxisIndex);
1713         if( rExplicitScale.ShiftedCategoryPosition )
1714         {
1715             //remove 'one' from max
1716             if( rExplicitScale.AxisType == ::com::sun::star::chart2::AxisType::DATE )
1717             {
1718                 Date aMaxDate(rExplicitScale.NullDate); aMaxDate += static_cast<long>(::rtl::math::approxFloor(rExplicitScale.Maximum));
1719                 //for explicit scales with shifted categories we need one interval more
1720                 switch( rExplicitScale.TimeResolution )
1721                 {
1722                 case ::com::sun::star::chart::TimeUnit::DAY:
1723                     aMaxDate--;break;
1724                 case ::com::sun::star::chart::TimeUnit::MONTH:
1725                     aMaxDate = DateHelper::GetDateSomeMonthsAway(aMaxDate,-1);
1726                     break;
1727                 case ::com::sun::star::chart::TimeUnit::YEAR:
1728                     aMaxDate = DateHelper::GetDateSomeYearsAway(aMaxDate,-1);
1729                     break;
1730                 }
1731                 rExplicitScale.Maximum = aMaxDate - rExplicitScale.NullDate;
1732             }
1733             else if( rExplicitScale.AxisType == ::com::sun::star::chart2::AxisType::CATEGORY )
1734                 rExplicitScale.Maximum -= 1.0;
1735             else if( rExplicitScale.AxisType == ::com::sun::star::chart2::AxisType::SERIES )
1736                 rExplicitScale.Maximum -= 1.0;
1737         }
1738         return sal_True;
1739     }
1740     return sal_False;
1741 }
1742 
getSdrPage()1743 SdrPage* ChartView::getSdrPage()
1744 {
1745     SdrPage* pPage=0;
1746     Reference< lang::XUnoTunnel> xUnoTunnel(m_xDrawPage,uno::UNO_QUERY);
1747     if(xUnoTunnel.is())
1748     {
1749         SvxDrawPage* pSvxDrawPage = reinterpret_cast<SvxDrawPage*>(xUnoTunnel->getSomething(
1750             SvxDrawPage::getUnoTunnelId() ));
1751         if(pSvxDrawPage)
1752         {
1753             pPage = pSvxDrawPage->GetSdrPage();
1754         }
1755     }
1756     return pPage;
1757 }
1758 
getShapeForCID(const rtl::OUString & rObjectCID)1759 uno::Reference< drawing::XShape > ChartView::getShapeForCID( const rtl::OUString& rObjectCID )
1760 {
1761     ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
1762     SdrObject* pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, this->getSdrPage() );
1763     if( pObj )
1764         return uno::Reference< drawing::XShape >( pObj->getUnoShape(), uno::UNO_QUERY);
1765     return 0;
1766 }
1767 
getDiagramRectangleExcludingAxes()1768 awt::Rectangle ChartView::getDiagramRectangleExcludingAxes()
1769 {
1770     impl_updateView();
1771     return m_aResultingDiagramRectangleExcludingAxes;
1772 }
1773 
getRectangleOfObject(const rtl::OUString & rObjectCID,bool bSnapRect)1774 awt::Rectangle ChartView::getRectangleOfObject( const rtl::OUString& rObjectCID, bool bSnapRect )
1775 {
1776     impl_updateView();
1777 
1778     awt::Rectangle aRet;
1779     uno::Reference< drawing::XShape > xShape( getShapeForCID(rObjectCID) );
1780     if(xShape.is())
1781     {
1782         //special handling for axis for old api:
1783         //same special handling for diagram
1784         ObjectType eObjectType( ObjectIdentifier::getObjectType( rObjectCID ) );
1785         if( eObjectType == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_DIAGRAM )
1786         {
1787             ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
1788             SvxShape* pRoot = SvxShape::getImplementation( xShape );
1789 	        if( pRoot )
1790             {
1791                 SdrObject* pRootSdrObject = pRoot->GetSdrObject();
1792                 if( pRootSdrObject )
1793                 {
1794                     SdrObjList* pRootList = pRootSdrObject->GetSubList();
1795                     if( pRootList )
1796                     {
1797                         OUString aShapeName = C2U("MarkHandles");
1798                         if( eObjectType == OBJECTTYPE_DIAGRAM )
1799                             aShapeName = C2U("PlotAreaIncludingAxes");
1800                         SdrObject* pShape = DrawModelWrapper::getNamedSdrObject( aShapeName, pRootList );
1801                         if( pShape )
1802                             xShape = uno::Reference< drawing::XShape >( pShape->getUnoShape(), uno::UNO_QUERY);
1803                     }
1804                 }
1805             }
1806         }
1807 
1808         awt::Size aSize( xShape->getSize() );
1809         awt::Point aPoint( xShape->getPosition() );
1810         aRet = awt::Rectangle( aPoint.X, aPoint.Y, aSize.Width, aSize.Height );
1811         if( bSnapRect )
1812         {
1813             //for rotated objects the shape size and position differs from the visible rectangle
1814             SvxShape* pShape = SvxShape::getImplementation( xShape );
1815 	        if( pShape )
1816             {
1817                 SdrObject* pSdrObject = pShape->GetSdrObject();
1818                 if( pSdrObject )
1819                 {
1820                     Rectangle aSnapRect( pSdrObject->GetSnapRect() );
1821                     aRet = awt::Rectangle(aSnapRect.Left(),aSnapRect.Top(),aSnapRect.GetWidth(),aSnapRect.GetHeight());
1822                 }
1823             }
1824         }
1825     }
1826     return aRet;
1827 }
1828 
getDrawModelWrapper()1829 ::boost::shared_ptr< DrawModelWrapper > ChartView::getDrawModelWrapper()
1830 {
1831     return m_pDrawModelWrapper;
1832 }
1833 
1834 namespace
1835 {
lcl_getDiagramTitleSpace()1836 sal_Int32 lcl_getDiagramTitleSpace()
1837 {
1838     return 200; //=0,2 cm spacing
1839 }
lcl_getPropertySwapXAndYAxis(const uno::Reference<XDiagram> & xDiagram)1840 bool lcl_getPropertySwapXAndYAxis( const uno::Reference< XDiagram >& xDiagram )
1841 {
1842     bool bSwapXAndY = false;
1843 
1844     uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY );
1845     if( xCooSysContainer.is() )
1846     {
1847         uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() );
1848         if( aCooSysList.getLength() )
1849         {
1850             uno::Reference<beans::XPropertySet> xProp(aCooSysList[0], uno::UNO_QUERY );
1851             if( xProp.is()) try
1852             {
1853                 xProp->getPropertyValue( C2U( "SwapXAndYAxis" ) ) >>= bSwapXAndY;
1854             }
1855             catch( uno::Exception& e )
1856             {
1857                 ASSERT_EXCEPTION( e );
1858             }
1859         }
1860     }
1861     return bSwapXAndY;
1862 }
1863 
1864 }
1865 
getExplicitNumberFormatKeyForAxis(const Reference<chart2::XAxis> & xAxis,const Reference<chart2::XCoordinateSystem> & xCorrespondingCoordinateSystem,const Reference<util::XNumberFormatsSupplier> & xNumberFormatsSupplier)1866 sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForAxis(
1867                   const Reference< chart2::XAxis >& xAxis
1868                 , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem
1869                 , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
1870 {
1871     return AxisHelper::getExplicitNumberFormatKeyForAxis( xAxis, xCorrespondingCoordinateSystem, xNumberFormatsSupplier
1872         , true /*bSearchForParallelAxisIfNothingIsFound*/ );
1873 }
1874 
getExplicitNumberFormatKeyForDataLabel(const uno::Reference<beans::XPropertySet> & xSeriesOrPointProp,const uno::Reference<XDataSeries> & xSeries,sal_Int32 nPointIndex,const uno::Reference<XDiagram> & xDiagram)1875 sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel(
1876         const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp,
1877         const uno::Reference< XDataSeries >& xSeries,
1878         sal_Int32 nPointIndex /*-1 for whole series*/,
1879         const uno::Reference< XDiagram >& xDiagram
1880         )
1881 {
1882     sal_Int32 nFormat=0;
1883     if( !xSeriesOrPointProp.is() )
1884         return nFormat;
1885 
1886     rtl::OUString aPropName( C2U( "NumberFormat" ) );
1887     if( !(xSeriesOrPointProp->getPropertyValue(aPropName) >>= nFormat) )
1888     {
1889         uno::Reference< chart2::XChartType > xChartType( DataSeriesHelper::getChartTypeOfSeries( xSeries, xDiagram ) );
1890 
1891         bool bFormatFound = false;
1892         if( ChartTypeHelper::shouldLabelNumberFormatKeyBeDetectedFromYAxis( xChartType ) )
1893         {
1894             uno::Reference< beans::XPropertySet > xAttachedAxisProps( DiagramHelper::getAttachedAxis( xSeries, xDiagram ), uno::UNO_QUERY );
1895             if( xAttachedAxisProps.is() && ( xAttachedAxisProps->getPropertyValue( aPropName ) >>= nFormat ) )
1896                 bFormatFound = true;
1897         }
1898         if( !bFormatFound )
1899         {
1900             Reference< chart2::data::XDataSource > xSeriesSource( xSeries, uno::UNO_QUERY );
1901             OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) );
1902 
1903             Reference< data::XLabeledDataSequence > xLabeledSequence(
1904                 DataSeriesHelper::getDataSequenceByRole( xSeriesSource, aRole, false ));
1905             if( xLabeledSequence.is() )
1906             {
1907                 Reference< data::XDataSequence > xValues( xLabeledSequence->getValues() );
1908                 if( xValues.is() )
1909                     nFormat = xValues->getNumberFormatKeyByIndex( nPointIndex );
1910             }
1911         }
1912     }
1913     if(nFormat<0)
1914         nFormat=0;
1915     return nFormat;
1916 }
1917 
getExplicitPercentageNumberFormatKeyForDataLabel(const uno::Reference<beans::XPropertySet> & xSeriesOrPointProp,const uno::Reference<util::XNumberFormatsSupplier> & xNumberFormatsSupplier)1918 sal_Int32 ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel(
1919         const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp,
1920         const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier )
1921 {
1922     sal_Int32 nFormat=0;
1923     if( !xSeriesOrPointProp.is() )
1924         return nFormat;
1925     if( !(xSeriesOrPointProp->getPropertyValue(C2U( "PercentageNumberFormat" )) >>= nFormat) )
1926     {
1927         nFormat = DiagramHelper::getPercentNumberFormat( xNumberFormatsSupplier );
1928     }
1929     if(nFormat<0)
1930         nFormat=0;
1931     return nFormat;
1932 }
1933 
addAxisTitleSizes(const Reference<frame::XModel> & xChartModel,const Reference<uno::XInterface> & xChartView,const awt::Rectangle & rExcludingPositionAndSize)1934 awt::Rectangle ExplicitValueProvider::addAxisTitleSizes(
1935             const Reference< frame::XModel >& xChartModel
1936             , const Reference< uno::XInterface >& xChartView
1937             , const awt::Rectangle& rExcludingPositionAndSize )
1938 {
1939     awt::Rectangle aRet(rExcludingPositionAndSize);
1940 
1941     //add axis title sizes to the diagram size
1942     uno::Reference< chart2::XTitle > xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, xChartModel ) );
1943     uno::Reference< chart2::XTitle > xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, xChartModel ) );
1944     uno::Reference< chart2::XTitle > xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xChartModel ) );
1945     uno::Reference< chart2::XTitle > xSecondTitle_Width( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xChartModel ) );
1946     if( xTitle_Height.is() || xTitle_Width.is() || xSecondTitle_Height.is() || xSecondTitle_Width.is() )
1947     {
1948         ExplicitValueProvider* pExplicitValueProvider = ExplicitValueProvider::getExplicitValueProvider(xChartView);
1949         if( pExplicitValueProvider )
1950         {
1951             //detect whether x axis points into x direction or not
1952             if( lcl_getPropertySwapXAndYAxis( ChartModelHelper::findDiagram( xChartModel ) ) )
1953             {
1954                 std::swap( xTitle_Height, xTitle_Width );
1955                 std::swap( xSecondTitle_Height, xSecondTitle_Width );
1956             }
1957 
1958             sal_Int32 nTitleSpaceWidth = 0;
1959             sal_Int32 nTitleSpaceHeight = 0;
1960             sal_Int32 nSecondTitleSpaceWidth = 0;
1961             sal_Int32 nSecondTitleSpaceHeight = 0;
1962 
1963             if( xTitle_Height.is() )
1964             {
1965                 rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height, xChartModel ) );
1966                 nTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
1967                 if( nTitleSpaceHeight )
1968                     nTitleSpaceHeight+=lcl_getDiagramTitleSpace();
1969             }
1970             if( xTitle_Width.is() )
1971             {
1972                 rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width, xChartModel ) );
1973                 nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
1974                 if(nTitleSpaceWidth)
1975                     nTitleSpaceWidth+=lcl_getDiagramTitleSpace();
1976             }
1977             if( xSecondTitle_Height.is() )
1978             {
1979                 rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height, xChartModel ) );
1980                 nSecondTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
1981                 if( nSecondTitleSpaceHeight )
1982                     nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace();
1983             }
1984             if( xSecondTitle_Width.is() )
1985             {
1986                 rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width, xChartModel ) );
1987                 nSecondTitleSpaceWidth += pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
1988                 if( nSecondTitleSpaceWidth )
1989                     nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace();
1990             }
1991 
1992             aRet.X -= nTitleSpaceWidth;
1993             aRet.Y -= nSecondTitleSpaceHeight;
1994             aRet.Width += nTitleSpaceWidth + nSecondTitleSpaceWidth;
1995             aRet.Height += nTitleSpaceHeight + nSecondTitleSpaceHeight;
1996         }
1997     }
1998     return aRet;
1999 }
2000 
substractAxisTitleSizes(const Reference<frame::XModel> & xChartModel,const Reference<uno::XInterface> & xChartView,const awt::Rectangle & rPositionAndSizeIncludingTitles)2001 awt::Rectangle ExplicitValueProvider::substractAxisTitleSizes(
2002             const Reference< frame::XModel >& xChartModel
2003             , const Reference< uno::XInterface >& xChartView
2004             , const awt::Rectangle& rPositionAndSizeIncludingTitles )
2005 {
2006     awt::Rectangle aRet(rPositionAndSizeIncludingTitles);
2007 
2008     //add axis title sizes to the diagram size
2009     uno::Reference< chart2::XTitle > xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, xChartModel ) );
2010     uno::Reference< chart2::XTitle > xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, xChartModel ) );
2011     uno::Reference< chart2::XTitle > xSecondTitle_Height( TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xChartModel ) );
2012     uno::Reference< chart2::XTitle > xSecondTitle_Width( TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xChartModel ) );
2013     if( xTitle_Height.is() || xTitle_Width.is() || xSecondTitle_Height.is() || xSecondTitle_Width.is() )
2014     {
2015         ExplicitValueProvider* pExplicitValueProvider = ExplicitValueProvider::getExplicitValueProvider(xChartView);
2016         if( pExplicitValueProvider )
2017         {
2018             //detect whether x axis points into x direction or not
2019             if( lcl_getPropertySwapXAndYAxis( ChartModelHelper::findDiagram( xChartModel ) ) )
2020             {
2021                 std::swap( xTitle_Height, xTitle_Width );
2022                 std::swap( xSecondTitle_Height, xSecondTitle_Width );
2023             }
2024 
2025             sal_Int32 nTitleSpaceWidth = 0;
2026             sal_Int32 nTitleSpaceHeight = 0;
2027             sal_Int32 nSecondTitleSpaceWidth = 0;
2028             sal_Int32 nSecondTitleSpaceHeight = 0;
2029 
2030             if( xTitle_Height.is() )
2031             {
2032                 rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height, xChartModel ) );
2033                 nTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
2034                 if( nTitleSpaceHeight )
2035                     nTitleSpaceHeight+=lcl_getDiagramTitleSpace();
2036             }
2037             if( xTitle_Width.is() )
2038             {
2039                 rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width, xChartModel ) );
2040                 nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
2041                 if(nTitleSpaceWidth)
2042                     nTitleSpaceWidth+=lcl_getDiagramTitleSpace();
2043             }
2044             if( xSecondTitle_Height.is() )
2045             {
2046                 rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Height, xChartModel ) );
2047                 nSecondTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height;
2048                 if( nSecondTitleSpaceHeight )
2049                     nSecondTitleSpaceHeight+=lcl_getDiagramTitleSpace();
2050             }
2051             if( xSecondTitle_Width.is() )
2052             {
2053                 rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xSecondTitle_Width, xChartModel ) );
2054                 nSecondTitleSpaceWidth += pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width;
2055                 if( nSecondTitleSpaceWidth )
2056                     nSecondTitleSpaceWidth+=lcl_getDiagramTitleSpace();
2057             }
2058 
2059             aRet.X += nTitleSpaceWidth;
2060             aRet.Y += nSecondTitleSpaceHeight;
2061             aRet.Width -= (nTitleSpaceWidth + nSecondTitleSpaceWidth);
2062             aRet.Height -= (nTitleSpaceHeight + nSecondTitleSpaceHeight);
2063         }
2064     }
2065     return aRet;
2066 }
2067 
lcl_getPageLayoutDistancePercentage()2068 double lcl_getPageLayoutDistancePercentage()
2069 {
2070     return 0.02;
2071 }
2072 
getAvailablePosAndSizeForDiagram(awt::Point & rOutPos,awt::Size & rOutAvailableDiagramSize,const awt::Rectangle & rSpaceLeft,const awt::Size & rPageSize,const uno::Reference<XDiagram> & xDiagram,bool & bUseFixedInnerSize)2073 bool getAvailablePosAndSizeForDiagram(
2074     awt::Point& rOutPos, awt::Size& rOutAvailableDiagramSize
2075     , const awt::Rectangle& rSpaceLeft
2076     , const awt::Size & rPageSize
2077     , const uno::Reference< XDiagram > & xDiagram
2078     , bool& bUseFixedInnerSize )
2079 {
2080     bUseFixedInnerSize = false;
2081 
2082     //@todo: we need a size dependent on the axis labels
2083     awt::Rectangle aRemainingSpace(rSpaceLeft);
2084     {
2085         sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
2086         sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
2087         aRemainingSpace.X+=nXDistance;
2088         aRemainingSpace.Width-=2*nXDistance;
2089         aRemainingSpace.Y+=nYDistance;
2090         aRemainingSpace.Height-=2*nYDistance;
2091     }
2092     if(aRemainingSpace.Width <= 0 || aRemainingSpace.Height <= 0 )
2093         return false;
2094 
2095     uno::Reference< beans::XPropertySet > xProp(xDiagram, uno::UNO_QUERY);
2096 
2097     bool bPosSizeExcludeAxes = false;
2098     if( xProp.is() )
2099         xProp->getPropertyValue( C2U( "PosSizeExcludeAxes" ) ) >>= bPosSizeExcludeAxes;
2100 
2101     //size:
2102     ::com::sun::star::chart2::RelativeSize aRelativeSize;
2103     if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativeSize" ) )>>=aRelativeSize) )
2104     {
2105         rOutAvailableDiagramSize.Height = static_cast<sal_Int32>(aRelativeSize.Secondary*rPageSize.Height);
2106         rOutAvailableDiagramSize.Width = static_cast<sal_Int32>(aRelativeSize.Primary*rPageSize.Width);
2107         bUseFixedInnerSize = bPosSizeExcludeAxes;
2108     }
2109     else
2110         rOutAvailableDiagramSize = awt::Size(aRemainingSpace.Width,aRemainingSpace.Height);
2111 
2112     //position:
2113     chart2::RelativePosition aRelativePosition;
2114     if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativePosition" ) )>>=aRelativePosition) )
2115     {
2116         //@todo decide whether x is primary or secondary
2117 
2118         //the coordinates re relative to the page
2119         double fX = aRelativePosition.Primary*rPageSize.Width;
2120         double fY = aRelativePosition.Secondary*rPageSize.Height;
2121 
2122         rOutPos = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject(
2123                     awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY))
2124                     , rOutAvailableDiagramSize, aRelativePosition.Anchor );
2125         bUseFixedInnerSize = bPosSizeExcludeAxes;
2126     }
2127     else
2128         rOutPos = awt::Point(aRemainingSpace.X,aRemainingSpace.Y);
2129 
2130     //ensure that the diagram does not lap out right side or out of bottom
2131     {
2132         if( rOutPos.Y + rOutAvailableDiagramSize.Height > rPageSize.Height )
2133             rOutAvailableDiagramSize.Height = rPageSize.Height - rOutPos.Y;
2134         if( rOutPos.X + rOutAvailableDiagramSize.Width > rPageSize.Width )
2135             rOutAvailableDiagramSize.Width = rPageSize.Width - rOutPos.X;
2136     }
2137 
2138     return true;
2139 }
2140 
2141 enum TitleAlignment { ALIGN_LEFT, ALIGN_TOP, ALIGN_RIGHT, ALIGN_BOTTOM, ALIGN_Z };
2142 
changePositionOfAxisTitle(VTitle * pVTitle,TitleAlignment eAlignment,awt::Rectangle & rDiagramPlusAxesRect,const awt::Size & rPageSize)2143 void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment
2144                                , awt::Rectangle& rDiagramPlusAxesRect, const awt::Size & rPageSize )
2145 {
2146     if(!pVTitle)
2147         return;
2148 
2149     awt::Point aNewPosition(0,0);
2150     awt::Size aTitleSize = pVTitle->getFinalSize();
2151     sal_Int32 nYDistance = static_cast<sal_Int32>(rPageSize.Height*lcl_getPageLayoutDistancePercentage());
2152     sal_Int32 nXDistance = static_cast<sal_Int32>(rPageSize.Width*lcl_getPageLayoutDistancePercentage());
2153     switch( eAlignment )
2154     {
2155     case ALIGN_TOP:
2156         aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
2157                                     , rDiagramPlusAxesRect.Y - aTitleSize.Height/2  - nYDistance );
2158         break;
2159     case ALIGN_BOTTOM:
2160         aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width/2
2161                                     , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height + aTitleSize.Height/2  + nYDistance );
2162         break;
2163     case ALIGN_LEFT:
2164         aNewPosition = awt::Point( rDiagramPlusAxesRect.X - aTitleSize.Width/2 - nXDistance
2165                                     , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
2166         break;
2167     case ALIGN_RIGHT:
2168         aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
2169                                     , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height/2 );
2170         break;
2171     case ALIGN_Z:
2172         aNewPosition = awt::Point( rDiagramPlusAxesRect.X + rDiagramPlusAxesRect.Width + aTitleSize.Width/2 + nXDistance
2173                                     , rDiagramPlusAxesRect.Y + rDiagramPlusAxesRect.Height - aTitleSize.Height/2 );
2174        break;
2175     default:
2176         break;
2177     }
2178 
2179     sal_Int32 nMaxY = rPageSize.Height - aTitleSize.Height/2;
2180     sal_Int32 nMaxX = rPageSize.Width - aTitleSize.Width/2;
2181     sal_Int32 nMinX = aTitleSize.Width/2;
2182     sal_Int32 nMinY = aTitleSize.Height/2;
2183     if( aNewPosition.Y > nMaxY )
2184         aNewPosition.Y = nMaxY;
2185     if( aNewPosition.X > nMaxX )
2186         aNewPosition.X = nMaxX;
2187     if( aNewPosition.Y < nMinY )
2188         aNewPosition.Y = nMinY;
2189     if( aNewPosition.X < nMinX )
2190         aNewPosition.X = nMinX;
2191 
2192     pVTitle->changePosition( aNewPosition );
2193 }
2194 
lcl_createTitle(TitleHelper::eTitleType eType,const uno::Reference<drawing::XShapes> & xPageShapes,const uno::Reference<lang::XMultiServiceFactory> & xShapeFactory,const uno::Reference<frame::XModel> & xChartModel,awt::Rectangle & rRemainingSpace,const awt::Size & rPageSize,TitleAlignment eAlignment,bool & rbAutoPosition)2195 std::auto_ptr<VTitle> lcl_createTitle( TitleHelper::eTitleType eType
2196                 , const uno::Reference< drawing::XShapes>& xPageShapes
2197                 , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
2198                 , const uno::Reference< frame::XModel >& xChartModel
2199                 , awt::Rectangle& rRemainingSpace
2200                 , const awt::Size & rPageSize
2201                 , TitleAlignment eAlignment
2202                 , bool& rbAutoPosition )
2203 {
2204     std::auto_ptr<VTitle> apVTitle;
2205 
2206     // #i109336# Improve auto positioning in chart
2207     double fPercentage = lcl_getPageLayoutDistancePercentage();
2208     sal_Int32 nXDistance = static_cast< sal_Int32 >( rPageSize.Width * fPercentage );
2209     sal_Int32 nYDistance = static_cast< sal_Int32 >( rPageSize.Height * fPercentage );
2210     if ( eType == TitleHelper::MAIN_TITLE )
2211     {
2212         sal_Int32 nYOffset = 135;  // 1/100 mm
2213         nYDistance += nYOffset;
2214     }
2215     else if ( eType == TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION )
2216     {
2217         sal_Int32 nYOffset = 420;  // 1/100 mm
2218         nYDistance = nYOffset;
2219     }
2220     else if ( eType == TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION )
2221     {
2222         sal_Int32 nXOffset = 450;  // 1/100 mm
2223         nXDistance = nXOffset;
2224     }
2225 
2226     uno::Reference< XTitle > xTitle( TitleHelper::getTitle( eType, xChartModel ) );
2227     rtl::OUString aCompleteString( TitleHelper::getCompleteString( xTitle ) );
2228     if( !aCompleteString.isEmpty() )
2229     {
2230         //create title
2231         apVTitle = std::auto_ptr<VTitle>(new VTitle(xTitle));
2232         rtl::OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle, xChartModel ) );
2233         apVTitle->init(xPageShapes,xShapeFactory,aCID);
2234         apVTitle->createShapes( awt::Point(0,0), rPageSize );
2235         awt::Size aTitleUnrotatedSize = apVTitle->getUnrotatedSize();
2236         awt::Size aTitleSize = apVTitle->getFinalSize();
2237 
2238         //position
2239         rbAutoPosition=true;
2240         awt::Point aNewPosition(0,0);
2241         chart2::RelativePosition aRelativePosition;
2242         uno::Reference< beans::XPropertySet > xProp(xTitle, uno::UNO_QUERY);
2243         if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativePosition" ) )>>=aRelativePosition) )
2244         {
2245             rbAutoPosition = false;
2246 
2247             //@todo decide whether x is primary or secondary
2248             double fX = aRelativePosition.Primary*rPageSize.Width;
2249             double fY = aRelativePosition.Secondary*rPageSize.Height;
2250 
2251             double fAnglePi = apVTitle->getRotationAnglePi();
2252             aNewPosition = RelativePositionHelper::getCenterOfAnchoredObject(
2253                     awt::Point(static_cast<sal_Int32>(fX),static_cast<sal_Int32>(fY))
2254                     , aTitleUnrotatedSize, aRelativePosition.Anchor, fAnglePi );
2255         }
2256         else //auto position
2257         {
2258             switch( eAlignment )
2259             {
2260             case ALIGN_TOP:
2261                 aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
2262                                          , rRemainingSpace.Y + aTitleSize.Height/2 + nYDistance );
2263                 break;
2264             case ALIGN_BOTTOM:
2265                 aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width/2
2266                                          , rRemainingSpace.Y + rRemainingSpace.Height - aTitleSize.Height/2 - nYDistance );
2267                 break;
2268             case ALIGN_LEFT:
2269                 aNewPosition = awt::Point( rRemainingSpace.X + aTitleSize.Width/2 + nXDistance
2270                                          , rRemainingSpace.Y + rRemainingSpace.Height/2 );
2271                 break;
2272             case ALIGN_RIGHT:
2273                 aNewPosition = awt::Point( rRemainingSpace.X + rRemainingSpace.Width - aTitleSize.Width/2 - nXDistance
2274                                          , rRemainingSpace.Y + rRemainingSpace.Height/2 );
2275                 break;
2276             default:
2277                 break;
2278 
2279             }
2280         }
2281         apVTitle->changePosition( aNewPosition );
2282 
2283         //remaining space
2284         switch( eAlignment )
2285         {
2286             case ALIGN_TOP:
2287                 rRemainingSpace.Y += ( aTitleSize.Height + nYDistance );
2288                 rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
2289                 break;
2290             case ALIGN_BOTTOM:
2291                 rRemainingSpace.Height -= ( aTitleSize.Height + nYDistance );
2292                 break;
2293             case ALIGN_LEFT:
2294                 rRemainingSpace.X += ( aTitleSize.Width + nXDistance );
2295                 rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
2296                 break;
2297             case ALIGN_RIGHT:
2298                 rRemainingSpace.Width -= ( aTitleSize.Width + nXDistance );
2299                 break;
2300             default:
2301                 break;
2302         }
2303     }
2304     else
2305     {
2306         // #i109336# Improve auto positioning in chart
2307         switch ( eAlignment )
2308         {
2309             case ALIGN_TOP:
2310                 {
2311                     rRemainingSpace.Y += nYDistance;
2312                     rRemainingSpace.Height -= nYDistance;
2313                 }
2314                 break;
2315             case ALIGN_BOTTOM:
2316                 {
2317                     rRemainingSpace.Height -= nYDistance;
2318                 }
2319                 break;
2320             case ALIGN_LEFT:
2321                 {
2322                     rRemainingSpace.X += nXDistance;
2323                     rRemainingSpace.Width -= nXDistance;
2324                 }
2325                 break;
2326             case ALIGN_RIGHT:
2327                 {
2328                     rRemainingSpace.Width -= nXDistance;
2329                 }
2330                 break;
2331             default:
2332                 break;
2333         }
2334     }
2335     return apVTitle;
2336 }
2337 
lcl_createLegend(const uno::Reference<XLegend> & xLegend,const uno::Reference<drawing::XShapes> & xPageShapes,const uno::Reference<lang::XMultiServiceFactory> & xShapeFactory,const uno::Reference<uno::XComponentContext> & xContext,awt::Rectangle & rRemainingSpace,const awt::Size & rPageSize,const uno::Reference<frame::XModel> & xModel,const std::vector<LegendEntryProvider * > & rLegendEntryProviderList,sal_Int16 nDefaultWritingMode)2338 bool lcl_createLegend( const uno::Reference< XLegend > & xLegend
2339                    , const uno::Reference< drawing::XShapes>& xPageShapes
2340                    , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
2341                    , const uno::Reference< uno::XComponentContext > & xContext
2342                    , awt::Rectangle & rRemainingSpace
2343                    , const awt::Size & rPageSize
2344                    , const uno::Reference< frame::XModel > & xModel
2345                    , const std::vector< LegendEntryProvider* >& rLegendEntryProviderList
2346                    , sal_Int16 nDefaultWritingMode )
2347 {
2348     if( VLegend::isVisible( xLegend ))
2349     {
2350         VLegend aVLegend( xLegend, xContext, rLegendEntryProviderList );
2351         aVLegend.init( xPageShapes, xShapeFactory, xModel );
2352         aVLegend.setDefaultWritingMode( nDefaultWritingMode );
2353         aVLegend.createShapes( awt::Size( rRemainingSpace.Width, rRemainingSpace.Height ),
2354                                rPageSize );
2355         aVLegend.changePosition( rRemainingSpace, rPageSize );
2356         return true;
2357     }
2358     return false;
2359 }
2360 
formatPage(const uno::Reference<frame::XModel> & xModel,const awt::Size rPageSize,const uno::Reference<drawing::XShapes> & xTarget,const uno::Reference<lang::XMultiServiceFactory> & xShapeFactory)2361 void formatPage(
2362       const uno::Reference< frame::XModel > & xModel
2363     , const awt::Size rPageSize
2364     , const uno::Reference< drawing::XShapes >& xTarget
2365     , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory
2366     )
2367 {
2368     try
2369     {
2370         uno::Reference< XChartDocument > xChartDoc( xModel, uno::UNO_QUERY );
2371         OSL_ASSERT( xChartDoc.is());
2372         if( ! xChartDoc.is())
2373             return;
2374         uno::Reference< beans::XPropertySet > xModelPage( xChartDoc->getPageBackground());
2375         if( ! xModelPage.is())
2376             return;
2377 
2378 
2379         if( !xShapeFactory.is() )
2380             return;
2381 
2382         uno::Reference< beans::XPropertySet > xPageProp;
2383         // create a shape for the background
2384         {
2385             uno::Reference< drawing::XShape > xShape(
2386                 xShapeFactory->createInstance(
2387                     C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY );
2388             if( xTarget.is() &&
2389                 xShape.is())
2390             {
2391                 xTarget->add( xShape );
2392                 xShape->setSize( rPageSize );
2393                 xPageProp.set( xShape, uno::UNO_QUERY );
2394                 if( xPageProp.is())
2395                 {
2396                     xPageProp->setPropertyValue( C2U("LineStyle"), uno::makeAny( drawing::LineStyle_NONE ));
2397                 }
2398             }
2399         }
2400 
2401         //format page
2402         if( xPageProp.is())
2403         {
2404             tPropertyNameValueMap aNameValueMap;
2405             PropertyMapper::getValueMap( aNameValueMap, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xModelPage );
2406 
2407             rtl::OUString aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, rtl::OUString() ) );
2408             aNameValueMap.insert( tPropertyNameValueMap::value_type( C2U("Name"), uno::makeAny( aCID ) ) ); //CID rtl::OUString
2409 
2410             tNameSequence aNames;
2411             tAnySequence aValues;
2412             PropertyMapper::getMultiPropertyListsFromValueMap( aNames, aValues, aNameValueMap );
2413             PropertyMapper::setMultiProperties( aNames, aValues, xPageProp );
2414         }
2415     }
2416     catch( uno::Exception & ex )
2417     {
2418         ASSERT_EXCEPTION( ex );
2419     }
2420 }
2421 
lcl_removeEmptyGroupShapes(const Reference<drawing::XShapes> & xParent)2422 void lcl_removeEmptyGroupShapes( const Reference< drawing::XShapes>& xParent )
2423 {
2424     if(!xParent.is())
2425         return;
2426     Reference< drawing::XShapeGroup > xParentGroup( xParent, uno::UNO_QUERY );
2427     if( !xParentGroup.is() )
2428     {
2429         Reference< drawing::XDrawPage > xPage( xParent, uno::UNO_QUERY );
2430         if( !xPage.is() )
2431             return;
2432     }
2433 
2434     //iterate from back!
2435     for( sal_Int32 nN = xParent->getCount(); nN--; )
2436     {
2437         uno::Any aAny = xParent->getByIndex( nN );
2438         Reference< drawing::XShapes> xShapes(0);
2439         if( aAny >>= xShapes )
2440             lcl_removeEmptyGroupShapes( xShapes );
2441         if( xShapes.is() && xShapes->getCount()==0 )
2442         {
2443             //remove empty group shape
2444             Reference< drawing::XShapeGroup > xGroup( xShapes, uno::UNO_QUERY );
2445             Reference< drawing::XShape > xShape( xShapes, uno::UNO_QUERY );
2446             if( xGroup.is() )
2447                 xParent->remove( xShape );
2448         }
2449     }
2450 }
2451 
impl_AddInDrawsAllByItself()2452 bool ChartView::impl_AddInDrawsAllByItself()
2453 {
2454     bool bRet = false;
2455     /*
2456     uno::Reference< beans::XPropertySet > xProp( m_xChartModel, uno::UNO_QUERY );
2457     if( xProp.is()) try
2458     {
2459         uno::Reference< util::XRefreshable > xAddIn;
2460         xProp->getPropertyValue( C2U( "AddIn" ) ) >>= xAddIn;
2461         if( xAddIn.is() )
2462         {
2463             rtl::OUString aBaseDiagram;
2464             xProp->getPropertyValue( C2U( "BaseDiagram" ) ) >>= aBaseDiagram;
2465             if(aBaseDiagram.getLength())
2466                 bRet = true;
2467         }
2468     }
2469     catch( uno::Exception& e )
2470     {
2471         ASSERT_EXCEPTION( e );
2472     }
2473     */
2474     return bRet;
2475 }
2476 
impl_refreshAddIn()2477 void ChartView::impl_refreshAddIn()
2478 {
2479     if( !m_bRefreshAddIn )
2480         return;
2481 
2482     uno::Reference< beans::XPropertySet > xProp( m_xChartModel, uno::UNO_QUERY );
2483     if( xProp.is()) try
2484     {
2485         uno::Reference< util::XRefreshable > xAddIn;
2486         xProp->getPropertyValue( C2U( "AddIn" ) ) >>= xAddIn;
2487         if( xAddIn.is() )
2488         {
2489             sal_Bool bRefreshAddInAllowed = sal_True;
2490             xProp->getPropertyValue( C2U( "RefreshAddInAllowed" ) ) >>= bRefreshAddInAllowed;
2491             if( bRefreshAddInAllowed )
2492                 xAddIn->refresh();
2493         }
2494     }
2495     catch( uno::Exception& e )
2496     {
2497         ASSERT_EXCEPTION( e );
2498     }
2499 }
2500 
createShapes()2501 void ChartView::createShapes()
2502 {
2503 #if OSL_DEBUG_LEVEL > 0
2504     clock_t nStart = clock();
2505     OSL_TRACE( "\nPPPPPPPPP>>>>>>>>>>>> chart view :: createShapes()" );
2506 #endif
2507 
2508     //make sure add-in is refreshed after creating the shapes
2509     const ::comphelper::ScopeGuard aGuard( boost::bind( &ChartView::impl_refreshAddIn, this ) );
2510     if( impl_AddInDrawsAllByItself() )
2511         return;
2512 
2513     m_aResultingDiagramRectangleExcludingAxes = awt::Rectangle(0,0,0,0);
2514     impl_deleteCoordinateSystems();
2515     if( m_pDrawModelWrapper )
2516     {
2517         // /--
2518         ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
2519         // #i12587# support for shapes in chart
2520         m_pDrawModelWrapper->getSdrModel().EnableUndo( sal_False );
2521         m_pDrawModelWrapper->clearMainDrawPage();
2522         // \--
2523     }
2524 
2525     lcl_setDefaultWritingMode( m_pDrawModelWrapper, m_xChartModel );
2526 
2527     awt::Size aPageSize = ChartModelHelper::getPageSize( m_xChartModel );
2528 
2529     uno::Reference<drawing::XShapes> xPageShapes( ShapeFactory(m_xShapeFactory)
2530         .getOrCreateChartRootShape( m_xDrawPage ) );
2531 
2532     SdrPage* pPage = ChartView::getSdrPage();
2533     if(pPage) //it is necessary to use the implementation here as the uno page does not provide a propertyset
2534         pPage->SetSize(Size(aPageSize.Width,aPageSize.Height));
2535     else
2536     {
2537         DBG_ERROR("could not set page size correctly");
2538     }
2539 
2540     {
2541         ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
2542 
2543         //------------ apply fill properties to page
2544         // todo: it would be nicer to just pass the page m_xDrawPage and format it,
2545         // but the draw page does not support XPropertySet
2546         formatPage( m_xChartModel, aPageSize, xPageShapes, m_xShapeFactory );
2547 
2548         //sal_Int32 nYDistance = static_cast<sal_Int32>(aPageSize.Height*lcl_getPageLayoutDistancePercentage());
2549         awt::Rectangle aRemainingSpace( 0, 0, aPageSize.Width, aPageSize.Height );
2550 
2551         //create the group shape for diagram and axes first to have title and legends on top of it
2552         uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) );
2553         rtl::OUString aDiagramCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, rtl::OUString::valueOf( sal_Int32(0) ) ) );//todo: other index if more than one diagram is possible
2554         uno::Reference< drawing::XShapes > xDiagramPlusAxesPlusMarkHandlesGroup_Shapes( ShapeFactory(m_xShapeFactory).createGroup2D(xPageShapes,aDiagramCID) );
2555 
2556         uno::Reference< drawing::XShape > xDiagram_MarkHandles( ShapeFactory(m_xShapeFactory).createInvisibleRectangle(
2557                     xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0,0) ) );
2558         ShapeFactory::setShapeName( xDiagram_MarkHandles, C2U("MarkHandles") );
2559 
2560         uno::Reference< drawing::XShape > xDiagram_OuterRect( ShapeFactory(m_xShapeFactory).createInvisibleRectangle(
2561                     xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0,0) ) );
2562         ShapeFactory::setShapeName( xDiagram_OuterRect, C2U("PlotAreaIncludingAxes") );
2563 
2564         uno::Reference< drawing::XShapes > xDiagramPlusAxes_Shapes( ShapeFactory(m_xShapeFactory).createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes ) );
2565 
2566         //------------ create some titles
2567         std::auto_ptr<VTitle> apVTitle(0);
2568         bool bAutoPositionDummy = true;
2569 
2570         //------------ create main title shape
2571         lcl_createTitle( TitleHelper::MAIN_TITLE, xPageShapes, m_xShapeFactory, m_xChartModel
2572                     , aRemainingSpace, aPageSize, ALIGN_TOP, bAutoPositionDummy );
2573         if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2574             return;
2575 
2576         //------------ create sub title shape
2577         lcl_createTitle( TitleHelper::SUB_TITLE, xPageShapes, m_xShapeFactory, m_xChartModel
2578                     , aRemainingSpace, aPageSize, ALIGN_TOP, bAutoPositionDummy );
2579         if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2580             return;
2581 
2582 
2583         //------------ prepare series to give input to the legend (create categories and symbols etc.)
2584         SeriesPlotterContainer aSeriesPlotterContainer( m_aVCooSysList );
2585         aSeriesPlotterContainer.initializeCooSysAndSeriesPlotter( m_xChartModel );
2586 
2587         //------------ create legend
2588         lcl_createLegend( LegendHelper::getLegend( m_xChartModel ), xPageShapes, m_xShapeFactory, m_xCC
2589                     , aRemainingSpace, aPageSize, m_xChartModel, aSeriesPlotterContainer.getLegendEntryProviderList()
2590                     , lcl_getDefaultWritingModeFromPool( m_pDrawModelWrapper ) );
2591         if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2592             return;
2593 
2594         Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
2595         sal_Int32 nDimension = DiagramHelper::getDimension( xDiagram );
2596 
2597         //------------ create x axis title
2598         bool bAutoPosition_XTitle = true;
2599         std::auto_ptr<VTitle> apVTitle_X;
2600         if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 0 ) )
2601             apVTitle_X = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, xPageShapes, m_xShapeFactory, m_xChartModel
2602                     , aRemainingSpace, aPageSize, ALIGN_BOTTOM, bAutoPosition_XTitle );
2603         if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2604             return;
2605 
2606         //------------ create y axis title
2607         bool bAutoPosition_YTitle = true;
2608         std::auto_ptr<VTitle> apVTitle_Y;
2609         if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 1 ) )
2610             apVTitle_Y = lcl_createTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, xPageShapes, m_xShapeFactory, m_xChartModel
2611                     , aRemainingSpace, aPageSize, ALIGN_LEFT, bAutoPosition_YTitle );
2612         if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2613             return;
2614 
2615         //------------ create z axis title
2616         bool bAutoPosition_ZTitle = true;
2617         std::auto_ptr<VTitle> apVTitle_Z;
2618         if( ChartTypeHelper::isSupportingMainAxis( xChartType, nDimension, 2 ) )
2619             apVTitle_Z = lcl_createTitle( TitleHelper::Z_AXIS_TITLE, xPageShapes, m_xShapeFactory, m_xChartModel
2620                     , aRemainingSpace, aPageSize, ALIGN_RIGHT, bAutoPosition_ZTitle );
2621         if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2622             return;
2623 
2624         bool bDummy = false;
2625         bool bIsVertical = DiagramHelper::getVertical( xDiagram, bDummy, bDummy );
2626 
2627         //------------ create secondary x axis title
2628         bool bAutoPosition_SecondXTitle = true;
2629         std::auto_ptr<VTitle> apVTitle_SecondX;
2630         if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension, 0 ) )
2631             apVTitle_SecondX = lcl_createTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xPageShapes, m_xShapeFactory, m_xChartModel
2632                     , aRemainingSpace, aPageSize, bIsVertical? ALIGN_RIGHT : ALIGN_TOP, bAutoPosition_SecondXTitle );
2633         if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2634             return;
2635 
2636         //------------ create secondary y axis title
2637         bool bAutoPosition_SecondYTitle = true;
2638         std::auto_ptr<VTitle> apVTitle_SecondY;
2639         if( ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimension, 1 ) )
2640             apVTitle_SecondY = lcl_createTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xPageShapes, m_xShapeFactory, m_xChartModel
2641                     , aRemainingSpace, aPageSize, bIsVertical? ALIGN_TOP : ALIGN_RIGHT, bAutoPosition_SecondYTitle );
2642         if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0)
2643             return;
2644 
2645         //------------ create complete diagram shape (inclusive axis and series)
2646         awt::Point aAvailablePosDia;
2647         awt::Size  aAvailableSizeForDiagram;
2648         bool bUseFixedInnerSize = false;
2649         if( getAvailablePosAndSizeForDiagram( aAvailablePosDia, aAvailableSizeForDiagram, aRemainingSpace, aPageSize
2650             , ChartModelHelper::findDiagram( m_xChartModel ), bUseFixedInnerSize ) )
2651         {
2652             awt::Rectangle aUsedOuterRect = impl_createDiagramAndContent( aSeriesPlotterContainer
2653                         , xDiagramPlusAxes_Shapes
2654                         , aAvailablePosDia ,aAvailableSizeForDiagram, aPageSize, bUseFixedInnerSize, xDiagram_MarkHandles );
2655 
2656             if( xDiagram_OuterRect.is() )
2657             {
2658                 xDiagram_OuterRect->setPosition( awt::Point( aUsedOuterRect.X, aUsedOuterRect.Y ) );
2659                 xDiagram_OuterRect->setSize( awt::Size( aUsedOuterRect.Width, aUsedOuterRect.Height ) );
2660             }
2661 
2662             //correct axis title position
2663             awt::Rectangle aDiagramPlusAxesRect( aUsedOuterRect );
2664             if(bAutoPosition_XTitle)
2665                 changePositionOfAxisTitle( apVTitle_X.get(), ALIGN_BOTTOM, aDiagramPlusAxesRect, aPageSize );
2666             if(bAutoPosition_YTitle)
2667                 changePositionOfAxisTitle( apVTitle_Y.get(), ALIGN_LEFT, aDiagramPlusAxesRect, aPageSize );
2668             if(bAutoPosition_ZTitle)
2669                 changePositionOfAxisTitle( apVTitle_Z.get(), ALIGN_Z, aDiagramPlusAxesRect, aPageSize );
2670             if(bAutoPosition_SecondXTitle)
2671                 changePositionOfAxisTitle( apVTitle_SecondX.get(), bIsVertical? ALIGN_RIGHT : ALIGN_TOP, aDiagramPlusAxesRect, aPageSize );
2672             if(bAutoPosition_SecondYTitle)
2673                 changePositionOfAxisTitle( apVTitle_SecondY.get(), bIsVertical? ALIGN_TOP : ALIGN_RIGHT, aDiagramPlusAxesRect, aPageSize );
2674         }
2675 
2676         //cleanup: remove all empty group shapes to avoid grey border lines:
2677         lcl_removeEmptyGroupShapes( xPageShapes );
2678     }
2679 
2680     // #i12587# support for shapes in chart
2681     if ( m_pDrawModelWrapper )
2682     {
2683         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
2684         m_pDrawModelWrapper->getSdrModel().EnableUndo( sal_True );
2685     }
2686 
2687 #if OSL_DEBUG_LEVEL > 0
2688     clock_t nEnd = clock();
2689     double fDuration =(double(nEnd-nStart)*1000.0)/double(CLOCKS_PER_SEC);
2690 
2691     OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< chart view :: createShapes():: needed %f msec", fDuration );
2692 #endif
2693 }
2694 
2695 //-----------------------------------------------------------------
2696 // util::XEventListener (base of XCloseListener)
2697 //-----------------------------------------------------------------
disposing(const lang::EventObject &)2698 void SAL_CALL ChartView::disposing( const lang::EventObject& /* rSource */ )
2699 		throw(uno::RuntimeException)
2700 {
2701     impl_setChartModel( 0 );
2702 }
2703 
impl_updateView()2704 void ChartView::impl_updateView()
2705 {
2706     if( !m_xChartModel.is() || !m_pDrawModelWrapper )
2707         return;
2708 
2709     // #i12587# support for shapes in chart
2710     if ( m_bSdrViewIsInEditMode )
2711     {
2712         return;
2713     }
2714 
2715     if( m_bViewDirty && !m_bInViewUpdate )
2716     {
2717         m_bInViewUpdate = true;
2718         //bool bOldRefreshAddIn = m_bRefreshAddIn;
2719         //m_bRefreshAddIn = false;
2720         try
2721 	    {
2722 		    impl_notifyModeChangeListener(C2U("invalid"));
2723 
2724 		    //prepare draw model
2725             {
2726                 // /--
2727                 ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
2728                 m_pDrawModelWrapper->lockControllers();
2729                 // \--
2730             }
2731 
2732 		    //create chart view
2733 		    {
2734                 m_bViewDirty = false;
2735                 m_bViewUpdatePending = false;
2736 			    createShapes();
2737 
2738 			    if( m_bViewDirty )
2739 			    {
2740 				    //avoid recursions due to add-in
2741 				    m_bRefreshAddIn = false;
2742                     m_bViewDirty = false;
2743                     m_bViewUpdatePending = false;
2744 				    //delete old chart view
2745 				    createShapes();
2746 				    m_bRefreshAddIn = true;
2747 			    }
2748 		    }
2749 
2750             m_bViewDirty = m_bViewUpdatePending;
2751 		    m_bViewUpdatePending = false;
2752 		    m_bInViewUpdate = false;
2753 	    }
2754 	    catch( uno::Exception& ex)
2755 	    {
2756 		    m_bViewDirty = m_bViewUpdatePending;
2757 		    m_bViewUpdatePending = false;
2758 		    m_bInViewUpdate = false;
2759 		    ASSERT_EXCEPTION( ex );
2760 	    }
2761 
2762         {
2763             // /--
2764             ::vos::OGuard aSolarGuard( Application::GetSolarMutex());
2765             m_pDrawModelWrapper->unlockControllers();
2766             // \--
2767         }
2768 
2769 	    impl_notifyModeChangeListener(C2U("valid"));
2770 
2771         //m_bRefreshAddIn = bOldRefreshAddIn;
2772     }
2773 }
2774 
2775 // ____ XModifyListener ____
modified(const lang::EventObject &)2776 void SAL_CALL ChartView::modified( const lang::EventObject& /* aEvent */ )
2777     throw (uno::RuntimeException)
2778 {
2779     m_bViewDirty = sal_True;
2780     if( m_bInViewUpdate )
2781         m_bViewUpdatePending = true;
2782 
2783     impl_notifyModeChangeListener(C2U("dirty"));
2784 }
2785 
2786 //SfxListener
Notify(SfxBroadcaster &,const SfxHint & rHint)2787 void ChartView::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
2788 {
2789     //#i77362 change notification for changes on additional shapes are missing
2790     if( m_bInViewUpdate )
2791         return;
2792 
2793     // #i12587# support for shapes in chart
2794     if ( m_bSdrViewIsInEditMode && m_xChartModel.is() )
2795     {
2796         uno::Reference< view::XSelectionSupplier > xSelectionSupplier( m_xChartModel->getCurrentController(), uno::UNO_QUERY );
2797         if ( xSelectionSupplier.is() )
2798         {
2799             ::rtl::OUString aSelObjCID;
2800             uno::Any aSelObj( xSelectionSupplier->getSelection() );
2801             aSelObj >>= aSelObjCID;
2802             if ( !aSelObjCID.isEmpty() )
2803             {
2804                 return;
2805             }
2806         }
2807     }
2808 
2809     const SdrHint* pSdrHint = dynamic_cast< const SdrHint* >(&rHint);
2810     if( !pSdrHint )
2811         return;
2812 
2813     bool bShapeChanged = false;
2814     switch( pSdrHint->GetKind() )
2815 	{
2816  		case HINT_OBJCHG:
2817 			bShapeChanged = true;
2818 			break;
2819 		case HINT_OBJINSERTED:
2820 			bShapeChanged = true;
2821 			break;
2822 		case HINT_OBJREMOVED:
2823 			bShapeChanged = true;
2824 			break;
2825 		case HINT_MODELCLEARED:
2826 			bShapeChanged = true;
2827 			break;
2828         case HINT_ENDEDIT:
2829             bShapeChanged = true;
2830             break;
2831         default:
2832             break;
2833 	}
2834 
2835     if(bShapeChanged)
2836     {
2837         //#i76053# do not send view modified notifications for changes on the hidden page which contains e.g. the symbols for the dialogs
2838         if( ChartView::getSdrPage() != pSdrHint->GetPage() )
2839             bShapeChanged=false;
2840     }
2841 
2842     if(!bShapeChanged)
2843         return;
2844 
2845     Reference< util::XModifiable > xModifiable( m_xChartModel, uno::UNO_QUERY );
2846     if( xModifiable.is() )
2847         xModifiable->setModified( sal_True );
2848 }
2849 
impl_notifyModeChangeListener(const rtl::OUString & rNewMode)2850 void ChartView::impl_notifyModeChangeListener( const rtl::OUString& rNewMode )
2851 {
2852     try
2853     {
2854 	    ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer
2855 		    .getContainer( ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0) );
2856 	    if( pIC )
2857 	    {
2858             util::ModeChangeEvent aEvent( static_cast< uno::XWeak* >( this ), rNewMode );
2859             ::cppu::OInterfaceIteratorHelper aIt( *pIC );
2860             while( aIt.hasMoreElements() )
2861             {
2862                 uno::Reference< util::XModeChangeListener > xListener( aIt.next(), uno::UNO_QUERY );
2863                 if( xListener.is() )
2864                     xListener->modeChanged( aEvent );
2865             }
2866 	    }
2867     }
2868     catch( uno::Exception& ex)
2869     {
2870         ASSERT_EXCEPTION( ex );
2871     }
2872 }
2873 
2874 // ____ XModeChangeBroadcaster ____
2875 
addModeChangeListener(const uno::Reference<util::XModeChangeListener> & xListener)2876 void SAL_CALL ChartView::addModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
2877     throw (uno::RuntimeException)
2878 {
2879     m_aListenerContainer.addInterface(
2880         ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0), xListener );
2881 }
removeModeChangeListener(const uno::Reference<util::XModeChangeListener> & xListener)2882 void SAL_CALL ChartView::removeModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener )
2883     throw (uno::RuntimeException)
2884 {
2885     m_aListenerContainer.removeInterface(
2886         ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0), xListener );
2887 }
addModeChangeApproveListener(const uno::Reference<util::XModeChangeApproveListener> &)2888 void SAL_CALL ChartView::addModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
2889     throw (lang::NoSupportException, uno::RuntimeException)
2890 {
2891 
2892 }
removeModeChangeApproveListener(const uno::Reference<util::XModeChangeApproveListener> &)2893 void SAL_CALL ChartView::removeModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& /* _rxListener */ )
2894     throw (lang::NoSupportException, uno::RuntimeException)
2895 {
2896 
2897 }
2898 
2899 // ____ XUpdatable ____
update()2900 void SAL_CALL ChartView::update() throw (uno::RuntimeException)
2901 {
2902     impl_updateView();
2903 
2904     //#i100778# migrate all imported or old documents to a plot area sizing exclusive axes (in case the save settings allow for this):
2905     //Although in general it is a bad idea to change the model from within the view this is exceptionally the best place to do this special conversion.
2906     //When a view update is requested (what happens for creating the metafile or displaying
2907     //the chart in edit mode or printing) it is most likely that all necessary informations are available - like the underlying spreadsheet data for example.
2908     //Those data is important for the correct axis lable sizes which are needed during conversion.
2909     if( DiagramHelper::switchDiagramPositioningToExcludingPositioning( m_xChartModel, true, false ) )
2910         impl_updateView();
2911 }
2912 
2913 // ____ XPropertySet ____
getPropertySetInfo()2914 Reference< beans::XPropertySetInfo > SAL_CALL ChartView::getPropertySetInfo()
2915     throw (uno::RuntimeException)
2916 {
2917     OSL_ENSURE(false,"not implemented");
2918     return 0;
2919 }
2920 
setPropertyValue(const::rtl::OUString & rPropertyName,const Any & rValue)2921 void SAL_CALL ChartView::setPropertyValue( const ::rtl::OUString& rPropertyName
2922                                                      , const Any& rValue )
2923     throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException
2924           , lang::WrappedTargetException, uno::RuntimeException)
2925 {
2926     if( rPropertyName.equals(C2U("Resolution")) )
2927     {
2928         awt::Size aNewResolution;
2929         if( ! (rValue >>= aNewResolution) )
2930             throw lang::IllegalArgumentException( C2U("Property 'Resolution' requires value of type awt::Size"), 0, 0 );
2931 
2932         if( m_aPageResolution.Width!=aNewResolution.Width || m_aPageResolution.Height!=aNewResolution.Height )
2933         {
2934             //set modified only when the new resolution is higher and points were skipped before
2935             bool bSetModified = m_bPointsWereSkipped && (m_aPageResolution.Width<aNewResolution.Width || m_aPageResolution.Height<aNewResolution.Height);
2936 
2937             m_aPageResolution = aNewResolution;
2938 
2939             if( bSetModified )
2940                 this->modified( lang::EventObject(  static_cast< uno::XWeak* >( this )  ) );
2941         }
2942     }
2943     else if( rPropertyName.equals(C2U("ZoomFactors")) )
2944     {
2945         //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
2946         uno::Sequence< beans::PropertyValue > aZoomFactors;
2947         if( ! (rValue >>= aZoomFactors) )
2948             throw lang::IllegalArgumentException( C2U("Property 'ZoomFactors' requires value of type Sequence< PropertyValue >"), 0, 0 );
2949 
2950         sal_Int32 nFilterArgs = aZoomFactors.getLength();
2951         beans::PropertyValue* pDataValues = aZoomFactors.getArray();
2952         while( nFilterArgs-- )
2953         {
2954             if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXNumerator" ) ) )
2955                 pDataValues->Value >>= m_nScaleXNumerator;
2956             else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleXDenominator" ) ) )
2957                 pDataValues->Value >>= m_nScaleXDenominator;
2958             else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYNumerator" ) ) )
2959                 pDataValues->Value >>= m_nScaleYNumerator;
2960             else if( pDataValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ScaleYDenominator" ) ) )
2961                 pDataValues->Value >>= m_nScaleYDenominator;
2962 
2963             pDataValues++;
2964         }
2965     }
2966     else if( rPropertyName.equals(C2U("SdrViewIsInEditMode")) )
2967     {
2968         //#i77362 change notification for changes on additional shapes are missing
2969         if( ! (rValue >>= m_bSdrViewIsInEditMode) )
2970             throw lang::IllegalArgumentException( C2U("Property 'SdrViewIsInEditMode' requires value of type sal_Bool"), 0, 0 );
2971     }
2972     else
2973         throw beans::UnknownPropertyException( C2U("unknown property was tried to set to chart wizard"), 0 );
2974 }
2975 
getPropertyValue(const::rtl::OUString & rPropertyName)2976 Any SAL_CALL ChartView::getPropertyValue( const ::rtl::OUString& rPropertyName )
2977     throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
2978 {
2979     Any aRet;
2980     if( rPropertyName.equals(C2U("Resolution")) )
2981     {
2982         aRet = uno::makeAny( m_aPageResolution );
2983     }
2984     else
2985         throw beans::UnknownPropertyException( C2U("unknown property was tried to get from chart wizard"), 0 );
2986     return aRet;
2987 }
2988 
addPropertyChangeListener(const::rtl::OUString &,const Reference<beans::XPropertyChangeListener> &)2989 void SAL_CALL ChartView::addPropertyChangeListener(
2990     const ::rtl::OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* xListener */ )
2991         throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
2992 {
2993     OSL_ENSURE(false,"not implemented");
2994 }
removePropertyChangeListener(const::rtl::OUString &,const Reference<beans::XPropertyChangeListener> &)2995 void SAL_CALL ChartView::removePropertyChangeListener(
2996     const ::rtl::OUString& /* aPropertyName */, const Reference< beans::XPropertyChangeListener >& /* aListener */ )
2997     throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
2998 {
2999     OSL_ENSURE(false,"not implemented");
3000 }
3001 
addVetoableChangeListener(const::rtl::OUString &,const Reference<beans::XVetoableChangeListener> &)3002 void SAL_CALL ChartView::addVetoableChangeListener( const ::rtl::OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
3003     throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
3004 {
3005     OSL_ENSURE(false,"not implemented");
3006 }
3007 
removeVetoableChangeListener(const::rtl::OUString &,const Reference<beans::XVetoableChangeListener> &)3008 void SAL_CALL ChartView::removeVetoableChangeListener( const ::rtl::OUString& /* PropertyName */, const Reference< beans::XVetoableChangeListener >& /* aListener */ )
3009     throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException)
3010 {
3011     OSL_ENSURE(false,"not implemented");
3012 }
3013 
3014 // ____ XMultiServiceFactory ____
3015 
createInstance(const::rtl::OUString & aServiceSpecifier)3016 Reference< uno::XInterface > ChartView::createInstance( const ::rtl::OUString& aServiceSpecifier )
3017     throw (uno::Exception, uno::RuntimeException)
3018 {
3019     SdrModel* pModel = ( m_pDrawModelWrapper ? &m_pDrawModelWrapper->getSdrModel() : NULL );
3020     if ( pModel )
3021     {
3022         if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.DashTable" ) ) == 0 )
3023         {
3024             if ( !m_xDashTable.is() )
3025             {
3026                 m_xDashTable = SvxUnoDashTable_createInstance( pModel );
3027             }
3028             return m_xDashTable;
3029         }
3030         else if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.GradientTable" ) ) == 0 )
3031         {
3032             if ( !m_xGradientTable.is() )
3033             {
3034                 m_xGradientTable = SvxUnoGradientTable_createInstance( pModel );
3035             }
3036             return m_xGradientTable;
3037         }
3038         else if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.HatchTable" ) ) == 0 )
3039         {
3040             if ( !m_xHatchTable.is() )
3041             {
3042                 m_xHatchTable = SvxUnoHatchTable_createInstance( pModel );
3043             }
3044             return m_xHatchTable;
3045         }
3046         else if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.BitmapTable" ) ) == 0 )
3047         {
3048             if ( !m_xBitmapTable.is() )
3049             {
3050                 m_xBitmapTable = SvxUnoBitmapTable_createInstance( pModel );
3051             }
3052             return m_xBitmapTable;
3053         }
3054         else if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.TransparencyGradientTable" ) ) == 0 )
3055         {
3056             if ( !m_xTransGradientTable.is() )
3057             {
3058                 m_xTransGradientTable = SvxUnoTransGradientTable_createInstance( pModel );
3059             }
3060             return m_xTransGradientTable;
3061         }
3062         else if ( aServiceSpecifier.reverseCompareToAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.MarkerTable" ) ) == 0 )
3063         {
3064             if ( !m_xMarkerTable.is() )
3065             {
3066                 m_xMarkerTable = SvxUnoMarkerTable_createInstance( pModel );
3067             }
3068             return m_xMarkerTable;
3069         }
3070     }
3071 
3072     return 0;
3073 }
3074 
createInstanceWithArguments(const::rtl::OUString & ServiceSpecifier,const uno::Sequence<uno::Any> & Arguments)3075 Reference< uno::XInterface > ChartView::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, const uno::Sequence< uno::Any >& Arguments )
3076     throw (uno::Exception, uno::RuntimeException)
3077 {
3078     OSL_ENSURE( Arguments.getLength(), "ChartView::createInstanceWithArguments: arguments are ignored" );
3079     (void) Arguments; // avoid warning
3080     return createInstance( ServiceSpecifier );
3081 }
3082 
getAvailableServiceNames()3083 uno::Sequence< ::rtl::OUString > ChartView::getAvailableServiceNames() throw (uno::RuntimeException)
3084 {
3085     uno::Sequence< ::rtl::OUString > aServiceNames( 6 );
3086 
3087     aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DashTable" ) );
3088     aServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.GradientTable" ) );
3089     aServiceNames[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.HatchTable" ) );
3090     aServiceNames[3] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.BitmapTable" ) );
3091     aServiceNames[4] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.TransparencyGradientTable" ) );
3092     aServiceNames[5] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.MarkerTable" ) );
3093 
3094 	return aServiceNames;
3095 }
3096 
3097 //.............................................................................
3098 } //namespace chart
3099 //.............................................................................
3100