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