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_chartcontroller.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 ()__anonf045f1700111::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__anonf045f1700111::lcl_DataSeriesContainerAppend161 explicit lcl_DataSeriesContainerAppend( tContainerType & rCnt )
162 : m_pDestCnt( &rCnt )
163 {}
164
operator =__anonf045f1700111::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_pDestCnt->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 *__anonf045f1700111::lcl_DataSeriesContainerAppend192 lcl_DataSeriesContainerAppend & operator* () { return *this; }
operator ++__anonf045f1700111::lcl_DataSeriesContainerAppend193 lcl_DataSeriesContainerAppend & operator++ () { return *this; }
operator ++__anonf045f1700111::lcl_DataSeriesContainerAppend194 lcl_DataSeriesContainerAppend & operator++ (int) { return *this; }
195
196 private:
197 // A pointer, not a reference: an output iterator must be CopyAssignable,
198 // and a reference member deletes the implicit copy assignment. MSVC's
199 // std::copy assigns the destination iterator (_Seek_wrapped); VC9's did
200 // not, which is why the reference went unnoticed.
201 tContainerType * m_pDestCnt;
202 };
203
204 struct lcl_RolesWithRangeAppend : public
205 ::std::iterator< ::std::output_iterator_tag, Reference< data::XLabeledDataSequence > >
206 {
207 typedef ::chart::DialogModel::tRolesWithRanges tContainerType;
208
lcl_RolesWithRangeAppend__anonf045f1700111::lcl_RolesWithRangeAppend209 explicit lcl_RolesWithRangeAppend( tContainerType & rCnt,
210 const ::rtl::OUString & aLabelRole )
211 : m_pDestCnt( &rCnt ),
212 m_aRoleForLabelSeq( aLabelRole )
213 {}
214
operator =__anonf045f1700111::lcl_RolesWithRangeAppend215 lcl_RolesWithRangeAppend & operator= ( const value_type & xVal )
216 {
217 try
218 {
219 if( xVal.is())
220 {
221 // data sequence
222 Reference< data::XDataSequence > xSeq( xVal->getValues());
223 if( xSeq.is())
224 {
225 OUString aRole;
226 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW );
227 if( xProp->getPropertyValue( C2U("Role")) >>= aRole )
228 {
229 m_pDestCnt->insert(
230 tContainerType::value_type(
231 aRole, xSeq->getSourceRangeRepresentation()));
232 // label
233 if( aRole.equals( m_aRoleForLabelSeq ))
234 {
235 Reference< data::XDataSequence > xLabelSeq( xVal->getLabel());
236 if( xLabelSeq.is())
237 {
238 m_pDestCnt->insert(
239 tContainerType::value_type(
240 lcl_aLabelRole, xLabelSeq->getSourceRangeRepresentation()));
241 }
242 }
243 }
244 }
245 }
246 }
247 catch( uno::Exception & ex )
248 {
249 ASSERT_EXCEPTION( ex );
250 }
251 return *this;
252 }
253
operator *__anonf045f1700111::lcl_RolesWithRangeAppend254 lcl_RolesWithRangeAppend & operator* () { return *this; }
operator ++__anonf045f1700111::lcl_RolesWithRangeAppend255 lcl_RolesWithRangeAppend & operator++ () { return *this; }
operator ++__anonf045f1700111::lcl_RolesWithRangeAppend256 lcl_RolesWithRangeAppend & operator++ (int) { return *this; }
257
258 private:
259 // A pointer, not a reference — see lcl_DataSeriesContainerAppend above.
260 tContainerType * m_pDestCnt;
261 OUString m_aRoleForLabelSeq;
262 };
263
lcl_SetSequenceRole(const Reference<data::XDataSequence> & xSeq,const OUString & rRole)264 void lcl_SetSequenceRole(
265 const Reference< data::XDataSequence > & xSeq,
266 const OUString & rRole )
267 {
268 Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
269 if( xProp.is())
270 xProp->setPropertyValue( C2U("Role"), uno::makeAny( rRole ));
271 }
272
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)273 Reference< XDataSeries > lcl_CreateNewSeries(
274 const Reference< uno::XComponentContext > & xContext,
275 const Reference< XChartType > & xChartType,
276 sal_Int32 nNewSeriesIndex,
277 sal_Int32 nTotalNumberOfSeriesInCTGroup,
278 const Reference< XDiagram > & xDiagram,
279 const Reference< XChartTypeTemplate > & xTemplate,
280 bool bCreateDataCachedSequences )
281 {
282 // create plain series
283 Reference< XDataSeries > xResult(
284 xContext->getServiceManager()->createInstanceWithContext(
285 C2U( "com.sun.star.chart2.DataSeries" ),
286 xContext ), uno::UNO_QUERY );
287 if( xTemplate.is())
288 {
289 Reference< beans::XPropertySet > xResultProp( xResult, uno::UNO_QUERY );
290 if( xResultProp.is())
291 {
292 // @deprecated: correct default color should be found by view
293 // without setting it as hard attribute
294 Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
295 if( xColorScheme.is())
296 xResultProp->setPropertyValue(
297 C2U("Color"), uno::makeAny( xColorScheme->getColorByIndex( nNewSeriesIndex )));
298 }
299 sal_Int32 nGroupIndex=0;
300 if( xChartType.is())
301 {
302 Sequence< Reference< XChartType > > aCTs(
303 ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram ));
304 for( ; nGroupIndex<aCTs.getLength(); ++nGroupIndex)
305 if( aCTs[nGroupIndex] == xChartType )
306 break;
307 if( nGroupIndex == aCTs.getLength())
308 nGroupIndex = 0;
309 }
310 xTemplate->applyStyle( xResult, nGroupIndex, nNewSeriesIndex, nTotalNumberOfSeriesInCTGroup );
311 }
312
313 if( bCreateDataCachedSequences )
314 {
315 // set chart type specific roles
316 Reference< data::XDataSink > xSink( xResult, uno::UNO_QUERY );
317 if( xChartType.is() && xSink.is())
318 {
319 ::std::vector< Reference< data::XLabeledDataSequence > > aNewSequences;
320 const OUString aRoleOfSeqForSeriesLabel = xChartType->getRoleOfSequenceForSeriesLabel();
321 const OUString aLabel( String( ::chart::SchResId( STR_DATA_UNNAMED_SERIES )));
322 const Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles());
323 const Sequence< OUString > aOptRoles( xChartType->getSupportedOptionalRoles());
324 sal_Int32 nI = 0;
325
326 for(nI=0; nI<aRoles.getLength(); ++nI)
327 {
328 if( aRoles[nI].equals( lcl_aLabelRole ))
329 continue;
330 Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence() );
331 lcl_SetSequenceRole( xSeq, aRoles[nI] );
332 // assert that aRoleOfSeqForSeriesLabel is part of the mandatory roles
333 if( aRoles[nI].equals( aRoleOfSeqForSeriesLabel ))
334 {
335 Reference< data::XDataSequence > xLabel( ::chart::DataSourceHelper::createCachedDataSequence( aLabel ));
336 lcl_SetSequenceRole( xLabel, lcl_aLabelRole );
337 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq, xLabel ));
338 }
339 else
340 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq ));
341 }
342
343 for(nI=0; nI<aOptRoles.getLength(); ++nI)
344 {
345 if( aOptRoles[nI].equals( lcl_aLabelRole ))
346 continue;
347 Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence());
348 lcl_SetSequenceRole( xSeq, aOptRoles[nI] );
349 aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq ));
350 }
351
352 xSink->setData( ContainerToSequence( aNewSequences ));
353 }
354 }
355
356 return xResult;
357 }
358
359 struct lcl_addSeriesNumber : public ::std::binary_function<
360 sal_Int32, Reference< XDataSeriesContainer >, sal_Int32 >
361 {
operator ()__anonf045f1700111::lcl_addSeriesNumber362 sal_Int32 operator() ( sal_Int32 nCurrentNumber, const Reference< XDataSeriesContainer > & xCnt ) const
363 {
364 if( xCnt.is())
365 return nCurrentNumber + (xCnt->getDataSeries().getLength());
366 return nCurrentNumber;
367 }
368 };
369
370 } // anonymous namespace
371
372 // ----------------------------------------
373
374
375 namespace chart
376 {
377
DialogModel(const Reference<XChartDocument> & xChartDocument,const Reference<uno::XComponentContext> & xContext)378 DialogModel::DialogModel(
379 const Reference< XChartDocument > & xChartDocument,
380 const Reference< uno::XComponentContext > & xContext ) :
381 m_xChartDocument( xChartDocument ),
382 m_xContext( xContext ),
383 m_aTimerTriggeredControllerLock( uno::Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) )
384 {
385 }
386
~DialogModel()387 DialogModel::~DialogModel()
388 {}
389
setTemplate(const Reference<XChartTypeTemplate> & xTemplate)390 void DialogModel::setTemplate(
391 const Reference< XChartTypeTemplate > & xTemplate )
392 {
393 m_xTemplate = xTemplate;
394 }
395
396 ::boost::shared_ptr< RangeSelectionHelper >
getRangeSelectionHelper() const397 DialogModel::getRangeSelectionHelper() const
398 {
399 if( ! m_spRangeSelectionHelper.get())
400 m_spRangeSelectionHelper.reset(
401 new RangeSelectionHelper( m_xChartDocument ));
402
403 return m_spRangeSelectionHelper;
404 }
405
getChartModel() const406 Reference< frame::XModel > DialogModel::getChartModel() const
407 {
408 Reference< frame::XModel > xResult( m_xChartDocument, uno::UNO_QUERY );
409 return xResult;
410 }
411
getDataProvider() const412 Reference< data::XDataProvider > DialogModel::getDataProvider() const
413 {
414 Reference< data::XDataProvider > xResult;
415 if( m_xChartDocument.is())
416 xResult.set( m_xChartDocument->getDataProvider());
417 return xResult;
418 }
419
420 ::std::vector< Reference< XDataSeriesContainer > >
getAllDataSeriesContainers() const421 DialogModel::getAllDataSeriesContainers() const
422 {
423 ::std::vector< Reference< XDataSeriesContainer > > aResult;
424
425 try
426 {
427 Reference< XDiagram > xDiagram;
428 if( m_xChartDocument.is())
429 xDiagram.set( m_xChartDocument->getFirstDiagram());
430 if( xDiagram.is())
431 {
432 Reference< XCoordinateSystemContainer > xCooSysCnt(
433 xDiagram, uno::UNO_QUERY_THROW );
434 Sequence< Reference< XCoordinateSystem > > aCooSysSeq(
435 xCooSysCnt->getCoordinateSystems());
436 for( sal_Int32 i=0; i<aCooSysSeq.getLength(); ++i )
437 {
438 Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[i], uno::UNO_QUERY_THROW );
439 Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes());
440 ::std::transform(
441 aChartTypeSeq.getConstArray(), aChartTypeSeq.getConstArray() + aChartTypeSeq.getLength(),
442 ::std::back_inserter( aResult ),
443 lcl_ChartTypeToSeriesCnt() );
444 }
445 }
446 }
447 catch( uno::Exception & ex )
448 {
449 ASSERT_EXCEPTION( ex );
450 }
451
452 return aResult;
453 }
454
455 ::std::vector< DialogModel::tSeriesWithChartTypeByName >
getAllDataSeriesWithLabel() const456 DialogModel::getAllDataSeriesWithLabel() const
457 {
458 ::std::vector< tSeriesWithChartTypeByName > aResult;
459 ::std::vector< Reference< XDataSeriesContainer > > aContainers(
460 getAllDataSeriesContainers());
461
462 ::std::copy( aContainers.begin(), aContainers.end(),
463 lcl_DataSeriesContainerAppend( aResult ));
464 return aResult;
465 }
466
getRolesWithRanges(const Reference<XDataSeries> & xSeries,const::rtl::OUString & aRoleOfSequenceForLabel,const Reference<chart2::XChartType> & xChartType) const467 DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges(
468 const Reference< XDataSeries > & xSeries,
469 const ::rtl::OUString & aRoleOfSequenceForLabel,
470 const Reference< chart2::XChartType > & xChartType ) const
471 {
472 DialogModel::tRolesWithRanges aResult;
473 try
474 {
475 Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW );
476 const Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
477 ::std::copy( aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength(),
478 lcl_RolesWithRangeAppend( aResult, aRoleOfSequenceForLabel ));
479 if( xChartType.is())
480 {
481 // add missing mandatory roles
482 Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles());
483 OUString aEmptyString;
484 sal_Int32 nI = 0;
485 for( nI=0; nI < aRoles.getLength(); ++nI )
486 {
487 if( aResult.find( aRoles[nI] ) == aResult.end() )
488 aResult.insert( DialogModel::tRolesWithRanges::value_type( aRoles[nI], aEmptyString ));
489 }
490
491 // add missing optional roles
492 aRoles = xChartType->getSupportedOptionalRoles();
493 for( nI=0; nI < aRoles.getLength(); ++nI )
494 {
495 if( aResult.find( aRoles[nI] ) == aResult.end() )
496 aResult.insert( DialogModel::tRolesWithRanges::value_type( aRoles[nI], aEmptyString ));
497 }
498 }
499 }
500 catch( uno::Exception & ex )
501 {
502 ASSERT_EXCEPTION( ex );
503 }
504 return aResult;
505 }
506
moveSeries(const Reference<XDataSeries> & xSeries,eMoveDirection eDirection)507 void DialogModel::moveSeries(
508 const Reference< XDataSeries > & xSeries,
509 eMoveDirection eDirection )
510 {
511 m_aTimerTriggeredControllerLock.startTimer();
512 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
513
514 Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
515 DiagramHelper::moveSeries( xDiagram, xSeries, eDirection==MOVE_UP );
516 }
517
insertSeriesAfter(const Reference<XDataSeries> & xSeries,const Reference<XChartType> & xChartType,bool bCreateDataCachedSequences)518 Reference< chart2::XDataSeries > DialogModel::insertSeriesAfter(
519 const Reference< XDataSeries > & xSeries,
520 const Reference< XChartType > & xChartType,
521 bool bCreateDataCachedSequences /* = false */ )
522 {
523 m_aTimerTriggeredControllerLock.startTimer();
524 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
525 Reference< XDataSeries > xNewSeries;
526
527 try
528 {
529 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() );
530 ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram );
531
532 sal_Int32 nSeriesInChartType = 0;
533 const sal_Int32 nTotalSeries = countSeries();
534 if( xChartType.is())
535 {
536 Reference< XDataSeriesContainer > xCnt( xChartType, uno::UNO_QUERY_THROW );
537 nSeriesInChartType = xCnt->getDataSeries().getLength();
538 }
539
540 // create new series
541 xNewSeries.set(
542 lcl_CreateNewSeries(
543 m_xContext,
544 xChartType,
545 nTotalSeries, // new series' index
546 nSeriesInChartType,
547 xDiagram,
548 m_xTemplate,
549 bCreateDataCachedSequences ));
550
551 // add new series to container
552 if( xNewSeries.is())
553 {
554 Reference< XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY_THROW );
555 ::std::vector< Reference< XDataSeries > > aSeries(
556 SequenceToVector( xSeriesCnt->getDataSeries()));
557 ::std::vector< Reference< XDataSeries > >::iterator aIt =
558 ::std::find( aSeries.begin(), aSeries.end(), xSeries );
559 if( aIt == aSeries.end())
560 // if we have no series we insert at the first position.
561 aIt = aSeries.begin();
562 else
563 // vector::insert inserts before, so we have to advance
564 ++aIt;
565 aSeries.insert( aIt, xNewSeries );
566 xSeriesCnt->setDataSeries( ContainerToSequence( aSeries ));
567 }
568
569 ThreeDHelper::setScheme( xDiagram, e3DScheme );
570 }
571 catch( uno::Exception & ex )
572 {
573 ASSERT_EXCEPTION( ex );
574 }
575 return xNewSeries;
576 }
577
deleteSeries(const Reference<XDataSeries> & xSeries,const Reference<XChartType> & xChartType)578 void DialogModel::deleteSeries(
579 const Reference< XDataSeries > & xSeries,
580 const Reference< XChartType > & xChartType )
581 {
582 m_aTimerTriggeredControllerLock.startTimer();
583 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
584
585 DataSeriesHelper::deleteSeries( xSeries, xChartType );
586 }
587
getCategories() const588 Reference< data::XLabeledDataSequence > DialogModel::getCategories() const
589 {
590 Reference< data::XLabeledDataSequence > xResult;
591 try
592 {
593 if( m_xChartDocument.is())
594 {
595 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
596 xResult.set( DiagramHelper::getCategoriesFromDiagram( xDiagram ));
597 }
598 }
599 catch( uno::Exception & ex )
600 {
601 ASSERT_EXCEPTION( ex );
602 }
603 return xResult;
604 }
605
setCategories(const Reference<chart2::data::XLabeledDataSequence> & xCategories)606 void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories )
607 {
608 if( m_xChartDocument.is())
609 {
610 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
611 if( xDiagram.is())
612 {
613 // categories
614 bool bSupportsCategories = true;
615
616 Reference< XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
617 if( xFirstChartType.is() )
618 {
619 sal_Int32 nAxisType = ChartTypeHelper::getAxisType( xFirstChartType, 0 ); // x-axis
620 bSupportsCategories = (nAxisType == AxisType::CATEGORY);
621 }
622 DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram, true, bSupportsCategories );
623 }
624 }
625 }
626
getCategoriesRange() const627 OUString DialogModel::getCategoriesRange() const
628 {
629 Reference< data::XLabeledDataSequence > xLSeq( getCategories());
630 OUString aRange;
631 if( xLSeq.is())
632 {
633 Reference< data::XDataSequence > xSeq( xLSeq->getValues());
634 if( xSeq.is())
635 aRange = xSeq->getSourceRangeRepresentation();
636 }
637 return aRange;
638 }
639
isCategoryDiagram() const640 bool DialogModel::isCategoryDiagram() const
641 {
642 bool bRet = false;
643 if( m_xChartDocument.is())
644 bRet = DiagramHelper::isCategoryDiagram( m_xChartDocument->getFirstDiagram() );
645 return bRet;
646 }
647
detectArguments(OUString & rOutRangeString,bool & rOutUseColumns,bool & rOutFirstCellAsLabel,bool & rOutHasCategories) const648 void DialogModel::detectArguments(
649 OUString & rOutRangeString,
650 bool & rOutUseColumns,
651 bool & rOutFirstCellAsLabel,
652 bool & rOutHasCategories ) const
653 {
654 try
655 {
656 uno::Sequence< sal_Int32 > aSequenceMapping;//todo YYYX
657
658 // Note: unused data is currently not supported in being passed to detectRangeSegmentation
659 if( m_xChartDocument.is())
660 DataSourceHelper::detectRangeSegmentation(
661 Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY_THROW ),
662 rOutRangeString, aSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories );
663 }
664 catch( uno::Exception & ex )
665 {
666 ASSERT_EXCEPTION( ex );
667 }
668 }
669
allArgumentsForRectRangeDetected() const670 bool DialogModel::allArgumentsForRectRangeDetected() const
671 {
672 return DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument );
673 }
674
startControllerLockTimer()675 void DialogModel::startControllerLockTimer()
676 {
677 m_aTimerTriggeredControllerLock.startTimer();
678 }
679
setData(const Sequence<beans::PropertyValue> & rArguments)680 bool DialogModel::setData(
681 const Sequence< beans::PropertyValue > & rArguments )
682 {
683 m_aTimerTriggeredControllerLock.startTimer();
684 ControllerLockGuard aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
685
686 Reference< data::XDataProvider > xDataProvider( getDataProvider());
687 if( ! xDataProvider.is() ||
688 ! m_xTemplate.is() )
689 {
690 OSL_ENSURE( false, "Model objects missing" );
691 return false;
692 }
693
694 try
695 {
696 Reference< chart2::data::XDataSource > xDataSource(
697 xDataProvider->createDataSource( rArguments ) );
698
699 Reference< chart2::XDataInterpreter > xInterpreter(
700 m_xTemplate->getDataInterpreter());
701 if( xInterpreter.is())
702 {
703 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() );
704 ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram );
705
706 ::std::vector< Reference< XDataSeries > > aSeriesToReUse(
707 DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
708 applyInterpretedData(
709 xInterpreter->interpretDataSource(
710 xDataSource, rArguments,
711 ContainerToSequence( aSeriesToReUse )),
712 aSeriesToReUse,
713 true /* bSetStyles */);
714
715 ThreeDHelper::setScheme( xDiagram, e3DScheme );
716 }
717 }
718 catch( uno::Exception & ex )
719 {
720 ASSERT_EXCEPTION( ex );
721 return false;
722 }
723
724 return true;
725 }
726
ConvertRoleFromInternalToUI(const OUString & rRoleString)727 OUString DialogModel::ConvertRoleFromInternalToUI( const OUString & rRoleString )
728 {
729 return lcl_ConvertRole( rRoleString, true );
730 }
731
GetRoleDataLabel()732 OUString DialogModel::GetRoleDataLabel()
733 {
734 return OUString( String( ::chart::SchResId( STR_OBJECT_DATALABELS )));
735 }
736
GetRoleIndexForSorting(const::rtl::OUString & rInternalRoleString)737 sal_Int32 DialogModel::GetRoleIndexForSorting( const ::rtl::OUString & rInternalRoleString )
738 {
739 static lcl_tRoleIndexMap aRoleIndexMap;
740
741 if( aRoleIndexMap.empty())
742 lcl_createRoleIndexMap( aRoleIndexMap );
743
744 lcl_tRoleIndexMap::const_iterator aIt( aRoleIndexMap.find( rInternalRoleString ));
745 if( aIt != aRoleIndexMap.end())
746 return aIt->second;
747
748 return 0;
749 }
750
751 // private methods
752
applyInterpretedData(const InterpretedData & rNewData,const::std::vector<Reference<XDataSeries>> & rSeriesToReUse,bool bSetStyles)753 void DialogModel::applyInterpretedData(
754 const InterpretedData & rNewData,
755 const ::std::vector< Reference< XDataSeries > > & rSeriesToReUse,
756 bool bSetStyles )
757 {
758 if( ! m_xChartDocument.is())
759 return;
760
761 m_aTimerTriggeredControllerLock.startTimer();
762 Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
763 if( xDiagram.is())
764 {
765 // styles
766 if( bSetStyles && m_xTemplate.is() )
767 {
768 sal_Int32 nGroup = 0;
769 sal_Int32 nSeriesCounter = 0;
770 sal_Int32 nNewSeriesIndex = static_cast< sal_Int32 >( rSeriesToReUse.size());
771 const sal_Int32 nOuterSize=rNewData.Series.getLength();
772
773 for(; nGroup < nOuterSize; ++nGroup)
774 {
775 Sequence< Reference< XDataSeries > > aSeries( rNewData.Series[ nGroup ] );
776 const sal_Int32 nSeriesInGroup = aSeries.getLength();
777 for( sal_Int32 nSeries=0; nSeries<nSeriesInGroup; ++nSeries, ++nSeriesCounter )
778 {
779 if( ::std::find( rSeriesToReUse.begin(), rSeriesToReUse.end(), aSeries[nSeries] )
780 == rSeriesToReUse.end())
781 {
782 Reference< beans::XPropertySet > xSeriesProp( aSeries[nSeries], uno::UNO_QUERY );
783 if( xSeriesProp.is())
784 {
785 // @deprecated: correct default color should be found by view
786 // without setting it as hard attribute
787 Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
788 if( xColorScheme.is())
789 xSeriesProp->setPropertyValue(
790 C2U("Color"), uno::makeAny( xColorScheme->getColorByIndex( nSeriesCounter )));
791 }
792 m_xTemplate->applyStyle( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup );
793 }
794 }
795 }
796 }
797
798 // data series
799 ::std::vector< Reference< XDataSeriesContainer > > aSeriesCnt( getAllDataSeriesContainers());
800 ::std::vector< Sequence< Reference< XDataSeries > > > aNewSeries(
801 SequenceToVector( rNewData.Series ));
802
803 OSL_ASSERT( aSeriesCnt.size() == aNewSeries.size());
804
805 ::std::vector< Sequence< Reference< XDataSeries > > >::const_iterator aSrcIt( aNewSeries.begin());
806 ::std::vector< Reference< XDataSeriesContainer > >::iterator aDestIt( aSeriesCnt.begin());
807 for(; aSrcIt != aNewSeries.end() && aDestIt != aSeriesCnt.end();
808 ++aSrcIt, ++aDestIt )
809 {
810 try
811 {
812 OSL_ASSERT( (*aDestIt).is());
813 (*aDestIt)->setDataSeries( *aSrcIt );
814 }
815 catch( uno::Exception & ex )
816 {
817 ASSERT_EXCEPTION( ex );
818 }
819 }
820
821 DialogModel::setCategories(rNewData.Categories);
822 }
823 }
824
countSeries() const825 sal_Int32 DialogModel::countSeries() const
826 {
827 ::std::vector< Reference< XDataSeriesContainer > > aCnt( getAllDataSeriesContainers());
828 return ::std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber());
829 }
830
831 } // namespace chart
832