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