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