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