1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <charthelper.hxx>
21 #include <document.hxx>
22 #include <drwlayer.hxx>
23 #include <rangelst.hxx>
24 #include <chartlis.hxx>
27 #include <comphelper/propertyvalue.hxx>
28 #include <svx/svditer.hxx>
29 #include <svx/svdoole2.hxx>
30 #include <svx/svdpage.hxx>
31 #include <svtools/embedhlp.hxx>
32 #include <comphelper/diagnose_ex.hxx>
34 #include <com/sun/star/chart2/XChartDocument.hpp>
35 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
36 #include <com/sun/star/embed/XEmbeddedObject.hpp>
37 #include <com/sun/star/util/XModifiable.hpp>
39 using namespace com::sun::star
;
40 using ::com::sun::star::uno::Reference
;
45 sal_uInt16
lcl_DoUpdateCharts( ScDocument
& rDoc
)
47 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
51 sal_uInt16 nFound
= 0;
53 sal_uInt16 nPageCount
= pModel
->GetPageCount();
54 for (sal_uInt16 nPageNo
=0; nPageNo
<nPageCount
; nPageNo
++)
56 SdrPage
* pPage
= pModel
->GetPage(nPageNo
);
57 OSL_ENSURE(pPage
,"Page ?");
59 SdrObjListIter
aIter( pPage
, SdrIterMode::DeepNoGroups
);
60 while (SdrObject
* pObject
= aIter
.Next())
62 if ( pObject
->GetObjIdentifier() == SdrObjKind::OLE2
&& ScDocument::IsChart( pObject
) )
64 OUString aName
= static_cast<SdrOle2Obj
*>(pObject
)->GetPersistName();
65 rDoc
.UpdateChart( aName
);
73 bool lcl_AdjustRanges( ScRangeList
& rRanges
, SCTAB nSourceTab
, SCTAB nDestTab
, SCTAB nTabCount
)
75 //TODO: if multiple sheets are copied, update references into the other copied sheets?
77 bool bChanged
= false;
79 for ( size_t i
=0, nCount
= rRanges
.size(); i
< nCount
; i
++ )
81 ScRange
& rRange
= rRanges
[ i
];
82 if ( rRange
.aStart
.Tab() == nSourceTab
&& rRange
.aEnd
.Tab() == nSourceTab
)
84 rRange
.aStart
.SetTab( nDestTab
);
85 rRange
.aEnd
.SetTab( nDestTab
);
88 if ( rRange
.aStart
.Tab() >= nTabCount
)
90 rRange
.aStart
.SetTab( nTabCount
> 0 ? ( nTabCount
- 1 ) : 0 );
93 if ( rRange
.aEnd
.Tab() >= nTabCount
)
95 rRange
.aEnd
.SetTab( nTabCount
> 0 ? ( nTabCount
- 1 ) : 0 );
103 }//end anonymous namespace
107 sal_uInt16
ScChartHelper::DoUpdateAllCharts( ScDocument
& rDoc
)
109 return lcl_DoUpdateCharts( rDoc
);
112 void ScChartHelper::AdjustRangesOfChartsOnDestinationPage( const ScDocument
& rSrcDoc
, ScDocument
& rDestDoc
, const SCTAB nSrcTab
, const SCTAB nDestTab
)
114 ScDrawLayer
* pDrawLayer
= rDestDoc
.GetDrawLayer();
118 SdrPage
* pDestPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nDestTab
));
122 SdrObjListIter
aIter( pDestPage
, SdrIterMode::Flat
);
123 while (SdrObject
* pObject
= aIter
.Next())
125 if( pObject
->GetObjIdentifier() == SdrObjKind::OLE2
&& static_cast<SdrOle2Obj
*>(pObject
)->IsChart() )
127 OUString aChartName
= static_cast<SdrOle2Obj
*>(pObject
)->GetPersistName();
129 Reference
< chart2::XChartDocument
> xChartDoc( rDestDoc
.GetChartByName( aChartName
) );
130 Reference
< chart2::data::XDataReceiver
> xReceiver( xChartDoc
, uno::UNO_QUERY
);
131 if( xChartDoc
.is() && xReceiver
.is() && !xChartDoc
->hasInternalDataProvider() )
133 ::std::vector
< ScRangeList
> aRangesVector
;
134 rDestDoc
.GetChartRanges( aChartName
, aRangesVector
, rSrcDoc
);
136 for( ScRangeList
& rScRangeList
: aRangesVector
)
138 lcl_AdjustRanges( rScRangeList
, nSrcTab
, nDestTab
, rDestDoc
.GetTableCount() );
140 rDestDoc
.SetChartRanges( aChartName
, aRangesVector
);
146 void ScChartHelper::UpdateChartsOnDestinationPage( ScDocument
& rDestDoc
, const SCTAB nDestTab
)
148 ScDrawLayer
* pDrawLayer
= rDestDoc
.GetDrawLayer();
152 SdrPage
* pDestPage
= pDrawLayer
->GetPage(static_cast<sal_uInt16
>(nDestTab
));
156 SdrObjListIter
aIter( pDestPage
, SdrIterMode::Flat
);
157 while (SdrObject
* pObject
= aIter
.Next())
159 if( pObject
->GetObjIdentifier() == SdrObjKind::OLE2
&& static_cast<SdrOle2Obj
*>(pObject
)->IsChart() )
161 OUString aChartName
= static_cast<SdrOle2Obj
*>(pObject
)->GetPersistName();
162 Reference
< chart2::XChartDocument
> xChartDoc( rDestDoc
.GetChartByName( aChartName
) );
163 Reference
< util::XModifiable
> xModif(xChartDoc
, uno::UNO_QUERY_THROW
);
164 xModif
->setModified( true);
169 uno::Reference
< chart2::XChartDocument
> ScChartHelper::GetChartFromSdrObject( const SdrObject
* pObject
)
171 uno::Reference
< chart2::XChartDocument
> xReturn
;
174 if( pObject
->GetObjIdentifier() == SdrObjKind::OLE2
&& static_cast<const SdrOle2Obj
*>(pObject
)->IsChart() )
176 uno::Reference
< embed::XEmbeddedObject
> xIPObj
= static_cast<const SdrOle2Obj
*>(pObject
)->GetObjRef();
179 (void)svt::EmbeddedObjectRef::TryRunningState( xIPObj
);
180 uno::Reference
< util::XCloseable
> xComponent
= xIPObj
->getComponent();
181 xReturn
.set( uno::Reference
< chart2::XChartDocument
>( xComponent
, uno::UNO_QUERY
) );
188 void ScChartHelper::GetChartRanges( const uno::Reference
< chart2::XChartDocument
>& xChartDoc
,
189 std::vector
< OUString
>& rRanges
)
192 uno::Reference
< chart2::data::XDataSource
> xDataSource( xChartDoc
, uno::UNO_QUERY
);
193 if( !xDataSource
.is() )
196 const uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aLabeledDataSequences( xDataSource
->getDataSequences() );
197 rRanges
.reserve(2*aLabeledDataSequences
.getLength());
198 for(const uno::Reference
<chart2::data::XLabeledDataSequence
>& xLabeledSequence
: aLabeledDataSequences
)
200 if(!xLabeledSequence
.is())
202 uno::Reference
< chart2::data::XDataSequence
> xLabel( xLabeledSequence
->getLabel());
203 uno::Reference
< chart2::data::XDataSequence
> xValues( xLabeledSequence
->getValues());
206 rRanges
.push_back( xLabel
->getSourceRangeRepresentation() );
208 rRanges
.push_back( xValues
->getSourceRangeRepresentation() );
212 void ScChartHelper::SetChartRanges( const uno::Reference
< chart2::XChartDocument
>& xChartDoc
,
213 const uno::Sequence
< OUString
>& rRanges
)
215 uno::Reference
< chart2::data::XDataSource
> xDataSource( xChartDoc
, uno::UNO_QUERY
);
216 if( !xDataSource
.is() )
218 uno::Reference
< chart2::data::XDataProvider
> xDataProvider
= xChartDoc
->getDataProvider();
219 if( !xDataProvider
.is() )
222 xChartDoc
->lockControllers();
226 OUString
aPropertyNameRole( u
"Role"_ustr
);
228 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aLabeledDataSequences( xDataSource
->getDataSequences() );
230 for( uno::Reference
<chart2::data::XLabeledDataSequence
>& xLabeledSequence
: asNonConstRange(aLabeledDataSequences
) )
232 if( nRange
>= rRanges
.getLength() )
235 if(!xLabeledSequence
.is())
237 uno::Reference
< beans::XPropertySet
> xLabel( xLabeledSequence
->getLabel(), uno::UNO_QUERY
);
238 uno::Reference
< beans::XPropertySet
> xValues( xLabeledSequence
->getValues(), uno::UNO_QUERY
);
242 uno::Reference
< chart2::data::XDataSequence
> xNewSeq(
243 xDataProvider
->createDataSequenceByRangeRepresentation( rRanges
[nRange
++] ));
245 uno::Reference
< beans::XPropertySet
> xNewProps( xNewSeq
, uno::UNO_QUERY
);
247 xNewProps
->setPropertyValue( aPropertyNameRole
, xLabel
->getPropertyValue( aPropertyNameRole
) );
249 xLabeledSequence
->setLabel( xNewSeq
);
252 if( nRange
>= rRanges
.getLength() )
257 uno::Reference
< chart2::data::XDataSequence
> xNewSeq(
258 xDataProvider
->createDataSequenceByRangeRepresentation( rRanges
[nRange
++] ));
260 uno::Reference
< beans::XPropertySet
> xNewProps( xNewSeq
, uno::UNO_QUERY
);
262 xNewProps
->setPropertyValue( aPropertyNameRole
, xValues
->getPropertyValue( aPropertyNameRole
) );
264 xLabeledSequence
->setValues( xNewSeq
);
268 catch (const uno::Exception
&)
270 TOOLS_WARN_EXCEPTION( "sc", "Exception in ScChartHelper::SetChartRanges - invalid range string?");
273 xChartDoc
->unlockControllers();
276 void ScChartHelper::AddRangesIfProtectedChart( ScRangeListVector
& rRangesVector
, const ScDocument
& rDocument
, SdrObject
* pObject
)
278 if ( !(pObject
&& ( pObject
->GetObjIdentifier() == SdrObjKind::OLE2
)) )
281 SdrOle2Obj
* pSdrOle2Obj
= dynamic_cast< SdrOle2Obj
* >( pObject
);
282 if ( !(pSdrOle2Obj
&& pSdrOle2Obj
->IsChart()) )
285 const uno::Reference
< embed::XEmbeddedObject
>& xEmbeddedObj
= pSdrOle2Obj
->GetObjRef();
286 if ( !xEmbeddedObj
.is() )
289 bool bDisableDataTableDialog
= false;
290 sal_Int32 nOldState
= xEmbeddedObj
->getCurrentState();
291 (void)svt::EmbeddedObjectRef::TryRunningState( xEmbeddedObj
);
292 uno::Reference
< beans::XPropertySet
> xProps( xEmbeddedObj
->getComponent(), uno::UNO_QUERY
);
294 ( xProps
->getPropertyValue(u
"DisableDataTableDialog"_ustr
) >>= bDisableDataTableDialog
) &&
295 bDisableDataTableDialog
)
297 ScChartListenerCollection
* pCollection
= rDocument
.GetChartListenerCollection();
300 const OUString
& aChartName
= pSdrOle2Obj
->GetPersistName();
301 const ScChartListener
* pListener
= pCollection
->findByName(aChartName
);
304 const ScRangeListRef xRangeList
= pListener
->GetRangeList();
305 if ( xRangeList
.is() )
307 rRangesVector
.push_back( *xRangeList
);
312 if ( xEmbeddedObj
->getCurrentState() != nOldState
)
314 xEmbeddedObj
->changeState( nOldState
);
318 void ScChartHelper::FillProtectedChartRangesVector( ScRangeListVector
& rRangesVector
, const ScDocument
& rDocument
, const SdrPage
* pPage
)
322 SdrObjListIter
aIter( pPage
, SdrIterMode::DeepNoGroups
);
323 while (SdrObject
* pObject
= aIter
.Next())
324 AddRangesIfProtectedChart( rRangesVector
, rDocument
, pObject
);
328 void ScChartHelper::GetChartNames( ::std::vector
< OUString
>& rChartNames
, const SdrPage
* pPage
)
333 SdrObjListIter
aIter( pPage
, SdrIterMode::DeepNoGroups
);
334 while (SdrObject
* pObject
= aIter
.Next())
336 if ( pObject
->GetObjIdentifier() == SdrObjKind::OLE2
)
338 SdrOle2Obj
* pSdrOle2Obj
= dynamic_cast< SdrOle2Obj
* >( pObject
);
339 if ( pSdrOle2Obj
&& pSdrOle2Obj
->IsChart() )
341 rChartNames
.push_back( pSdrOle2Obj
->GetPersistName() );
347 void ScChartHelper::CreateProtectedChartListenersAndNotify( ScDocument
& rDoc
, const SdrPage
* pPage
, ScModelObj
* pModelObj
, SCTAB nTab
,
348 const ScRangeListVector
& rRangesVector
, const ::std::vector
< OUString
>& rExcludedChartNames
, bool bSameDoc
)
350 if ( !(pPage
&& pModelObj
) )
353 size_t nRangeListCount
= rRangesVector
.size();
354 size_t nRangeList
= 0;
355 SdrObjListIter
aIter( pPage
, SdrIterMode::DeepNoGroups
);
356 while (SdrObject
* pObject
= aIter
.Next())
358 if ( pObject
->GetObjIdentifier() == SdrObjKind::OLE2
)
360 SdrOle2Obj
* pSdrOle2Obj
= dynamic_cast< SdrOle2Obj
* >( pObject
);
361 if ( pSdrOle2Obj
&& pSdrOle2Obj
->IsChart() )
363 const OUString
& aChartName
= pSdrOle2Obj
->GetPersistName();
364 ::std::vector
< OUString
>::const_iterator aEnd
= rExcludedChartNames
.end();
365 ::std::vector
< OUString
>::const_iterator aFound
= ::std::find( rExcludedChartNames
.begin(), aEnd
, aChartName
);
366 if ( aFound
== aEnd
)
368 const uno::Reference
< embed::XEmbeddedObject
>& xEmbeddedObj
= pSdrOle2Obj
->GetObjRef();
369 if ( xEmbeddedObj
.is() && ( nRangeList
< nRangeListCount
) )
371 bool bDisableDataTableDialog
= false;
372 (void)svt::EmbeddedObjectRef::TryRunningState( xEmbeddedObj
);
373 uno::Reference
< beans::XPropertySet
> xProps( xEmbeddedObj
->getComponent(), uno::UNO_QUERY
);
375 ( xProps
->getPropertyValue(u
"DisableDataTableDialog"_ustr
) >>= bDisableDataTableDialog
) &&
376 bDisableDataTableDialog
)
380 ScChartListenerCollection
* pCollection
= rDoc
.GetChartListenerCollection();
381 if (pCollection
&& !pCollection
->findByName(aChartName
))
383 ScRangeListRef
rRangeList(new ScRangeList(rRangesVector
[nRangeList
++]));
384 ScChartListener
* pChartListener
= new ScChartListener( aChartName
, rDoc
, rRangeList
);
385 pCollection
->insert( pChartListener
);
386 pChartListener
->StartListeningTo();
391 xProps
->setPropertyValue(u
"DisableDataTableDialog"_ustr
,
393 xProps
->setPropertyValue(u
"DisableComplexChartTypes"_ustr
,
399 if (pModelObj
->HasChangesListeners())
401 tools::Rectangle aRectangle
= pSdrOle2Obj
->GetSnapRect();
402 ScRange
aRange( rDoc
.GetRange( nTab
, aRectangle
) );
403 ScRangeList
aChangeRanges( aRange
);
405 uno::Sequence
< beans::PropertyValue
> aProperties
{
406 comphelper::makePropertyValue(u
"Name"_ustr
, aChartName
)
409 pModelObj
->NotifyChanges( u
"insert-chart"_ustr
, aChangeRanges
, aProperties
);
417 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */