LibreOffice Module chart2 (master) 1
res_Trendline.cxx
Go to the documentation of this file.
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 "res_Trendline.hxx"
21#include <bitmaps.hlst>
23
24#include <com/sun/star/chart2/MovingAverageType.hpp>
25
26#include <svl/intitem.hxx>
27#include <svl/numformat.hxx>
28#include <svl/stritem.hxx>
29#include <vcl/formatter.hxx>
30#include <vcl/weld.hxx>
31
32using namespace css::chart2;
33
34namespace chart
35{
36
37static void lcl_setValue(weld::FormattedSpinButton& rFmtField, double fValue )
38{
39 Formatter& rFieldFormatter = rFmtField.GetFormatter();
40 rFieldFormatter.SetValue(fValue);
41 rFieldFormatter.SetDefaultValue( fValue );
42}
43
45 : m_eTrendLineType(SvxChartRegress::Linear)
46 , m_bTrendLineUnique(true)
47 , m_pNumFormatter(nullptr)
48 , m_nNbPoints(0)
49 , m_xRB_Linear(rBuilder.weld_radio_button("linear"))
50 , m_xRB_Logarithmic(rBuilder.weld_radio_button("logarithmic"))
51 , m_xRB_Exponential(rBuilder.weld_radio_button("exponential"))
52 , m_xRB_Power(rBuilder.weld_radio_button("power"))
53 , m_xRB_Polynomial(rBuilder.weld_radio_button("polynomial"))
54 , m_xRB_MovingAverage(rBuilder.weld_radio_button("movingAverage"))
55 , m_xFI_Linear(rBuilder.weld_image("imageLinear"))
56 , m_xFI_Logarithmic(rBuilder.weld_image("imageLogarithmic"))
57 , m_xFI_Exponential(rBuilder.weld_image("imageExponential"))
58 , m_xFI_Power(rBuilder.weld_image("imagePower"))
59 , m_xFI_Polynomial(rBuilder.weld_image("imagePolynomial"))
60 , m_xFI_MovingAverage(rBuilder.weld_image("imageMovingAverage"))
61 , m_xNF_Degree(rBuilder.weld_spin_button("degree"))
62 , m_xNF_Period(rBuilder.weld_spin_button("period"))
63 , m_xEE_Name(rBuilder.weld_entry("entry_name"))
64 , m_xFmtFld_ExtrapolateForward(rBuilder.weld_formatted_spin_button("extrapolateForward"))
65 , m_xFmtFld_ExtrapolateBackward(rBuilder.weld_formatted_spin_button("extrapolateBackward"))
66 , m_xCB_SetIntercept(rBuilder.weld_check_button("setIntercept"))
67 , m_xFmtFld_InterceptValue(rBuilder.weld_formatted_spin_button("interceptValue"))
68 , m_xCB_ShowEquation(rBuilder.weld_check_button("showEquation"))
69 , m_xEE_XName(rBuilder.weld_entry("entry_Xname"))
70 , m_xEE_YName(rBuilder.weld_entry("entry_Yname"))
71 , m_xCB_ShowCorrelationCoeff(rBuilder.weld_check_button("showCorrelationCoefficient"))
72 , m_xCB_RegressionMovingType(rBuilder.weld_combo_box("combo_moving_type"))
73{
75
76 Formatter& rForwardFormatter = m_xFmtFld_ExtrapolateForward->GetFormatter();
77 rForwardFormatter.ClearMinValue();
78 rForwardFormatter.ClearMaxValue();
79 Formatter& rBackwardFormatter = m_xFmtFld_ExtrapolateBackward->GetFormatter();
80 rBackwardFormatter.ClearMinValue();
81 rBackwardFormatter.ClearMaxValue();
82 Formatter& rInterceptFormatter = m_xFmtFld_InterceptValue->GetFormatter();
83 rInterceptFormatter.ClearMinValue();
84 rInterceptFormatter.ClearMaxValue();
85
86 Link<weld::Toggleable&,void> aLink = LINK(this, TrendlineResources, SelectTrendLine);
87 m_xRB_Linear->connect_toggled( aLink );
88 m_xRB_Logarithmic->connect_toggled( aLink );
89 m_xRB_Exponential->connect_toggled( aLink );
90 m_xRB_Power->connect_toggled( aLink );
91 m_xRB_Polynomial->connect_toggled( aLink );
92 m_xRB_MovingAverage->connect_toggled( aLink );
93
94 Link<weld::SpinButton&,void> aLink2 = LINK(this, TrendlineResources, ChangeSpinValue);
95 m_xNF_Degree->connect_value_changed(aLink2);
96 m_xNF_Period->connect_value_changed(aLink2);
97 m_xFmtFld_InterceptValue->connect_value_changed(LINK(this, TrendlineResources, ChangeFormattedValue));
98
99 m_xCB_ShowEquation->connect_toggled(LINK(this, TrendlineResources, ShowEquation));
100
101 Reset( rInAttrs );
103}
104
106{}
107
109{
110 if (m_xRB_Linear->get_active())
111 m_eTrendLineType = SvxChartRegress::Linear;
112 else if (m_xRB_Logarithmic->get_active())
113 m_eTrendLineType = SvxChartRegress::Log;
114 else if (m_xRB_Exponential->get_active())
115 m_eTrendLineType = SvxChartRegress::Exp;
116 else if (m_xRB_Power->get_active())
117 m_eTrendLineType = SvxChartRegress::Power;
118 else if (m_xRB_Polynomial->get_active())
119 m_eTrendLineType = SvxChartRegress::Polynomial;
120 else if (m_xRB_MovingAverage->get_active())
121 m_eTrendLineType = SvxChartRegress::MovingAverage;
122 m_bTrendLineUnique = true;
123
124 UpdateControlStates();
125}
126
128{
129 if( const SfxStringItem* pCurveNameItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_CURVE_NAME ) )
130 {
131 OUString aName = pCurveNameItem->GetValue();
132 m_xEE_Name->set_text(aName);
133 }
134 else
135 {
136 m_xEE_Name->set_text("");
137 }
138 if( const SfxStringItem* pRegressionXNameItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_XNAME ) )
139 {
140 OUString aName = pRegressionXNameItem->GetValue();
141 m_xEE_XName->set_text(aName);
142 }
143 else
144 {
145 m_xEE_XName->set_text("x");
146 }
147 if( const SfxStringItem* pRegressionYNameItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_YNAME ) )
148 {
149 OUString aName = pRegressionYNameItem->GetValue();
150 m_xEE_YName->set_text(aName);
151 }
152 else
153 {
154 m_xEE_YName->set_text("f(x)");
155 }
156
157 const SfxPoolItem* pPoolItem = nullptr;
158 SfxItemState aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_TYPE, true, &pPoolItem );
159 m_bTrendLineUnique = ( aState != SfxItemState::DONTCARE );
160 if( aState == SfxItemState::SET )
161 {
162 const SvxChartRegressItem * pItem = dynamic_cast< const SvxChartRegressItem * >( pPoolItem );
163 if( pItem )
164 {
165 m_eTrendLineType = pItem->GetValue();
166 }
167 }
168
169 if( const SfxInt32Item* pDegreeItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_DEGREE ) )
170 {
171 sal_Int32 nDegree = pDegreeItem->GetValue();
172 m_xNF_Degree->set_value( nDegree );
173 }
174 else
175 {
176 m_xNF_Degree->set_value( 2 );
177 }
178
179 m_xNF_Degree->save_value();
180
181 if( const SfxInt32Item* pPeriodItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_PERIOD ) )
182 {
183 sal_Int32 nPeriod = pPeriodItem->GetValue();
184 m_xNF_Period->set_value( nPeriod );
185 }
186 else
187 {
188 m_xNF_Period->set_value( 2 );
189 }
190
191 m_xNF_Period->save_value();
192
193 double nValue = 0.0;
194 if( const SvxDoubleItem* pForwardItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD ) )
195 {
196 nValue = pForwardItem->GetValue() ;
197 }
199
200 nValue = 0.0;
201 if( const SvxDoubleItem* pBackwardItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD ) )
202 {
203 nValue = pBackwardItem->GetValue() ;
204 }
206
207 nValue = 0.0;
208 if( const SvxDoubleItem* pValueItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_INTERCEPT_VALUE ) )
209 {
210 nValue = pValueItem->GetValue() ;
211 }
213
214 aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SET_INTERCEPT, true, &pPoolItem );
215 if( aState == SfxItemState::DONTCARE )
216 {
218 }
219 else
220 {
221 if( aState == SfxItemState::SET )
222 m_xCB_SetIntercept->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue());
223 }
224
225 aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SHOW_EQUATION, true, &pPoolItem );
226 if( aState == SfxItemState::DONTCARE )
227 {
229 }
230 else
231 {
232 if( aState == SfxItemState::SET )
233 m_xCB_ShowEquation->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue());
234 }
235
236 aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SHOW_COEFF, true, &pPoolItem );
237 if( aState == SfxItemState::DONTCARE )
238 {
240 }
241 else
242 {
243 if( aState == SfxItemState::SET )
244 m_xCB_ShowCorrelationCoeff->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue());
245 }
246
247 if( const SfxInt32Item* pMovingTypeItem = rInAttrs.GetItemIfSet( SCHATTR_REGRESSION_MOVING_TYPE ) )
248 {
249 sal_Int32 nMovingType = pMovingTypeItem->GetValue();
250 if (nMovingType == MovingAverageType::Prior)
251 m_xCB_RegressionMovingType->set_active(0);
252 else if (nMovingType == MovingAverageType::Central)
253 m_xCB_RegressionMovingType->set_active(1);
254 else if (nMovingType == MovingAverageType::AveragedAbscissa)
255 m_xCB_RegressionMovingType->set_active(2);
256 }
257 else
258 {
259 m_xCB_RegressionMovingType->set_active(0);
260 }
261
262 if( !m_bTrendLineUnique )
263 return;
264
265 switch( m_eTrendLineType )
266 {
267 case SvxChartRegress::Linear :
268 m_xRB_Linear->set_active(true);
269 break;
270 case SvxChartRegress::Log :
271 m_xRB_Logarithmic->set_active(true);
272 break;
273 case SvxChartRegress::Exp :
274 m_xRB_Exponential->set_active(true);
275 break;
276 case SvxChartRegress::Power :
277 m_xRB_Power->set_active(true);
278 break;
279 case SvxChartRegress::Polynomial :
280 m_xRB_Polynomial->set_active(true);
281 break;
282 case SvxChartRegress::MovingAverage :
283 m_xRB_MovingAverage->set_active(true);
284 break;
285 default:
286 break;
287 }
288}
289
291{
294
295 if (m_eTrendLineType == SvxChartRegress::MovingAverage)
296 {
297 sal_Int32 nType = MovingAverageType::Prior;
298 if (m_xCB_RegressionMovingType->get_active() == 1)
299 nType = MovingAverageType::Central;
300 else if (m_xCB_RegressionMovingType->get_active() == 2)
301 nType = MovingAverageType::AveragedAbscissa;
302
304 }
305
306 if( m_xCB_ShowEquation->get_state() != TRISTATE_INDET )
308
309 if( m_xCB_ShowCorrelationCoeff->get_state() != TRISTATE_INDET )
311
312 OUString aName = m_xEE_Name->get_text();
314 aName = m_xEE_XName->get_text();
315 if ( aName.isEmpty() )
316 aName = "x";
318 aName = m_xEE_YName->get_text();
319 if ( aName.isEmpty() )
320 aName = "f(x)";
322
323 sal_Int32 aDegree = m_xNF_Degree->get_value();
324 rOutAttrs->Put(SfxInt32Item( SCHATTR_REGRESSION_DEGREE, aDegree ) );
325
326 sal_Int32 aPeriod = m_xNF_Period->get_value();
327 rOutAttrs->Put(SfxInt32Item( SCHATTR_REGRESSION_PERIOD, aPeriod ) );
328
329 sal_uInt32 nIndex = 0;
330 double aValue = 0.0;
333
334 aValue = 0.0;
337
338 if( m_xCB_SetIntercept->get_state() != TRISTATE_INDET )
340
341 aValue = 0.0;
344}
345
347{
348 m_xFI_Linear->set_from_icon_name(BMP_REGRESSION_LINEAR);
349 m_xFI_Logarithmic->set_from_icon_name(BMP_REGRESSION_LOG);
350 m_xFI_Exponential->set_from_icon_name(BMP_REGRESSION_EXP);
351 m_xFI_Power->set_from_icon_name(BMP_REGRESSION_POWER);
352 m_xFI_Polynomial->set_from_icon_name(BMP_REGRESSION_POLYNOMIAL);
353 m_xFI_MovingAverage->set_from_icon_name(BMP_REGRESSION_MOVING_AVERAGE);
354}
355
357{
358 if( m_nNbPoints > 0 )
359 {
360 sal_Int32 nMaxValue = m_nNbPoints - 1 + (m_xCB_SetIntercept->get_active() ? 1 : 0);
361 m_xNF_Degree->set_max(nMaxValue);
362 m_xNF_Period->set_max(m_nNbPoints - 1);
363 }
364 bool bMovingAverage = ( m_eTrendLineType == SvxChartRegress::MovingAverage );
365 bool bPolynomial = ( m_eTrendLineType == SvxChartRegress::Polynomial );
366 bool bInterceptAvailable = ( m_eTrendLineType == SvxChartRegress::Linear )
367 || ( m_eTrendLineType == SvxChartRegress::Polynomial )
368 || ( m_eTrendLineType == SvxChartRegress::Exp );
369 m_xFmtFld_ExtrapolateForward->set_sensitive( !bMovingAverage );
370 m_xFmtFld_ExtrapolateBackward->set_sensitive( !bMovingAverage );
371 m_xCB_SetIntercept->set_sensitive( bInterceptAvailable );
372 m_xFmtFld_InterceptValue->set_sensitive( bInterceptAvailable );
373 if( bMovingAverage )
374 {
376 }
377 m_xCB_ShowCorrelationCoeff->set_sensitive( !bMovingAverage );
378 m_xCB_RegressionMovingType->set_sensitive(bMovingAverage);
379 m_xNF_Period->set_sensitive(bMovingAverage);
380 m_xNF_Degree->set_sensitive(bPolynomial);
381 m_xEE_XName->set_sensitive( !bMovingAverage && m_xCB_ShowEquation->get_active() );
382 m_xEE_YName->set_sensitive( !bMovingAverage && m_xCB_ShowEquation->get_active() );
383}
384
385IMPL_LINK(TrendlineResources, ChangeSpinValue, weld::SpinButton&, rNumericField, void)
386{
387 if (&rNumericField == m_xNF_Degree.get())
388 {
389 if (!m_xRB_Polynomial->get_active() && m_xNF_Degree->get_value_changed_from_saved())
390 {
391 m_xRB_Polynomial->set_active(true);
392 SelectTrendLine(*m_xRB_Polynomial);
393 }
394 }
395 else if (&rNumericField == m_xNF_Period.get())
396 {
397 if (!m_xRB_MovingAverage->get_active() && m_xNF_Period->get_value_changed_from_saved())
398 {
399 m_xRB_MovingAverage->set_active(true);
400 SelectTrendLine(*m_xRB_MovingAverage);
401 }
402 }
403 UpdateControlStates();
404}
405
407{
408 if (!m_xCB_SetIntercept->get_active())
409 m_xCB_SetIntercept->set_active(true);
410 UpdateControlStates();
411}
412
414{
415 m_pNumFormatter = pFormatter;
416 m_xFmtFld_ExtrapolateForward->GetFormatter().SetFormatter(m_pNumFormatter);
417 m_xFmtFld_ExtrapolateBackward->GetFormatter().SetFormatter(m_pNumFormatter);
418 m_xFmtFld_InterceptValue->GetFormatter().SetFormatter(m_pNumFormatter);
419}
420
421void TrendlineResources::SetNbPoints( sal_Int32 nNbPoints )
422{
423 m_nNbPoints = nNbPoints;
425}
426
428{
429 UpdateControlStates();
430}
431
432} // namespace chart
433
434/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr TypedWhichId< SvxChartRegressItem > SCHATTR_REGRESSION_TYPE(SCHATTR_REGRESSION_START)
constexpr TypedWhichId< SvxDoubleItem > SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD(SCHATTR_REGRESSION_START+5)
constexpr TypedWhichId< SfxBoolItem > SCHATTR_REGRESSION_SHOW_EQUATION(SCHATTR_REGRESSION_START+1)
constexpr TypedWhichId< SfxBoolItem > SCHATTR_REGRESSION_SET_INTERCEPT(SCHATTR_REGRESSION_START+7)
constexpr TypedWhichId< SfxInt32Item > SCHATTR_REGRESSION_MOVING_TYPE(SCHATTR_REGRESSION_START+12)
constexpr TypedWhichId< SfxStringItem > SCHATTR_REGRESSION_CURVE_NAME(SCHATTR_REGRESSION_START+9)
constexpr TypedWhichId< SfxStringItem > SCHATTR_REGRESSION_YNAME(SCHATTR_REGRESSION_START+11)
constexpr TypedWhichId< SfxInt32Item > SCHATTR_REGRESSION_DEGREE(SCHATTR_REGRESSION_START+3)
constexpr TypedWhichId< SfxBoolItem > SCHATTR_REGRESSION_SHOW_COEFF(SCHATTR_REGRESSION_START+2)
constexpr TypedWhichId< SvxDoubleItem > SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD(SCHATTR_REGRESSION_START+6)
constexpr TypedWhichId< SfxStringItem > SCHATTR_REGRESSION_XNAME(SCHATTR_REGRESSION_START+10)
constexpr TypedWhichId< SvxDoubleItem > SCHATTR_REGRESSION_INTERCEPT_VALUE(SCHATTR_REGRESSION_START+8)
constexpr TypedWhichId< SfxInt32Item > SCHATTR_REGRESSION_PERIOD(SCHATTR_REGRESSION_START+4)
SvxChartRegress
void SetValue(double dVal)
virtual void ClearMinValue()
void SetDefaultValue(double dDefault)
virtual void ClearMaxValue()
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
std::unique_ptr< weld::RadioButton > m_xRB_Logarithmic
std::unique_ptr< weld::Entry > m_xEE_Name
void SetNbPoints(sal_Int32 nNbPoints)
TrendlineResources(weld::Builder &rParent, const SfxItemSet &rInAttrs)
std::unique_ptr< weld::CheckButton > m_xCB_ShowEquation
std::unique_ptr< weld::FormattedSpinButton > m_xFmtFld_ExtrapolateBackward
std::unique_ptr< weld::RadioButton > m_xRB_Linear
std::unique_ptr< weld::RadioButton > m_xRB_Exponential
std::unique_ptr< weld::RadioButton > m_xRB_Polynomial
std::unique_ptr< weld::Entry > m_xEE_YName
std::unique_ptr< weld::Image > m_xFI_Logarithmic
std::unique_ptr< weld::ComboBox > m_xCB_RegressionMovingType
SvxChartRegress m_eTrendLineType
std::unique_ptr< weld::SpinButton > m_xNF_Degree
std::unique_ptr< weld::Entry > m_xEE_XName
std::unique_ptr< weld::FormattedSpinButton > m_xFmtFld_ExtrapolateForward
std::unique_ptr< weld::CheckButton > m_xCB_SetIntercept
std::unique_ptr< weld::Image > m_xFI_Linear
std::unique_ptr< weld::RadioButton > m_xRB_Power
void FillItemSet(SfxItemSet *rOutAttrs) const
void Reset(const SfxItemSet &rInAttrs)
std::unique_ptr< weld::RadioButton > m_xRB_MovingAverage
std::unique_ptr< weld::Image > m_xFI_Polynomial
std::unique_ptr< weld::CheckButton > m_xCB_ShowCorrelationCoeff
std::unique_ptr< weld::Image > m_xFI_Exponential
std::unique_ptr< weld::FormattedSpinButton > m_xFmtFld_InterceptValue
void SetNumFormatter(SvNumberFormatter *pFormatter)
std::unique_ptr< weld::SpinButton > m_xNF_Period
SvNumberFormatter * m_pNumFormatter
std::unique_ptr< weld::Image > m_xFI_MovingAverage
std::unique_ptr< weld::Image > m_xFI_Power
virtual Formatter & GetFormatter()=0
sal_Int16 nValue
TRISTATE_FALSE
TRISTATE_INDET
sal_Int32 nIndex
OUString aName
static void lcl_setValue(weld::FormattedSpinButton &rFmtField, double fValue)
IMPL_LINK(StackingResourceGroup, StackingChangeHdl, weld::Toggleable &, rRadio, void)
IMPL_LINK_NOARG(SplinePropertiesDialog, SplineTypeListBoxHdl, weld::ComboBox &, void)
const char GetValue[]
SfxItemState
QPRO_FUNC_TYPE nType