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 <sal/config.h>
21 
22 #include <string_view>
23 
24 #include <ObjectNameProvider.hxx>
25 #include <ResId.hxx>
26 #include <strings.hrc>
27 #include <Axis.hxx>
28 #include <AxisHelper.hxx>
29 #include <ChartModel.hxx>
30 #include <ChartType.hxx>
31 #include <Diagram.hxx>
32 #include <DataSeries.hxx>
33 #include <DataSeriesHelper.hxx>
34 #include <TitleHelper.hxx>
35 #include <ExplicitCategoriesProvider.hxx>
36 #include <CommonConverters.hxx>
37 #include <NumberFormatterWrapper.hxx>
38 #include <RegressionCurveHelper.hxx>
39 #include <BaseCoordinateSystem.hxx>
40 #include <RegressionCurveModel.hxx>
41 #include <rtl/math.hxx>
42 #include <rtl/ustring.hxx>
43 #include <vcl/settings.hxx>
44 #include <vcl/svapp.hxx>
45 #include <unotools/localedatawrapper.hxx>
46 
47 #include <com/sun/star/chart2/MovingAverageType.hpp>
48 #include <comphelper/diagnose_ex.hxx>
49 #include <o3tl/string_view.hxx>
50 
51 namespace chart
52 {
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::chart2;
55 using ::com::sun::star::uno::Reference;
56 using ::com::sun::star::uno::Sequence;
57 using ::com::sun::star::uno::Any;
58 
59 namespace
60 {
61 
lcl_getDataSeriesName(std::u16string_view rObjectCID,const rtl::Reference<::chart::ChartModel> & xChartModel)62 OUString lcl_getDataSeriesName( std::u16string_view rObjectCID, const rtl::Reference<::chart::ChartModel>& xChartModel )
63 {
64     OUString aRet;
65 
66     rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
67     rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel );
68     if( xDiagram.is() && xSeries.is() )
69     {
70         rtl::Reference< ChartType > xChartType( xDiagram->getChartTypeOfSeries( xSeries ) );
71         if( xChartType.is() )
72         {
73             aRet = xSeries->getLabelForRole(
74                     xChartType->getRoleOfSequenceForSeriesLabel() ) ;
75         }
76     }
77 
78     return aRet;
79 }
80 
lcl_getFullSeriesName(std::u16string_view rObjectCID,const rtl::Reference<::chart::ChartModel> & xChartModel)81 OUString lcl_getFullSeriesName( std::u16string_view rObjectCID, const rtl::Reference<::chart::ChartModel>& xChartModel )
82 {
83     OUString aRet(SchResId(STR_TIP_DATASERIES));
84     OUString aWildcard( u"%SERIESNAME"_ustr );
85     sal_Int32 nIndex = aRet.indexOf( aWildcard );
86     if( nIndex != -1 )
87         aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataSeriesName( rObjectCID, xChartModel ) );
88     return aRet;
89 }
90 
lcl_addText(OUString & rOut,std::u16string_view rSeparator,std::u16string_view rNext)91 void lcl_addText( OUString& rOut, std::u16string_view rSeparator, std::u16string_view rNext )
92 {
93     if( !(rOut.isEmpty() || rNext.empty()) )
94         rOut+=rSeparator;
95     if( !rNext.empty() )
96         rOut+=rNext;
97 }
98 
lcl_getDataPointValueText(const rtl::Reference<DataSeries> & xSeries,sal_Int32 nPointIndex,const rtl::Reference<BaseCoordinateSystem> & xCooSys,const Reference<frame::XModel> & xChartModel)99 OUString lcl_getDataPointValueText( const rtl::Reference< DataSeries >& xSeries, sal_Int32 nPointIndex,
100                                     const rtl::Reference< BaseCoordinateSystem >& xCooSys,
101                                     const Reference< frame::XModel >& xChartModel )
102 {
103 
104     OUString aRet;
105 
106     if(!xSeries.is())
107         return aRet;
108 
109     const std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > & aDataSequences = xSeries->getDataSequences2();
110 
111     OUString aX, aY, aY_Min, aY_Max, aY_First, aY_Last, a_Size;
112     double fValue = 0;
113 
114     uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartModel, uno::UNO_QUERY );
115     NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier );
116     Color nLabelColor;//dummy
117     bool bColorChanged;//dummy
118 
119     for(sal_Int32 nN = aDataSequences.size();nN--;)
120     {
121         uno::Reference<data::XDataSequence>  xDataSequence( aDataSequences[nN]->getValues());
122         if( !xDataSequence.is() )
123             continue;
124 
125         try
126         {
127             Sequence< Any > aData( xDataSequence->getData() );
128 
129             if( nPointIndex >= aData.getLength() )
130                 continue;
131             uno::Reference<beans::XPropertySet> xProp(xDataSequence, uno::UNO_QUERY );
132             if( xProp.is())
133             {
134                 uno::Any aARole = xProp->getPropertyValue( u"Role"_ustr );
135                 OUString aRole;
136                 aARole >>= aRole;
137 
138                 if( aRole == "values-x" )
139                 {
140                     aData[nPointIndex]>>= fValue;
141                     sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
142                     aX = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
143                 }
144                 else if( aRole == "values-y")
145                 {
146                     aData[nPointIndex]>>= fValue;
147                     sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
148                     aY = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
149                 }
150                 else if( aRole == "values-first" )
151                 {
152                     aData[nPointIndex]>>= fValue;
153                     sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
154                     aY_First = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
155                 }
156                 else if( aRole == "values-min" )
157                 {
158                     aData[nPointIndex]>>= fValue;
159                     sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
160                     aY_Min = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
161                 }
162                 else if( aRole == "values-max" )
163                 {
164                     aData[nPointIndex]>>= fValue;
165                     sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
166                     aY_Max = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
167                 }
168                 else if( aRole == "values-last" )
169                 {
170                     aData[nPointIndex]>>= fValue;
171                     sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
172                     aY_Last = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
173                 }
174                 else if( aRole == "values-size" )
175                 {
176                     aData[nPointIndex]>>= fValue;
177                     sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex );
178                     a_Size = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged );
179                 }
180             }
181         }
182         catch (const lang::DisposedException&)
183         {
184             TOOLS_WARN_EXCEPTION( "chart2", "unexpected exception caught" );
185         }
186         catch( const uno::Exception& )
187         {
188             TOOLS_WARN_EXCEPTION("chart2", "" );
189         }
190     }
191 
192     if( aX.isEmpty() )
193     {
194         ChartModel& rModel = dynamic_cast<ChartModel&>(*xChartModel);
195         aRet = ExplicitCategoriesProvider::getCategoryByIndex( xCooSys, rModel, nPointIndex );
196     }
197     else
198     {
199         aRet = aX;
200     }
201 
202     OUString aSeparator( u" "_ustr );
203 
204     lcl_addText( aRet, aSeparator, aY );
205     lcl_addText( aRet, aSeparator, aY_First );
206     lcl_addText( aRet, aSeparator, aY_Min );
207     lcl_addText( aRet, aSeparator, aY_Max );
208     lcl_addText( aRet, aSeparator, aY_Last );
209     lcl_addText( aRet, aSeparator, a_Size );
210 
211     return aRet;
212 }
213 
214 } //end anonymous namespace
215 
getName(ObjectType eObjectType,bool bPlural)216 OUString ObjectNameProvider::getName( ObjectType eObjectType, bool bPlural )
217 {
218     OUString aRet;
219     switch( eObjectType )
220     {
221         case OBJECTTYPE_PAGE:
222                 aRet=SchResId(STR_OBJECT_PAGE);
223                 break;
224         case OBJECTTYPE_TITLE:
225             {
226                 if(bPlural)
227                     aRet=SchResId(STR_OBJECT_TITLES);
228                 else
229                     aRet=SchResId(STR_OBJECT_TITLE);
230             }
231                 break;
232         case OBJECTTYPE_LEGEND:
233                 aRet=SchResId(STR_OBJECT_LEGEND);
234                 break;
235         case OBJECTTYPE_LEGEND_ENTRY:
236                 aRet=SchResId(STR_OBJECT_LEGEND_SYMBOL);//@todo change string if we do differentiate symbol and legend entry in future
237                 break;
238         case OBJECTTYPE_DIAGRAM:
239                 aRet=SchResId(STR_OBJECT_DIAGRAM);
240                 break;
241         case OBJECTTYPE_DIAGRAM_WALL:
242                 aRet=SchResId(STR_OBJECT_DIAGRAM_WALL);
243                 break;
244         case OBJECTTYPE_DIAGRAM_FLOOR:
245                 aRet=SchResId(STR_OBJECT_DIAGRAM_FLOOR);
246                 break;
247         case OBJECTTYPE_AXIS:
248             {
249                 if(bPlural)
250                     aRet=SchResId(STR_OBJECT_AXES);
251                 else
252                     aRet=SchResId(STR_OBJECT_AXIS);
253             }
254                 break;
255         case OBJECTTYPE_AXIS_UNITLABEL:
256                 aRet=SchResId(STR_OBJECT_LABEL);//@todo maybe a more concrete name
257                 break;
258         case OBJECTTYPE_GRID:
259         case OBJECTTYPE_SUBGRID: //maybe todo: different names for subgrids
260             {
261                 if(bPlural)
262                     aRet=SchResId(STR_OBJECT_GRIDS);
263                 else
264                     aRet=SchResId(STR_OBJECT_GRID);
265             }
266                 break;
267         case OBJECTTYPE_DATA_SERIES:
268             {
269                 if(bPlural)
270                     aRet=SchResId(STR_OBJECT_DATASERIES_PLURAL);
271                 else
272                     aRet=SchResId(STR_OBJECT_DATASERIES);
273             }
274                 break;
275         case OBJECTTYPE_DATA_POINT:
276             {
277                 if(bPlural)
278                     aRet=SchResId(STR_OBJECT_DATAPOINTS);
279                 else
280                     aRet=SchResId(STR_OBJECT_DATAPOINT);
281             }
282                 break;
283         case OBJECTTYPE_DATA_LABELS:
284                 aRet=SchResId(STR_OBJECT_DATALABELS);
285                 break;
286         case OBJECTTYPE_DATA_LABEL:
287                 aRet=SchResId(STR_OBJECT_LABEL);
288                 break;
289         case OBJECTTYPE_DATA_ERRORS_X:
290                 aRet=SchResId(STR_OBJECT_ERROR_BARS_X);
291                 break;
292         case OBJECTTYPE_DATA_ERRORS_Y:
293                 aRet=SchResId(STR_OBJECT_ERROR_BARS_Y);
294                 break;
295         case OBJECTTYPE_DATA_ERRORS_Z:
296                 aRet=SchResId(STR_OBJECT_ERROR_BARS_Z);
297                 break;
298         case OBJECTTYPE_DATA_AVERAGE_LINE:
299                 aRet=SchResId(STR_OBJECT_AVERAGE_LINE);
300                 break;
301         case OBJECTTYPE_DATA_CURVE:
302             {
303                 if(bPlural)
304                     aRet=SchResId(STR_OBJECT_CURVES);
305                 else
306                     aRet=SchResId(STR_OBJECT_CURVE);
307             }
308                 break;
309         case OBJECTTYPE_DATA_STOCK_RANGE:
310                 break;
311         case OBJECTTYPE_DATA_STOCK_LOSS:
312                 aRet=SchResId(STR_OBJECT_STOCK_LOSS);
313                 break;
314         case OBJECTTYPE_DATA_STOCK_GAIN:
315                 aRet=SchResId(STR_OBJECT_STOCK_GAIN);
316                 break;
317         case OBJECTTYPE_DATA_CURVE_EQUATION:
318                 aRet=SchResId(STR_OBJECT_CURVE_EQUATION);
319                 break;
320         case OBJECTTYPE_DATA_TABLE:
321                 aRet=SchResId(STR_DATA_TABLE);
322                 break;
323         default: //OBJECTTYPE_UNKNOWN
324             ;
325     }
326     return aRet;
327 }
328 
getAxisName(std::u16string_view rObjectCID,const rtl::Reference<::chart::ChartModel> & xChartModel)329 OUString ObjectNameProvider::getAxisName( std::u16string_view rObjectCID
330                         , const rtl::Reference<::chart::ChartModel>& xChartModel  )
331 {
332     OUString aRet;
333 
334     rtl::Reference< ::chart::Axis > xAxis =
335         dynamic_cast<::chart::Axis*>(ObjectIdentifier::getObjectPropertySet( rObjectCID , xChartModel ).get());
336 
337     sal_Int32 nCooSysIndex = 0;
338     sal_Int32 nDimensionIndex = 0;
339     sal_Int32 nAxisIndex = 0;
340     AxisHelper::getIndicesForAxis( xAxis, xChartModel->getFirstChartDiagram(), nCooSysIndex, nDimensionIndex, nAxisIndex );
341 
342     switch(nDimensionIndex)
343     {
344         case 0://x-axis
345             if( nAxisIndex == 0 )
346                 aRet=SchResId(STR_OBJECT_AXIS_X);
347             else
348                 aRet=SchResId(STR_OBJECT_SECONDARY_X_AXIS);
349             break;
350         case 1://y-axis
351             if( nAxisIndex == 0 )
352                 aRet=SchResId(STR_OBJECT_AXIS_Y);
353             else
354                 aRet=SchResId(STR_OBJECT_SECONDARY_Y_AXIS);
355             break;
356         case 2://z-axis
357             aRet=SchResId(STR_OBJECT_AXIS_Z);
358             break;
359         default://axis
360             aRet=SchResId(STR_OBJECT_AXIS);
361             break;
362     }
363 
364     return aRet;
365 }
366 
getTitleNameByType(TitleHelper::eTitleType eType)367 OUString ObjectNameProvider::getTitleNameByType( TitleHelper::eTitleType eType )
368 {
369     OUString aRet;
370 
371     switch(eType)
372     {
373         case TitleHelper::MAIN_TITLE:
374             aRet=SchResId(STR_OBJECT_TITLE_MAIN);
375             break;
376         case TitleHelper::SUB_TITLE:
377             aRet=SchResId(STR_OBJECT_TITLE_SUB);
378             break;
379         case TitleHelper::X_AXIS_TITLE:
380             aRet=SchResId(STR_OBJECT_TITLE_X_AXIS);
381             break;
382         case TitleHelper::Y_AXIS_TITLE:
383             aRet=SchResId(STR_OBJECT_TITLE_Y_AXIS);
384             break;
385         case TitleHelper::Z_AXIS_TITLE:
386             aRet=SchResId(STR_OBJECT_TITLE_Z_AXIS);
387             break;
388         case TitleHelper::SECONDARY_X_AXIS_TITLE:
389             aRet=SchResId(STR_OBJECT_TITLE_SECONDARY_X_AXIS);
390             break;
391         case TitleHelper::SECONDARY_Y_AXIS_TITLE:
392             aRet=SchResId(STR_OBJECT_TITLE_SECONDARY_Y_AXIS);
393             break;
394         default:
395             OSL_FAIL("unknown title type");
396             break;
397     }
398 
399     if( aRet.isEmpty() )
400         aRet=SchResId(STR_OBJECT_TITLE);
401 
402     return aRet;
403 }
404 
getTitleName(std::u16string_view rObjectCID,const rtl::Reference<::chart::ChartModel> & xChartModel)405 OUString ObjectNameProvider::getTitleName( std::u16string_view rObjectCID
406                         , const rtl::Reference<::chart::ChartModel>& xChartModel )
407 {
408     OUString aRet;
409 
410     rtl::Reference<Title> xTitle =
411         dynamic_cast<Title*>(ObjectIdentifier::getObjectPropertySet( rObjectCID , xChartModel ).get());
412     if( xTitle )
413     {
414         TitleHelper::eTitleType eType;
415         if( TitleHelper::getTitleType( eType, xTitle, xChartModel ) )
416             aRet = ObjectNameProvider::getTitleNameByType( eType );
417     }
418     if( aRet.isEmpty() )
419         aRet=SchResId(STR_OBJECT_TITLE);
420 
421     return aRet;
422 }
423 
getGridName(std::u16string_view rObjectCID,const rtl::Reference<::chart::ChartModel> & xChartModel)424 OUString ObjectNameProvider::getGridName( std::u16string_view rObjectCID
425                         , const rtl::Reference<::chart::ChartModel>& xChartModel )
426 {
427     OUString aRet;
428 
429     sal_Int32 nCooSysIndex = -1;
430     sal_Int32 nDimensionIndex = -1;
431     sal_Int32 nAxisIndex = -1;
432     rtl::Reference< Axis > xAxis = ObjectIdentifier::getAxisForCID( rObjectCID , xChartModel );
433     AxisHelper::getIndicesForAxis( xAxis, xChartModel->getFirstChartDiagram()
434               , nCooSysIndex , nDimensionIndex, nAxisIndex );
435 
436     bool bMainGrid = (ObjectIdentifier::getObjectType( rObjectCID ) == OBJECTTYPE_GRID);
437 
438     if( bMainGrid )
439     {
440         switch(nDimensionIndex)
441         {
442             case 0://x-axis
443                 aRet=SchResId(STR_OBJECT_GRID_MAJOR_X);
444                 break;
445             case 1://y-axis
446                 aRet=SchResId(STR_OBJECT_GRID_MAJOR_Y);
447                 break;
448             case 2://z-axis
449                 aRet=SchResId(STR_OBJECT_GRID_MAJOR_Z);
450                 break;
451             default://axis
452                 aRet=SchResId(STR_OBJECT_GRID);
453                 break;
454         }
455     }
456     else
457     {
458         switch(nDimensionIndex)
459         {
460             case 0://x-axis
461                 aRet=SchResId(STR_OBJECT_GRID_MINOR_X);
462                 break;
463             case 1://y-axis
464                 aRet=SchResId(STR_OBJECT_GRID_MINOR_Y);
465                 break;
466             case 2://z-axis
467                 aRet=SchResId(STR_OBJECT_GRID_MINOR_Z);
468                 break;
469             default://axis
470                 aRet=SchResId(STR_OBJECT_GRID);
471                 break;
472         }
473     }
474     return aRet;
475 }
476 
getHelpText(std::u16string_view rObjectCID,const rtl::Reference<::chart::ChartModel> & xChartModel,bool bVerbose)477 OUString ObjectNameProvider::getHelpText( std::u16string_view rObjectCID, const rtl::Reference<::chart::ChartModel>& xChartModel, bool bVerbose )
478 {
479     OUString aRet;
480     ObjectType eObjectType( ObjectIdentifier::getObjectType(rObjectCID) );
481     if( eObjectType == OBJECTTYPE_AXIS )
482     {
483         aRet=ObjectNameProvider::getAxisName( rObjectCID, xChartModel );
484     }
485     else if( eObjectType == OBJECTTYPE_GRID
486         || eObjectType == OBJECTTYPE_SUBGRID )
487     {
488         aRet=ObjectNameProvider::getGridName( rObjectCID, xChartModel );
489     }
490     else if( eObjectType == OBJECTTYPE_TITLE )
491     {
492         aRet=ObjectNameProvider::getTitleName( rObjectCID, xChartModel );
493     }
494     else if( eObjectType == OBJECTTYPE_DATA_SERIES )
495     {
496         aRet = lcl_getFullSeriesName( rObjectCID, xChartModel );
497     }
498     else if( eObjectType == OBJECTTYPE_DATA_POINT )
499     {
500         if( bVerbose )
501         {
502             aRet= SchResId(STR_TIP_DATAPOINT_INDEX) + "\n"
503                 + SchResId(STR_TIP_DATASERIES) + "\n"
504                 + SchResId(STR_TIP_DATAPOINT_VALUES);
505         }
506         else
507             aRet=SchResId(STR_TIP_DATAPOINT);
508 
509         rtl::Reference< Diagram > xDiagram( xChartModel->getFirstChartDiagram() );
510         rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel );
511         if( xDiagram.is() && xSeries.is() )
512         {
513             sal_Int32 nPointIndex = o3tl::toInt32(ObjectIdentifier::getParticleID(rObjectCID));
514 
515             //replace data point index
516             OUString aWildcard(  u"%POINTNUMBER"_ustr );
517             sal_Int32 nIndex = aRet.indexOf( aWildcard );
518             if( nIndex != -1 )
519             {
520                 aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), OUString::number(nPointIndex+1) );
521             }
522 
523             //replace data series index
524             aWildcard =  "%SERIESNUMBER";
525             nIndex = aRet.indexOf( aWildcard );
526             if( nIndex != -1 )
527             {
528                 std::vector< rtl::Reference< DataSeries > > aSeriesVector =
529                     xDiagram->getDataSeries();
530                 sal_Int32 nSeriesIndex = -1;
531                 for( nSeriesIndex=aSeriesVector.size();nSeriesIndex--;)
532                 {
533                     if( aSeriesVector[nSeriesIndex] == xSeries )
534                     {
535                         break;
536                     }
537                 }
538 
539                 OUString aReplacement( OUString::number(nSeriesIndex+1) );
540                 aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), aReplacement );
541             }
542 
543             //replace point values
544             aWildcard =  "%POINTVALUES";
545             nIndex = aRet.indexOf( aWildcard );
546             if( nIndex != -1 )
547                 aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataPointValueText(
548                 xSeries,nPointIndex, DataSeriesHelper::getCoordinateSystemOfSeries(xSeries, xDiagram), xChartModel ) );
549 
550             //replace series name
551             aWildcard = "%SERIESNAME";
552             nIndex = aRet.indexOf( aWildcard );
553             if( nIndex != -1 )
554                 aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataSeriesName( rObjectCID, xChartModel ) );
555         }
556     }
557     else if( eObjectType == OBJECTTYPE_DATA_CURVE )
558     {
559         if( bVerbose )
560         {
561             aRet = SchResId( STR_OBJECT_CURVE_WITH_PARAMETERS );
562             rtl::Reference< DataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ));
563 
564             if( xSeries.is())
565             {
566                 sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID );
567                 rtl::Reference< RegressionCurveModel > xCurve = RegressionCurveHelper::getRegressionCurveAtIndex(xSeries, nCurveIndex);
568                 if( xCurve.is())
569                 {
570                     try
571                     {
572                         Reference< chart2::XRegressionCurveCalculator > xCalculator( xCurve->getCalculator(), uno::UNO_SET_THROW );
573                         sal_Int32 aDegree = 2;
574                         sal_Int32 aPeriod = 2;
575                         sal_Int32 aMovingType = css::chart2::MovingAverageType::Prior;
576                         bool bForceIntercept = false;
577                         double aInterceptValue = 0.0;
578                         OUString aXName (u"x"_ustr), aYName (u"f(x)"_ustr);
579                         const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
580                         const OUString& aNumDecimalSep = rLocaleDataWrapper.getNumDecimalSep();
581                         sal_Unicode cDecSeparator = aNumDecimalSep[0];
582 
583                         xCurve->getPropertyValue( u"PolynomialDegree"_ustr) >>= aDegree;
584                         xCurve->getPropertyValue( u"MovingAveragePeriod"_ustr) >>= aPeriod;
585                         xCurve->getPropertyValue( u"MovingAverageType"_ustr) >>= aMovingType;
586                         xCurve->getPropertyValue( u"ForceIntercept"_ustr) >>= bForceIntercept;
587                         if (bForceIntercept)
588                                 xCurve->getPropertyValue( u"InterceptValue"_ustr) >>= aInterceptValue;
589                         uno::Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties());
590                         if( xEqProp.is())
591                         {
592                             if ( !(xEqProp->getPropertyValue( u"XName"_ustr) >>= aXName) )
593                                 aXName = "x";
594                             if ( !(xEqProp->getPropertyValue( u"YName"_ustr) >>= aYName) )
595                                 aYName = "f(x)";
596                         }
597                         xCalculator->setRegressionProperties(aDegree, bForceIntercept, aInterceptValue, aPeriod, aMovingType);
598                         xCalculator->setXYNames ( aXName, aYName );
599                         RegressionCurveHelper::initializeCurveCalculator( xCalculator, xSeries, xChartModel );
600 
601                         // change text for Moving Average
602                         if ( RegressionCurveHelper::getRegressionType( xCurve ) == SvxChartRegress::MovingAverage )
603                         {
604                             aRet = xCalculator->getRepresentation();
605                         }
606                         else
607                         {
608                             // replace formula
609                             OUString aWildcard = u"%FORMULA"_ustr;
610                             sal_Int32 nIndex = aRet.indexOf( aWildcard );
611                             if( nIndex != -1 )
612                             {
613                                 OUString aFormula ( xCalculator->getRepresentation() );
614                                 if ( cDecSeparator != '.' )
615                                 {
616                                     aFormula = aFormula.replace( '.', cDecSeparator );
617                                 }
618                                 aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), aFormula );
619                             }
620 
621                             // replace r^2
622                             aWildcard = "%RSQUARED";
623                             nIndex = aRet.indexOf( aWildcard );
624                             if( nIndex != -1 )
625                             {
626                                 double fR( xCalculator->getCorrelationCoefficient());
627                                 aRet = aRet.replaceAt(
628                                     nIndex, aWildcard.getLength(),
629                                     ::rtl::math::doubleToUString(
630                                         fR*fR, rtl_math_StringFormat_G, 4, cDecSeparator, true ));
631                             }
632                         }
633                     }
634                     catch( const uno::Exception & )
635                     {
636                         DBG_UNHANDLED_EXCEPTION("chart2");
637                     }
638                 }
639             }
640         }
641         else
642         {
643             rtl::Reference< DataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID(rObjectCID , xChartModel));
644             aRet += getName(eObjectType);
645 
646             if( xSeries.is())
647             {
648                 sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID );
649                 rtl::Reference< RegressionCurveModel > xCurve( RegressionCurveHelper::getRegressionCurveAtIndex(xSeries, nCurveIndex) );
650                 if( xCurve.is())
651                 {
652                     aRet += " (" + RegressionCurveHelper::getRegressionCurveName(xCurve) + " )";
653                 }
654             }
655         }
656     }
657     else if( eObjectType == OBJECTTYPE_DATA_AVERAGE_LINE )
658     {
659         if( bVerbose )
660         {
661             aRet = SchResId(STR_OBJECT_AVERAGE_LINE_WITH_PARAMETERS);
662             rtl::Reference< DataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ));
663             if( xSeries.is())
664             {
665                 rtl::Reference< RegressionCurveModel > xCurve( RegressionCurveHelper::getMeanValueLine( xSeries ));
666                 if( xCurve.is())
667                 {
668                     try
669                     {
670                         Reference< chart2::XRegressionCurveCalculator > xCalculator( xCurve->getCalculator(), uno::UNO_SET_THROW );
671                         RegressionCurveHelper::initializeCurveCalculator( xCalculator, xSeries, xChartModel );
672 
673                         const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper();
674                         const OUString& aNumDecimalSep = rLocaleDataWrapper.getNumDecimalSep();
675                         sal_Unicode cDecSeparator = aNumDecimalSep[0];
676 
677                         OUString aWildcard( u"%AVERAGE_VALUE"_ustr );
678                         sal_Int32 nIndex = aRet.indexOf( aWildcard );
679                         // as the curve is constant, the value at any x-value is ok
680                         if( nIndex != -1 )
681                         {
682                             const double fMeanValue( xCalculator->getCurveValue( 0.0 ));
683                             aRet = aRet.replaceAt(
684                                 nIndex, aWildcard.getLength(),
685                                 ::rtl::math::doubleToUString(
686                                     fMeanValue, rtl_math_StringFormat_G, 4, cDecSeparator, true ));
687                         }
688 
689                         // replace standard deviation
690                         aWildcard = "%STD_DEVIATION";
691                         nIndex = aRet.indexOf( aWildcard );
692                         if( nIndex != -1 )
693                         {
694                             const double fStdDev( xCalculator->getCorrelationCoefficient());
695                             aRet = aRet.replaceAt(
696                                 nIndex, aWildcard.getLength(),
697                                 ::rtl::math::doubleToUString(
698                                     fStdDev, rtl_math_StringFormat_G, 4, cDecSeparator, true ));
699                         }
700                     }
701                     catch( const uno::Exception & )
702                     {
703                         DBG_UNHANDLED_EXCEPTION("chart2");
704                     }
705                 }
706             }
707         }
708         else
709         {
710             // non-verbose
711             aRet = ObjectNameProvider::getName( eObjectType );
712         }
713     }
714     else
715     {
716         aRet = ObjectNameProvider::getName( eObjectType );
717     }
718     return aRet;
719 }
720 
getSelectedObjectText(std::u16string_view rObjectCID,const rtl::Reference<::chart::ChartModel> & xChartDocument)721 OUString ObjectNameProvider::getSelectedObjectText( std::u16string_view rObjectCID, const rtl::Reference<::chart::ChartModel>& xChartDocument )
722 {
723     OUString aRet;
724     ObjectType eObjectType( ObjectIdentifier::getObjectType(rObjectCID) );
725 
726     if( eObjectType == OBJECTTYPE_DATA_POINT )
727     {
728         aRet = SchResId( STR_STATUS_DATAPOINT_MARKED );
729 
730         rtl::Reference< Diagram > xDiagram( xChartDocument->getFirstChartDiagram() );
731         rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartDocument );
732         if( xDiagram.is() && xSeries.is() )
733         {
734             sal_Int32 nPointIndex = o3tl::toInt32( ObjectIdentifier::getParticleID(rObjectCID) );
735 
736             // replace data point index
737             replaceParamterInString( aRet, u"%POINTNUMBER", OUString::number( nPointIndex + 1 ));
738 
739             // replace data series index
740             {
741                 std::vector< rtl::Reference< DataSeries > > aSeriesVector(
742                     xDiagram->getDataSeries() );
743                 sal_Int32 nSeriesIndex = -1;
744                 for( nSeriesIndex=aSeriesVector.size();nSeriesIndex--;)
745                 {
746                     if( aSeriesVector[nSeriesIndex] == xSeries )
747                         break;
748                 }
749                 replaceParamterInString( aRet, u"%SERIESNUMBER", OUString::number( nSeriesIndex + 1 ) );
750             }
751 
752             // replace point value
753             replaceParamterInString( aRet, u"%POINTVALUES", lcl_getDataPointValueText(
754                 xSeries, nPointIndex, DataSeriesHelper::getCoordinateSystemOfSeries(xSeries, xDiagram), xChartDocument ) );
755         }
756     }
757     else
758     {
759         // use the verbose text including the formula for trend lines
760         const bool bVerbose( eObjectType == OBJECTTYPE_DATA_CURVE || eObjectType == OBJECTTYPE_DATA_AVERAGE_LINE );
761         const OUString aHelpText( getHelpText( rObjectCID, xChartDocument, bVerbose ));
762         if( !aHelpText.isEmpty())
763         {
764             aRet = SchResId( STR_STATUS_OBJECT_MARKED );
765             replaceParamterInString( aRet, u"%OBJECTNAME", aHelpText );
766         }
767     }
768 
769     return aRet;
770 }
771 
getNameForCID(std::u16string_view rObjectCID,const rtl::Reference<::chart::ChartModel> & xChartDocument)772 OUString ObjectNameProvider::getNameForCID(
773     std::u16string_view rObjectCID,
774     const rtl::Reference<::chart::ChartModel>& xChartDocument )
775 {
776     ObjectType eType( ObjectIdentifier::getObjectType( rObjectCID ));
777 
778     switch( eType )
779     {
780         case OBJECTTYPE_AXIS:
781             return getAxisName( rObjectCID, xChartDocument );
782         case OBJECTTYPE_TITLE:
783             return getTitleName( rObjectCID, xChartDocument );
784         case OBJECTTYPE_GRID:
785         case OBJECTTYPE_SUBGRID:
786             return getGridName( rObjectCID, xChartDocument );
787         case OBJECTTYPE_DATA_SERIES:
788             return lcl_getFullSeriesName( rObjectCID, xChartDocument );
789         case OBJECTTYPE_DATA_POINT:
790         case OBJECTTYPE_DATA_LABELS:
791         case OBJECTTYPE_DATA_LABEL:
792         case OBJECTTYPE_DATA_ERRORS_X:
793         case OBJECTTYPE_DATA_ERRORS_Y:
794         case OBJECTTYPE_DATA_ERRORS_Z:
795         case OBJECTTYPE_DATA_AVERAGE_LINE:
796         case OBJECTTYPE_DATA_CURVE:
797         case OBJECTTYPE_DATA_CURVE_EQUATION:
798             {
799                 OUString aRet = lcl_getFullSeriesName( rObjectCID, xChartDocument ) + " ";
800                 if( eType == OBJECTTYPE_DATA_POINT || eType == OBJECTTYPE_DATA_LABEL )
801                 {
802                     aRet += getName( OBJECTTYPE_DATA_POINT  );
803                     sal_Int32 nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID );
804                     aRet += " " + OUString::number(nPointIndex+1);
805                     if( eType == OBJECTTYPE_DATA_LABEL )
806                     {
807                         aRet += " " + getName( OBJECTTYPE_DATA_LABEL  );
808                     }
809                 }
810                 else if (eType == OBJECTTYPE_DATA_CURVE || eType == OBJECTTYPE_DATA_CURVE_EQUATION)
811                 {
812                     rtl::Reference< DataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartDocument ));
813 
814                     aRet += " " + getName(eType);
815 
816                     if( xSeries.is())
817                     {
818                         sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID );
819                         rtl::Reference< RegressionCurveModel > xCurve( RegressionCurveHelper::getRegressionCurveAtIndex(xSeries, nCurveIndex) );
820                         if( xCurve.is())
821                         {
822                            aRet += " (" + RegressionCurveHelper::getRegressionCurveName(xCurve) + ")";
823                         }
824                     }
825                 }
826                 else
827                 {
828                     aRet += getName( eType );
829                 }
830                 return aRet;
831             }
832         default:
833             break;
834     }
835 
836     return getName( eType );
837 }
838 
getName_ObjectForSeries(ObjectType eObjectType,std::u16string_view rSeriesCID,const rtl::Reference<::chart::ChartModel> & xChartDocument)839 OUString ObjectNameProvider::getName_ObjectForSeries(
840         ObjectType eObjectType,
841         std::u16string_view rSeriesCID,
842         const rtl::Reference<::chart::ChartModel>& xChartDocument )
843 {
844     rtl::Reference< DataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rSeriesCID , xChartDocument );
845     if( xSeries.is() )
846     {
847         OUString aRet = SchResId(STR_OBJECT_FOR_SERIES);
848         replaceParamterInString( aRet, u"%OBJECTNAME", getName( eObjectType ) );
849         replaceParamterInString( aRet, u"%SERIESNAME", lcl_getDataSeriesName( rSeriesCID, xChartDocument ) );
850         return aRet;
851     }
852     else
853         return ObjectNameProvider::getName_ObjectForAllSeries( eObjectType );
854 }
855 
getName_ObjectForAllSeries(ObjectType eObjectType)856 OUString ObjectNameProvider::getName_ObjectForAllSeries( ObjectType eObjectType )
857 {
858     OUString aRet = SchResId(STR_OBJECT_FOR_ALL_SERIES);
859     replaceParamterInString( aRet, u"%OBJECTNAME", getName( eObjectType, true /*bPlural*/ ) );
860     return aRet;
861 }
862 
863 } //namespace chart
864 
865 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
866