1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <ChartModel.hxx>
21 #include <servicenames.hxx>
22 #include <DataSourceHelper.hxx>
23 #include <ChartModelHelper.hxx>
24 #include <DisposeHelper.hxx>
25 #include <ControllerLockGuard.hxx>
26 #include <ObjectIdentifier.hxx>
27 #include "PageBackground.hxx"
28 #include <CloneHelper.hxx>
29 #include <NameContainer.hxx>
30 #include "UndoManager.hxx"
31 #include <ChartView.hxx>
32 #include <PopupRequest.hxx>
33 #include <ModifyListenerHelper.hxx>
34
35 #include <com/sun/star/chart/ChartDataRowSource.hpp>
36 #include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
37
38 #include <comphelper/processfactory.hxx>
39 #include <comphelper/propertysequence.hxx>
40 #include <cppuhelper/supportsservice.hxx>
41
42 #include <svl/numuno.hxx>
43 #include <com/sun/star/lang/DisposedException.hpp>
44 #include <com/sun/star/lang/XInitialization.hpp>
45 #include <com/sun/star/view/XSelectionSupplier.hpp>
46 #include <com/sun/star/embed/EmbedMapUnits.hpp>
47 #include <com/sun/star/embed/Aspects.hpp>
48 #include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp>
49 #include <com/sun/star/datatransfer/XTransferable.hpp>
50 #include <com/sun/star/drawing/XShapes.hpp>
51 #include <com/sun/star/document/DocumentProperties.hpp>
52 #include <com/sun/star/util/CloseVetoException.hpp>
53 #include <com/sun/star/util/XModifyBroadcaster.hpp>
54 #include <com/sun/star/chart2/XChartTypeTemplate.hpp>
55
56 #include <sal/log.hxx>
57 #include <svl/zforlist.hxx>
58 #include <tools/diagnose_ex.h>
59
60 using ::com::sun::star::uno::Sequence;
61 using ::com::sun::star::uno::Reference;
62 using ::com::sun::star::uno::Any;
63 using ::osl::MutexGuard;
64
65 using namespace ::com::sun::star;
66 using namespace ::apphelper;
67 using namespace ::chart::CloneHelper;
68
69 namespace
70 {
71 const OUString lcl_aGDIMetaFileMIMEType(
72 "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"");
73 const OUString lcl_aGDIMetaFileMIMETypeHighContrast(
74 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"");
75
76 } // anonymous namespace
77
78 // ChartModel Constructor and Destructor
79
80 namespace chart
81 {
82
ChartModel(uno::Reference<uno::XComponentContext> const & xContext)83 ChartModel::ChartModel(uno::Reference<uno::XComponentContext > const & xContext)
84 : m_aLifeTimeManager( this, this )
85 , m_bReadOnly( false )
86 , m_bModified( false )
87 , m_nInLoad(0)
88 , m_bUpdateNotificationsPending(false)
89 , mbTimeBased(false)
90 , m_aControllers( m_aModelMutex )
91 , m_nControllerLockCount(0)
92 , m_xContext( xContext )
93 , m_aVisualAreaSize( ChartModelHelper::getDefaultPageSize() )
94 , m_xPageBackground( new PageBackground )
95 , m_xXMLNamespaceMap( createNameContainer( ::cppu::UnoType<OUString>::get(),
96 "com.sun.star.xml.NamespaceMap", "com.sun.star.comp.chart.XMLNameSpaceMap" ) )
97 , mnStart(0)
98 , mnEnd(0)
99 {
100 osl_atomic_increment(&m_refCount);
101 {
102 m_xOldModelAgg.set(
103 m_xContext->getServiceManager()->createInstanceWithContext(
104 CHART_CHARTAPIWRAPPER_SERVICE_NAME,
105 m_xContext ), uno::UNO_QUERY_THROW );
106 m_xOldModelAgg->setDelegator( *this );
107 }
108
109 {
110 ModifyListenerHelper::addListener( m_xPageBackground, this );
111 m_xChartTypeManager.set( xContext->getServiceManager()->createInstanceWithContext(
112 "com.sun.star.chart2.ChartTypeManager", m_xContext ), uno::UNO_QUERY );
113 }
114 osl_atomic_decrement(&m_refCount);
115 }
116
ChartModel(const ChartModel & rOther)117 ChartModel::ChartModel( const ChartModel & rOther )
118 : impl::ChartModel_Base(rOther)
119 , m_aLifeTimeManager( this, this )
120 , m_bReadOnly( rOther.m_bReadOnly )
121 , m_bModified( rOther.m_bModified )
122 , m_nInLoad(0)
123 , m_bUpdateNotificationsPending(false)
124 , mbTimeBased(rOther.mbTimeBased)
125 , m_aResource( rOther.m_aResource )
126 , m_aMediaDescriptor( rOther.m_aMediaDescriptor )
127 , m_aControllers( m_aModelMutex )
128 , m_nControllerLockCount(0)
129 , m_xContext( rOther.m_xContext )
130 // @note: the old model aggregate must not be shared with other models if it
131 // is, you get mutex deadlocks
132 //, m_xOldModelAgg( nullptr ) //rOther.m_xOldModelAgg )
133 // m_xStorage( nullptr ) //rOther.m_xStorage )
134 , m_aVisualAreaSize( rOther.m_aVisualAreaSize )
135 , m_aGraphicObjectVector( rOther.m_aGraphicObjectVector )
136 , m_xDataProvider( rOther.m_xDataProvider )
137 , m_xInternalDataProvider( rOther.m_xInternalDataProvider )
138 , mnStart(rOther.mnStart)
139 , mnEnd(rOther.mnEnd)
140 {
141 osl_atomic_increment(&m_refCount);
142 {
143 m_xOldModelAgg.set(
144 m_xContext->getServiceManager()->createInstanceWithContext(
145 CHART_CHARTAPIWRAPPER_SERVICE_NAME,
146 m_xContext ), uno::UNO_QUERY_THROW );
147 m_xOldModelAgg->setDelegator( *this );
148
149 Reference< util::XModifyListener > xListener;
150 Reference< chart2::XTitle > xNewTitle = CreateRefClone< chart2::XTitle >()( rOther.m_xTitle );
151 Reference< chart2::XDiagram > xNewDiagram = CreateRefClone< chart2::XDiagram >()( rOther.m_xDiagram );
152 Reference< beans::XPropertySet > xNewPageBackground = CreateRefClone< beans::XPropertySet >()( rOther.m_xPageBackground );
153 Reference< chart2::XChartTypeManager > xChartTypeManager = CreateRefClone< chart2::XChartTypeManager >()( rOther.m_xChartTypeManager );
154 Reference< container::XNameAccess > xXMLNamespaceMap = CreateRefClone< container::XNameAccess >()( rOther.m_xXMLNamespaceMap );
155
156 {
157 MutexGuard aGuard( m_aModelMutex );
158 xListener = this;
159 m_xTitle = xNewTitle;
160 m_xDiagram = xNewDiagram;
161 m_xPageBackground = xNewPageBackground;
162 m_xChartTypeManager = xChartTypeManager;
163 m_xXMLNamespaceMap = xXMLNamespaceMap;
164 }
165
166 ModifyListenerHelper::addListener( xNewTitle, xListener );
167 ModifyListenerHelper::addListener( xNewDiagram, xListener );
168 ModifyListenerHelper::addListener( xNewPageBackground, xListener );
169 xListener.clear();
170 }
171 osl_atomic_decrement(&m_refCount);
172 }
173
~ChartModel()174 ChartModel::~ChartModel()
175 {
176 if( m_xOldModelAgg.is())
177 m_xOldModelAgg->setDelegator( nullptr );
178 }
179
initialize(const Sequence<Any> &)180 void SAL_CALL ChartModel::initialize( const Sequence< Any >& /*rArguments*/ )
181 {
182 //#i113722# avoid duplicate creation
183
184 //maybe additional todo?:
185 //support argument "EmbeddedObject"?
186 //support argument "EmbeddedScriptSupport"?
187 //support argument "DocumentRecoverySupport"?
188 }
189
getChartView() const190 css::uno::Reference< css::uno::XInterface > ChartModel::getChartView() const
191 {
192 return static_cast< ::cppu::OWeakObject* >( mxChartView.get() );
193 }
194
195 // private methods
196
impl_g_getLocation()197 OUString ChartModel::impl_g_getLocation()
198 {
199
200 LifeTimeGuard aGuard(m_aLifeTimeManager);
201 if(!aGuard.startApiCall())
202 return OUString(); //behave passive if already disposed or closed or throw exception @todo?
203 //mutex is acquired
204 return m_aResource;
205 }
206
impl_isControllerConnected(const uno::Reference<frame::XController> & xController)207 bool ChartModel::impl_isControllerConnected( const uno::Reference< frame::XController >& xController )
208 {
209 try
210 {
211 std::vector< uno::Reference<uno::XInterface> > aSeq = m_aControllers.getElements();
212 for( const auto & r : aSeq )
213 {
214 if( r == xController )
215 return true;
216 }
217 }
218 catch (const uno::Exception&)
219 {
220 }
221 return false;
222 }
223
impl_getCurrentController()224 uno::Reference< frame::XController > ChartModel::impl_getCurrentController()
225 {
226 //@todo? hold only weak references to controllers
227
228 // get the last active controller of this model
229 if( m_xCurrentController.is() )
230 return m_xCurrentController;
231
232 // get the first controller of this model
233 if( m_aControllers.getLength() )
234 {
235 uno::Reference<uno::XInterface> xI = m_aControllers.getElements()[0];
236 return uno::Reference<frame::XController>( xI, uno::UNO_QUERY );
237 }
238
239 //return nothing if no controllers are connected at all
240 return uno::Reference< frame::XController > ();
241 }
242
impl_notifyCloseListeners()243 void ChartModel::impl_notifyCloseListeners()
244 {
245 ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer
246 .getContainer( cppu::UnoType<util::XCloseListener>::get());
247 if( pIC )
248 {
249 lang::EventObject aEvent( static_cast< lang::XComponent*>(this) );
250 ::cppu::OInterfaceIteratorHelper aIt( *pIC );
251 while( aIt.hasMoreElements() )
252 {
253 uno::Reference< util::XCloseListener > xListener( aIt.next(), uno::UNO_QUERY );
254 if( xListener.is() )
255 xListener->notifyClosing( aEvent );
256 }
257 }
258 }
259
impl_adjustAdditionalShapesPositionAndSize(const awt::Size & aVisualAreaSize)260 void ChartModel::impl_adjustAdditionalShapesPositionAndSize( const awt::Size& aVisualAreaSize )
261 {
262 uno::Reference< beans::XPropertySet > xProperties( static_cast< ::cppu::OWeakObject* >( this ), uno::UNO_QUERY );
263 if ( xProperties.is() )
264 {
265 uno::Reference< drawing::XShapes > xShapes;
266 xProperties->getPropertyValue( "AdditionalShapes" ) >>= xShapes;
267 if ( xShapes.is() )
268 {
269 sal_Int32 nCount = xShapes->getCount();
270 for ( sal_Int32 i = 0; i < nCount; ++i )
271 {
272 Reference< drawing::XShape > xShape;
273 if ( xShapes->getByIndex( i ) >>= xShape )
274 {
275 if ( xShape.is() )
276 {
277 awt::Point aPos( xShape->getPosition() );
278 awt::Size aSize( xShape->getSize() );
279
280 double fWidth = static_cast< double >( aVisualAreaSize.Width ) / m_aVisualAreaSize.Width;
281 double fHeight = static_cast< double >( aVisualAreaSize.Height ) / m_aVisualAreaSize.Height;
282
283 aPos.X = static_cast< long >( aPos.X * fWidth );
284 aPos.Y = static_cast< long >( aPos.Y * fHeight );
285 aSize.Width = static_cast< long >( aSize.Width * fWidth );
286 aSize.Height = static_cast< long >( aSize.Height * fHeight );
287
288 xShape->setPosition( aPos );
289 xShape->setSize( aSize );
290 }
291 }
292 }
293 }
294 }
295 }
296
297 // lang::XServiceInfo
298
getImplementationName()299 OUString SAL_CALL ChartModel::getImplementationName()
300 {
301 return CHART_MODEL_SERVICE_IMPLEMENTATION_NAME;
302 }
303
supportsService(const OUString & rServiceName)304 sal_Bool SAL_CALL ChartModel::supportsService( const OUString& rServiceName )
305 {
306 return cppu::supportsService(this, rServiceName);
307 }
308
getSupportedServiceNames()309 css::uno::Sequence< OUString > SAL_CALL ChartModel::getSupportedServiceNames()
310 {
311 return {
312 CHART_MODEL_SERVICE_NAME,
313 "com.sun.star.document.OfficeDocument",
314 "com.sun.star.chart.ChartDocument"
315 };
316 }
317
318 // frame::XModel (required interface)
319
attachResource(const OUString & rURL,const uno::Sequence<beans::PropertyValue> & rMediaDescriptor)320 sal_Bool SAL_CALL ChartModel::attachResource( const OUString& rURL
321 , const uno::Sequence< beans::PropertyValue >& rMediaDescriptor )
322 {
323 /*
324 The method attachResource() is used by the frame loader implementations
325 to inform the model about its URL and MediaDescriptor.
326 */
327
328 LifeTimeGuard aGuard(m_aLifeTimeManager);
329 if(!aGuard.startApiCall())
330 return false; //behave passive if already disposed or closed or throw exception @todo?
331 //mutex is acquired
332
333 if(!m_aResource.isEmpty())//we have a resource already //@todo? or is setting a new resource allowed?
334 return false;
335 m_aResource = rURL;
336 m_aMediaDescriptor = rMediaDescriptor;
337
338 //@todo ? check rURL ??
339 //@todo ? evaluate m_aMediaDescriptor;
340 //@todo ? ... ??? --> nothing, this method is only for setting information
341
342 return true;
343 }
344
getURL()345 OUString SAL_CALL ChartModel::getURL()
346 {
347 return impl_g_getLocation();
348 }
349
getArgs()350 uno::Sequence< beans::PropertyValue > SAL_CALL ChartModel::getArgs()
351 {
352 /*
353 The method getArgs() returns a sequence of property values
354 that report the resource description according to com.sun.star.document.MediaDescriptor,
355 specified on loading or saving with storeAsURL.
356 */
357
358 LifeTimeGuard aGuard(m_aLifeTimeManager);
359 if(!aGuard.startApiCall())
360 return uno::Sequence< beans::PropertyValue >(); //behave passive if already disposed or closed or throw exception @todo?
361 //mutex is acquired
362
363 return m_aMediaDescriptor;
364 }
365
connectController(const uno::Reference<frame::XController> & xController)366 void SAL_CALL ChartModel::connectController( const uno::Reference< frame::XController >& xController )
367 {
368 //@todo? this method is declared as oneway -> ...?
369
370 LifeTimeGuard aGuard(m_aLifeTimeManager);
371 if(!aGuard.startApiCall())
372 return ; //behave passive if already disposed or closed
373 //mutex is acquired
374
375 //--add controller
376 m_aControllers.addInterface(xController);
377 }
378
disconnectController(const uno::Reference<frame::XController> & xController)379 void SAL_CALL ChartModel::disconnectController( const uno::Reference< frame::XController >& xController )
380 {
381 //@todo? this method is declared as oneway -> ...?
382
383 LifeTimeGuard aGuard(m_aLifeTimeManager);
384 if(!aGuard.startApiCall())
385 return; //behave passive if already disposed or closed
386
387 //--remove controller
388 m_aControllers.removeInterface(xController);
389
390 //case: current controller is disconnected:
391 if( m_xCurrentController == xController )
392 m_xCurrentController.clear();
393
394 DisposeHelper::DisposeAndClear( m_xRangeHighlighter );
395 DisposeHelper::DisposeAndClear(m_xPopupRequest);
396 }
397
lockControllers()398 void SAL_CALL ChartModel::lockControllers()
399 {
400 /*
401 suspends some notifications to the controllers which are used for display updates.
402
403 The calls to lockControllers() and unlockControllers() may be nested
404 and even overlapping, but they must be in pairs. While there is at least one lock
405 remaining, some notifications for display updates are not broadcasted.
406 */
407
408 //@todo? this method is declared as oneway -> ...?
409
410 LifeTimeGuard aGuard(m_aLifeTimeManager);
411 if(!aGuard.startApiCall())
412 return; //behave passive if already disposed or closed or throw exception @todo?
413 ++m_nControllerLockCount;
414 }
415
unlockControllers()416 void SAL_CALL ChartModel::unlockControllers()
417 {
418 /*
419 resumes the notifications which were suspended by lockControllers() .
420
421 The calls to lockControllers() and unlockControllers() may be nested
422 and even overlapping, but they must be in pairs. While there is at least one lock
423 remaining, some notifications for display updates are not broadcasted.
424 */
425
426 //@todo? this method is declared as oneway -> ...?
427
428 LifeTimeGuard aGuard(m_aLifeTimeManager);
429 if(!aGuard.startApiCall())
430 return; //behave passive if already disposed or closed or throw exception @todo?
431 if( m_nControllerLockCount == 0 )
432 {
433 SAL_WARN("chart2", "ChartModel: unlockControllers called with m_nControllerLockCount == 0" );
434 return;
435 }
436 --m_nControllerLockCount;
437 if( m_nControllerLockCount == 0 && m_bUpdateNotificationsPending )
438 {
439 aGuard.clear();
440 impl_notifyModifiedListeners();
441 }
442 }
443
hasControllersLocked()444 sal_Bool SAL_CALL ChartModel::hasControllersLocked()
445 {
446 LifeTimeGuard aGuard(m_aLifeTimeManager);
447 if(!aGuard.startApiCall())
448 return false; //behave passive if already disposed or closed or throw exception @todo?
449 return ( m_nControllerLockCount != 0 ) ;
450 }
451
getCurrentController()452 uno::Reference< frame::XController > SAL_CALL ChartModel::getCurrentController()
453 {
454 LifeTimeGuard aGuard(m_aLifeTimeManager);
455 if(!aGuard.startApiCall())
456 throw lang::DisposedException(
457 "getCurrentController was called on an already disposed or closed model",
458 static_cast< ::cppu::OWeakObject* >(this) );
459
460 return impl_getCurrentController();
461 }
462
setCurrentController(const uno::Reference<frame::XController> & xController)463 void SAL_CALL ChartModel::setCurrentController( const uno::Reference< frame::XController >& xController )
464 {
465 LifeTimeGuard aGuard(m_aLifeTimeManager);
466 if(!aGuard.startApiCall())
467 throw lang::DisposedException(
468 "setCurrentController was called on an already disposed or closed model",
469 static_cast< ::cppu::OWeakObject* >(this) );
470
471 //OSL_ENSURE( impl_isControllerConnected(xController), "setCurrentController is called with a Controller which is not connected" );
472 if(!impl_isControllerConnected(xController))
473 throw container::NoSuchElementException(
474 "setCurrentController is called with a Controller which is not connected",
475 static_cast< ::cppu::OWeakObject* >(this) );
476
477 m_xCurrentController = xController;
478
479 DisposeHelper::DisposeAndClear( m_xRangeHighlighter );
480 DisposeHelper::DisposeAndClear(m_xPopupRequest);
481 }
482
getCurrentSelection()483 uno::Reference< uno::XInterface > SAL_CALL ChartModel::getCurrentSelection()
484 {
485 LifeTimeGuard aGuard(m_aLifeTimeManager);
486 if(!aGuard.startApiCall())
487 throw lang::DisposedException(
488 "getCurrentSelection was called on an already disposed or closed model",
489 static_cast< ::cppu::OWeakObject* >(this) );
490
491 uno::Reference< uno::XInterface > xReturn;
492 uno::Reference< frame::XController > xController = impl_getCurrentController();
493
494 aGuard.clear();
495 if( xController.is() )
496 {
497 uno::Reference< view::XSelectionSupplier > xSelectionSupl( xController, uno::UNO_QUERY );
498 if ( xSelectionSupl.is() )
499 {
500 uno::Any aSel = xSelectionSupl->getSelection();
501 OUString aObjectCID;
502 if( aSel >>= aObjectCID )
503 xReturn.set( ObjectIdentifier::getObjectPropertySet( aObjectCID, Reference< XChartDocument >(this)));
504 }
505 }
506 return xReturn;
507 }
508
509 // lang::XComponent (base of XModel)
dispose()510 void SAL_CALL ChartModel::dispose()
511 {
512 Reference< XInterface > xKeepAlive( *this );
513
514 //This object should release all resources and references in the
515 //easiest possible manner
516 //This object must notify all registered listeners using the method
517 //<member>XEventListener::disposing</member>
518
519 //hold no mutex
520 if( !m_aLifeTimeManager.dispose() )
521 return;
522
523 //--release all resources and references
524 //// @todo
525
526 if ( m_xDiagram.is() )
527 ModifyListenerHelper::removeListener( m_xDiagram, this );
528
529 if ( m_xDataProvider.is() )
530 {
531 Reference<util::XModifyBroadcaster> xModifyBroadcaster( m_xDataProvider, uno::UNO_QUERY );
532 if ( xModifyBroadcaster.is() )
533 xModifyBroadcaster->removeModifyListener( this );
534 }
535
536 m_xDataProvider.clear();
537 m_xInternalDataProvider.clear();
538 m_xNumberFormatsSupplier.clear();
539 DisposeHelper::DisposeAndClear( m_xOwnNumberFormatsSupplier );
540 DisposeHelper::DisposeAndClear( m_xChartTypeManager );
541 DisposeHelper::DisposeAndClear( m_xDiagram );
542 DisposeHelper::DisposeAndClear( m_xTitle );
543 DisposeHelper::DisposeAndClear( m_xPageBackground );
544 DisposeHelper::DisposeAndClear( m_xXMLNamespaceMap );
545
546 m_xStorage.clear();
547 // just clear, don't dispose - we're not the owner
548
549 if ( m_pUndoManager.is() )
550 m_pUndoManager->disposing();
551 m_pUndoManager.clear();
552 // that's important, since the UndoManager implementation delegates its ref counting to ourself.
553
554 if( m_xOldModelAgg.is()) // #i120828#, to release cyclic reference to ChartModel object
555 m_xOldModelAgg->setDelegator( nullptr );
556
557 m_aControllers.disposeAndClear( lang::EventObject( static_cast< cppu::OWeakObject * >( this )));
558 m_xCurrentController.clear();
559
560 DisposeHelper::DisposeAndClear( m_xRangeHighlighter );
561 DisposeHelper::DisposeAndClear(m_xPopupRequest);
562
563 if( m_xOldModelAgg.is())
564 m_xOldModelAgg->setDelegator( nullptr );
565 }
566
addEventListener(const uno::Reference<lang::XEventListener> & xListener)567 void SAL_CALL ChartModel::addEventListener( const uno::Reference< lang::XEventListener > & xListener )
568 {
569 if( m_aLifeTimeManager.impl_isDisposedOrClosed() )
570 return; //behave passive if already disposed or closed
571
572 m_aLifeTimeManager.m_aListenerContainer.addInterface( cppu::UnoType<lang::XEventListener>::get(), xListener );
573 }
574
removeEventListener(const uno::Reference<lang::XEventListener> & xListener)575 void SAL_CALL ChartModel::removeEventListener( const uno::Reference< lang::XEventListener > & xListener )
576 {
577 if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
578 return; //behave passive if already disposed or closed
579
580 m_aLifeTimeManager.m_aListenerContainer.removeInterface( cppu::UnoType<lang::XEventListener>::get(), xListener );
581 }
582
583 // util::XCloseBroadcaster (base of XCloseable)
addCloseListener(const uno::Reference<util::XCloseListener> & xListener)584 void SAL_CALL ChartModel::addCloseListener( const uno::Reference< util::XCloseListener > & xListener )
585 {
586 m_aLifeTimeManager.g_addCloseListener( xListener );
587 }
588
removeCloseListener(const uno::Reference<util::XCloseListener> & xListener)589 void SAL_CALL ChartModel::removeCloseListener( const uno::Reference< util::XCloseListener > & xListener )
590 {
591 if( m_aLifeTimeManager.impl_isDisposedOrClosed(false) )
592 return; //behave passive if already disposed or closed
593
594 m_aLifeTimeManager.m_aListenerContainer.removeInterface( cppu::UnoType<util::XCloseListener>::get(), xListener );
595 }
596
597 // util::XCloseable
close(sal_Bool bDeliverOwnership)598 void SAL_CALL ChartModel::close( sal_Bool bDeliverOwnership )
599 {
600 //hold no mutex
601
602 if( !m_aLifeTimeManager.g_close_startTryClose( bDeliverOwnership ) )
603 return;
604 //no mutex is acquired
605
606 // At the end of this method may we must dispose ourself ...
607 // and may nobody from outside hold a reference to us ...
608 // then it's a good idea to do that by ourself.
609 uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) );
610
611 //the listeners have had no veto
612 //check whether we self can close
613 {
614 util::CloseVetoException aVetoException(
615 "the model itself could not be closed",
616 static_cast< ::cppu::OWeakObject* >(this) );
617
618 m_aLifeTimeManager.g_close_isNeedToCancelLongLastingCalls( bDeliverOwnership, aVetoException );
619 }
620 m_aLifeTimeManager.g_close_endTryClose_doClose();
621
622 // BM @todo: is it ok to call the listeners here?
623 impl_notifyCloseListeners();
624 }
625
626 // lang::XTypeProvider
getTypes()627 uno::Sequence< uno::Type > SAL_CALL ChartModel::getTypes()
628 {
629 uno::Reference< lang::XTypeProvider > xAggTypeProvider;
630 if( (m_xOldModelAgg->queryAggregation( cppu::UnoType<decltype(xAggTypeProvider)>::get()) >>= xAggTypeProvider)
631 && xAggTypeProvider.is())
632 {
633 return comphelper::concatSequences(
634 impl::ChartModel_Base::getTypes(),
635 xAggTypeProvider->getTypes());
636 }
637
638 return impl::ChartModel_Base::getTypes();
639 }
640
641 // document::XDocumentPropertiesSupplier
642 uno::Reference< document::XDocumentProperties > SAL_CALL
getDocumentProperties()643 ChartModel::getDocumentProperties()
644 {
645 ::osl::MutexGuard aGuard( m_aModelMutex );
646 if ( !m_xDocumentProperties.is() )
647 {
648 m_xDocumentProperties.set( document::DocumentProperties::create( ::comphelper::getProcessComponentContext() ) );
649 }
650 return m_xDocumentProperties;
651 }
652
653 // document::XDocumentPropertiesSupplier
getUndoManager()654 Reference< document::XUndoManager > SAL_CALL ChartModel::getUndoManager( )
655 {
656 ::osl::MutexGuard aGuard( m_aModelMutex );
657 if ( !m_pUndoManager.is() )
658 m_pUndoManager.set( new UndoManager( *this, m_aModelMutex ) );
659 return m_pUndoManager.get();
660 }
661
662 // chart2::XChartDocument
663
getFirstDiagram()664 uno::Reference< chart2::XDiagram > SAL_CALL ChartModel::getFirstDiagram()
665 {
666 MutexGuard aGuard( m_aModelMutex );
667 return m_xDiagram;
668 }
669
setFirstDiagram(const uno::Reference<chart2::XDiagram> & xDiagram)670 void SAL_CALL ChartModel::setFirstDiagram( const uno::Reference< chart2::XDiagram >& xDiagram )
671 {
672 Reference< chart2::XDiagram > xOldDiagram;
673 Reference< util::XModifyListener > xListener;
674 {
675 MutexGuard aGuard( m_aModelMutex );
676 if( xDiagram == m_xDiagram )
677 return;
678 xOldDiagram = m_xDiagram;
679 m_xDiagram = xDiagram;
680 xListener = this;
681 }
682 //don't keep the mutex locked while calling out
683 ModifyListenerHelper::removeListener( xOldDiagram, xListener );
684 ModifyListenerHelper::addListener( xDiagram, xListener );
685 setModified( true );
686 }
687
impl_createDefaultData()688 Reference< chart2::data::XDataSource > ChartModel::impl_createDefaultData()
689 {
690 Reference< chart2::data::XDataSource > xDataSource;
691 if( hasInternalDataProvider() )
692 {
693 uno::Reference< lang::XInitialization > xIni(m_xInternalDataProvider,uno::UNO_QUERY);
694 if( xIni.is() )
695 {
696 //init internal dataprovider
697 {
698 uno::Sequence< uno::Any > aArgs(1);
699 beans::NamedValue aParam( "CreateDefaultData" ,uno::Any(true) );
700 aArgs[0] <<= aParam;
701 xIni->initialize(aArgs);
702 }
703 //create data
704 uno::Sequence<beans::PropertyValue> aArgs( comphelper::InitPropertySequence({
705 { "CellRangeRepresentation", uno::Any( OUString("all") ) },
706 { "HasCategories", uno::Any( true ) },
707 { "FirstCellAsLabel", uno::Any( true ) },
708 { "DataRowSource", uno::Any( css::chart::ChartDataRowSource_COLUMNS ) }
709 }));
710 xDataSource = m_xInternalDataProvider->createDataSource( aArgs );
711 }
712 }
713 return xDataSource;
714 }
715
createInternalDataProvider(sal_Bool bCloneExistingData)716 void SAL_CALL ChartModel::createInternalDataProvider( sal_Bool bCloneExistingData )
717 {
718 // don't lock the mutex, because this call calls out to code that tries to
719 // lock the solar mutex. On the other hand, a paint locks the solar mutex
720 // and calls to the model lock the model's mutex => deadlock
721 // @todo: lock a separate mutex in the InternalData class
722 if( !hasInternalDataProvider() )
723 {
724 if( bCloneExistingData )
725 m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider( this, true );
726 else
727 m_xInternalDataProvider = ChartModelHelper::createInternalDataProvider( Reference<XChartDocument>(), true );
728 m_xDataProvider.set( m_xInternalDataProvider );
729 }
730 setModified( true );
731 }
732
removeDataProviders()733 void ChartModel::removeDataProviders()
734 {
735 if (m_xInternalDataProvider.is())
736 m_xInternalDataProvider.clear();
737 if (m_xDataProvider.is())
738 m_xDataProvider.clear();
739 }
740
hasInternalDataProvider()741 sal_Bool SAL_CALL ChartModel::hasInternalDataProvider()
742 {
743 return m_xDataProvider.is() && m_xInternalDataProvider.is();
744 }
745
getDataProvider()746 uno::Reference< chart2::data::XDataProvider > SAL_CALL ChartModel::getDataProvider()
747 {
748 MutexGuard aGuard( m_aModelMutex );
749 return m_xDataProvider;
750 }
751
752 // ____ XDataReceiver ____
753
attachDataProvider(const uno::Reference<chart2::data::XDataProvider> & xDataProvider)754 void SAL_CALL ChartModel::attachDataProvider( const uno::Reference< chart2::data::XDataProvider >& xDataProvider )
755 {
756 {
757 MutexGuard aGuard( m_aModelMutex );
758 uno::Reference< beans::XPropertySet > xProp( xDataProvider, uno::UNO_QUERY );
759 if( xProp.is() )
760 {
761 try
762 {
763 bool bIncludeHiddenCells = ChartModelHelper::isIncludeHiddenCells( Reference< frame::XModel >(this) );
764 xProp->setPropertyValue("IncludeHiddenCells", uno::Any(bIncludeHiddenCells));
765 }
766 catch (const beans::UnknownPropertyException&)
767 {
768 }
769 }
770
771 uno::Reference<util::XModifyBroadcaster> xModifyBroadcaster(xDataProvider, uno::UNO_QUERY);
772 if (xModifyBroadcaster.is())
773 {
774 xModifyBroadcaster->addModifyListener(this);
775 }
776
777 m_xDataProvider.set( xDataProvider );
778 m_xInternalDataProvider.clear();
779
780 //the numberformatter is kept independent of the data provider!
781 }
782 setModified( true );
783 }
784
attachNumberFormatsSupplier(const uno::Reference<util::XNumberFormatsSupplier> & xNewSupplier)785 void SAL_CALL ChartModel::attachNumberFormatsSupplier( const uno::Reference< util::XNumberFormatsSupplier >& xNewSupplier )
786 {
787 {
788 MutexGuard aGuard( m_aModelMutex );
789 if( xNewSupplier==m_xNumberFormatsSupplier )
790 return;
791 if( xNewSupplier==m_xOwnNumberFormatsSupplier )
792 return;
793 if( m_xOwnNumberFormatsSupplier.is() && xNewSupplier.is() )
794 {
795 //@todo
796 //merge missing numberformats from own to new formatter
797 }
798 else if( !xNewSupplier.is() )
799 {
800 if( m_xNumberFormatsSupplier.is() )
801 {
802 //@todo
803 //merge missing numberformats from old numberformatter to own numberformatter
804 //create own numberformatter if necessary
805 }
806 }
807
808 m_xNumberFormatsSupplier.set( xNewSupplier );
809 m_xOwnNumberFormatsSupplier.clear();
810 }
811 setModified( true );
812 }
813
setArguments(const Sequence<beans::PropertyValue> & aArguments)814 void SAL_CALL ChartModel::setArguments( const Sequence< beans::PropertyValue >& aArguments )
815 {
816 {
817 MutexGuard aGuard( m_aModelMutex );
818 if( !m_xDataProvider.is() )
819 return;
820 lockControllers();
821
822 try
823 {
824 Reference< chart2::data::XDataSource > xDataSource( m_xDataProvider->createDataSource( aArguments ) );
825 if( xDataSource.is() )
826 {
827 Reference< chart2::XDiagram > xDia( getFirstDiagram() );
828 if( !xDia.is() )
829 {
830 Reference< chart2::XChartTypeTemplate > xTemplate( impl_createDefaultChartTypeTemplate() );
831 if( xTemplate.is())
832 setFirstDiagram( xTemplate->createDiagramByDataSource( xDataSource, aArguments ) );
833 }
834 else
835 xDia->setDiagramData( xDataSource, aArguments );
836 }
837 }
838 catch (const lang::IllegalArgumentException&)
839 {
840 throw;
841 }
842 catch (const uno::Exception&)
843 {
844 DBG_UNHANDLED_EXCEPTION("chart2");
845 }
846 unlockControllers();
847 }
848 setModified( true );
849 }
850
getUsedRangeRepresentations()851 Sequence< OUString > SAL_CALL ChartModel::getUsedRangeRepresentations()
852 {
853 return DataSourceHelper::getUsedDataRanges( Reference< frame::XModel >(this));
854 }
855
getUsedData()856 Reference< chart2::data::XDataSource > SAL_CALL ChartModel::getUsedData()
857 {
858 return DataSourceHelper::getUsedData( Reference< chart2::XChartDocument >(this));
859 }
860
getRangeHighlighter()861 Reference< chart2::data::XRangeHighlighter > SAL_CALL ChartModel::getRangeHighlighter()
862 {
863 if( ! m_xRangeHighlighter.is())
864 {
865 uno::Reference< view::XSelectionSupplier > xSelSupp( getCurrentController(), uno::UNO_QUERY );
866 if( xSelSupp.is() )
867 m_xRangeHighlighter.set( ChartModelHelper::createRangeHighlighter( xSelSupp ));
868 }
869 return m_xRangeHighlighter;
870 }
871
getPopupRequest()872 Reference<awt::XRequestCallback> SAL_CALL ChartModel::getPopupRequest()
873 {
874 if (!m_xPopupRequest.is())
875 m_xPopupRequest.set(new PopupRequest);
876 return m_xPopupRequest;
877 }
878
impl_createDefaultChartTypeTemplate()879 Reference< chart2::XChartTypeTemplate > ChartModel::impl_createDefaultChartTypeTemplate()
880 {
881 Reference< chart2::XChartTypeTemplate > xTemplate;
882 Reference< lang::XMultiServiceFactory > xFact( m_xChartTypeManager, uno::UNO_QUERY );
883 if( xFact.is() )
884 xTemplate.set( xFact->createInstance( "com.sun.star.chart2.template.Column" ), uno::UNO_QUERY );
885 return xTemplate;
886 }
887
setChartTypeManager(const uno::Reference<chart2::XChartTypeManager> & xNewManager)888 void SAL_CALL ChartModel::setChartTypeManager( const uno::Reference< chart2::XChartTypeManager >& xNewManager )
889 {
890 {
891 MutexGuard aGuard( m_aModelMutex );
892 m_xChartTypeManager = xNewManager;
893 }
894 setModified( true );
895 }
896
getChartTypeManager()897 uno::Reference< chart2::XChartTypeManager > SAL_CALL ChartModel::getChartTypeManager()
898 {
899 MutexGuard aGuard( m_aModelMutex );
900 return m_xChartTypeManager;
901 }
902
getPageBackground()903 uno::Reference< beans::XPropertySet > SAL_CALL ChartModel::getPageBackground()
904 {
905 MutexGuard aGuard( m_aModelMutex );
906 return m_xPageBackground;
907 }
908
createDefaultChart()909 void SAL_CALL ChartModel::createDefaultChart()
910 {
911 insertDefaultChart();
912 }
913
914 // ____ XTitled ____
getTitleObject()915 uno::Reference< chart2::XTitle > SAL_CALL ChartModel::getTitleObject()
916 {
917 MutexGuard aGuard( m_aModelMutex );
918 return m_xTitle;
919 }
920
setTitleObject(const uno::Reference<chart2::XTitle> & xTitle)921 void SAL_CALL ChartModel::setTitleObject( const uno::Reference< chart2::XTitle >& xTitle )
922 {
923 {
924 MutexGuard aGuard( m_aModelMutex );
925 if( m_xTitle.is() )
926 ModifyListenerHelper::removeListener( m_xTitle, this );
927 m_xTitle = xTitle;
928 ModifyListenerHelper::addListener( m_xTitle, this );
929 }
930 setModified( true );
931 }
932
933 // ____ XInterface (for old API wrapper) ____
queryInterface(const uno::Type & aType)934 uno::Any SAL_CALL ChartModel::queryInterface( const uno::Type& aType )
935 {
936 uno::Any aResult( impl::ChartModel_Base::queryInterface( aType ));
937
938 if( ! aResult.hasValue())
939 {
940 // try old API wrapper
941 try
942 {
943 if( m_xOldModelAgg.is())
944 aResult = m_xOldModelAgg->queryAggregation( aType );
945 }
946 catch (const uno::Exception&)
947 {
948 DBG_UNHANDLED_EXCEPTION("chart2");
949 }
950 }
951
952 return aResult;
953 }
954
955 // ____ XCloneable ____
createClone()956 Reference< util::XCloneable > SAL_CALL ChartModel::createClone()
957 {
958 return Reference< util::XCloneable >( new ChartModel( *this ));
959 }
960
961 // ____ XVisualObject ____
setVisualAreaSize(::sal_Int64 nAspect,const awt::Size & aSize)962 void SAL_CALL ChartModel::setVisualAreaSize( ::sal_Int64 nAspect, const awt::Size& aSize )
963 {
964 if( nAspect == embed::Aspects::MSOLE_CONTENT )
965 {
966 ControllerLockGuard aLockGuard( *this );
967 bool bChanged =
968 (m_aVisualAreaSize.Width != aSize.Width ||
969 m_aVisualAreaSize.Height != aSize.Height);
970
971 // #i12587# support for shapes in chart
972 if ( bChanged )
973 {
974 impl_adjustAdditionalShapesPositionAndSize( aSize );
975 }
976
977 m_aVisualAreaSize = aSize;
978 if( bChanged )
979 setModified( true );
980 }
981 else
982 {
983 OSL_FAIL( "setVisualAreaSize: Aspect not implemented yet.");
984 }
985 }
986
getVisualAreaSize(::sal_Int64 nAspect)987 awt::Size SAL_CALL ChartModel::getVisualAreaSize( ::sal_Int64 nAspect )
988 {
989 OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT,
990 "No aspects other than content are supported" );
991 // other possible aspects are MSOLE_THUMBNAIL, MSOLE_ICON and MSOLE_DOCPRINT
992
993 return m_aVisualAreaSize;
994 }
995
getPreferredVisualRepresentation(::sal_Int64 nAspect)996 embed::VisualRepresentation SAL_CALL ChartModel::getPreferredVisualRepresentation( ::sal_Int64 nAspect )
997 {
998 OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT,
999 "No aspects other than content are supported" );
1000
1001 embed::VisualRepresentation aResult;
1002
1003 try
1004 {
1005 Sequence< sal_Int8 > aMetafile;
1006
1007 //get view from old api wrapper
1008 Reference< datatransfer::XTransferable > xTransferable(
1009 createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY );
1010 if( xTransferable.is() )
1011 {
1012 datatransfer::DataFlavor aDataFlavor( lcl_aGDIMetaFileMIMEType,
1013 "GDIMetaFile",
1014 cppu::UnoType<uno::Sequence< sal_Int8 >>::get() );
1015
1016 uno::Any aData( xTransferable->getTransferData( aDataFlavor ) );
1017 aData >>= aMetafile;
1018 }
1019
1020 aResult.Flavor.MimeType = lcl_aGDIMetaFileMIMEType;
1021 aResult.Flavor.DataType = cppu::UnoType<decltype(aMetafile)>::get();
1022
1023 aResult.Data <<= aMetafile;
1024 }
1025 catch (const uno::Exception&)
1026 {
1027 DBG_UNHANDLED_EXCEPTION("chart2");
1028 }
1029
1030 return aResult;
1031 }
1032
getMapUnit(::sal_Int64 nAspect)1033 ::sal_Int32 SAL_CALL ChartModel::getMapUnit( ::sal_Int64 nAspect )
1034 {
1035 OSL_ENSURE( nAspect == embed::Aspects::MSOLE_CONTENT,
1036 "No aspects other than content are supported" );
1037 return embed::EmbedMapUnits::ONE_100TH_MM;
1038 }
1039
1040 // ____ datatransfer::XTransferable ____
getTransferData(const datatransfer::DataFlavor & aFlavor)1041 uno::Any SAL_CALL ChartModel::getTransferData( const datatransfer::DataFlavor& aFlavor )
1042 {
1043 uno::Any aResult;
1044 if( !isDataFlavorSupported( aFlavor ) )
1045 throw datatransfer::UnsupportedFlavorException(
1046 aFlavor.MimeType, static_cast< ::cppu::OWeakObject* >( this ));
1047
1048 try
1049 {
1050 //get view from old api wrapper
1051 Reference< datatransfer::XTransferable > xTransferable(
1052 createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY );
1053 if( xTransferable.is() &&
1054 xTransferable->isDataFlavorSupported( aFlavor ))
1055 {
1056 aResult = xTransferable->getTransferData( aFlavor );
1057 }
1058 }
1059 catch (const uno::Exception&)
1060 {
1061 DBG_UNHANDLED_EXCEPTION("chart2");
1062 }
1063
1064 return aResult;
1065 }
1066
getTransferDataFlavors()1067 Sequence< datatransfer::DataFlavor > SAL_CALL ChartModel::getTransferDataFlavors()
1068 {
1069 uno::Sequence< datatransfer::DataFlavor > aRet(1);
1070
1071 aRet[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast,
1072 "GDIMetaFile",
1073 cppu::UnoType<uno::Sequence< sal_Int8 >>::get() );
1074
1075 return aRet;
1076 }
1077
isDataFlavorSupported(const datatransfer::DataFlavor & aFlavor)1078 sal_Bool SAL_CALL ChartModel::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor )
1079 {
1080 return aFlavor.MimeType == lcl_aGDIMetaFileMIMETypeHighContrast;
1081 }
1082
1083 namespace
1084 {
1085 enum eServiceType
1086 {
1087 SERVICE_DASH_TABLE,
1088 SERVICE_GARDIENT_TABLE,
1089 SERVICE_HATCH_TABLE,
1090 SERVICE_BITMAP_TABLE,
1091 SERVICE_TRANSP_GRADIENT_TABLE,
1092 SERVICE_MARKER_TABLE,
1093 SERVICE_NAMESPACE_MAP
1094 };
1095
1096 typedef std::map< OUString, enum eServiceType > tServiceNameMap;
1097
lcl_getStaticServiceNameMap()1098 tServiceNameMap & lcl_getStaticServiceNameMap()
1099 {
1100 static tServiceNameMap aServiceNameMap{
1101 {"com.sun.star.drawing.DashTable", SERVICE_DASH_TABLE},
1102 {"com.sun.star.drawing.GradientTable", SERVICE_GARDIENT_TABLE},
1103 {"com.sun.star.drawing.HatchTable", SERVICE_HATCH_TABLE},
1104 {"com.sun.star.drawing.BitmapTable", SERVICE_BITMAP_TABLE},
1105 {"com.sun.star.drawing.TransparencyGradientTable", SERVICE_TRANSP_GRADIENT_TABLE},
1106 {"com.sun.star.drawing.MarkerTable", SERVICE_MARKER_TABLE},
1107 {"com.sun.star.xml.NamespaceMap", SERVICE_NAMESPACE_MAP}};
1108 return aServiceNameMap;
1109 }
1110 }
1111 // ____ XMultiServiceFactory ____
createInstance(const OUString & rServiceSpecifier)1112 Reference< uno::XInterface > SAL_CALL ChartModel::createInstance( const OUString& rServiceSpecifier )
1113 {
1114 tServiceNameMap & rMap = lcl_getStaticServiceNameMap();
1115
1116 tServiceNameMap::const_iterator aIt( rMap.find( rServiceSpecifier ));
1117 if( aIt != rMap.end())
1118 {
1119 switch( (*aIt).second )
1120 {
1121 case SERVICE_DASH_TABLE:
1122 case SERVICE_GARDIENT_TABLE:
1123 case SERVICE_HATCH_TABLE:
1124 case SERVICE_BITMAP_TABLE:
1125 case SERVICE_TRANSP_GRADIENT_TABLE:
1126 case SERVICE_MARKER_TABLE:
1127 {
1128 if(!mxChartView.is())
1129 {
1130 mxChartView = new ChartView( m_xContext, *this);
1131 }
1132 return mxChartView->createInstance( rServiceSpecifier );
1133 }
1134 break;
1135 case SERVICE_NAMESPACE_MAP:
1136 return Reference< uno::XInterface >( m_xXMLNamespaceMap );
1137 }
1138 }
1139 else if(rServiceSpecifier == CHART_VIEW_SERVICE_NAME)
1140 {
1141 if(!mxChartView.is())
1142 {
1143 mxChartView = new ChartView( m_xContext, *this);
1144 }
1145
1146 return static_cast< ::cppu::OWeakObject* >( mxChartView.get() );
1147 }
1148 else
1149 {
1150 if( m_xOldModelAgg.is() )
1151 {
1152 Any aAny = m_xOldModelAgg->queryAggregation( cppu::UnoType<lang::XMultiServiceFactory>::get());
1153 uno::Reference< lang::XMultiServiceFactory > xOldModelFactory;
1154 if( (aAny >>= xOldModelFactory) && xOldModelFactory.is() )
1155 {
1156 return xOldModelFactory->createInstance( rServiceSpecifier );
1157 }
1158 }
1159 }
1160 return nullptr;
1161 }
1162
createInstanceWithArguments(const OUString & rServiceSpecifier,const Sequence<Any> & Arguments)1163 Reference< uno::XInterface > SAL_CALL ChartModel::createInstanceWithArguments(
1164 const OUString& rServiceSpecifier , const Sequence< Any >& Arguments )
1165 {
1166 OSL_ENSURE( Arguments.hasElements(), "createInstanceWithArguments: Warning: Arguments are ignored" );
1167 return createInstance( rServiceSpecifier );
1168 }
1169
getAvailableServiceNames()1170 Sequence< OUString > SAL_CALL ChartModel::getAvailableServiceNames()
1171 {
1172 uno::Sequence< OUString > aResult;
1173
1174 if( m_xOldModelAgg.is())
1175 {
1176 Any aAny = m_xOldModelAgg->queryAggregation( cppu::UnoType<lang::XMultiServiceFactory>::get());
1177 uno::Reference< lang::XMultiServiceFactory > xOldModelFactory;
1178 if( (aAny >>= xOldModelFactory) && xOldModelFactory.is() )
1179 {
1180 return xOldModelFactory->getAvailableServiceNames();
1181 }
1182 }
1183 return aResult;
1184 }
1185
getNumberFormatsSupplier()1186 Reference< util::XNumberFormatsSupplier > const & ChartModel::getNumberFormatsSupplier()
1187 {
1188 if( !m_xNumberFormatsSupplier.is() )
1189 {
1190 if( !m_xOwnNumberFormatsSupplier.is() )
1191 {
1192 m_apSvNumberFormatter.reset( new SvNumberFormatter( m_xContext, LANGUAGE_SYSTEM ) );
1193 m_xOwnNumberFormatsSupplier = new SvNumberFormatsSupplierObj( m_apSvNumberFormatter.get() );
1194 //pOwnNumberFormatter->ChangeStandardPrec( 15 ); todo?
1195 }
1196 m_xNumberFormatsSupplier = m_xOwnNumberFormatsSupplier;
1197 }
1198 return m_xNumberFormatsSupplier;
1199 }
1200
1201 // ____ XUnoTunnel ___
getSomething(const Sequence<::sal_Int8> & aIdentifier)1202 ::sal_Int64 SAL_CALL ChartModel::getSomething( const Sequence< ::sal_Int8 >& aIdentifier )
1203 {
1204 if( isUnoTunnelId<SvNumberFormatsSupplierObj>(aIdentifier) )
1205 {
1206 Reference< lang::XUnoTunnel > xTunnel( getNumberFormatsSupplier(), uno::UNO_QUERY );
1207 if( xTunnel.is() )
1208 return xTunnel->getSomething( aIdentifier );
1209 }
1210 return 0;
1211 }
1212
1213 // ____ XNumberFormatsSupplier ____
getNumberFormatSettings()1214 uno::Reference< beans::XPropertySet > SAL_CALL ChartModel::getNumberFormatSettings()
1215 {
1216 Reference< util::XNumberFormatsSupplier > xSupplier( getNumberFormatsSupplier() );
1217 if( xSupplier.is() )
1218 return xSupplier->getNumberFormatSettings();
1219 return uno::Reference< beans::XPropertySet >();
1220 }
1221
getNumberFormats()1222 uno::Reference< util::XNumberFormats > SAL_CALL ChartModel::getNumberFormats()
1223 {
1224 Reference< util::XNumberFormatsSupplier > xSupplier( getNumberFormatsSupplier() );
1225 if( xSupplier.is() )
1226 return xSupplier->getNumberFormats();
1227 return uno::Reference< util::XNumberFormats >();
1228 }
1229
1230 // ____ XChild ____
getParent()1231 Reference< uno::XInterface > SAL_CALL ChartModel::getParent()
1232 {
1233 return Reference< uno::XInterface >(m_xParent,uno::UNO_QUERY);
1234 }
1235
setParent(const Reference<uno::XInterface> & Parent)1236 void SAL_CALL ChartModel::setParent( const Reference< uno::XInterface >& Parent )
1237 {
1238 if( Parent != m_xParent )
1239 m_xParent.set( Parent, uno::UNO_QUERY );
1240 }
1241
1242 // ____ XDataSource ____
getDataSequences()1243 uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > SAL_CALL ChartModel::getDataSequences()
1244 {
1245 Reference< chart2::data::XDataSource > xSource(
1246 DataSourceHelper::getUsedData( uno::Reference< frame::XModel >(this) ) );
1247 if( xSource.is())
1248 return xSource->getDataSequences();
1249
1250 return uno::Sequence< Reference< chart2::data::XLabeledDataSequence > >();
1251 }
1252
1253 //XDumper
dump()1254 OUString SAL_CALL ChartModel::dump()
1255 {
1256 uno::Reference< qa::XDumper > xDumper(
1257 createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY );
1258 if (xDumper.is())
1259 return xDumper->dump();
1260
1261 return OUString();
1262 }
1263
setTimeBasedRange(sal_Int32 nStart,sal_Int32 nEnd)1264 void ChartModel::setTimeBasedRange(sal_Int32 nStart, sal_Int32 nEnd)
1265 {
1266 mnStart = nStart;
1267 mnEnd = nEnd;
1268 mbTimeBased = true;
1269 }
1270
update()1271 void ChartModel::update()
1272 {
1273 if(!mxChartView.is())
1274 {
1275 mxChartView = new ChartView( m_xContext, *this);
1276 }
1277 mxChartView->setViewDirty();
1278 mxChartView->update();
1279 }
1280
isDataFromSpreadsheet()1281 bool ChartModel::isDataFromSpreadsheet()
1282 {
1283 return !isDataFromPivotTable() && !hasInternalDataProvider();
1284 }
1285
isDataFromPivotTable() const1286 bool ChartModel::isDataFromPivotTable() const
1287 {
1288 uno::Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(m_xDataProvider, uno::UNO_QUERY);
1289 return xPivotTableDataProvider.is();
1290 }
1291
1292 } // namespace chart
1293
1294 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_chart2_ChartModel_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)1295 com_sun_star_comp_chart2_ChartModel_get_implementation(css::uno::XComponentContext *context,
1296 css::uno::Sequence<css::uno::Any> const &)
1297 {
1298 return cppu::acquire(new ::chart::ChartModel(context));
1299 }
1300
1301 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1302