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