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