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