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