xref: /aoo41x/main/sc/source/ui/unoobj/chartuno.cxx (revision 7d1ce60b)
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 
43 #include "chartuno.hxx"
44 #include "miscuno.hxx"
45 #include "docsh.hxx"
46 #include "drwlayer.hxx"
47 #include "undodat.hxx"
48 #include "chartarr.hxx"
49 #include "chartlis.hxx"
50 #include "unoguard.hxx"
51 #include "chart2uno.hxx"
52 #include "convuno.hxx"
53 
54 using namespace com::sun::star;
55 
56 #define PROP_HANDLE_RELATED_CELLRANGES  1
57 
58 //------------------------------------------------------------------------
59 
60 SC_SIMPLE_SERVICE_INFO( ScChartObj, "ScChartObj", "com.sun.star.table.TableChart" )
61 SC_SIMPLE_SERVICE_INFO( ScChartsObj, "ScChartsObj", "com.sun.star.table.TableCharts" )
62 
63 //------------------------------------------------------------------------
64 
65 SdrOle2Obj* lcl_FindChartObj( ScDocShell* pDocShell, SCTAB nTab, const String& rName )
66 {
67 	if (pDocShell)
68 	{
69 		ScDocument* pDoc = pDocShell->GetDocument();
70 		ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
71 		if (pDrawLayer)
72 		{
73 			SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
74 			DBG_ASSERT(pPage, "Page nicht gefunden");
75 			if (pPage)
76 			{
77 				SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
78 				SdrObject* pObject = aIter.Next();
79 				while (pObject)
80 				{
81 					if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) )
82 					{
83                         uno::Reference < embed::XEmbeddedObject > xObj = ((SdrOle2Obj*)pObject)->GetObjRef();
84                         if ( xObj.is() )
85 						{
86                             String aObjName = pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName( xObj );
87                             if ( aObjName == rName )
88                                 return (SdrOle2Obj*)pObject;
89 						}
90 					}
91 					pObject = aIter.Next();
92 				}
93 			}
94 		}
95 	}
96 	return NULL;
97 }
98 
99 //------------------------------------------------------------------------
100 
101 ScChartsObj::ScChartsObj(ScDocShell* pDocSh, SCTAB nT) :
102 	pDocShell( pDocSh ),
103 	nTab( nT )
104 {
105 	pDocShell->GetDocument()->AddUnoObject(*this);
106 }
107 
108 ScChartsObj::~ScChartsObj()
109 {
110 	if (pDocShell)
111 		pDocShell->GetDocument()->RemoveUnoObject(*this);
112 }
113 
114 void ScChartsObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
115 {
116 	//!	Referenz-Update
117 
118 	if ( rHint.ISA( SfxSimpleHint ) &&
119 			((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
120 	{
121 		pDocShell = NULL;		// ungueltig geworden
122 	}
123 }
124 
125 ScChartObj* ScChartsObj::GetObjectByIndex_Impl(long nIndex) const
126 {
127 	String aName;
128 	if ( pDocShell )
129 	{
130 		ScDocument* pDoc = pDocShell->GetDocument();
131 		ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
132 		if (pDrawLayer)
133 		{
134 			SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
135 			DBG_ASSERT(pPage, "Page nicht gefunden");
136 			if (pPage)
137 			{
138 				long nPos = 0;
139 				SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
140 				SdrObject* pObject = aIter.Next();
141 				while (pObject)
142 				{
143 					if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) )
144 					{
145 						if ( nPos == nIndex )
146 						{
147                             uno::Reference < embed::XEmbeddedObject > xObj = ((SdrOle2Obj*)pObject)->GetObjRef();
148                             if ( xObj.is() )
149                                 aName = pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName( xObj );
150 							break;	// nicht weitersuchen
151 						}
152 						++nPos;
153 					}
154 					pObject = aIter.Next();
155 				}
156 			}
157 		}
158 	}
159 
160 	if (aName.Len())
161 		return new ScChartObj( pDocShell, nTab, aName );
162 	return NULL;
163 }
164 
165 ScChartObj* ScChartsObj::GetObjectByName_Impl(const rtl::OUString& aName) const
166 {
167 	String aNameString(aName);
168 	if ( lcl_FindChartObj( pDocShell, nTab, aNameString ) )
169 		return new ScChartObj( pDocShell, nTab, aNameString );
170 	return NULL;
171 }
172 
173 // XTableCharts
174 
175 void SAL_CALL ScChartsObj::addNewByName( const rtl::OUString& aName,
176 										const awt::Rectangle& aRect,
177 										const uno::Sequence<table::CellRangeAddress>& aRanges,
178 										sal_Bool bColumnHeaders, sal_Bool bRowHeaders )
179 									throw(::com::sun::star::uno::RuntimeException)
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 			pPage->InsertObject( pObj );
295             pModel->AddUndo( new SdrUndoNewObj( *pObj ) );
296 
297 			// Dies veranlaesst Chart zum sofortigen Update
298 			//SvData aEmpty;
299 			//aIPObj->SendDataChanged( aEmpty );
300 	}
301 }
302 
303 void SAL_CALL ScChartsObj::removeByName( const rtl::OUString& aName )
304 											throw(uno::RuntimeException)
305 {
306 	ScUnoGuard aGuard;
307 	String aNameString(aName);
308 	SdrOle2Obj* pObj = lcl_FindChartObj( pDocShell, nTab, aNameString );
309 	if (pObj)
310 	{
311 		ScDocument* pDoc = pDocShell->GetDocument();
312 		ScDrawLayer* pModel = pDoc->GetDrawLayer();		// ist nicht 0
313 		SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));    // ist nicht 0
314 
315         pModel->AddUndo( new SdrUndoDelObj( *pObj ) );
316 		pPage->RemoveObject( pObj->GetOrdNum() );
317 
318 		//!	Notify etc.???
319 	}
320 }
321 
322 // XEnumerationAccess
323 
324 uno::Reference<container::XEnumeration> SAL_CALL ScChartsObj::createEnumeration()
325 													throw(uno::RuntimeException)
326 {
327 	ScUnoGuard aGuard;
328     return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.TableChartsEnumeration")));
329 }
330 
331 // XIndexAccess
332 
333 sal_Int32 SAL_CALL ScChartsObj::getCount() throw(uno::RuntimeException)
334 {
335 	ScUnoGuard aGuard;
336 	sal_Int32 nCount = 0;
337 	if ( pDocShell )
338 	{
339 		ScDocument* pDoc = pDocShell->GetDocument();
340 		ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
341 		if (pDrawLayer)
342 		{
343 			SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
344 			DBG_ASSERT(pPage, "Page nicht gefunden");
345 			if (pPage)
346 			{
347 				SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
348 				SdrObject* pObject = aIter.Next();
349 				while (pObject)
350 				{
351 					if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) )
352 						++nCount;
353 					pObject = aIter.Next();
354 				}
355 			}
356 		}
357 	}
358 	return nCount;
359 }
360 
361 uno::Any SAL_CALL ScChartsObj::getByIndex( sal_Int32 nIndex )
362 							throw(lang::IndexOutOfBoundsException,
363 									lang::WrappedTargetException, uno::RuntimeException)
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 
374 uno::Type SAL_CALL ScChartsObj::getElementType() throw(uno::RuntimeException)
375 {
376 	ScUnoGuard aGuard;
377 	return getCppuType((uno::Reference<table::XTableChart>*)0);
378 }
379 
380 sal_Bool SAL_CALL ScChartsObj::hasElements() throw(uno::RuntimeException)
381 {
382 	ScUnoGuard aGuard;
383 	return getCount() != 0;
384 }
385 
386 uno::Any SAL_CALL ScChartsObj::getByName( const rtl::OUString& aName )
387 			throw(container::NoSuchElementException,
388 					lang::WrappedTargetException, uno::RuntimeException)
389 {
390 	ScUnoGuard aGuard;
391 	uno::Reference<table::XTableChart> xChart(GetObjectByName_Impl(aName));
392 	if (xChart.is())
393         return uno::makeAny(xChart);
394 	else
395 		throw container::NoSuchElementException();
396 //    return uno::Any();
397 }
398 
399 uno::Sequence<rtl::OUString> SAL_CALL ScChartsObj::getElementNames() throw(uno::RuntimeException)
400 {
401 	ScUnoGuard aGuard;
402 	if (pDocShell)
403 	{
404 		ScDocument* pDoc = pDocShell->GetDocument();
405 
406 		long nCount = getCount();
407 		uno::Sequence<rtl::OUString> aSeq(nCount);
408 		rtl::OUString* pAry = aSeq.getArray();
409 
410 		long nPos = 0;
411 		ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
412 		if (pDrawLayer)
413 		{
414 			SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
415 			DBG_ASSERT(pPage, "Page nicht gefunden");
416 			if (pPage)
417 			{
418 				SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
419 				SdrObject* pObject = aIter.Next();
420 				while (pObject)
421 				{
422 					if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) )
423 					{
424 						String aName;
425                         uno::Reference < embed::XEmbeddedObject > xObj = ((SdrOle2Obj*)pObject)->GetObjRef();
426                         if ( xObj.is() )
427                             aName = pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName( xObj );
428 
429 						DBG_ASSERT(nPos<nCount, "huch, verzaehlt?");
430 						pAry[nPos++] = aName;
431 					}
432 					pObject = aIter.Next();
433 				}
434 			}
435 		}
436 		DBG_ASSERT(nPos==nCount, "nanu, verzaehlt?");
437 
438 		return aSeq;
439 	}
440 	return uno::Sequence<rtl::OUString>(0);
441 }
442 
443 sal_Bool SAL_CALL ScChartsObj::hasByName( const rtl::OUString& aName )
444 										throw(uno::RuntimeException)
445 {
446 	ScUnoGuard aGuard;
447 	String aNameString(aName);
448 	return ( lcl_FindChartObj( pDocShell, nTab, aNameString ) != NULL );
449 }
450 
451 //------------------------------------------------------------------------
452 
453 ScChartObj::ScChartObj(ScDocShell* pDocSh, SCTAB nT, const String& rN)
454     :ScChartObj_Base( m_aMutex )
455     ,ScChartObj_PBase( ScChartObj_Base::rBHelper )
456 	,pDocShell( pDocSh )
457 	,nTab( nT )
458 	,aChartName( rN )
459 {
460     pDocShell->GetDocument()->AddUnoObject(*this);
461     SdrOle2Obj* pObject = lcl_FindChartObj( pDocShell, nTab, aChartName );
462     if ( pObject && svt::EmbeddedObjectRef::TryRunningState( pObject->GetObjRef() ) )
463         aObjectName = pObject->GetName();   // #i121178#: keep the OLE object's name
464     uno::Sequence< table::CellRangeAddress > aInitialPropValue;
465     registerPropertyNoMember( ::rtl::OUString::createFromAscii( "RelatedCellRanges" ),
466         PROP_HANDLE_RELATED_CELLRANGES, beans::PropertyAttribute::MAYBEVOID,
467         ::getCppuType( &aInitialPropValue ), &aInitialPropValue );
468 }
469 
470 ScChartObj::~ScChartObj()
471 {
472 	if (pDocShell)
473 		pDocShell->GetDocument()->RemoveUnoObject(*this);
474 }
475 
476 void ScChartObj::Notify( SfxBroadcaster&, const SfxHint& rHint )
477 {
478 	//!	Referenz-Update
479 
480 	if ( rHint.ISA( SfxSimpleHint ) &&
481 			((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
482 	{
483 		pDocShell = NULL;		// ungueltig geworden
484 	}
485 }
486 
487 void ScChartObj::GetData_Impl( ScRangeListRef& rRanges, bool& rColHeaders, bool& rRowHeaders ) const
488 {
489 	bool bFound = false;
490     ScDocument* pDoc = (pDocShell? pDocShell->GetDocument(): 0);
491 
492     if( pDoc )
493     {
494         uno::Reference< chart2::XChartDocument > xChartDoc( pDoc->GetChartByName( aChartName ) );
495         if( xChartDoc.is() )
496         {
497             uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
498             uno::Reference< chart2::data::XDataProvider > xProvider = xChartDoc->getDataProvider();
499             if( xReceiver.is() && xProvider.is() )
500             {
501                 uno::Sequence< beans::PropertyValue > aArgs( xProvider->detectArguments( xReceiver->getUsedData() ) );
502 
503                 rtl::OUString aRanges;
504                 chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
505                 bool bHasCategories=false;
506                 bool bFirstCellAsLabel=false;
507                 const beans::PropertyValue* pPropArray = aArgs.getConstArray();
508                 long nPropCount = aArgs.getLength();
509                 for (long i = 0; i < nPropCount; i++)
510                 {
511                     const beans::PropertyValue& rProp = pPropArray[i];
512                     String aPropName(rProp.Name);
513 
514                     if (aPropName.EqualsAscii( "CellRangeRepresentation" ))
515                         rProp.Value >>= aRanges;
516                     else if (aPropName.EqualsAscii( "DataRowSource" ))
517                         eDataRowSource = (chart::ChartDataRowSource)ScUnoHelpFunctions::GetEnumFromAny( rProp.Value );
518                     else if (aPropName.EqualsAscii( "HasCategories" ))
519                         bHasCategories = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
520                     else if (aPropName.EqualsAscii( "FirstCellAsLabel" ))
521                         bFirstCellAsLabel = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
522                 }
523 
524                 if( chart::ChartDataRowSource_COLUMNS == eDataRowSource )
525                 {
526                     rColHeaders=bFirstCellAsLabel;
527                     rRowHeaders=bHasCategories;
528                 }
529                 else
530                 {
531                     rColHeaders=bHasCategories;
532                     rRowHeaders=bFirstCellAsLabel;
533                 }
534                 rRanges->Parse( aRanges, pDoc);
535             }
536             bFound = true;
537         }
538  	}
539 	if( !bFound )
540 	{
541 		rRanges = 0;
542 		rColHeaders = false;
543 		rRowHeaders = false;
544 	}
545 }
546 
547 void ScChartObj::Update_Impl( const ScRangeListRef& rRanges, bool bColHeaders, bool bRowHeaders )
548 {
549 	if (pDocShell)
550 	{
551 		ScDocument* pDoc = pDocShell->GetDocument();
552 		sal_Bool bUndo(pDoc->IsUndoEnabled());
553 
554 		if (bUndo)
555 		{
556 			pDocShell->GetUndoManager()->AddUndoAction(
557 				new ScUndoChartData( pDocShell, aChartName, rRanges, bColHeaders, bRowHeaders, sal_False ) );
558 		}
559 		pDoc->UpdateChartArea( aChartName, rRanges, bColHeaders, bRowHeaders, sal_False );
560 	}
561 }
562 
563 // ::comphelper::OPropertySetHelper
564 
565 ::cppu::IPropertyArrayHelper& ScChartObj::getInfoHelper()
566 {
567     return *ScChartObj_PABase::getArrayHelper();
568 }
569 
570 void ScChartObj::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const uno::Any& rValue ) throw (uno::Exception)
571 {
572     switch ( nHandle )
573 	{
574         case PROP_HANDLE_RELATED_CELLRANGES:
575             {
576                 uno::Sequence< table::CellRangeAddress > aCellRanges;
577                 if ( rValue >>= aCellRanges )
578                 {
579                     ScRangeListRef rRangeList = new ScRangeList();
580                     const table::CellRangeAddress* pCellRanges = aCellRanges.getArray();
581                     sal_Int32 nCount = aCellRanges.getLength();
582                     for ( sal_Int32 i = 0; i < nCount; ++i )
583                     {
584                         table::CellRangeAddress aCellRange = pCellRanges[ i ];
585                         ScRange aRange;
586                         ScUnoConversion::FillScRange( aRange, aCellRange );
587                         rRangeList->Append( aRange );
588                     }
589                     ScDocument* pDoc = ( pDocShell ? pDocShell->GetDocument() : NULL );
590                     ScChartListenerCollection* pCollection = ( pDoc ? pDoc->GetChartListenerCollection() : NULL );
591                     if ( pCollection )
592                     {
593                         pCollection->ChangeListening( aChartName, rRangeList );
594                     }
595                 }
596             }
597             break;
598         default:
599             {
600             }
601             break;
602     }
603 }
604 
605 void ScChartObj::getFastPropertyValue( uno::Any& rValue, sal_Int32 nHandle ) const
606 {
607     switch ( nHandle )
608 	{
609         case PROP_HANDLE_RELATED_CELLRANGES:
610             {
611                 ScDocument* pDoc = ( pDocShell ? pDocShell->GetDocument() : NULL );
612                 if ( pDoc )
613                 {
614                     ScRange aEmptyRange;
615                     sal_uInt16 nIndex = 0;
616                     ScChartListener aSearcher( aChartName, pDoc, aEmptyRange );
617                     ScChartListenerCollection* pCollection = pDoc->GetChartListenerCollection();
618                     if ( pCollection && pCollection->Search( &aSearcher, nIndex ) )
619                     {
620                         ScChartListener* pListener = static_cast< ScChartListener* >( pCollection->At( nIndex ) );
621                         if ( pListener )
622                         {
623                             const ScRangeListRef& rRangeList = pListener->GetRangeList();
624                             if ( rRangeList.Is() )
625                             {
626                                 sal_uLong nCount = rRangeList->Count();
627                                 uno::Sequence< table::CellRangeAddress > aCellRanges( nCount );
628                                 table::CellRangeAddress* pCellRanges = aCellRanges.getArray();
629                                 for ( sal_uInt16 i = 0; i < nCount; ++i )
630                                 {
631                                     ScRange aRange( *rRangeList->GetObject( i ) );
632                                     table::CellRangeAddress aCellRange;
633                                     ScUnoConversion::FillApiRange( aCellRange, aRange );
634                                     pCellRanges[ i ] = aCellRange;
635                                 }
636                                 rValue <<= aCellRanges;
637                             }
638                         }
639                     }
640                 }
641             }
642             break;
643         default:
644             {
645             }
646             break;
647     }
648 }
649 
650 // ::comphelper::OPropertyArrayUsageHelper
651 
652 ::cppu::IPropertyArrayHelper* ScChartObj::createArrayHelper() const
653 {
654     uno::Sequence< beans::Property > aProps;
655     describeProperties( aProps );
656     return new ::cppu::OPropertyArrayHelper( aProps );
657 }
658 
659 // XInterface
660 
661 IMPLEMENT_FORWARD_XINTERFACE2( ScChartObj, ScChartObj_Base, ScChartObj_PBase )
662 
663 // XTypeProvider
664 
665 IMPLEMENT_FORWARD_XTYPEPROVIDER2( ScChartObj, ScChartObj_Base, ScChartObj_PBase )
666 
667 // XComponent
668 
669 void ScChartObj::disposing()
670 {
671     ScChartObj_Base::disposing();
672 }
673 
674 // XTableChart
675 
676 sal_Bool SAL_CALL ScChartObj::getHasColumnHeaders() throw(uno::RuntimeException)
677 {
678 	ScUnoGuard aGuard;
679 	ScRangeListRef xRanges = new ScRangeList;
680 	bool bColHeaders, bRowHeaders;
681 	GetData_Impl( xRanges, bColHeaders, bRowHeaders );
682 	return bColHeaders;
683 }
684 
685 void SAL_CALL ScChartObj::setHasColumnHeaders( sal_Bool bHasColumnHeaders )
686 												throw(uno::RuntimeException)
687 {
688 	ScUnoGuard aGuard;
689 	ScRangeListRef xRanges = new ScRangeList;
690 	bool bOldColHeaders, bOldRowHeaders;
691 	GetData_Impl( xRanges, bOldColHeaders, bOldRowHeaders );
692 	if ( bOldColHeaders != (bHasColumnHeaders != sal_False) )
693 		Update_Impl( xRanges, bHasColumnHeaders, bOldRowHeaders );
694 }
695 
696 sal_Bool SAL_CALL ScChartObj::getHasRowHeaders() throw(uno::RuntimeException)
697 {
698 	ScUnoGuard aGuard;
699 	ScRangeListRef xRanges = new ScRangeList;
700 	bool bColHeaders, bRowHeaders;
701 	GetData_Impl( xRanges, bColHeaders, bRowHeaders );
702 	return bRowHeaders;
703 }
704 
705 void SAL_CALL ScChartObj::setHasRowHeaders( sal_Bool bHasRowHeaders )
706 												throw(uno::RuntimeException)
707 {
708 	ScUnoGuard aGuard;
709 	ScRangeListRef xRanges = new ScRangeList;
710 	bool bOldColHeaders, bOldRowHeaders;
711 	GetData_Impl( xRanges, bOldColHeaders, bOldRowHeaders );
712 	if ( bOldRowHeaders != (bHasRowHeaders != sal_False) )
713 		Update_Impl( xRanges, bOldColHeaders, bHasRowHeaders );
714 }
715 
716 uno::Sequence<table::CellRangeAddress> SAL_CALL ScChartObj::getRanges() throw(uno::RuntimeException)
717 {
718 	ScUnoGuard aGuard;
719 	ScRangeListRef xRanges = new ScRangeList;
720 	bool bColHeaders, bRowHeaders;
721 	GetData_Impl( xRanges, bColHeaders, bRowHeaders );
722 	if ( xRanges.Is() )
723 	{
724 		sal_uLong nCount = xRanges->Count();
725 
726 		table::CellRangeAddress aRangeAddress;
727 		uno::Sequence<table::CellRangeAddress> aSeq(nCount);
728 		table::CellRangeAddress* pAry = aSeq.getArray();
729 		for (sal_uInt16 i=0; i<nCount; i++)
730 		{
731 			ScRange aRange(*xRanges->GetObject(i));
732 
733 			aRangeAddress.Sheet		  = aRange.aStart.Tab();
734 			aRangeAddress.StartColumn = aRange.aStart.Col();
735 			aRangeAddress.StartRow	  = aRange.aStart.Row();
736 			aRangeAddress.EndColumn	  = aRange.aEnd.Col();
737 			aRangeAddress.EndRow	  = aRange.aEnd.Row();
738 
739 			pAry[i] = aRangeAddress;
740 		}
741 		return aSeq;
742 	}
743 
744 	DBG_ERROR("ScChartObj::getRanges: keine Ranges");
745 	return uno::Sequence<table::CellRangeAddress>();
746 }
747 
748 void SAL_CALL ScChartObj::setRanges( const uno::Sequence<table::CellRangeAddress>& aRanges )
749 												throw(uno::RuntimeException)
750 {
751 	ScUnoGuard aGuard;
752 	ScRangeListRef xOldRanges = new ScRangeList;
753 	bool bColHeaders, bRowHeaders;
754 	GetData_Impl( xOldRanges, bColHeaders, bRowHeaders );
755 
756 	ScRangeList* pList = new ScRangeList;
757 	sal_uInt16 nRangeCount = (sal_uInt16)aRanges.getLength();
758 	if (nRangeCount)
759 	{
760 		const table::CellRangeAddress* pAry = aRanges.getConstArray();
761 		for (sal_uInt16 i=0; i<nRangeCount; i++)
762 		{
763 			ScRange aRange( static_cast<SCCOL>(pAry[i].StartColumn), pAry[i].StartRow, pAry[i].Sheet,
764 							static_cast<SCCOL>(pAry[i].EndColumn),   pAry[i].EndRow,   pAry[i].Sheet );
765 			pList->Append( aRange );
766 		}
767 	}
768 	ScRangeListRef xNewRanges( pList );
769 
770 	if ( !xOldRanges.Is() || *xOldRanges != *xNewRanges )
771 		Update_Impl( xNewRanges, bColHeaders, bRowHeaders );
772 }
773 
774 // XEmbeddedObjectSupplier
775 
776 uno::Reference<lang::XComponent> SAL_CALL ScChartObj::getEmbeddedObject() throw(uno::RuntimeException)
777 {
778 	ScUnoGuard aGuard;
779 	SdrOle2Obj* pObject = lcl_FindChartObj( pDocShell, nTab, aChartName );
780     if ( pObject && svt::EmbeddedObjectRef::TryRunningState( pObject->GetObjRef() ) )
781 	{
782         //TODO/LATER: is it OK that something is returned for *all* objects, not only own objects?
783         return uno::Reference < lang::XComponent > ( pObject->GetObjRef()->getComponent(), uno::UNO_QUERY );
784 	}
785 
786 	return NULL;
787 }
788 
789 // XNamed
790 
791 rtl::OUString SAL_CALL ScChartObj::getName() throw(uno::RuntimeException)
792 {
793 	ScUnoGuard aGuard;
794 	return aChartName;
795 }
796 
797 void SAL_CALL ScChartObj::setName( const rtl::OUString& /* aName */ ) throw(uno::RuntimeException)
798 {
799 	ScUnoGuard aGuard;
800 	throw uno::RuntimeException();		// name cannot be changed
801 }
802 
803 // XNamedEx
804 
805 rtl::OUString SAL_CALL ScChartObj::getDisplayName() throw(uno::RuntimeException)
806 {
807 	ScUnoGuard aGuard;
808 	return aObjectName;
809 }
810 
811 void SAL_CALL ScChartObj::setDisplayName( const rtl::OUString& aName ) throw(uno::RuntimeException)
812 {
813 	ScUnoGuard aGuard;
814 	aObjectName = aName;
815 }
816 
817 // XPropertySet
818 
819 uno::Reference< beans::XPropertySetInfo > ScChartObj::getPropertySetInfo() throw (uno::RuntimeException)
820 {
821     return createPropertySetInfo( getInfoHelper() ) ;
822 }
823 
824 //------------------------------------------------------------------------
825 
826 
827 
828