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