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