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