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