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