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 19 : 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 : namespace {
472 :
473 0 : void addMissingRoles(DialogModel::tRolesWithRanges& rResult, const uno::Sequence<OUString>& rRoles)
474 : {
475 0 : for(sal_Int32 i = 0, n = rRoles.getLength(); i < n; ++i)
476 : {
477 0 : if(rResult.find(rRoles[i]) == rResult.end())
478 0 : rResult.insert(DialogModel::tRolesWithRanges::value_type(rRoles[i], OUString()));
479 : }
480 0 : }
481 :
482 : /**
483 : * Insert a new data series to chart type at position after specified series
484 : * position.
485 : *
486 : * @param xChartType chart type that contains data series.
487 : * @param xSeries insertion position. The new series will be inserted after
488 : * this one.
489 : * @param xNewSeries new data series to insert.
490 : */
491 0 : void addNewSeriesToContainer(
492 : const Reference<XChartType>& xChartType,
493 : const Reference<XDataSeries>& xSeries,
494 : const Reference<XDataSeries>& xNewSeries )
495 : {
496 0 : Reference<XDataSeriesContainer> xSeriesCnt(xChartType, uno::UNO_QUERY_THROW);
497 0 : std::vector<Reference<XDataSeries> > aSeries = SequenceToVector(xSeriesCnt->getDataSeries());
498 :
499 : std::vector<Reference<XDataSeries> >::iterator aIt =
500 0 : std::find( aSeries.begin(), aSeries.end(), xSeries);
501 :
502 0 : if( aIt == aSeries.end())
503 : // if we have no series we insert at the first position.
504 0 : aIt = aSeries.begin();
505 : else
506 : // vector::insert inserts before, so we have to advance
507 0 : ++aIt;
508 :
509 0 : aSeries.insert(aIt, xNewSeries);
510 0 : xSeriesCnt->setDataSeries(ContainerToSequence(aSeries));
511 0 : }
512 :
513 : }
514 :
515 0 : DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges(
516 : const Reference< XDataSeries > & xSeries,
517 : const OUString & aRoleOfSequenceForLabel,
518 : const Reference< chart2::XChartType > & xChartType )
519 : {
520 0 : DialogModel::tRolesWithRanges aResult;
521 : try
522 : {
523 0 : Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW );
524 0 : const Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSource->getDataSequences());
525 : ::std::copy( aSeq.begin(), aSeq.end(),
526 0 : lcl_RolesWithRangeAppend( &aResult, aRoleOfSequenceForLabel ));
527 0 : if( xChartType.is())
528 : {
529 : // add missing mandatory roles
530 0 : Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles());
531 0 : addMissingRoles(aResult, aRoles);
532 :
533 : // add missing optional roles
534 0 : aRoles = xChartType->getSupportedOptionalRoles();
535 0 : addMissingRoles(aResult, aRoles);
536 :
537 : // add missing property roles
538 0 : aRoles = xChartType->getSupportedPropertyRoles();
539 0 : addMissingRoles(aResult, aRoles);
540 0 : }
541 : }
542 0 : catch( const uno::Exception & ex )
543 : {
544 : ASSERT_EXCEPTION( ex );
545 : }
546 0 : return aResult;
547 : }
548 :
549 0 : void DialogModel::moveSeries(
550 : const Reference< XDataSeries > & xSeries,
551 : eMoveDirection eDirection )
552 : {
553 0 : m_aTimerTriggeredControllerLock.startTimer();
554 0 : ControllerLockGuardUNO aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
555 :
556 0 : Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
557 0 : DiagramHelper::moveSeries( xDiagram, xSeries, eDirection==MOVE_UP );
558 0 : }
559 :
560 0 : Reference< chart2::XDataSeries > DialogModel::insertSeriesAfter(
561 : const Reference< XDataSeries > & xSeries,
562 : const Reference< XChartType > & xChartType,
563 : bool bCreateDataCachedSequences /* = false */ )
564 : {
565 0 : m_aTimerTriggeredControllerLock.startTimer();
566 0 : ControllerLockGuardUNO aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
567 0 : Reference< XDataSeries > xNewSeries;
568 :
569 : try
570 : {
571 0 : Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() );
572 0 : ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram );
573 :
574 0 : sal_Int32 nSeriesInChartType = 0;
575 0 : const sal_Int32 nTotalSeries = countSeries();
576 0 : if( xChartType.is())
577 : {
578 0 : Reference< XDataSeriesContainer > xCnt( xChartType, uno::UNO_QUERY_THROW );
579 0 : nSeriesInChartType = xCnt->getDataSeries().getLength();
580 : }
581 :
582 : // create new series
583 : xNewSeries.set(
584 : lcl_CreateNewSeries(
585 : m_xContext,
586 : xChartType,
587 : nTotalSeries, // new series' index
588 : nSeriesInChartType,
589 : xDiagram,
590 : m_xTemplate,
591 0 : bCreateDataCachedSequences ));
592 :
593 : // add new series to container
594 0 : if( xNewSeries.is())
595 0 : addNewSeriesToContainer(xChartType, xSeries, xNewSeries);
596 :
597 0 : ThreeDHelper::setScheme( xDiagram, e3DScheme );
598 : }
599 0 : catch( const uno::Exception & ex )
600 : {
601 : ASSERT_EXCEPTION( ex );
602 : }
603 0 : return xNewSeries;
604 : }
605 :
606 0 : void DialogModel::deleteSeries(
607 : const Reference< XDataSeries > & xSeries,
608 : const Reference< XChartType > & xChartType )
609 : {
610 0 : m_aTimerTriggeredControllerLock.startTimer();
611 0 : ControllerLockGuardUNO aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
612 :
613 0 : DataSeriesHelper::deleteSeries( xSeries, xChartType );
614 0 : }
615 :
616 0 : Reference< data::XLabeledDataSequence > DialogModel::getCategories() const
617 : {
618 0 : Reference< data::XLabeledDataSequence > xResult;
619 : try
620 : {
621 0 : if( m_xChartDocument.is())
622 : {
623 0 : Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
624 0 : xResult.set( DiagramHelper::getCategoriesFromDiagram( xDiagram ));
625 : }
626 : }
627 0 : catch( const uno::Exception & ex )
628 : {
629 : ASSERT_EXCEPTION( ex );
630 : }
631 0 : return xResult;
632 : }
633 :
634 0 : void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories )
635 : {
636 0 : if( m_xChartDocument.is())
637 : {
638 0 : Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
639 0 : if( xDiagram.is())
640 : {
641 : // categories
642 0 : bool bSupportsCategories = true;
643 :
644 0 : Reference< XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) );
645 0 : if( xFirstChartType.is() )
646 : {
647 0 : sal_Int32 nAxisType = ChartTypeHelper::getAxisType( xFirstChartType, 0 ); // x-axis
648 0 : bSupportsCategories = (nAxisType == AxisType::CATEGORY);
649 : }
650 0 : DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram, true, bSupportsCategories );
651 0 : }
652 : }
653 0 : }
654 :
655 0 : OUString DialogModel::getCategoriesRange() const
656 : {
657 0 : Reference< data::XLabeledDataSequence > xLSeq( getCategories());
658 0 : OUString aRange;
659 0 : if( xLSeq.is())
660 : {
661 0 : Reference< data::XDataSequence > xSeq( xLSeq->getValues());
662 0 : if( xSeq.is())
663 0 : aRange = xSeq->getSourceRangeRepresentation();
664 : }
665 0 : return aRange;
666 : }
667 :
668 0 : bool DialogModel::isCategoryDiagram() const
669 : {
670 0 : bool bRet = false;
671 0 : if( m_xChartDocument.is())
672 0 : bRet = DiagramHelper::isCategoryDiagram( m_xChartDocument->getFirstDiagram() );
673 0 : return bRet;
674 : }
675 :
676 0 : void DialogModel::detectArguments(
677 : OUString & rOutRangeString,
678 : bool & rOutUseColumns,
679 : bool & rOutFirstCellAsLabel,
680 : bool & rOutHasCategories ) const
681 : {
682 : try
683 : {
684 0 : uno::Sequence< sal_Int32 > aSequenceMapping;//todo YYYX
685 :
686 : // Note: unused data is currently not supported in being passed to detectRangeSegmentation
687 0 : if( m_xChartDocument.is())
688 : DataSourceHelper::detectRangeSegmentation(
689 : Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY_THROW ),
690 0 : rOutRangeString, aSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories );
691 : }
692 0 : catch( const uno::Exception & ex )
693 : {
694 : ASSERT_EXCEPTION( ex );
695 : }
696 0 : }
697 :
698 0 : bool DialogModel::allArgumentsForRectRangeDetected() const
699 : {
700 0 : return DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument );
701 : }
702 :
703 0 : void DialogModel::startControllerLockTimer()
704 : {
705 0 : m_aTimerTriggeredControllerLock.startTimer();
706 0 : }
707 :
708 0 : bool DialogModel::setData(
709 : const Sequence< beans::PropertyValue > & rArguments )
710 : {
711 0 : m_aTimerTriggeredControllerLock.startTimer();
712 0 : ControllerLockGuardUNO aLockedControllers( Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY ) );
713 :
714 0 : Reference< data::XDataProvider > xDataProvider( getDataProvider());
715 0 : if( ! xDataProvider.is() ||
716 0 : ! m_xTemplate.is() )
717 : {
718 : OSL_FAIL( "Model objects missing" );
719 0 : return false;
720 : }
721 :
722 : try
723 : {
724 : Reference< chart2::data::XDataSource > xDataSource(
725 0 : xDataProvider->createDataSource( rArguments ) );
726 :
727 : Reference< chart2::XDataInterpreter > xInterpreter(
728 0 : m_xTemplate->getDataInterpreter());
729 0 : if( xInterpreter.is())
730 : {
731 0 : Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() );
732 0 : ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram );
733 :
734 : ::std::vector< Reference< XDataSeries > > aSeriesToReUse(
735 0 : DiagramHelper::getDataSeriesFromDiagram( xDiagram ));
736 : applyInterpretedData(
737 0 : xInterpreter->interpretDataSource(
738 : xDataSource, rArguments,
739 0 : ContainerToSequence( aSeriesToReUse )),
740 : aSeriesToReUse,
741 0 : true /* bSetStyles */);
742 :
743 0 : ThreeDHelper::setScheme( xDiagram, e3DScheme );
744 0 : }
745 : }
746 0 : catch( const uno::Exception & ex )
747 : {
748 : ASSERT_EXCEPTION( ex );
749 0 : return false;
750 : }
751 :
752 0 : return true;
753 : }
754 :
755 0 : void DialogModel::setTimeBasedRange( bool bTimeBased, sal_Int32 nStart, sal_Int32 nEnd) const
756 : {
757 0 : maTimeBasedInfo.nStart = nStart;
758 0 : maTimeBasedInfo.nEnd = nEnd;
759 0 : maTimeBasedInfo.bTimeBased = bTimeBased;
760 0 : }
761 :
762 0 : OUString DialogModel::ConvertRoleFromInternalToUI( const OUString & rRoleString )
763 : {
764 0 : return lcl_ConvertRole( rRoleString, true );
765 : }
766 :
767 0 : OUString DialogModel::GetRoleDataLabel()
768 : {
769 0 : return ::chart::SchResId(STR_OBJECT_DATALABELS).toString();
770 : }
771 :
772 0 : sal_Int32 DialogModel::GetRoleIndexForSorting( const OUString & rInternalRoleString )
773 : {
774 0 : static lcl_tRoleIndexMap aRoleIndexMap;
775 :
776 0 : if( aRoleIndexMap.empty())
777 0 : lcl_createRoleIndexMap( aRoleIndexMap );
778 :
779 0 : lcl_tRoleIndexMap::const_iterator aIt( aRoleIndexMap.find( rInternalRoleString ));
780 0 : if( aIt != aRoleIndexMap.end())
781 0 : return aIt->second;
782 :
783 0 : return 0;
784 : }
785 :
786 : // private methods
787 :
788 0 : void DialogModel::applyInterpretedData(
789 : const InterpretedData & rNewData,
790 : const ::std::vector< Reference< XDataSeries > > & rSeriesToReUse,
791 : bool bSetStyles )
792 : {
793 0 : if( ! m_xChartDocument.is())
794 0 : return;
795 :
796 0 : m_aTimerTriggeredControllerLock.startTimer();
797 0 : Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram());
798 0 : if( xDiagram.is())
799 : {
800 : // styles
801 0 : if( bSetStyles && m_xTemplate.is() )
802 : {
803 0 : sal_Int32 nGroup = 0;
804 0 : sal_Int32 nSeriesCounter = 0;
805 0 : sal_Int32 nNewSeriesIndex = static_cast< sal_Int32 >( rSeriesToReUse.size());
806 0 : const sal_Int32 nOuterSize=rNewData.Series.getLength();
807 :
808 0 : for(; nGroup < nOuterSize; ++nGroup)
809 : {
810 0 : Sequence< Reference< XDataSeries > > aSeries( rNewData.Series[ nGroup ] );
811 0 : const sal_Int32 nSeriesInGroup = aSeries.getLength();
812 0 : for( sal_Int32 nSeries=0; nSeries<nSeriesInGroup; ++nSeries, ++nSeriesCounter )
813 : {
814 0 : if( ::std::find( rSeriesToReUse.begin(), rSeriesToReUse.end(), aSeries[nSeries] )
815 0 : == rSeriesToReUse.end())
816 : {
817 0 : Reference< beans::XPropertySet > xSeriesProp( aSeries[nSeries], uno::UNO_QUERY );
818 0 : if( xSeriesProp.is())
819 : {
820 : // @deprecated: correct default color should be found by view
821 : // without setting it as hard attribute
822 0 : Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme());
823 0 : if( xColorScheme.is())
824 0 : xSeriesProp->setPropertyValue( "Color" ,
825 0 : uno::makeAny( xColorScheme->getColorByIndex( nSeriesCounter )));
826 : }
827 0 : m_xTemplate->applyStyle( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup );
828 : }
829 : }
830 0 : }
831 : }
832 :
833 : // data series
834 0 : ::std::vector< Reference< XDataSeriesContainer > > aSeriesCnt( getAllDataSeriesContainers());
835 : ::std::vector< Sequence< Reference< XDataSeries > > > aNewSeries(
836 0 : SequenceToVector( rNewData.Series ));
837 :
838 : OSL_ASSERT( aSeriesCnt.size() == aNewSeries.size());
839 :
840 0 : ::std::vector< Sequence< Reference< XDataSeries > > >::const_iterator aSrcIt( aNewSeries.begin());
841 0 : ::std::vector< Reference< XDataSeriesContainer > >::iterator aDestIt( aSeriesCnt.begin());
842 0 : for(; aSrcIt != aNewSeries.end() && aDestIt != aSeriesCnt.end();
843 : ++aSrcIt, ++aDestIt )
844 : {
845 : try
846 : {
847 : OSL_ASSERT( (*aDestIt).is());
848 0 : (*aDestIt)->setDataSeries( *aSrcIt );
849 : }
850 0 : catch( const uno::Exception & ex )
851 : {
852 : ASSERT_EXCEPTION( ex );
853 : }
854 : }
855 :
856 0 : DialogModel::setCategories(rNewData.Categories);
857 0 : }
858 : }
859 :
860 0 : sal_Int32 DialogModel::countSeries() const
861 : {
862 0 : ::std::vector< Reference< XDataSeriesContainer > > aCnt( getAllDataSeriesContainers());
863 0 : return ::std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber());
864 : }
865 :
866 0 : ChartModel& DialogModel::getModel() const
867 : {
868 0 : uno::Reference< frame::XModel > xModel = getChartModel();
869 0 : ChartModel* pModel = dynamic_cast<ChartModel*>(xModel.get());
870 0 : return *pModel;
871 : }
872 :
873 57 : } // namespace chart
874 :
875 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|