xref: /trunk/main/sc/source/ui/unoobj/chartuno.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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sc.hxx"
24 
25 #include <com/sun/star/embed/Aspects.hpp>
26 #include <com/sun/star/awt/Size.hpp>
27 #include <com/sun/star/beans/PropertyAttribute.hpp>
28 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
29 #include <com/sun/star/chart/ChartDataRowSource.hpp>
30 #include <com/sun/star/chart2/XChartDocument.hpp>
31 #include <com/sun/star/embed/Aspects.hpp>
32 #include <com/sun/star/table/CellRangeAddress.hpp>
33 
34 #include <svx/svditer.hxx>
35 #include <svx/svdoole2.hxx>
36 #include <svx/svdpage.hxx>
37 #include <svx/svdundo.hxx>
38 #include <sfx2/app.hxx>
39 #include <unotools/moduleoptions.hxx>
40 #include <sot/clsids.hxx>
41 #include <toolkit/helper/vclunohelper.hxx>
42 #include <svx/charthelper.hxx>
43 
44 #include "chartuno.hxx"
45 #include "miscuno.hxx"
46 #include "docsh.hxx"
47 #include "drwlayer.hxx"
48 #include "undodat.hxx"
49 #include "chartarr.hxx"
50 #include "chartlis.hxx"
51 #include "unoguard.hxx"
52 #include "chart2uno.hxx"
53 #include "convuno.hxx"
54 
55 using namespace com::sun::star;
56 
57 #define PROP_HANDLE_RELATED_CELLRANGES  1
58 
59 //------------------------------------------------------------------------
60 
61 SC_SIMPLE_SERVICE_INFO( ScChartObj, "ScChartObj", "com.sun.star.table.TableChart" )
62 SC_SIMPLE_SERVICE_INFO( ScChartsObj, "ScChartsObj", "com.sun.star.table.TableCharts" )
63 
64 //------------------------------------------------------------------------
65 
lcl_FindChartObj(ScDocShell * pDocShell,SCTAB nTab,const String & rName)66 SdrOle2Obj* lcl_FindChartObj( ScDocShell* pDocShell, SCTAB nTab, const String& rName )
67 {
68     if (pDocShell)
69     {
70         ScDocument* pDoc = pDocShell->GetDocument();
71         ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
72         if (pDrawLayer)
73         {
74             SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
75             DBG_ASSERT(pPage, "Page nicht gefunden");
76             if (pPage)
77             {
78                 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
79                 SdrObject* pObject = aIter.Next();
80                 while (pObject)
81                 {
82                     if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) )
83                     {
84                         uno::Reference < embed::XEmbeddedObject > xObj = ((SdrOle2Obj*)pObject)->GetObjRef();
85                         if ( xObj.is() )
86                         {
87                             String aObjName = pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName( xObj );
88                             if ( aObjName == rName )
89                                 return (SdrOle2Obj*)pObject;
90                         }
91                     }
92                     pObject = aIter.Next();
93                 }
94             }
95         }
96     }
97     return NULL;
98 }
99 
100 //------------------------------------------------------------------------
101 
ScChartsObj(ScDocShell * pDocSh,SCTAB nT)102 ScChartsObj::ScChartsObj(ScDocShell* pDocSh, SCTAB nT) :
103     pDocShell( pDocSh ),
104     nTab( nT )
105 {
106     pDocShell->GetDocument()->AddUnoObject(*this);
107 }
108 
~ScChartsObj()109 ScChartsObj::~ScChartsObj()
110 {
111     if (pDocShell)
112         pDocShell->GetDocument()->RemoveUnoObject(*this);
113 }
114 
Notify(SfxBroadcaster &,const SfxHint & rHint)115 void ScChartsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
116 {
117     //! Referenz-Update
118 
119     if ( rHint.ISA( SfxSimpleHint ) &&
120             ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
121     {
122         pDocShell = NULL;       // ungueltig geworden
123     }
124 }
125 
GetObjectByIndex_Impl(long nIndex) const126 ScChartObj* ScChartsObj::GetObjectByIndex_Impl(long nIndex) const
127 {
128     String aName;
129     if ( pDocShell )
130     {
131         ScDocument* pDoc = pDocShell->GetDocument();
132         ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
133         if (pDrawLayer)
134         {
135             SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
136             DBG_ASSERT(pPage, "Page nicht gefunden");
137             if (pPage)
138             {
139                 long nPos = 0;
140                 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
141                 SdrObject* pObject = aIter.Next();
142                 while (pObject)
143                 {
144                     if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) )
145                     {
146                         if ( nPos == nIndex )
147                         {
148                             uno::Reference < embed::XEmbeddedObject > xObj = ((SdrOle2Obj*)pObject)->GetObjRef();
149                             if ( xObj.is() )
150                                 aName = pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName( xObj );
151                             break;  // nicht weitersuchen
152                         }
153                         ++nPos;
154                     }
155                     pObject = aIter.Next();
156                 }
157             }
158         }
159     }
160 
161     if (aName.Len())
162         return new ScChartObj( pDocShell, nTab, aName );
163     return NULL;
164 }
165 
GetObjectByName_Impl(const rtl::OUString & aName) const166 ScChartObj* ScChartsObj::GetObjectByName_Impl(const rtl::OUString& aName) const
167 {
168     String aNameString(aName);
169     if ( lcl_FindChartObj( pDocShell, nTab, aNameString ) )
170         return new ScChartObj( pDocShell, nTab, aNameString );
171     return NULL;
172 }
173 
174 // XTableCharts
175 
addNewByName(const rtl::OUString & aName,const awt::Rectangle & aRect,const uno::Sequence<table::CellRangeAddress> & aRanges,sal_Bool bColumnHeaders,sal_Bool bRowHeaders)176 void SAL_CALL ScChartsObj::addNewByName( const rtl::OUString& aName,
177                                         const awt::Rectangle& aRect,
178                                         const uno::Sequence<table::CellRangeAddress>& aRanges,
179                                         sal_Bool bColumnHeaders, sal_Bool bRowHeaders )
180 {
181     ScUnoGuard aGuard;
182     if (!pDocShell)
183         return;
184 
185     ScDocument* pDoc = pDocShell->GetDocument();
186     ScDrawLayer* pModel = pDocShell->MakeDrawLayer();
187     SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
188     DBG_ASSERT(pPage,"addChart: keine Page");
189     if (!pPage || !pDoc)
190         return;
191 
192     //  chart can't be inserted if any ole object with that name exists on any table
193     //  (empty string: generate valid name)
194 
195     String aNameString(aName);
196     SCTAB nDummy;
197     if ( aNameString.Len() && pModel->GetNamedObject( aNameString, OBJ_OLE2, nDummy ) )
198     {
199         //  object exists - only RuntimeException is specified
200         throw uno::RuntimeException();
201     }
202 
203     ScRangeList* pList = new ScRangeList;
204     sal_uInt16 nRangeCount = (sal_uInt16)aRanges.getLength();
205     if (nRangeCount)
206     {
207         const table::CellRangeAddress* pAry = aRanges.getConstArray();
208         for (sal_uInt16 i=0; i<nRangeCount; i++)
209         {
210             ScRange aRange( static_cast<SCCOL>(pAry[i].StartColumn), pAry[i].StartRow, pAry[i].Sheet,
211                             static_cast<SCCOL>(pAry[i].EndColumn),   pAry[i].EndRow,   pAry[i].Sheet );
212             pList->Append( aRange );
213         }
214     }
215     ScRangeListRef xNewRanges( pList );
216 
217     uno::Reference < embed::XEmbeddedObject > xObj;
218     ::rtl::OUString aTmp( aNameString );
219     if ( SvtModuleOptions().IsChart() )
220         xObj = pDocShell->GetEmbeddedObjectContainer().CreateEmbeddedObject( SvGlobalName( SO3_SCH_CLASSID ).GetByteSequence(), aTmp );
221     if ( xObj.is() )
222     {
223             String aObjName = aTmp;       // wirklich eingefuegter Name...
224 
225             //  Rechteck anpassen
226             //! Fehler/Exception, wenn leer/ungueltig ???
227             Point aRectPos( aRect.X, aRect.Y );
228             bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
229             if ( ( aRectPos.X() < 0 && !bLayoutRTL ) || ( aRectPos.X() > 0 && bLayoutRTL ) ) aRectPos.X() = 0;
230             if (aRectPos.Y() < 0) aRectPos.Y() = 0;
231             Size aRectSize( aRect.Width, aRect.Height );
232             if (aRectSize.Width() <= 0) aRectSize.Width() = 5000;   // Default-Groesse
233             if (aRectSize.Height() <= 0) aRectSize.Height() = 5000;
234             Rectangle aInsRect( aRectPos, aRectSize );
235 
236             sal_Int64 nAspect(embed::Aspects::MSOLE_CONTENT);
237             MapUnit aMapUnit(VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) ));
238             Size aSize(aInsRect.GetSize());
239             aSize = Window::LogicToLogic( aSize, MapMode( MAP_100TH_MM ), MapMode( aMapUnit ) );
240             awt::Size aSz;
241             aSz.Width = aSize.Width();
242             aSz.Height = aSize.Height();
243 
244             // Calc -> DataProvider
245             uno::Reference< chart2::data::XDataProvider > xDataProvider = new
246                 ScChart2DataProvider( pDoc );
247             // Chart -> DataReceiver
248             uno::Reference< chart2::data::XDataReceiver > xReceiver;
249             uno::Reference< embed::XComponentSupplier > xCompSupp( xObj, uno::UNO_QUERY );
250             if( xCompSupp.is())
251                 xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY );
252             if( xReceiver.is())
253             {
254                 String sRangeStr;
255                 xNewRanges->Format(sRangeStr, SCR_ABS_3D, pDoc);
256 
257                 // connect
258                 if( sRangeStr.Len() )
259                     xReceiver->attachDataProvider( xDataProvider );
260                 else
261                     sRangeStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( "all" ) );
262 
263                 uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( pDocShell->GetModel(), uno::UNO_QUERY );
264                 xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
265 
266                 // set arguments
267                 uno::Sequence< beans::PropertyValue > aArgs( 4 );
268                 aArgs[0] = beans::PropertyValue(
269                     ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1,
270                     uno::makeAny( ::rtl::OUString( sRangeStr )), beans::PropertyState_DIRECT_VALUE );
271                 aArgs[1] = beans::PropertyValue(
272                     ::rtl::OUString::createFromAscii("HasCategories"), -1,
273                     uno::makeAny( bRowHeaders ), beans::PropertyState_DIRECT_VALUE );
274                 aArgs[2] = beans::PropertyValue(
275                     ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1,
276                     uno::makeAny( bColumnHeaders ), beans::PropertyState_DIRECT_VALUE );
277                 aArgs[3] = beans::PropertyValue(
278                     ::rtl::OUString::createFromAscii("DataRowSource"), -1,
279                     uno::makeAny( chart::ChartDataRowSource_COLUMNS ), beans::PropertyState_DIRECT_VALUE );
280                 xReceiver->setArguments( aArgs );
281             }
282 
283             ScChartListener* pChartListener =
284                 new ScChartListener( aObjName, pDoc, xNewRanges );
285             pDoc->GetChartListenerCollection()->Insert( pChartListener );
286             pChartListener->StartListeningTo();
287 
288             SdrOle2Obj* pObj = new SdrOle2Obj( ::svt::EmbeddedObjectRef( xObj, embed::Aspects::MSOLE_CONTENT ), aObjName, aInsRect );
289 
290             // set VisArea
291             if( xObj.is())
292                 xObj->setVisualAreaSize( nAspect, aSz );
293 
294             // #121334# This call will change the chart's default background fill from white to transparent.
295             // Add here again if this is wanted (see task description for details)
296             // ChartHelper::AdaptDefaultsForChart( xObj );
297 
298             pPage->InsertObject( pObj );
299             pModel->AddUndo( new SdrUndoNewObj( *pObj ) );
300 
301             // Dies veranlaesst Chart zum sofortigen Update
302             //SvData aEmpty;
303             //aIPObj->SendDataChanged( aEmpty );
304     }
305 }
306 
removeByName(const rtl::OUString & aName)307 void SAL_CALL ScChartsObj::removeByName( const rtl::OUString& aName )
308 {
309     ScUnoGuard aGuard;
310     String aNameString(aName);
311     SdrOle2Obj* pObj = lcl_FindChartObj( pDocShell, nTab, aNameString );
312     if (pObj)
313     {
314         ScDocument* pDoc = pDocShell->GetDocument();
315         ScDrawLayer* pModel = pDoc->GetDrawLayer();     // ist nicht 0
316         SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));    // ist nicht 0
317 
318         pModel->AddUndo( new SdrUndoDelObj( *pObj ) );
319         pPage->RemoveObject( pObj->GetOrdNum() );
320 
321         //! Notify etc.???
322     }
323 }
324 
325 // XEnumerationAccess
326 
createEnumeration()327 uno::Reference<container::XEnumeration> SAL_CALL ScChartsObj::createEnumeration()
328 {
329     ScUnoGuard aGuard;
330     return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.TableChartsEnumeration")));
331 }
332 
333 // XIndexAccess
334 
getCount()335 sal_Int32 SAL_CALL ScChartsObj::getCount()
336 {
337     ScUnoGuard aGuard;
338     sal_Int32 nCount = 0;
339     if ( pDocShell )
340     {
341         ScDocument* pDoc = pDocShell->GetDocument();
342         ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
343         if (pDrawLayer)
344         {
345             SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
346             DBG_ASSERT(pPage, "Page nicht gefunden");
347             if (pPage)
348             {
349                 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
350                 SdrObject* pObject = aIter.Next();
351                 while (pObject)
352                 {
353                     if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) )
354                         ++nCount;
355                     pObject = aIter.Next();
356                 }
357             }
358         }
359     }
360     return nCount;
361 }
362 
getByIndex(sal_Int32 nIndex)363 uno::Any SAL_CALL ScChartsObj::getByIndex( sal_Int32 nIndex )
364 {
365     ScUnoGuard aGuard;
366     uno::Reference<table::XTableChart> xChart(GetObjectByIndex_Impl(nIndex));
367     if (xChart.is())
368         return uno::makeAny(xChart);
369     else
370         throw lang::IndexOutOfBoundsException();
371 //    return uno::Any();
372 }
373 
getElementType()374 uno::Type SAL_CALL ScChartsObj::getElementType()
375 {
376     ScUnoGuard aGuard;
377     return getCppuType((uno::Reference<table::XTableChart>*)0);
378 }
379 
hasElements()380 sal_Bool SAL_CALL ScChartsObj::hasElements()
381 {
382     ScUnoGuard aGuard;
383     return getCount() != 0;
384 }
385 
getByName(const rtl::OUString & aName)386 uno::Any SAL_CALL ScChartsObj::getByName( const rtl::OUString& aName )
387 {
388     ScUnoGuard aGuard;
389     uno::Reference<table::XTableChart> xChart(GetObjectByName_Impl(aName));
390     if (xChart.is())
391         return uno::makeAny(xChart);
392     else
393         throw container::NoSuchElementException();
394 //    return uno::Any();
395 }
396 
getElementNames()397 uno::Sequence<rtl::OUString> SAL_CALL ScChartsObj::getElementNames()
398 {
399     ScUnoGuard aGuard;
400     if (pDocShell)
401     {
402         ScDocument* pDoc = pDocShell->GetDocument();
403 
404         long nCount = getCount();
405         uno::Sequence<rtl::OUString> aSeq(nCount);
406         rtl::OUString* pAry = aSeq.getArray();
407 
408         long nPos = 0;
409         ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
410         if (pDrawLayer)
411         {
412             SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
413             DBG_ASSERT(pPage, "Page nicht gefunden");
414             if (pPage)
415             {
416                 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
417                 SdrObject* pObject = aIter.Next();
418                 while (pObject)
419                 {
420                     if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) )
421                     {
422                         String aName;
423                         uno::Reference < embed::XEmbeddedObject > xObj = ((SdrOle2Obj*)pObject)->GetObjRef();
424                         if ( xObj.is() )
425                             aName = pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName( xObj );
426 
427                         DBG_ASSERT(nPos<nCount, "huch, verzaehlt?");
428                         pAry[nPos++] = aName;
429                     }
430                     pObject = aIter.Next();
431                 }
432             }
433         }
434         DBG_ASSERT(nPos==nCount, "nanu, verzaehlt?");
435 
436         return aSeq;
437     }
438     return uno::Sequence<rtl::OUString>(0);
439 }
440 
hasByName(const rtl::OUString & aName)441 sal_Bool SAL_CALL ScChartsObj::hasByName( const rtl::OUString& aName )
442 {
443     ScUnoGuard aGuard;
444     String aNameString(aName);
445     return ( lcl_FindChartObj( pDocShell, nTab, aNameString ) != NULL );
446 }
447 
448 //------------------------------------------------------------------------
449 
ScChartObj(ScDocShell * pDocSh,SCTAB nT,const String & rN)450 ScChartObj::ScChartObj(ScDocShell* pDocSh, SCTAB nT, const String& rN)
451     :ScChartObj_Base( m_aMutex )
452     ,ScChartObj_PBase( ScChartObj_Base::rBHelper )
453     ,pDocShell( pDocSh )
454     ,nTab( nT )
455     ,aChartName( rN )
456 {
457     pDocShell->GetDocument()->AddUnoObject(*this);
458     SdrOle2Obj* pObject = lcl_FindChartObj( pDocShell, nTab, aChartName );
459     if ( pObject && svt::EmbeddedObjectRef::TryRunningState( pObject->GetObjRef() ) )
460         aObjectName = pObject->GetName();   // #i121178#: keep the OLE object's name
461     uno::Sequence< table::CellRangeAddress > aInitialPropValue;
462     registerPropertyNoMember( ::rtl::OUString::createFromAscii( "RelatedCellRanges" ),
463         PROP_HANDLE_RELATED_CELLRANGES, beans::PropertyAttribute::MAYBEVOID,
464         ::getCppuType( &aInitialPropValue ), &aInitialPropValue );
465 }
466 
~ScChartObj()467 ScChartObj::~ScChartObj()
468 {
469     if (pDocShell)
470         pDocShell->GetDocument()->RemoveUnoObject(*this);
471 }
472 
Notify(SfxBroadcaster &,const SfxHint & rHint)473 void ScChartObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
474 {
475     //! Referenz-Update
476 
477     if ( rHint.ISA( SfxSimpleHint ) &&
478             ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
479     {
480         pDocShell = NULL;       // ungueltig geworden
481     }
482 }
483 
GetData_Impl(ScRangeListRef & rRanges,bool & rColHeaders,bool & rRowHeaders) const484 void ScChartObj::GetData_Impl( ScRangeListRef& rRanges, bool& rColHeaders, bool& rRowHeaders ) const
485 {
486     bool bFound = false;
487     ScDocument* pDoc = (pDocShell? pDocShell->GetDocument(): 0);
488 
489     if( pDoc )
490     {
491         uno::Reference< chart2::XChartDocument > xChartDoc( pDoc->GetChartByName( aChartName ) );
492         if( xChartDoc.is() )
493         {
494             uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
495             uno::Reference< chart2::data::XDataProvider > xProvider = xChartDoc->getDataProvider();
496             if( xReceiver.is() && xProvider.is() )
497             {
498                 uno::Sequence< beans::PropertyValue > aArgs( xProvider->detectArguments( xReceiver->getUsedData() ) );
499 
500                 rtl::OUString aRanges;
501                 chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
502                 bool bHasCategories=false;
503                 bool bFirstCellAsLabel=false;
504                 const beans::PropertyValue* pPropArray = aArgs.getConstArray();
505                 long nPropCount = aArgs.getLength();
506                 for (long i = 0; i < nPropCount; i++)
507                 {
508                     const beans::PropertyValue& rProp = pPropArray[i];
509                     String aPropName(rProp.Name);
510 
511                     if (aPropName.EqualsAscii( "CellRangeRepresentation" ))
512                         rProp.Value >>= aRanges;
513                     else if (aPropName.EqualsAscii( "DataRowSource" ))
514                         eDataRowSource = (chart::ChartDataRowSource)ScUnoHelpFunctions::GetEnumFromAny( rProp.Value );
515                     else if (aPropName.EqualsAscii( "HasCategories" ))
516                         bHasCategories = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
517                     else if (aPropName.EqualsAscii( "FirstCellAsLabel" ))
518                         bFirstCellAsLabel = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
519                 }
520 
521                 if( chart::ChartDataRowSource_COLUMNS == eDataRowSource )
522                 {
523                     rColHeaders=bFirstCellAsLabel;
524                     rRowHeaders=bHasCategories;
525                 }
526                 else
527                 {
528                     rColHeaders=bHasCategories;
529                     rRowHeaders=bFirstCellAsLabel;
530                 }
531                 rRanges->Parse( aRanges, pDoc);
532             }
533             bFound = true;
534         }
535     }
536     if( !bFound )
537     {
538         rRanges = 0;
539         rColHeaders = false;
540         rRowHeaders = false;
541     }
542 }
543 
Update_Impl(const ScRangeListRef & rRanges,bool bColHeaders,bool bRowHeaders)544 void ScChartObj::Update_Impl( const ScRangeListRef& rRanges, bool bColHeaders, bool bRowHeaders )
545 {
546     if (pDocShell)
547     {
548         ScDocument* pDoc = pDocShell->GetDocument();
549         sal_Bool bUndo(pDoc->IsUndoEnabled());
550 
551         if (bUndo)
552         {
553             pDocShell->GetUndoManager()->AddUndoAction(
554                 new ScUndoChartData( pDocShell, aChartName, rRanges, bColHeaders, bRowHeaders, sal_False ) );
555         }
556         pDoc->UpdateChartArea( aChartName, rRanges, bColHeaders, bRowHeaders, sal_False );
557     }
558 }
559 
560 // ::comphelper::OPropertySetHelper
561 
getInfoHelper()562 ::cppu::IPropertyArrayHelper& ScChartObj::getInfoHelper()
563 {
564     return *ScChartObj_PABase::getArrayHelper();
565 }
566 
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const uno::Any & rValue)567 void ScChartObj::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const uno::Any& rValue )
568 {
569     switch ( nHandle )
570     {
571         case PROP_HANDLE_RELATED_CELLRANGES:
572             {
573                 uno::Sequence< table::CellRangeAddress > aCellRanges;
574                 if ( rValue >>= aCellRanges )
575                 {
576                     ScRangeListRef rRangeList = new ScRangeList();
577                     const table::CellRangeAddress* pCellRanges = aCellRanges.getArray();
578                     sal_Int32 nCount = aCellRanges.getLength();
579                     for ( sal_Int32 i = 0; i < nCount; ++i )
580                     {
581                         table::CellRangeAddress aCellRange = pCellRanges[ i ];
582                         ScRange aRange;
583                         ScUnoConversion::FillScRange( aRange, aCellRange );
584                         rRangeList->Append( aRange );
585                     }
586                     ScDocument* pDoc = ( pDocShell ? pDocShell->GetDocument() : NULL );
587                     ScChartListenerCollection* pCollection = ( pDoc ? pDoc->GetChartListenerCollection() : NULL );
588                     if ( pCollection )
589                     {
590                         pCollection->ChangeListening( aChartName, rRangeList );
591                     }
592                 }
593             }
594             break;
595         default:
596             {
597             }
598             break;
599     }
600 }
601 
getFastPropertyValue(uno::Any & rValue,sal_Int32 nHandle) const602 void ScChartObj::getFastPropertyValue( uno::Any& rValue, sal_Int32 nHandle ) const
603 {
604     switch ( nHandle )
605     {
606         case PROP_HANDLE_RELATED_CELLRANGES:
607             {
608                 ScDocument* pDoc = ( pDocShell ? pDocShell->GetDocument() : NULL );
609                 if ( pDoc )
610                 {
611                     ScRange aEmptyRange;
612                     sal_uInt16 nIndex = 0;
613                     ScChartListener aSearcher( aChartName, pDoc, aEmptyRange );
614                     ScChartListenerCollection* pCollection = pDoc->GetChartListenerCollection();
615                     if ( pCollection && pCollection->Search( &aSearcher, nIndex ) )
616                     {
617                         ScChartListener* pListener = static_cast< ScChartListener* >( pCollection->At( nIndex ) );
618                         if ( pListener )
619                         {
620                             const ScRangeListRef& rRangeList = pListener->GetRangeList();
621                             if ( rRangeList.Is() )
622                             {
623                                 sal_uLong nCount = rRangeList->Count();
624                                 uno::Sequence< table::CellRangeAddress > aCellRanges( nCount );
625                                 table::CellRangeAddress* pCellRanges = aCellRanges.getArray();
626                                 for ( sal_uInt16 i = 0; i < nCount; ++i )
627                                 {
628                                     ScRange aRange( *rRangeList->GetObject( i ) );
629                                     table::CellRangeAddress aCellRange;
630                                     ScUnoConversion::FillApiRange( aCellRange, aRange );
631                                     pCellRanges[ i ] = aCellRange;
632                                 }
633                                 rValue <<= aCellRanges;
634                             }
635                         }
636                     }
637                 }
638             }
639             break;
640         default:
641             {
642             }
643             break;
644     }
645 }
646 
647 // ::comphelper::OPropertyArrayUsageHelper
648 
createArrayHelper() const649 ::cppu::IPropertyArrayHelper* ScChartObj::createArrayHelper() const
650 {
651     uno::Sequence< beans::Property > aProps;
652     describeProperties( aProps );
653     return new ::cppu::OPropertyArrayHelper( aProps );
654 }
655 
656 // XInterface
657 
IMPLEMENT_FORWARD_XINTERFACE2(ScChartObj,ScChartObj_Base,ScChartObj_PBase)658 IMPLEMENT_FORWARD_XINTERFACE2( ScChartObj, ScChartObj_Base, ScChartObj_PBase )
659 
660 // XTypeProvider
661 
662 IMPLEMENT_FORWARD_XTYPEPROVIDER2( ScChartObj, ScChartObj_Base, ScChartObj_PBase )
663 
664 // XComponent
665 
666 void ScChartObj::disposing()
667 {
668     ScChartObj_Base::disposing();
669 }
670 
671 // XTableChart
672 
getHasColumnHeaders()673 sal_Bool SAL_CALL ScChartObj::getHasColumnHeaders()
674 {
675     ScUnoGuard aGuard;
676     ScRangeListRef xRanges = new ScRangeList;
677     bool bColHeaders, bRowHeaders;
678     GetData_Impl( xRanges, bColHeaders, bRowHeaders );
679     return bColHeaders;
680 }
681 
setHasColumnHeaders(sal_Bool bHasColumnHeaders)682 void SAL_CALL ScChartObj::setHasColumnHeaders( sal_Bool bHasColumnHeaders )
683 {
684     ScUnoGuard aGuard;
685     ScRangeListRef xRanges = new ScRangeList;
686     bool bOldColHeaders, bOldRowHeaders;
687     GetData_Impl( xRanges, bOldColHeaders, bOldRowHeaders );
688     if ( bOldColHeaders != (bHasColumnHeaders != sal_False) )
689         Update_Impl( xRanges, bHasColumnHeaders, bOldRowHeaders );
690 }
691 
getHasRowHeaders()692 sal_Bool SAL_CALL ScChartObj::getHasRowHeaders()
693 {
694     ScUnoGuard aGuard;
695     ScRangeListRef xRanges = new ScRangeList;
696     bool bColHeaders, bRowHeaders;
697     GetData_Impl( xRanges, bColHeaders, bRowHeaders );
698     return bRowHeaders;
699 }
700 
setHasRowHeaders(sal_Bool bHasRowHeaders)701 void SAL_CALL ScChartObj::setHasRowHeaders( sal_Bool bHasRowHeaders )
702 {
703     ScUnoGuard aGuard;
704     ScRangeListRef xRanges = new ScRangeList;
705     bool bOldColHeaders, bOldRowHeaders;
706     GetData_Impl( xRanges, bOldColHeaders, bOldRowHeaders );
707     if ( bOldRowHeaders != (bHasRowHeaders != sal_False) )
708         Update_Impl( xRanges, bOldColHeaders, bHasRowHeaders );
709 }
710 
getRanges()711 uno::Sequence<table::CellRangeAddress> SAL_CALL ScChartObj::getRanges()
712 {
713     ScUnoGuard aGuard;
714     ScRangeListRef xRanges = new ScRangeList;
715     bool bColHeaders, bRowHeaders;
716     GetData_Impl( xRanges, bColHeaders, bRowHeaders );
717     if ( xRanges.Is() )
718     {
719         sal_uLong nCount = xRanges->Count();
720 
721         table::CellRangeAddress aRangeAddress;
722         uno::Sequence<table::CellRangeAddress> aSeq(nCount);
723         table::CellRangeAddress* pAry = aSeq.getArray();
724         for (sal_uInt16 i=0; i<nCount; i++)
725         {
726             ScRange aRange(*xRanges->GetObject(i));
727 
728             aRangeAddress.Sheet       = aRange.aStart.Tab();
729             aRangeAddress.StartColumn = aRange.aStart.Col();
730             aRangeAddress.StartRow    = aRange.aStart.Row();
731             aRangeAddress.EndColumn   = aRange.aEnd.Col();
732             aRangeAddress.EndRow      = aRange.aEnd.Row();
733 
734             pAry[i] = aRangeAddress;
735         }
736         return aSeq;
737     }
738 
739     DBG_ERROR("ScChartObj::getRanges: keine Ranges");
740     return uno::Sequence<table::CellRangeAddress>();
741 }
742 
setRanges(const uno::Sequence<table::CellRangeAddress> & aRanges)743 void SAL_CALL ScChartObj::setRanges( const uno::Sequence<table::CellRangeAddress>& aRanges )
744 {
745     ScUnoGuard aGuard;
746     ScRangeListRef xOldRanges = new ScRangeList;
747     bool bColHeaders, bRowHeaders;
748     GetData_Impl( xOldRanges, bColHeaders, bRowHeaders );
749 
750     ScRangeList* pList = new ScRangeList;
751     sal_uInt16 nRangeCount = (sal_uInt16)aRanges.getLength();
752     if (nRangeCount)
753     {
754         const table::CellRangeAddress* pAry = aRanges.getConstArray();
755         for (sal_uInt16 i=0; i<nRangeCount; i++)
756         {
757             ScRange aRange( static_cast<SCCOL>(pAry[i].StartColumn), pAry[i].StartRow, pAry[i].Sheet,
758                             static_cast<SCCOL>(pAry[i].EndColumn),   pAry[i].EndRow,   pAry[i].Sheet );
759             pList->Append( aRange );
760         }
761     }
762     ScRangeListRef xNewRanges( pList );
763 
764     if ( !xOldRanges.Is() || *xOldRanges != *xNewRanges )
765         Update_Impl( xNewRanges, bColHeaders, bRowHeaders );
766 }
767 
768 // XEmbeddedObjectSupplier
769 
getEmbeddedObject()770 uno::Reference<lang::XComponent> SAL_CALL ScChartObj::getEmbeddedObject()
771 {
772     ScUnoGuard aGuard;
773     SdrOle2Obj* pObject = lcl_FindChartObj( pDocShell, nTab, aChartName );
774     if ( pObject && svt::EmbeddedObjectRef::TryRunningState( pObject->GetObjRef() ) )
775     {
776         //TODO/LATER: is it OK that something is returned for *all* objects, not only own objects?
777         return uno::Reference < lang::XComponent > ( pObject->GetObjRef()->getComponent(), uno::UNO_QUERY );
778     }
779 
780     return NULL;
781 }
782 
783 // XNamed
784 
getName()785 rtl::OUString SAL_CALL ScChartObj::getName()
786 {
787     ScUnoGuard aGuard;
788     return aChartName;
789 }
790 
setName(const rtl::OUString &)791 void SAL_CALL ScChartObj::setName( const rtl::OUString& /* aName */ )
792 {
793     ScUnoGuard aGuard;
794     throw uno::RuntimeException();      // name cannot be changed
795 }
796 
797 // XNamedEx
798 
getDisplayName()799 rtl::OUString SAL_CALL ScChartObj::getDisplayName()
800 {
801     ScUnoGuard aGuard;
802     return aObjectName;
803 }
804 
setDisplayName(const rtl::OUString & aName)805 void SAL_CALL ScChartObj::setDisplayName( const rtl::OUString& aName )
806 {
807     ScUnoGuard aGuard;
808     aObjectName = aName;
809 }
810 
811 // XPropertySet
812 
getPropertySetInfo()813 uno::Reference< beans::XPropertySetInfo > ScChartObj::getPropertySetInfo()
814 {
815     return createPropertySetInfo( getInfoHelper() ) ;
816 }
817 
818 //------------------------------------------------------------------------
819