1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26
27 #include "DialogModel.hxx"
28 #include "RangeSelectionHelper.hxx"
29 #include "PropertyHelper.hxx"
30 #include "DataSeriesHelper.hxx"
31 #include "DataSourceHelper.hxx"
32 #include "DiagramHelper.hxx"
33 #include "macros.hxx"
34 #include "Strings.hrc"
35 #include "ResId.hxx"
36 #include "ContainerHelper.hxx"
37 #include "CommonFunctors.hxx"
38 #include "ControllerLockGuard.hxx"
39 #include "ChartTypeHelper.hxx"
40 #include "ThreeDHelper.hxx"
41
42 #include <com/sun/star/util/XCloneable.hpp>
43 #include <com/sun/star/chart2/AxisType.hpp>
44 #include <com/sun/star/chart2/XTitled.hpp>
45 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
46 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
47 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
48 #include <com/sun/star/chart2/data/XDataSink.hpp>
49
50 #include <tools/string.hxx>
51
52 #include <utility>
53 #include <algorithm>
54 #include <iterator>
55 #include <functional>
56 #include <numeric>
57
58 using namespace ::com::sun::star;
59 using namespace ::com::sun::star::chart2;
60 using namespace ::chart::ContainerHelper;
61
62 using ::com::sun::star::uno::Reference;
63 using ::com::sun::star::uno::Sequence;
64 using ::rtl::OUString;
65
66 // ----------------------------------------
67
68 namespace
69 {
70 const OUString lcl_aLabelRole( RTL_CONSTASCII_USTRINGPARAM( "label" ));
71
72 struct lcl_ChartTypeToSeriesCnt : ::std::unary_function<
73 Reference< XChartType >, Reference< XDataSeriesContainer > >
74 {
operator ()__anonff2df0710111::lcl_ChartTypeToSeriesCnt75 Reference< XDataSeriesContainer > operator() (
76 const Reference< XChartType > & xChartType )
77 {
78 return Reference< XDataSeriesContainer >::query( xChartType );
79 }
80 };
81
lcl_ConvertRole(const OUString & rRoleString,bool bFromInternalToUI)82 OUString lcl_ConvertRole( const OUString & rRoleString, bool bFromInternalToUI )
83 {
84 OUString aResult( rRoleString );
85
86 typedef ::std::map< OUString, OUString > tTranslationMap;
87 static tTranslationMap aTranslationMap;
88
89 if( aTranslationMap.size() == 0 )
90 {
91 aTranslationMap[ C2U( "categories" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_CATEGORIES )));
92 aTranslationMap[ C2U( "error-bars-x" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X_ERROR )));
93 aTranslationMap[ C2U( "error-bars-x-positive" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X_ERROR_POSITIVE )));
94 aTranslationMap[ C2U( "error-bars-x-negative" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X_ERROR_NEGATIVE )));
95 aTranslationMap[ C2U( "error-bars-y" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y_ERROR )));
96 aTranslationMap[ C2U( "error-bars-y-positive" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_POSITIVE )));
97 aTranslationMap[ C2U( "error-bars-y-negative" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_NEGATIVE )));
98 aTranslationMap[ C2U( "label" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_LABEL )));
99 aTranslationMap[ C2U( "values-first" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_FIRST )));
100 aTranslationMap[ C2U( "values-last" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_LAST )));
101 aTranslationMap[ C2U( "values-max" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_MAX )));
102 aTranslationMap[ C2U( "values-min" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_MIN )));
103 aTranslationMap[ C2U( "values-x" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X )));
104 aTranslationMap[ C2U( "values-y" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y )));
105 aTranslationMap[ C2U( "values-size" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_SIZE )));
106 }
107
108 if( bFromInternalToUI )
109 {
110 tTranslationMap::const_iterator aIt( aTranslationMap.find( rRoleString ));
111 if( aIt != aTranslationMap.end())
112 {
113 aResult = (*aIt).second;
114 }
115 }
116 else
117 {
118 tTranslationMap::const_iterator aIt(
119 ::std::find_if( aTranslationMap.begin(), aTranslationMap.end(),
120 ::std::compose1( ::std::bind2nd(
121 ::std::equal_to< tTranslationMap::mapped_type >(),
122 rRoleString ),
123 ::std::select2nd< tTranslationMap::value_type >())));
124
125 if( aIt != aTranslationMap.end())
126 aResult = (*aIt).first;
127 }
128
129 return aResult;
130 }
131
132 typedef ::std::map< ::rtl::OUString, sal_Int32 > lcl_tRoleIndexMap;
133
lcl_createRoleIndexMap(lcl_tRoleIndexMap & rOutMap)134 void lcl_createRoleIndexMap( lcl_tRoleIndexMap & rOutMap )
135 {
136 rOutMap.clear();
137 sal_Int32 nIndex = 0;
138
139 rOutMap[ C2U( "label" ) ] = ++nIndex;
140 rOutMap[ C2U( "categories" ) ] = ++nIndex;
141 rOutMap[ C2U( "values-x" ) ] = ++nIndex;
142 rOutMap[ C2U( "values-y" ) ] = ++nIndex;
143 rOutMap[ C2U( "error-bars-x" ) ] = ++nIndex;
144 rOutMap[ C2U( "error-bars-x-positive" ) ] = ++nIndex;
145 rOutMap[ C2U( "error-bars-x-negative" ) ] = ++nIndex;
146 rOutMap[ C2U( "error-bars-y" ) ] = ++nIndex;
147 rOutMap[ C2U( "error-bars-y-positive" ) ] = ++nIndex;
148 rOutMap[ C2U( "error-bars-y-negative" ) ] = ++nIndex;
149 rOutMap[ C2U( "values-first" ) ] = ++nIndex;
150 rOutMap[ C2U( "values-min" ) ] = ++nIndex;
151 rOutMap[ C2U( "values-max" ) ] = ++nIndex;
152 rOutMap[ C2U( "values-last" ) ] = ++nIndex;
153 rOutMap[ C2U( "values-size" ) ] = ++nIndex;
154 }
155
156 struct lcl_DataSeriesContainerAppend : public
157 ::std::iterator< ::std::output_iterator_tag, Reference< XDataSeriesContainer > >
158 {
159 typedef ::std::vector< ::chart::DialogModel::tSeriesWithChartTypeByName > tContainerType;
160
lcl_DataSeriesContainerAppend__anonff2df0710111::lcl_DataSeriesContainerAppend161 explicit lcl_DataSeriesContainerAppend( tContainerType & rCnt )
162 : m_rDestCnt( rCnt )
163 {}
164
operator =__anonff2df0710111::lcl_DataSeriesContainerAppend165 lcl_DataSeriesContainerAppend & operator= ( const value_type & xVal )
166 {
167 try
168 {
169 if( xVal.is())
170 {
171 Sequence< Reference< XDataSeries > > aSeq( xVal->getDataSeries());
172 OUString aRole( RTL_CONSTASCII_USTRINGPARAM("values-y"));
173 Reference< XChartType > xCT( xVal, uno::UNO_QUERY );
174 if( xCT.is())
175 aRole = xCT->getRoleOfSequenceForSeriesLabel();
176 for( sal_Int32 nI = 0; nI < aSeq.getLength(); ++ nI )
177 {
178 m_rDestCnt.push_back(
179 ::chart::DialogModel::tSeriesWithChartTypeByName(
180 ::chart::DataSeriesHelper::getDataSeriesLabel( aSeq[nI], aRole ),
181 ::std::make_pair( aSeq[nI], xCT )));
182 }
183 }
184 }
185 catch( uno::Exception & ex )
186 {
187 ASSERT_EXCEPTION( ex );
188 }
189 return *this;
190 }
191
operator *__anonff2df0710111::lcl_DataSeriesContainerAppend192 lcl_DataSeriesContainerAppend & operator* () { return *this; }
operator ++__anonff2df0710111::lcl_DataSeriesContainerAppend193 lcl_DataSeriesContainerAppend & operator++ () { return *this; }
operator ++__anonff2df0710111::lcl_DataSeriesContainerAppend194 lcl_DataSeriesContainerAppend & operator++ (int) { return *this; }
195
196 private:
197 tContainerType & m_rDestCnt;
198 };
199
200 struct lcl_RolesWithRangeAppend : public
201 ::std::iterator< ::std::output_iterator_tag, Reference< data::XLabeledDataSequence > >
202 {
203 typedef ::chart::DialogModel::tRolesWithRanges tContainerType;
204
lcl_RolesWithRangeAppend__anonff2df0710111::lcl_RolesWithRangeAppend205 explicit lcl_RolesWithRangeAppend( tContainerType & rCnt,
206 const ::rtl::OUString & aLabelRole )
207 : m_rDestCnt( rCnt ),
208 m_aRoleForLabelSeq( aLabelRole )
209 {}
210
operator =__anonff2df0710111::lcl_RolesWithRangeAppend211 lcl_RolesWithRangeAppend & operator= ( const value_type & xVal )
212 {
213 try
214 {
215 if( xVal.is())
216 {
217 // data sequence
218 Reference< data::XDataSequence > xSeq( xVal->getValues());
219 if( xSeq.is())
220 {
221 OUString aRole;
222 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
223 if( xProp->getPropertyValue( C2U("Role")) >>= aRole )
224 {
225 m_rDestCnt.insert(
226 tContainerType::value_type(
227 aRole, xSeq->getSourceRangeRepresentation()));
228 // label
229 if( aRole.equals( m_aRoleForLabelSeq ))
230 {
231 Reference< data::XDataSequence > xLabelSeq( xVal->getLabel());
232 if( xLabelSeq.is())
233 {
234 m_rDestCnt.insert(
235 tContainerType::value_type(
236 lcl_aLabelRole, xLabelSeq->getSourceRangeRepresentation()));
237 }
238 }
239 }
240 }
241 }
242 }
243 catch( uno::Exception & ex )
244 {
245 ASSERT_EXCEPTION( ex );
246 }
247 return *this;
248 }
249
operator *__anonff2df0710111::lcl_RolesWithRangeAppend250 lcl_RolesWithRangeAppend & operator* () { return *this; }
operator ++__anonff2df0710111::lcl_RolesWithRangeAppend251 lcl_RolesWithRangeAppend & operator++ () { return *this; }
operator ++__anonff2df0710111::lcl_RolesWithRangeAppend252 lcl_RolesWithRangeAppend & operator++ (int) { return *this; }
253
254 private:
255 tContainerType & m_rDestCnt;
256 OUString m_aRoleForLabelSeq;
257 };
258
lcl_SetSequenceRole(const Reference<data::XDataSequence> & xSeq,const OUString & rRole)259 void lcl_SetSequenceRole(
260 const Reference< data::XDataSequence > & xSeq,
261 const OUString & rRole )
262 {
263 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
264 if( xProp.is())
265 xProp->setPropertyValue( C2U("Role"), uno::makeAny( rRole ));
266 }
267
lcl_CreateNewSeries(const Reference<uno::XComponentContext> & xContext,const Reference<XChartType> & xChartType,sal_Int32 nNewSeriesIndex,sal_Int32 nTotalNumberOfSeriesInCTGroup,const Reference<XDiagram> & xDiagram,const Reference<XChartTypeTemplate> & xTemplate,bool bCreateDataCachedSequences)268 Reference< XDataSeries > lcl_CreateNewSeries(
269 const Reference< uno::XComponentContext > & xContext,
270 const Reference< XChartType > & xChartType,
271 sal_Int32 nNewSeriesIndex,
272 sal_Int32 nTotalNumberOfSeriesInCTGroup,
273 const Reference< XDiagram > & xDiagram,
274 const Reference< XChartTypeTemplate > & xTemplate,
275 bool bCreateDataCachedSequences )
276 {
277 // create plain series
278 Reference< XDataSeries > xResult(
279 xContext->getServiceManager()->createInstanceWithContext(
280 C2U( "com.sun.star.chart2.DataSeries" ),
281 xContext ), uno::UNO_QUERY );
282 if( xTemplate.is())
283 {
284 Reference< beans::XPropertySet > xResultProp( xResult, uno::UNO_QUERY );
285 if( xResultProp.is())
286 {
287 // @deprecated: correct default color should be found by view
288 // without setting it as hard attribute
289 Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
290 if( xColorScheme.is())
291 xResultProp->setPropertyValue(
292 C2U("Color"), uno::makeAny( xColorScheme->getColorByIndex( nNewSeriesIndex )));
293 }
294 sal_Int32 nGroupIndex=0;
295 if( xChartType.is())
296 {
297 Sequence< Reference< XChartType > > aCTs(
298 ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram ));
299 for( ; nGroupIndex<aCTs.getLength(); ++nGroupIndex)
300 if( aCTs[nGroupIndex] == xChartType )
301 break;
302 if( nGroupIndex == aCTs.getLength())
303 nGroupIndex = 0;
304 }
305 xTemplate->applyStyle( xResult, nGroupIndex, nNewSeriesIndex, nTotalNumberOfSeriesInCTGroup );
306 }
307
308 if( bCreateDataCachedSequences )
309 {
310 // set chart type specific roles
311 Reference< data::XDataSink > xSink( xResult, uno::UNO_QUERY );
312 if( xChartType.is() && xSink.is())
313 {
314 ::std::vector< Reference< data::XLabeledDataSequence > > aNewSequences;
315 const OUString aRoleOfSeqForSeriesLabel = xChartType->getRoleOfSequenceForSeriesLabel();
316 const OUString aLabel( String( ::chart::SchResId( STR_DATA_UNNAMED_SERIES )));
317 const Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles());
318 const Sequence< OUString > aOptRoles( xChartType->getSupportedOptionalRoles());
319 sal_Int32 nI = 0;
320
321 for(nI=0; nI<aRoles.getLength(); ++nI)
322 {
323 if( aRoles[nI].equals( lcl_aLabelRole ))
324 continue;
325 Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence() );
326 lcl_SetSequenceRole( xSeq, aRoles[nI] );
327 // assert that aRoleOfSeqForSeriesLabel is part of the mandatory roles
328 if( aRoles[nI].equals( aRoleOfSeqForSeriesLabel ))
329 {
330 Reference< data::XDataSequence > xLabel( ::chart::DataSourceHelper::createCachedDataSequence( aLabel ));
331 lcl_SetSequenceRole( xLabel, lcl_aLabelRole );
332 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq, xLabel ));
333 }
334 else
335 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq ));
336 }
337
338 for(nI=0; nI<aOptRoles.getLength(); ++nI)
339 {
340 if( aOptRoles[nI].equals( lcl_aLabelRole ))
341 continue;
342 Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence());
343 lcl_SetSequenceRole( xSeq, aOptRoles[nI] );
344 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq ));
345 }
346
347 xSink->setData( ContainerToSequence( aNewSequences ));
348 }
349 }
350
351 return xResult;
352 }
353
354 struct lcl_addSeriesNumber : public ::std::binary_function<
355 sal_Int32, Reference< XDataSeriesContainer >, sal_Int32 >
356 {
operator ()__anonff2df0710111::lcl_addSeriesNumber357 sal_Int32 operator() ( sal_Int32 nCurrentNumber, const Reference< XDataSeriesContainer > & xCnt ) const
358 {
359 if( xCnt.is())
360 return nCurrentNumber + (xCnt->getDataSeries().getLength());
361 return nCurrentNumber;
362 }
363 };
364
365 } // anonymous namespace
366
367 // ----------------------------------------
368
369
370 namespace chart
371 {
372
DialogModel(const Reference<XChartDocument> & xChartDocument,const Reference<uno::XComponentContext> & xContext)373 DialogModel::DialogModel(
374 const Reference< XChartDocument > & xChartDocument,
375 const Reference< uno::XComponentContext > & xContext ) :
376 m_xChartDocument( xChartDocument ),
377 m_xContext( xContext ),
378 m_aTimerTriggeredControllerLock( uno::Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) )
379 {
380 }
381
~DialogModel()382 DialogModel::~DialogModel()
383 {}
384
setTemplate(const Reference<XChartTypeTemplate> & xTemplate)385 void DialogModel::setTemplate(
386 const Reference< XChartTypeTemplate > & xTemplate )
387 {
388 m_xTemplate = xTemplate;
389 }
390
391 ::boost::shared_ptr< RangeSelectionHelper >
getRangeSelectionHelper() const392 DialogModel::getRangeSelectionHelper() const
393 {
394 if( ! m_spRangeSelectionHelper.get())
395 m_spRangeSelectionHelper.reset(
396 new RangeSelectionHelper( m_xChartDocument ));
397
398 return m_spRangeSelectionHelper;
399 }
400
getChartModel() const401 Reference< frame::XModel > DialogModel::getChartModel() const
402 {
403 Reference< frame::XModel > xResult( m_xChartDocument, uno::UNO_QUERY );
404 return xResult;
405 }
406
getDataProvider() const407 Reference< data::XDataProvider > DialogModel::getDataProvider() const
408 {
409 Reference< data::XDataProvider > xResult;
410 if( m_xChartDocument.is())
411 xResult.set( m_xChartDocument->getDataProvider());
412 return xResult;
413 }
414
415 ::std::vector< Reference< XDataSeriesContainer > >
getAllDataSeriesContainers() const416 DialogModel::getAllDataSeriesContainers() const
417 {
418 ::std::vector< Reference< XDataSeriesContainer > > aResult;
419
420 try
421 {
422 Reference< XDiagram > xDiagram;
423 if( m_xChartDocument.is())
424 xDiagram.set( m_xChartDocument->getFirstDiagram());
425 if( xDiagram.is())
426 {
427 Reference< XCoordinateSystemContainer > xCooSysCnt(
428 xDiagram, uno::UNO_QUERY_THROW );
429 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
430 xCooSysCnt->getCoordinateSystems());
431 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
432 {
433 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW );
434 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
435 ::std::transform(
436 aChartTypeSeq.getConstArray(), aChartTypeSeq.getConstArray() + aChartTypeSeq.getLength(),
437 ::std::back_inserter( aResult ),
438 lcl_ChartTypeToSeriesCnt() );
439 }
440 }
441 }
442 catch( uno::Exception & ex )
443 {
444 ASSERT_EXCEPTION( ex );
445 }
446
447 return aResult;
448 }
449
450 ::std::vector< DialogModel::tSeriesWithChartTypeByName >
getAllDataSeriesWithLabel() const451 DialogModel::getAllDataSeriesWithLabel() const
452 {
453 ::std::vector< tSeriesWithChartTypeByName > aResult;
454 ::std::vector< Reference< XDataSeriesContainer > > aContainers(
455 getAllDataSeriesContainers());
456
457 ::std::copy( aContainers.begin(), aContainers.end(),
458 lcl_DataSeriesContainerAppend( aResult ));
459 return aResult;
460 }
461
getRolesWithRanges(const Reference<XDataSeries> & xSeries,const::rtl::OUString & aRoleOfSequenceForLabel,const Reference<chart2::XChartType> & xChartType) const462 DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges(
463 const Reference< XDataSeries > & xSeries,
464 const ::rtl::OUString & aRoleOfSequenceForLabel,
465 const Reference< chart2::XChartType > & xChartType ) const
466 {
467 DialogModel::tRolesWithRanges aResult;
468 try
469 {
470 Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW );
471 const Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
472 ::std::copy( aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength(),
473 lcl_RolesWithRangeAppend( aResult, aRoleOfSequenceForLabel ));
474 if( xChartType.is())
475 {
476 // add missing mandatory roles
477 Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles());
478 OUString aEmptyString;
479 sal_Int32 nI = 0;
480 for( nI=0; nI < aRoles.getLength(); ++nI )
481 {
482 if( aResult.find( aRoles[nI] ) == aResult.end() )
483 aResult.insert( DialogModel::tRolesWithRanges::value_type( aRoles[nI], aEmptyString ));
484 }
485
486 // add missing optional roles
487 aRoles = xChartType->getSupportedOptionalRoles();
488 for( nI=0; nI < aRoles.getLength(); ++nI )
489 {
490 if( aResult.find( aRoles[nI] ) == aResult.end() )
491 aResult.insert( DialogModel::tRolesWithRanges::value_type( aRoles[nI], aEmptyString ));
492 }
493 }
494 }
495 catch( uno::Exception & ex )
496 {
497 ASSERT_EXCEPTION( ex );
498 }
499 return aResult;
500 }
501
moveSeries(const Reference<XDataSeries> & xSeries,eMoveDirection eDirection)502 void DialogModel::moveSeries(
503 const Reference< XDataSeries > & xSeries,
504 eMoveDirection eDirection )
505 {
506 m_aTimerTriggeredControllerLock.startTimer();
507 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
508
509 Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
510 DiagramHelper::moveSeries( xDiagram, xSeries, eDirection==MOVE_UP );
511 }
512
insertSeriesAfter(const Reference<XDataSeries> & xSeries,const Reference<XChartType> & xChartType,bool bCreateDataCachedSequences)513 Reference< chart2::XDataSeries > DialogModel::insertSeriesAfter(
514 const Reference< XDataSeries > & xSeries,
515 const Reference< XChartType > & xChartType,
516 bool bCreateDataCachedSequences /* = false */ )
517 {
518 m_aTimerTriggeredControllerLock.startTimer();
519 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
520 Reference< XDataSeries > xNewSeries;
521
522 try
523 {
524 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() );
525 ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram );
526
527 sal_Int32 nSeriesInChartType = 0;
528 const sal_Int32 nTotalSeries = countSeries();
529 if( xChartType.is())
530 {
531 Reference< XDataSeriesContainer > xCnt( xChartType, uno::UNO_QUERY_THROW );
532 nSeriesInChartType = xCnt->getDataSeries().getLength();
533 }
534
535 // create new series
536 xNewSeries.set(
537 lcl_CreateNewSeries(
538 m_xContext,
539 xChartType,
540 nTotalSeries, // new series' index
541 nSeriesInChartType,
542 xDiagram,
543 m_xTemplate,
544 bCreateDataCachedSequences ));
545
546 // add new series to container
547 if( xNewSeries.is())
548 {
549 Reference< XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY_THROW );
550 ::std::vector< Reference< XDataSeries > > aSeries(
551 SequenceToVector( xSeriesCnt->getDataSeries()));
552 ::std::vector< Reference< XDataSeries > >::iterator aIt =
553 ::std::find( aSeries.begin(), aSeries.end(), xSeries );
554 if( aIt == aSeries.end())
555 // if we have no series we insert at the first position.
556 aIt = aSeries.begin();
557 else
558 // vector::insert inserts before, so we have to advance
559 ++aIt;
560 aSeries.insert( aIt, xNewSeries );
561 xSeriesCnt->setDataSeries( ContainerToSequence( aSeries ));
562 }
563
564 ThreeDHelper::setScheme( xDiagram, e3DScheme );
565 }
566 catch( uno::Exception & ex )
567 {
568 ASSERT_EXCEPTION( ex );
569 }
570 return xNewSeries;
571 }
572
deleteSeries(const Reference<XDataSeries> & xSeries,const Reference<XChartType> & xChartType)573 void DialogModel::deleteSeries(
574 const Reference< XDataSeries > & xSeries,
575 const Reference< XChartType > & xChartType )
576 {
577 m_aTimerTriggeredControllerLock.startTimer();
578 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
579
580 DataSeriesHelper::deleteSeries( xSeries, xChartType );
581 }
582
getCategories() const583 Reference< data::XLabeledDataSequence > DialogModel::getCategories() const
584 {
585 Reference< data::XLabeledDataSequence > xResult;
586 try
587 {
588 if( m_xChartDocument.is())
589 {
590 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
591 xResult.set( DiagramHelper::getCategoriesFromDiagram( xDiagram ));
592 }
593 }
594 catch( uno::Exception & ex )
595 {
596 ASSERT_EXCEPTION( ex );
597 }
598 return xResult;
599 }
600
setCategories(const Reference<chart2::data::XLabeledDataSequence> & xCategories)601 void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories )
602 {
603 if( m_xChartDocument.is())
604 {
605 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
606 if( xDiagram.is())
607 {
608 // categories
609 bool bSupportsCategories = true;
610
611 Reference< XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
612 if( xFirstChartType.is() )
613 {
614 sal_Int32 nAxisType = ChartTypeHelper::getAxisType( xFirstChartType, 0 ); // x-axis
615 bSupportsCategories = (nAxisType == AxisType::CATEGORY);
616 }
617 DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram, true, bSupportsCategories );
618 }
619 }
620 }
621
getCategoriesRange() const622 OUString DialogModel::getCategoriesRange() const
623 {
624 Reference< data::XLabeledDataSequence > xLSeq( getCategories());
625 OUString aRange;
626 if( xLSeq.is())
627 {
628 Reference< data::XDataSequence > xSeq( xLSeq->getValues());
629 if( xSeq.is())
630 aRange = xSeq->getSourceRangeRepresentation();
631 }
632 return aRange;
633 }
634
isCategoryDiagram() const635 bool DialogModel::isCategoryDiagram() const
636 {
637 bool bRet = false;
638 if( m_xChartDocument.is())
639 bRet = DiagramHelper::isCategoryDiagram( m_xChartDocument->getFirstDiagram() );
640 return bRet;
641 }
642
detectArguments(OUString & rOutRangeString,bool & rOutUseColumns,bool & rOutFirstCellAsLabel,bool & rOutHasCategories) const643 void DialogModel::detectArguments(
644 OUString & rOutRangeString,
645 bool & rOutUseColumns,
646 bool & rOutFirstCellAsLabel,
647 bool & rOutHasCategories ) const
648 {
649 try
650 {
651 uno::Sequence< sal_Int32 > aSequenceMapping;//todo YYYX
652
653 // Note: unused data is currently not supported in being passed to detectRangeSegmentation
654 if( m_xChartDocument.is())
655 DataSourceHelper::detectRangeSegmentation(
656 Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY_THROW ),
657 rOutRangeString, aSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories );
658 }
659 catch( uno::Exception & ex )
660 {
661 ASSERT_EXCEPTION( ex );
662 }
663 }
664
allArgumentsForRectRangeDetected() const665 bool DialogModel::allArgumentsForRectRangeDetected() const
666 {
667 return DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument );
668 }
669
startControllerLockTimer()670 void DialogModel::startControllerLockTimer()
671 {
672 m_aTimerTriggeredControllerLock.startTimer();
673 }
674
setData(const Sequence<beans::PropertyValue> & rArguments)675 bool DialogModel::setData(
676 const Sequence< beans::PropertyValue > & rArguments )
677 {
678 m_aTimerTriggeredControllerLock.startTimer();
679 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
680
681 Reference< data::XDataProvider > xDataProvider( getDataProvider());
682 if( ! xDataProvider.is() ||
683 ! m_xTemplate.is() )
684 {
685 OSL_ENSURE( false, "Model objects missing" );
686 return false;
687 }
688
689 try
690 {
691 Reference< chart2::data::XDataSource > xDataSource(
692 xDataProvider->createDataSource( rArguments ) );
693
694 Reference< chart2::XDataInterpreter > xInterpreter(
695 m_xTemplate->getDataInterpreter());
696 if( xInterpreter.is())
697 {
698 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() );
699 ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram );
700
701 ::std::vector< Reference< XDataSeries > > aSeriesToReUse(
702 DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
703 applyInterpretedData(
704 xInterpreter->interpretDataSource(
705 xDataSource, rArguments,
706 ContainerToSequence( aSeriesToReUse )),
707 aSeriesToReUse,
708 true /* bSetStyles */);
709
710 ThreeDHelper::setScheme( xDiagram, e3DScheme );
711 }
712 }
713 catch( uno::Exception & ex )
714 {
715 ASSERT_EXCEPTION( ex );
716 return false;
717 }
718
719 return true;
720 }
721
ConvertRoleFromInternalToUI(const OUString & rRoleString)722 OUString DialogModel::ConvertRoleFromInternalToUI( const OUString & rRoleString )
723 {
724 return lcl_ConvertRole( rRoleString, true );
725 }
726
GetRoleDataLabel()727 OUString DialogModel::GetRoleDataLabel()
728 {
729 return OUString( String( ::chart::SchResId( STR_OBJECT_DATALABELS )));
730 }
731
GetRoleIndexForSorting(const::rtl::OUString & rInternalRoleString)732 sal_Int32 DialogModel::GetRoleIndexForSorting( const ::rtl::OUString & rInternalRoleString )
733 {
734 static lcl_tRoleIndexMap aRoleIndexMap;
735
736 if( aRoleIndexMap.empty())
737 lcl_createRoleIndexMap( aRoleIndexMap );
738
739 lcl_tRoleIndexMap::const_iterator aIt( aRoleIndexMap.find( rInternalRoleString ));
740 if( aIt != aRoleIndexMap.end())
741 return aIt->second;
742
743 return 0;
744 }
745
746 // private methods
747
applyInterpretedData(const InterpretedData & rNewData,const::std::vector<Reference<XDataSeries>> & rSeriesToReUse,bool bSetStyles)748 void DialogModel::applyInterpretedData(
749 const InterpretedData & rNewData,
750 const ::std::vector< Reference< XDataSeries > > & rSeriesToReUse,
751 bool bSetStyles )
752 {
753 if( ! m_xChartDocument.is())
754 return;
755
756 m_aTimerTriggeredControllerLock.startTimer();
757 Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
758 if( xDiagram.is())
759 {
760 // styles
761 if( bSetStyles && m_xTemplate.is() )
762 {
763 sal_Int32 nGroup = 0;
764 sal_Int32 nSeriesCounter = 0;
765 sal_Int32 nNewSeriesIndex = static_cast< sal_Int32 >( rSeriesToReUse.size());
766 const sal_Int32 nOuterSize=rNewData.Series.getLength();
767
768 for(; nGroup < nOuterSize; ++nGroup)
769 {
770 Sequence< Reference< XDataSeries > > aSeries( rNewData.Series[ nGroup ] );
771 const sal_Int32 nSeriesInGroup = aSeries.getLength();
772 for( sal_Int32 nSeries=0; nSeries<nSeriesInGroup; ++nSeries, ++nSeriesCounter )
773 {
774 if( ::std::find( rSeriesToReUse.begin(), rSeriesToReUse.end(), aSeries[nSeries] )
775 == rSeriesToReUse.end())
776 {
777 Reference< beans::XPropertySet > xSeriesProp( aSeries[nSeries], uno::UNO_QUERY );
778 if( xSeriesProp.is())
779 {
780 // @deprecated: correct default color should be found by view
781 // without setting it as hard attribute
782 Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
783 if( xColorScheme.is())
784 xSeriesProp->setPropertyValue(
785 C2U("Color"), uno::makeAny( xColorScheme->getColorByIndex( nSeriesCounter )));
786 }
787 m_xTemplate->applyStyle( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup );
788 }
789 }
790 }
791 }
792
793 // data series
794 ::std::vector< Reference< XDataSeriesContainer > > aSeriesCnt( getAllDataSeriesContainers());
795 ::std::vector< Sequence< Reference< XDataSeries > > > aNewSeries(
796 SequenceToVector( rNewData.Series ));
797
798 OSL_ASSERT( aSeriesCnt.size() == aNewSeries.size());
799
800 ::std::vector< Sequence< Reference< XDataSeries > > >::const_iterator aSrcIt( aNewSeries.begin());
801 ::std::vector< Reference< XDataSeriesContainer > >::iterator aDestIt( aSeriesCnt.begin());
802 for(; aSrcIt != aNewSeries.end() && aDestIt != aSeriesCnt.end();
803 ++aSrcIt, ++aDestIt )
804 {
805 try
806 {
807 OSL_ASSERT( (*aDestIt).is());
808 (*aDestIt)->setDataSeries( *aSrcIt );
809 }
810 catch( uno::Exception & ex )
811 {
812 ASSERT_EXCEPTION( ex );
813 }
814 }
815
816 DialogModel::setCategories(rNewData.Categories);
817 }
818 }
819
countSeries() const820 sal_Int32 DialogModel::countSeries() const
821 {
822 ::std::vector< Reference< XDataSeriesContainer > > aCnt( getAllDataSeriesContainers());
823 return ::std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber());
824 }
825
826 } // namespace chart
827