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 24 : static void lcl_GetChartParameters( const uno::Reference< chart2::XChartDocument >& xChartDoc,
51 : OUString& rRanges, chart::ChartDataRowSource& rDataRowSource,
52 : bool& rHasCategories, bool& rFirstCellAsLabel )
53 : {
54 24 : rHasCategories = rFirstCellAsLabel = false; // default if not in sequence
55 :
56 24 : uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
57 :
58 48 : uno::Reference< chart2::data::XDataSource > xDataSource = xReceiver->getUsedData();
59 48 : uno::Reference< chart2::data::XDataProvider > xProvider = xChartDoc->getDataProvider();
60 :
61 24 : if ( xProvider.is() )
62 : {
63 24 : uno::Sequence< beans::PropertyValue > aArgs( xProvider->detectArguments( xDataSource ) );
64 :
65 24 : const beans::PropertyValue* pPropArray = aArgs.getConstArray();
66 24 : long nPropCount = aArgs.getLength();
67 144 : for (long i = 0; i < nPropCount; i++)
68 : {
69 120 : const beans::PropertyValue& rProp = pPropArray[i];
70 120 : OUString aPropName(rProp.Name);
71 :
72 120 : if ( aPropName == "CellRangeRepresentation" )
73 24 : rProp.Value >>= rRanges;
74 96 : else if ( aPropName == "DataRowSource" )
75 24 : rDataRowSource = (chart::ChartDataRowSource)ScUnoHelpFunctions::GetEnumFromAny( rProp.Value );
76 72 : else if ( aPropName == "HasCategories" )
77 24 : rHasCategories = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
78 48 : else if ( aPropName == "FirstCellAsLabel" )
79 24 : rFirstCellAsLabel = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value );
80 144 : }
81 24 : }
82 24 : }
83 :
84 12 : 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 12 : if ( xReceiver.is() )
89 : {
90 12 : uno::Sequence< beans::PropertyValue > aArgs( 4 );
91 24 : aArgs[0] = beans::PropertyValue(
92 : OUString("CellRangeRepresentation"), -1,
93 12 : uno::makeAny( rRanges ), beans::PropertyState_DIRECT_VALUE );
94 24 : aArgs[1] = beans::PropertyValue(
95 : OUString("HasCategories"), -1,
96 12 : uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE );
97 24 : aArgs[2] = beans::PropertyValue(
98 : OUString("FirstCellAsLabel"), -1,
99 12 : uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE );
100 24 : aArgs[3] = beans::PropertyValue(
101 : OUString("DataRowSource"), -1,
102 12 : uno::makeAny( eDataRowSource ), beans::PropertyState_DIRECT_VALUE );
103 12 : xReceiver->setArguments( aArgs );
104 : }
105 12 : }
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 : // auch Chart-Objekte die nicht in der Collection sind
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 = OUString();
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 28 : uno::Reference< chart2::XChartDocument > ScDocument::GetChartByName( const OUString& rChartName )
228 : {
229 28 : uno::Reference< chart2::XChartDocument > xReturn;
230 :
231 28 : if (pDrawLayer)
232 : {
233 28 : sal_uInt16 nCount = pDrawLayer->GetPageCount();
234 28 : SCTAB nSize = static_cast<SCTAB>(maTabs.size());
235 28 : for (sal_uInt16 nTab=0; nTab<nCount && nTab < nSize; nTab++)
236 : {
237 28 : SdrPage* pPage = pDrawLayer->GetPage(nTab);
238 : OSL_ENSURE(pPage,"Page ?");
239 :
240 28 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
241 28 : SdrObject* pObject = aIter.Next();
242 56 : while (pObject)
243 : {
244 112 : if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
245 112 : OUString(static_cast<SdrOle2Obj*>(pObject)->GetPersistName()) == rChartName )
246 : {
247 28 : xReturn.set( ScChartHelper::GetChartFromSdrObject( pObject ) );
248 28 : return xReturn;
249 : }
250 0 : pObject = aIter.Next();
251 : }
252 0 : }
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 12 : 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 12 : if (!pDrawLayer)
297 0 : return;
298 :
299 12 : sal_uInt16 nCount = pDrawLayer->GetPageCount();
300 12 : for (sal_uInt16 nTab=0; nTab<nCount && nTab < static_cast<SCTAB>(maTabs.size()); nTab++)
301 : {
302 12 : SdrPage* pPage = pDrawLayer->GetPage(nTab);
303 : OSL_ENSURE(pPage,"Page ?");
304 :
305 12 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
306 12 : SdrObject* pObject = aIter.Next();
307 24 : while (pObject)
308 : {
309 48 : if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
310 48 : OUString(static_cast<SdrOle2Obj*>(pObject)->GetPersistName()) == rName )
311 : {
312 12 : uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) );
313 12 : if ( xChartDoc.is() )
314 : {
315 12 : chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
316 12 : bool bHasCategories = false;
317 12 : bool bFirstCellAsLabel = false;
318 12 : OUString aRangesStr;
319 12 : lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
320 :
321 12 : rRanges.Parse( aRangesStr, this );
322 12 : if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
323 : {
324 12 : rRowHeaders = bHasCategories;
325 12 : rColHeaders = bFirstCellAsLabel;
326 : }
327 : else
328 : {
329 0 : rColHeaders = bHasCategories;
330 0 : rRowHeaders = bFirstCellAsLabel;
331 12 : }
332 : }
333 12 : return;
334 : }
335 0 : pObject = aIter.Next();
336 : }
337 0 : }
338 : }
339 :
340 12 : void ScDocument::UpdateChartArea( const OUString& rChartName,
341 : const ScRangeListRef& rNewList, bool bColHeaders, bool bRowHeaders,
342 : bool bAdd )
343 : {
344 12 : if (!pDrawLayer)
345 0 : return;
346 :
347 12 : for (SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]; nTab++)
348 : {
349 12 : SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
350 : OSL_ENSURE(pPage,"Page ?");
351 :
352 12 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
353 12 : SdrObject* pObject = aIter.Next();
354 24 : while (pObject)
355 : {
356 48 : if ( pObject->GetObjIdentifier() == OBJ_OLE2 &&
357 48 : OUString(static_cast<SdrOle2Obj*>(pObject)->GetPersistName()) == rChartName )
358 : {
359 12 : uno::Reference< chart2::XChartDocument > xChartDoc( ScChartHelper::GetChartFromSdrObject( pObject ) );
360 12 : uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY );
361 12 : if ( xChartDoc.is() && xReceiver.is() )
362 : {
363 12 : ScRangeListRef aNewRanges;
364 12 : chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS;
365 12 : bool bHasCategories = false;
366 12 : bool bFirstCellAsLabel = false;
367 24 : OUString aRangesStr;
368 12 : lcl_GetChartParameters( xChartDoc, aRangesStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
369 :
370 12 : bool bInternalData = xChartDoc->hasInternalDataProvider();
371 :
372 12 : 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 12 : if ( eDataRowSource == chart::ChartDataRowSource_COLUMNS )
387 : {
388 12 : bHasCategories = bRowHeaders;
389 12 : bFirstCellAsLabel = bColHeaders;
390 : }
391 : else
392 : {
393 0 : bHasCategories = bColHeaders;
394 0 : bFirstCellAsLabel = bRowHeaders;
395 : }
396 12 : aNewRanges = rNewList;
397 : }
398 :
399 12 : 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 24 : OUString sRangeStr;
410 12 : aNewRanges->Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() );
411 :
412 12 : lcl_SetChartParameters( xReceiver, sRangeStr, eDataRowSource, bHasCategories, bFirstCellAsLabel );
413 :
414 12 : pChartListenerCollection->ChangeListening( rChartName, aNewRanges );
415 :
416 24 : return; // do not search anymore
417 0 : }
418 : }
419 0 : pObject = aIter.Next();
420 : }
421 0 : }
422 : }
423 :
424 2 : void ScDocument::UpdateChart( const OUString& rChartName )
425 : {
426 2 : if (!pDrawLayer || bInDtorClear)
427 2 : return;
428 2 : uno::Reference< chart2::XChartDocument > xChartDoc( GetChartByName( rChartName ) );
429 2 : if( xChartDoc.is() )
430 : {
431 : try
432 : {
433 2 : uno::Reference< util::XModifiable > xModif( xChartDoc, uno::UNO_QUERY_THROW );
434 2 : if( apTemporaryChartLock.get() )
435 2 : apTemporaryChartLock->AlsoLockThisChart( uno::Reference< frame::XModel >( xModif, uno::UNO_QUERY ) );
436 2 : 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 2 : if ( !( xChartDoc.is() && xChartDoc->hasInternalDataProvider() ) && pChartListenerCollection )
447 : {
448 2 : pChartListenerCollection->ChangeListening( rChartName, new ScRangeList );
449 2 : }
450 : }
451 :
452 10 : 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 10 : uno::Reference< embed::XEmbeddedObject > xObject = FindOleObjectByName( rName );
458 10 : if ( xObject.is() )
459 : {
460 8 : uno::Reference< util::XCloseable > xComponent = xObject->getComponent();
461 16 : uno::Reference< chart2::XChartDocument > xChartDoc( xComponent, uno::UNO_QUERY );
462 16 : uno::Reference< chart2::data::XDataReceiver > xReceiver( xComponent, uno::UNO_QUERY );
463 8 : if ( xChartDoc.is() && xReceiver.is() && !xChartDoc->hasInternalDataProvider())
464 : {
465 8 : uno::Sequence<OUString> aRepresentations( xReceiver->getUsedRangeRepresentations() );
466 16 : ScRangeListRef aRanges = new ScRangeList;
467 8 : sal_Int32 nRangeCount = aRepresentations.getLength();
468 32 : for ( sal_Int32 i=0; i<nRangeCount; i++ )
469 : {
470 24 : ScRange aRange;
471 24 : ScAddress::Details aDetails(GetAddressConvention(), 0, 0);
472 24 : if ( aRange.ParseAny( aRepresentations[i], this, aDetails ) & SCA_VALID )
473 22 : aRanges->Append( aRange );
474 : }
475 :
476 16 : pChartListenerCollection->ChangeListening( rName, aRanges );
477 8 : }
478 10 : }
479 10 : }
480 :
481 666 : 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 666 : if (!pDrawLayer)
487 1158 : return;
488 :
489 174 : ScChartListenerCollection::ListenersType& rListeners = pChartListenerCollection->getListeners();
490 174 : ScChartListenerCollection::ListenersType::iterator it = rListeners.begin(), itEnd = rListeners.end();
491 174 : 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 1822 : bool ScDocument::HasData( SCCOL nCol, SCROW nRow, SCTAB nTab )
621 : {
622 1822 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
623 1822 : return maTabs[nTab]->HasData( nCol, nRow );
624 : else
625 0 : return false;
626 : }
627 :
628 : uno::Reference< embed::XEmbeddedObject >
629 10 : ScDocument::FindOleObjectByName( const OUString& rName )
630 : {
631 10 : if (!pDrawLayer)
632 0 : return uno::Reference< embed::XEmbeddedObject >();
633 :
634 : // die Seiten hier vom Draw-Layer nehmen,
635 : // weil sie evtl. nicht mit den Tabellen uebereinstimmen
636 : // (z.B. Redo von Tabelle loeschen, Draw-Redo passiert vor DeleteTab).
637 :
638 10 : sal_uInt16 nCount = pDrawLayer->GetPageCount();
639 12 : for (sal_uInt16 nTab=0; nTab<nCount; nTab++)
640 : {
641 10 : SdrPage* pPage = pDrawLayer->GetPage(nTab);
642 : OSL_ENSURE(pPage,"Page ?");
643 :
644 10 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
645 10 : SdrObject* pObject = aIter.Next();
646 22 : while (pObject)
647 : {
648 10 : if ( pObject->GetObjIdentifier() == OBJ_OLE2 )
649 : {
650 10 : SdrOle2Obj * pOleObject ( dynamic_cast< SdrOle2Obj * >( pObject ));
651 40 : if( pOleObject &&
652 40 : OUString(pOleObject->GetPersistName()) == rName )
653 : {
654 8 : return pOleObject->GetObjRef();
655 : }
656 : }
657 2 : pObject = aIter.Next();
658 : }
659 2 : }
660 :
661 2 : return uno::Reference< embed::XEmbeddedObject >();
662 : }
663 :
664 1106 : void ScDocument::UpdateChartListenerCollection()
665 : {
666 : OSL_ASSERT(pChartListenerCollection);
667 :
668 1106 : bChartListenerCollectionNeedsUpdate = false;
669 1106 : if (!pDrawLayer)
670 1106 : return;
671 :
672 3172 : for (SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()); nTab++)
673 : {
674 2066 : if (!maTabs[nTab])
675 0 : continue;
676 :
677 2066 : SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
678 : OSL_ENSURE(pPage,"Page ?");
679 :
680 2066 : if (!pPage)
681 0 : continue;
682 :
683 2066 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
684 : ScChartListenerCollection::StringSetType& rNonOleObjects =
685 2066 : pChartListenerCollection->getNonOleObjectNames();
686 :
687 2918 : for (SdrObject* pObject = aIter.Next(); pObject; pObject = aIter.Next())
688 : {
689 852 : if ( pObject->GetObjIdentifier() != OBJ_OLE2 )
690 642 : continue;
691 :
692 210 : OUString aObjName = static_cast<SdrOle2Obj*>(pObject)->GetPersistName();
693 210 : ScChartListener* pListener = pChartListenerCollection->findByName(aObjName);
694 :
695 210 : if (pListener)
696 174 : pListener->SetUsed(true);
697 36 : else if (rNonOleObjects.count(aObjName) > 0)
698 : {
699 : // non-chart OLE object -> don't touch
700 : }
701 : else
702 : {
703 36 : uno::Reference< embed::XEmbeddedObject > xIPObj = static_cast<SdrOle2Obj*>(pObject)->GetObjRef();
704 : OSL_ENSURE( xIPObj.is(), "No embedded object is given!");
705 72 : uno::Reference< ::com::sun::star::chart2::data::XDataReceiver > xReceiver;
706 72 : uno::Reference< embed::XComponentSupplier > xCompSupp( xIPObj, uno::UNO_QUERY );
707 36 : if( xCompSupp.is())
708 36 : xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY );
709 :
710 : // if the object is a chart2::XDataReceiver, we must attach as XDataProvider
711 72 : if( xReceiver.is() &&
712 36 : !PastingDrawFromOtherDoc())
713 : {
714 : // NOTE: this currently does not work as we are
715 : // unable to set the data. So a chart from the
716 : // same document is treated like a chart with
717 : // own data for the time being.
718 :
719 : // data provider
720 : // number formats supplier
721 :
722 : // data ?
723 : // how to set?? Defined in XML-file, which is already loaded!!!
724 : // => we have to do this stuff here, BEFORE the chart is actually loaded
725 : }
726 :
727 : // put into list of other ole objects, so the object doesn't have to
728 : // be swapped in the next time UpdateChartListenerCollection is called
729 : //! remove names when objects are no longer there?
730 : // (object names aren't used again before reloading the document)
731 :
732 72 : rNonOleObjects.insert(aObjName);
733 : }
734 210 : }
735 2066 : }
736 : // alle nicht auf SetUsed gesetzten loeschen
737 1106 : pChartListenerCollection->FreeUnused();
738 : }
739 :
740 0 : void ScDocument::AddOLEObjectToCollection(const OUString& rName)
741 : {
742 : OSL_ASSERT(pChartListenerCollection);
743 : ScChartListenerCollection::StringSetType& rNonOleObjects =
744 0 : pChartListenerCollection->getNonOleObjectNames();
745 :
746 0 : rNonOleObjects.insert(rName);
747 228 : }
748 :
749 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|