Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <com/sun/star/util/XModifiable.hpp>
22 : #include <com/sun/star/chart/ChartDataRowSource.hpp>
23 : #include <com/sun/star/chart2/XChartDocument.hpp>
24 : #include <com/sun/star/chart2/data/XDataProvider.hpp>
25 : #include <com/sun/star/chart2/data/XDataReceiver.hpp>
26 : #include <com/sun/star/embed/EmbedStates.hpp>
27 : #include <com/sun/star/embed/XEmbeddedObject.hpp>
28 :
29 :
30 : #ifdef _MSC_VER
31 : #pragma optimize("",off)
32 : #endif
33 :
34 : #include <sfx2/objsh.hxx>
35 : #include <svx/svditer.hxx>
36 : #include <svx/svdoole2.hxx>
37 : #include <svx/svdpage.hxx>
38 :
39 : #include "document.hxx"
40 : #include "table.hxx"
41 : #include "drwlayer.hxx"
42 : #include "chartarr.hxx"
43 : #include "chartlis.hxx"
44 : #include "chartlock.hxx"
45 : #include "refupdat.hxx"
46 : #include <tools/globname.hxx>
47 : #include <sot/exchange.hxx>
48 :
49 : #include "miscuno.hxx"
50 : #include "chart2uno.hxx"
51 : #include "charthelper.hxx"
52 :
53 : using namespace ::com::sun::star;
54 :
55 : // -----------------------------------------------------------------------
56 :
57 0 : static void lcl_GetChartParameters( const uno::Reference< chart2::XChartDocument >& xChartDoc,
58 : rtl::OUString& rRanges, chart::ChartDataRowSource& rDataRowSource,
59 : bool& rHasCategories, bool& rFirstCellAsLabel )
60 : {
61 0 : rHasCategories = rFirstCellAsLabel = false; // default if not in sequence
62 :
63 0 : uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
64 :
65 0 : uno::Reference< chart2::data::XDataSource > xDataSource = xReceiver->getUsedData();
66 0 : uno::Reference< chart2::data::XDataProvider > xProvider = xChartDoc->getDataProvider();
67 :
68 0 : if ( xProvider.is() )
69 : {
70 0 : uno::Sequence< beans::PropertyValue > aArgs( xProvider->detectArguments( xDataSource ) );
71 :
72 0 : const beans::PropertyValue* pPropArray = aArgs.getConstArray();
73 0 : long nPropCount = aArgs.getLength();
74 0 : for (long i = 0; i < nPropCount; i++)
75 : {
76 0 : const beans::PropertyValue& rProp = pPropArray[i];
77 0 : rtl::OUString aPropName(rProp.Name);
78 :
79 0 : if ( aPropName == "CellRangeRepresentation" )
80 0 : rProp.Value >>= rRanges;
81 0 : else if ( aPropName == "DataRowSource" )
82 0 : rDataRowSource = (chart::ChartDataRowSource)ScUnoHelpFunctions::GetEnumFromAny( rProp.Value );
83 0 : else if ( aPropName == "HasCategories" )
84 0 : rHasCategories = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
85 0 : else if ( aPropName == "FirstCellAsLabel" )
86 0 : rFirstCellAsLabel = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
87 0 : }
88 0 : }
89 0 : }
90 :
91 0 : static void lcl_SetChartParameters( const uno::Reference< chart2::data::XDataReceiver >& xReceiver,
92 : const rtl::OUString& rRanges, chart::ChartDataRowSource eDataRowSource,
93 : bool bHasCategories, bool bFirstCellAsLabel )
94 : {
95 0 : if ( xReceiver.is() )
96 : {
97 0 : uno::Sequence< beans::PropertyValue > aArgs( 4 );
98 0 : aArgs[0] = beans::PropertyValue(
99 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CellRangeRepresentation")), -1,
100 0 : uno::makeAny( rRanges ), beans::PropertyState_DIRECT_VALUE );
101 0 : aArgs[1] = beans::PropertyValue(
102 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HasCategories")), -1,
103 0 : uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE );
104 0 : aArgs[2] = beans::PropertyValue(
105 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel")), -1,
106 0 : uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE );
107 0 : aArgs[3] = beans::PropertyValue(
108 : ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource")), -1,
109 0 : uno::makeAny( eDataRowSource ), beans::PropertyState_DIRECT_VALUE );
110 0 : xReceiver->setArguments( aArgs );
111 : }
112 0 : }
113 :
114 : // update charts after loading old document
115 :
116 0 : void ScDocument::UpdateAllCharts()
117 : {
118 0 : if ( !pDrawLayer || !pShell )
119 0 : return;
120 :
121 0 : if (pChartCollection->empty())
122 0 : return ; // nothing to do
123 :
124 0 : size_t nDataCount = pChartCollection->size();
125 :
126 0 : SCTAB nSize = static_cast<SCTAB>(maTabs.size());
127 0 : for (SCTAB nTab=0; nTab< nSize; nTab++)
128 : {
129 0 : if (maTabs[nTab])
130 : {
131 0 : SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
132 : OSL_ENSURE(pPage,"Page ?");
133 :
134 0 : ScRange aRange;
135 0 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
136 0 : SdrObject* pObject = aIter.Next();
137 0 : while (pObject)
138 : {
139 0 : if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
140 : {
141 0 : uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
142 0 : if ( xIPObj.is() )
143 : {
144 0 : ::rtl::OUString aIPName = ((SdrOle2Obj*)pObject)->GetPersistName();
145 :
146 0 : for (size_t nPos = 0; nPos < nDataCount; ++nPos)
147 : {
148 0 : ScChartArray* pChartObj = (*pChartCollection)[nPos];
149 0 : if (pChartObj->GetName() == aIPName)
150 : {
151 0 : ScRangeListRef aRanges = pChartObj->GetRangeList();
152 0 : rtl::OUString sRangeStr;
153 0 : aRanges->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() );
154 :
155 0 : chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
156 0 : bool bHasCategories = pChartObj->HasRowHeaders();
157 0 : bool bFirstCellAsLabel = pChartObj->HasColHeaders();
158 :
159 : // Calc -> DataProvider
160 : uno::Reference< chart2::data::XDataProvider > xDataProvider =
161 0 : new ScChart2DataProvider( this );
162 : // Chart -> DataReceiver
163 0 : uno::Reference< chart2::data::XDataReceiver > xReceiver;
164 0 : uno::Reference< embed::XComponentSupplier > xCompSupp( xIPObj, uno::UNO_QUERY );
165 0 : if( xCompSupp.is())
166 0 : xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY );
167 0 : if( xReceiver.is())
168 : {
169 : // connect
170 0 : xReceiver->attachDataProvider( xDataProvider );
171 : uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier(
172 0 : pShell->GetModel(), uno::UNO_QUERY );
173 0 : xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
174 :
175 : lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource,
176 0 : bHasCategories, bFirstCellAsLabel );
177 : }
178 :
179 : ScChartListener* pCL = new ScChartListener(
180 0 : aIPName, this, pChartObj->GetRangeList() );
181 0 : pChartListenerCollection->insert( pCL );
182 0 : pCL->StartListeningTo();
183 : }
184 0 : }
185 0 : }
186 : }
187 0 : pObject = aIter.Next();
188 0 : }
189 : }
190 : }
191 :
192 0 : pChartCollection->clear();
193 : }
194 :
195 0 : bool ScDocument::HasChartAtPoint( SCTAB nTab, const Point& rPos, rtl::OUString& rName )
196 : {
197 0 : if (pDrawLayer && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
198 : {
199 0 : SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
200 : OSL_ENSURE(pPage,"Page ?");
201 :
202 0 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
203 0 : SdrObject* pObject = aIter.Next();
204 0 : while (pObject)
205 : {
206 0 : if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
207 0 : pObject->GetCurrentBoundRect().IsInside(rPos) )
208 : {
209 : // auch Chart-Objekte die nicht in der Collection sind
210 :
211 0 : if (IsChart(pObject))
212 : {
213 0 : rName = (static_cast<SdrOle2Obj*>(pObject))->GetPersistName();
214 0 : return true;
215 : }
216 : }
217 0 : pObject = aIter.Next();
218 0 : }
219 : }
220 :
221 0 : rName = rtl::OUString();
222 0 : return false; // nothing found
223 : }
224 :
225 0 : void ScDocument::UpdateChartArea( const rtl::OUString& rChartName,
226 : const ScRange& rNewArea, bool bColHeaders, bool bRowHeaders,
227 : bool bAdd )
228 : {
229 0 : ScRangeListRef aRLR( new ScRangeList );
230 0 : aRLR->Append( rNewArea );
231 0 : UpdateChartArea( rChartName, aRLR, bColHeaders, bRowHeaders, bAdd );
232 0 : }
233 :
234 0 : uno::Reference< chart2::XChartDocument > ScDocument::GetChartByName( const rtl::OUString& rChartName )
235 : {
236 0 : uno::Reference< chart2::XChartDocument > xReturn;
237 :
238 0 : if (pDrawLayer)
239 : {
240 0 : sal_uInt16 nCount = pDrawLayer->GetPageCount();
241 0 : SCTAB nSize = static_cast<SCTAB>(maTabs.size());
242 0 : for (sal_uInt16 nTab=0; nTab<nCount && nTab < nSize; nTab++)
243 : {
244 0 : SdrPage* pPage = pDrawLayer->GetPage(nTab);
245 : OSL_ENSURE(pPage,"Page ?");
246 :
247 0 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
248 0 : SdrObject* pObject = aIter.Next();
249 0 : while (pObject)
250 : {
251 0 : if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
252 0 : rtl::OUString(((SdrOle2Obj*)pObject)->GetPersistName()) == rChartName )
253 : {
254 0 : xReturn.set( ScChartHelper::GetChartFromSdrObject( pObject ) );
255 : return xReturn;
256 : }
257 0 : pObject = aIter.Next();
258 : }
259 0 : }
260 : }
261 0 : return xReturn;
262 : }
263 0 : void ScDocument::GetChartRanges( const rtl::OUString& rChartName, ::std::vector< ScRangeList >& rRangesVector, ScDocument* pSheetNameDoc )
264 : {
265 0 : rRangesVector.clear();
266 0 : uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) );
267 0 : if ( xChartDoc.is() )
268 : {
269 0 : uno::Sequence< rtl::OUString > aRangeStrings;
270 0 : ScChartHelper::GetChartRanges( xChartDoc, aRangeStrings );
271 0 : for( sal_Int32 nN=0; nN<aRangeStrings.getLength(); nN++ )
272 : {
273 0 : ScRangeList aRanges;
274 0 : aRanges.Parse( aRangeStrings[nN], pSheetNameDoc, SCA_VALID, pSheetNameDoc->GetAddressConvention() );
275 0 : rRangesVector.push_back(aRanges);
276 0 : }
277 0 : }
278 0 : }
279 :
280 0 : void ScDocument::SetChartRanges( const rtl::OUString& rChartName, const ::std::vector< ScRangeList >& rRangesVector )
281 : {
282 0 : uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) );
283 0 : if ( xChartDoc.is() )
284 : {
285 0 : sal_Int32 nCount = static_cast<sal_Int32>( rRangesVector.size() );
286 0 : uno::Sequence< rtl::OUString > aRangeStrings(nCount);
287 0 : for( sal_Int32 nN=0; nN<nCount; nN++ )
288 : {
289 0 : ScRangeList aScRangeList( rRangesVector[nN] );
290 0 : rtl::OUString sRangeStr;
291 0 : aScRangeList.Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() );
292 0 : aRangeStrings[nN]=sRangeStr;
293 0 : }
294 0 : ScChartHelper::SetChartRanges( xChartDoc, aRangeStrings );
295 0 : }
296 0 : }
297 :
298 0 : void ScDocument::GetOldChartParameters( const rtl::OUString& rName,
299 : ScRangeList& rRanges, bool& rColHeaders, bool& rRowHeaders )
300 : {
301 : // used for undo of changing chart source area
302 :
303 0 : if (!pDrawLayer)
304 0 : return;
305 :
306 0 : sal_uInt16 nCount = pDrawLayer->GetPageCount();
307 0 : for (sal_uInt16 nTab=0; nTab<nCount && nTab < static_cast<SCTAB>(maTabs.size()); nTab++)
308 : {
309 0 : SdrPage* pPage = pDrawLayer->GetPage(nTab);
310 : OSL_ENSURE(pPage,"Page ?");
311 :
312 0 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
313 0 : SdrObject* pObject = aIter.Next();
314 0 : while (pObject)
315 : {
316 0 : if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
317 0 : rtl::OUString(((SdrOle2Obj*)pObject)->GetPersistName()) == rName )
318 : {
319 0 : uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) );
320 0 : if ( xChartDoc.is() )
321 : {
322 0 : chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
323 0 : bool bHasCategories = false;
324 0 : bool bFirstCellAsLabel = false;
325 0 : rtl::OUString aRangesStr;
326 0 : lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
327 :
328 0 : rRanges.Parse( aRangesStr, this );
329 0 : if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
330 : {
331 0 : rRowHeaders = bHasCategories;
332 0 : rColHeaders = bFirstCellAsLabel;
333 : }
334 : else
335 : {
336 0 : rColHeaders = bHasCategories;
337 0 : rRowHeaders = bFirstCellAsLabel;
338 0 : }
339 : }
340 0 : return;
341 : }
342 0 : pObject = aIter.Next();
343 : }
344 0 : }
345 : }
346 :
347 0 : void ScDocument::UpdateChartArea( const rtl::OUString& rChartName,
348 : const ScRangeListRef& rNewList, bool bColHeaders, bool bRowHeaders,
349 : bool bAdd )
350 : {
351 0 : if (!pDrawLayer)
352 0 : return;
353 :
354 0 : for (SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]; nTab++)
355 : {
356 0 : SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
357 : OSL_ENSURE(pPage,"Page ?");
358 :
359 0 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
360 0 : SdrObject* pObject = aIter.Next();
361 0 : while (pObject)
362 : {
363 0 : if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
364 0 : rtl::OUString(((SdrOle2Obj*)pObject)->GetPersistName()) == rChartName )
365 : {
366 0 : uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) );
367 0 : uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
368 0 : if ( xChartDoc.is() && xReceiver.is() )
369 : {
370 0 : ScRangeListRef aNewRanges;
371 0 : chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
372 0 : bool bHasCategories = false;
373 0 : bool bFirstCellAsLabel = false;
374 0 : rtl::OUString aRangesStr;
375 0 : lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
376 :
377 0 : bool bInternalData = xChartDoc->hasInternalDataProvider();
378 :
379 0 : if ( bAdd && !bInternalData )
380 : {
381 : // append to old ranges, keep other settings
382 :
383 0 : aNewRanges = new ScRangeList;
384 0 : aNewRanges->Parse( aRangesStr, this );
385 :
386 0 : for ( size_t nAdd = 0, nAddCount = rNewList->size(); nAdd < nAddCount; ++nAdd )
387 0 : aNewRanges->Append( *(*rNewList)[nAdd] );
388 : }
389 : else
390 : {
391 : // directly use new ranges (only eDataRowSource is used from old settings)
392 :
393 0 : if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
394 : {
395 0 : bHasCategories = bRowHeaders;
396 0 : bFirstCellAsLabel = bColHeaders;
397 : }
398 : else
399 : {
400 0 : bHasCategories = bColHeaders;
401 0 : bFirstCellAsLabel = bRowHeaders;
402 : }
403 0 : aNewRanges = rNewList;
404 : }
405 :
406 0 : if ( bInternalData && pShell )
407 : {
408 : // Calc -> DataProvider
409 0 : uno::Reference< chart2::data::XDataProvider > xDataProvider = new ScChart2DataProvider( this );
410 0 : xReceiver->attachDataProvider( xDataProvider );
411 : uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier(
412 0 : pShell->GetModel(), uno::UNO_QUERY );
413 0 : xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier );
414 : }
415 :
416 0 : rtl::OUString sRangeStr;
417 0 : aNewRanges->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() );
418 :
419 0 : lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
420 :
421 0 : pChartListenerCollection->ChangeListening( rChartName, aNewRanges );
422 :
423 0 : return; // do not search anymore
424 0 : }
425 : }
426 0 : pObject = aIter.Next();
427 : }
428 0 : }
429 : }
430 :
431 0 : void ScDocument::UpdateChart( const rtl::OUString& rChartName )
432 : {
433 0 : if (!pDrawLayer || bInDtorClear)
434 0 : return;
435 0 : uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) );
436 0 : if( xChartDoc.is() )
437 : {
438 : try
439 : {
440 0 : uno::Reference< util::XModifiable > xModif( xChartDoc, uno::UNO_QUERY_THROW );
441 0 : if( apTemporaryChartLock.get() )
442 0 : apTemporaryChartLock->AlsoLockThisChart( uno::Reference< frame::XModel >( xModif, uno::UNO_QUERY ) );
443 0 : xModif->setModified( true );
444 : }
445 0 : catch ( uno::Exception& )
446 : {
447 : }
448 : }
449 :
450 : // After the update, chart keeps track of its own data source ranges,
451 : // the listener doesn't need to listen anymore, except the chart has
452 : // an internal data provider.
453 0 : if ( !( xChartDoc.is() && xChartDoc->hasInternalDataProvider() ) && pChartListenerCollection )
454 : {
455 0 : pChartListenerCollection->ChangeListening( rChartName, new ScRangeList );
456 0 : }
457 : }
458 :
459 0 : void ScDocument::RestoreChartListener( const rtl::OUString& rName )
460 : {
461 : // Read the data ranges from the chart object, and start listening to those ranges again
462 : // (called when a chart is saved, because then it might be swapped out and stop listening itself).
463 :
464 0 : uno::Reference< embed::XEmbeddedObject > xObject = FindOleObjectByName( rName );
465 0 : if ( xObject.is() )
466 : {
467 0 : uno::Reference< util::XCloseable > xComponent = xObject->getComponent();
468 0 : uno::Reference< chart2::XChartDocument > xChartDoc( xComponent, uno::UNO_QUERY );
469 0 : uno::Reference< chart2::data::XDataReceiver > xReceiver( xComponent, uno::UNO_QUERY );
470 0 : if ( xChartDoc.is() && xReceiver.is() && !xChartDoc->hasInternalDataProvider())
471 : {
472 0 : uno::Sequence<rtl::OUString> aRepresentations( xReceiver->getUsedRangeRepresentations() );
473 0 : ScRangeListRef aRanges = new ScRangeList;
474 0 : sal_Int32 nRangeCount = aRepresentations.getLength();
475 0 : for ( sal_Int32 i=0; i<nRangeCount; i++ )
476 : {
477 0 : ScRange aRange;
478 0 : ScAddress::Details aDetails(GetAddressConvention(), 0, 0);
479 0 : if ( aRange.ParseAny( aRepresentations[i], this, aDetails ) & SCA_VALID )
480 0 : aRanges->Append( aRange );
481 : }
482 :
483 0 : pChartListenerCollection->ChangeListening( rName, aRanges );
484 0 : }
485 0 : }
486 0 : }
487 :
488 66 : void ScDocument::UpdateChartRef( UpdateRefMode eUpdateRefMode,
489 : SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
490 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
491 : SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
492 : {
493 66 : if (!pDrawLayer)
494 66 : return;
495 :
496 9 : ScChartListenerCollection::ListenersType& rListeners = pChartListenerCollection->getListeners();
497 9 : ScChartListenerCollection::ListenersType::iterator it = rListeners.begin(), itEnd = rListeners.end();
498 9 : for (; it != itEnd; ++it)
499 : {
500 0 : ScChartListener* pChartListener = it->second;
501 0 : ScRangeListRef aRLR( pChartListener->GetRangeList() );
502 0 : ScRangeListRef aNewRLR( new ScRangeList );
503 0 : bool bChanged = false;
504 0 : bool bDataChanged = false;
505 0 : for ( size_t i = 0, nListSize = aRLR->size(); i < nListSize; ++i )
506 : {
507 0 : ScRange* pR = (*aRLR)[i];
508 0 : SCCOL theCol1 = pR->aStart.Col();
509 0 : SCROW theRow1 = pR->aStart.Row();
510 0 : SCTAB theTab1 = pR->aStart.Tab();
511 0 : SCCOL theCol2 = pR->aEnd.Col();
512 0 : SCROW theRow2 = pR->aEnd.Row();
513 0 : SCTAB theTab2 = pR->aEnd.Tab();
514 : ScRefUpdateRes eRes = ScRefUpdate::Update(
515 : this, eUpdateRefMode,
516 : nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
517 : nDx,nDy,nDz,
518 : theCol1,theRow1,theTab1,
519 0 : theCol2,theRow2,theTab2 );
520 0 : if ( eRes != UR_NOTHING )
521 : {
522 0 : bChanged = true;
523 : aNewRLR->Append( ScRange(
524 : theCol1, theRow1, theTab1,
525 0 : theCol2, theRow2, theTab2 ));
526 0 : if ( eUpdateRefMode == URM_INSDEL
527 0 : && !bDataChanged
528 : && (eRes == UR_INVALID ||
529 0 : ((pR->aEnd.Col() - pR->aStart.Col()
530 : != theCol2 - theCol1)
531 0 : || (pR->aEnd.Row() - pR->aStart.Row()
532 : != theRow2 - theRow1)
533 0 : || (pR->aEnd.Tab() - pR->aStart.Tab()
534 : != theTab2 - theTab1))) )
535 : {
536 0 : bDataChanged = true;
537 : }
538 : }
539 : else
540 0 : aNewRLR->Append( *pR );
541 : }
542 0 : if ( bChanged )
543 : {
544 : {
545 : // Force the chart to be loaded now, so it registers itself for UNO events.
546 : // UNO broadcasts are done after UpdateChartRef, so the chart will get this
547 : // reference change.
548 :
549 : uno::Reference<embed::XEmbeddedObject> xIPObj =
550 0 : FindOleObjectByName(pChartListener->GetName());
551 :
552 0 : svt::EmbeddedObjectRef::TryRunningState( xIPObj );
553 :
554 : // After the change, chart keeps track of its own data source ranges,
555 : // the listener doesn't need to listen anymore, except the chart has
556 : // an internal data provider.
557 0 : bool bInternalDataProvider = false;
558 0 : if ( xIPObj.is() )
559 : {
560 : try
561 : {
562 0 : uno::Reference< chart2::XChartDocument > xChartDoc( xIPObj->getComponent(), uno::UNO_QUERY_THROW );
563 0 : bInternalDataProvider = xChartDoc->hasInternalDataProvider();
564 : }
565 0 : catch ( uno::Exception& )
566 : {
567 : }
568 : }
569 0 : if ( bInternalDataProvider )
570 : {
571 0 : pChartListener->ChangeListening( aNewRLR, bDataChanged );
572 : }
573 : else
574 : {
575 0 : pChartListener->ChangeListening( new ScRangeList, bDataChanged );
576 0 : }
577 : }
578 : }
579 0 : }
580 : }
581 :
582 :
583 0 : void ScDocument::SetChartRangeList( const rtl::OUString& rChartName,
584 : const ScRangeListRef& rNewRangeListRef )
585 : {
586 : // called from ChartListener
587 :
588 0 : if (!pDrawLayer)
589 0 : return;
590 :
591 0 : for (SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]; nTab++)
592 : {
593 0 : SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
594 : OSL_ENSURE(pPage,"Page ?");
595 :
596 0 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
597 0 : SdrObject* pObject = aIter.Next();
598 0 : while (pObject)
599 : {
600 0 : if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
601 0 : rtl::OUString(((SdrOle2Obj*)pObject)->GetPersistName()) == rChartName )
602 : {
603 0 : uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) );
604 0 : uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
605 0 : if ( xChartDoc.is() && xReceiver.is() )
606 : {
607 0 : ScRangeListRef aNewRanges;
608 0 : chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
609 0 : bool bHasCategories = false;
610 0 : bool bFirstCellAsLabel = false;
611 0 : rtl::OUString aRangesStr;
612 0 : lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
613 :
614 0 : rtl::OUString sRangeStr;
615 0 : rNewRangeListRef->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() );
616 :
617 0 : lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
618 :
619 : // don't modify pChartListenerCollection here, called from there
620 0 : return;
621 0 : }
622 : }
623 0 : pObject = aIter.Next();
624 : }
625 0 : }
626 : }
627 :
628 :
629 162 : bool ScDocument::HasData( SCCOL nCol, SCROW nRow, SCTAB nTab )
630 : {
631 162 : if ( VALIDTAB(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
632 162 : return maTabs[nTab]->HasData( nCol, nRow );
633 : else
634 0 : return false;
635 : }
636 :
637 : uno::Reference< embed::XEmbeddedObject >
638 0 : ScDocument::FindOleObjectByName( const rtl::OUString& rName )
639 : {
640 0 : if (!pDrawLayer)
641 0 : return uno::Reference< embed::XEmbeddedObject >();
642 :
643 : // die Seiten hier vom Draw-Layer nehmen,
644 : // weil sie evtl. nicht mit den Tabellen uebereinstimmen
645 : // (z.B. Redo von Tabelle loeschen, Draw-Redo passiert vor DeleteTab).
646 :
647 0 : sal_uInt16 nCount = pDrawLayer->GetPageCount();
648 0 : for (sal_uInt16 nTab=0; nTab<nCount; nTab++)
649 : {
650 0 : SdrPage* pPage = pDrawLayer->GetPage(nTab);
651 : OSL_ENSURE(pPage,"Page ?");
652 :
653 0 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
654 0 : SdrObject* pObject = aIter.Next();
655 0 : while (pObject)
656 : {
657 0 : if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
658 : {
659 0 : SdrOle2Obj * pOleObject ( dynamic_cast< SdrOle2Obj * >( pObject ));
660 0 : if( pOleObject &&
661 0 : rtl::OUString(pOleObject->GetPersistName()) == rName )
662 : {
663 0 : return pOleObject->GetObjRef();
664 : }
665 : }
666 0 : pObject = aIter.Next();
667 : }
668 0 : }
669 :
670 0 : return uno::Reference< embed::XEmbeddedObject >();
671 : }
672 :
673 36 : void ScDocument::UpdateChartListenerCollection()
674 : {
675 : OSL_ASSERT(pChartListenerCollection);
676 :
677 36 : bChartListenerCollectionNeedsUpdate = false;
678 36 : if (!pDrawLayer)
679 36 : return;
680 :
681 145 : for (SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()); nTab++)
682 : {
683 109 : if (!maTabs[nTab])
684 0 : continue;
685 :
686 109 : SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
687 : OSL_ENSURE(pPage,"Page ?");
688 :
689 109 : if (!pPage)
690 0 : continue;
691 :
692 109 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
693 : ScChartListenerCollection::StringSetType& rNonOleObjects =
694 109 : pChartListenerCollection->getNonOleObjectNames();
695 :
696 174 : for (SdrObject* pObject = aIter.Next(); pObject; pObject = aIter.Next())
697 : {
698 65 : if ( pObject->GetObjIdentifier() != OBJ_OLE2 )
699 24 : continue;
700 :
701 41 : rtl::OUString aObjName = ((SdrOle2Obj*)pObject)->GetPersistName();
702 41 : ScChartListener* pListener = pChartListenerCollection->findByName(aObjName);
703 :
704 41 : if (pListener)
705 40 : pListener->SetUsed(true);
706 1 : else if (rNonOleObjects.count(aObjName) > 0)
707 : {
708 : // non-chart OLE object -> don't touch
709 : }
710 : else
711 : {
712 1 : bool bIsChart = false;
713 :
714 1 : uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pObject)->GetObjRef();
715 : OSL_ENSURE( xIPObj.is(), "No embedded object is given!");
716 1 : uno::Reference< ::com::sun::star::chart2::data::XDataReceiver > xReceiver;
717 1 : uno::Reference< embed::XComponentSupplier > xCompSupp( xIPObj, uno::UNO_QUERY );
718 1 : if( xCompSupp.is())
719 1 : xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY );
720 :
721 : // if the object is a chart2::XDataReceiver, we must attach as XDataProvider
722 2 : if( xReceiver.is() &&
723 1 : !PastingDrawFromOtherDoc())
724 : {
725 : // NOTE: this currently does not work as we are
726 : // unable to set the data. So a chart from the
727 : // same document is treated like a chart with
728 : // own data for the time being.
729 :
730 : // data provider
731 : // number formats supplier
732 :
733 : // data ?
734 : // how to set?? Defined in XML-file, which is already loaded!!!
735 : // => we have to do this stuff here, BEFORE the chart is actually loaded
736 : }
737 :
738 1 : if (!bIsChart)
739 : {
740 : // put into list of other ole objects, so the object doesn't have to
741 : // be swapped in the next time UpdateChartListenerCollection is called
742 : //! remove names when objects are no longer there?
743 : // (object names aren't used again before reloading the document)
744 :
745 1 : rNonOleObjects.insert(aObjName);
746 1 : }
747 : }
748 41 : }
749 109 : }
750 : // alle nicht auf SetUsed gesetzten loeschen
751 36 : pChartListenerCollection->FreeUnused();
752 : }
753 :
754 0 : void ScDocument::AddOLEObjectToCollection(const rtl::OUString& rName)
755 : {
756 : OSL_ASSERT(pChartListenerCollection);
757 : ScChartListenerCollection::StringSetType& rNonOleObjects =
758 0 : pChartListenerCollection->getNonOleObjectNames();
759 :
760 0 : rNonOleObjects.insert(rName);
761 0 : }
762 :
763 :
764 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|