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