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