1 /*
2 KmPlot - a math. function plotter for the KDE-Desktop
3
4 SPDX-FileCopyrightText: 2006 David Saxton <david@bluehaze.org>
5
6 This file is part of the KDE Project.
7 KmPlot is part of the KDE-EDU Project.
8
9 SPDX-License-Identifier: GPL-2.0-or-later
10
11 */
12
13 #include "parameteranimator.h"
14 #include "ui_parameteranimator.h"
15 #include "view.h"
16
17 #include <KConfigGroup>
18
19 #include <QDialogButtonBox>
20 #include <QIcon>
21 #include <QTimer>
22
23 #include <assert.h>
24 #include <cmath>
25
26 using namespace std;
27
28 #ifndef KDEWIN_MATH_H
log(int n)29 double inline log(int n)
30 {
31 return log(double(n));
32 }
33 #endif
34
35 class ParameterAnimatorWidget : public QWidget, public Ui::ParameterAnimator
36 {
37 public:
ParameterAnimatorWidget(QWidget * parent=0)38 ParameterAnimatorWidget( QWidget * parent = 0 )
39 : QWidget( parent )
40 { setupUi(this); }
41 };
42
43
44
45 //BEGIN class ParameterAnimator
ParameterAnimator(QWidget * parent,Function * function)46 ParameterAnimator::ParameterAnimator( QWidget * parent, Function * function )
47 : QDialog( parent ),
48 m_function( function )
49 {
50 m_widget = new ParameterAnimatorWidget( this );
51
52 setWindowTitle( i18nc("@title:window", "Parameter Animator") );
53 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
54 connect(buttonBox, &QDialogButtonBox::rejected, this, &ParameterAnimator::reject);
55
56 QVBoxLayout *dialogLayout = new QVBoxLayout( this );
57 dialogLayout->addWidget(m_widget);
58 dialogLayout->addWidget(buttonBox);
59
60 m_mode = Paused;
61 m_currentValue = 0;
62 m_function->m_parameters.animating = true;
63 m_function->k = m_currentValue;
64
65 if ( function->eq[0]->usesParameter() )
66 m_widget->warningLabel->hide();
67
68 m_timer = new QTimer( this );
69 connect(m_timer, &QTimer::timeout, this, &ParameterAnimator::step);
70
71 m_widget->gotoInitial->setIcon( QIcon::fromTheme( "go-first" ) );
72 m_widget->gotoFinal->setIcon( QIcon::fromTheme( "go-last" ) );
73 m_widget->stepBackwards->setIcon( QIcon::fromTheme( "go-previous" ) );
74 m_widget->stepForwards->setIcon( QIcon::fromTheme( "go-next" ) );
75 m_widget->pause->setIcon( QIcon::fromTheme( "media-playback-pause" ) );
76
77 connect(m_widget->gotoInitial, &QToolButton::clicked, this, &ParameterAnimator::gotoInitial);
78 connect(m_widget->gotoFinal, &QToolButton::clicked, this, &ParameterAnimator::gotoFinal);
79 connect(m_widget->stepBackwards, &QToolButton::toggled, this, &ParameterAnimator::stepBackwards);
80 connect(m_widget->stepForwards, &QToolButton::toggled, this, &ParameterAnimator::stepForwards);
81 connect(m_widget->pause, &QToolButton::clicked, this, &ParameterAnimator::pause);
82 connect(m_widget->speed, &QSlider::valueChanged, this, &ParameterAnimator::updateSpeed);
83
84 updateUI();
85 updateFunctionParameter();
86
87 connect(this, &ParameterAnimator::finished, this, &ParameterAnimator::deleteLater);
88 }
89
90
~ParameterAnimator()91 ParameterAnimator::~ ParameterAnimator()
92 {
93 qDebug() ;
94 m_function->m_parameters.animating = false;
95 View::self()->drawPlot();
96 }
97
98
step()99 void ParameterAnimator::step()
100 {
101 // This function shouldn't get called when we aren't actually stepping
102 assert( m_mode != Paused );
103
104 double dx = m_widget->step->value();
105
106 bool increasing = ( (m_mode == StepBackwards && (dx < 0)) || (m_mode == StepForwards && (dx > 0)) );
107 bool decreasing = ( (m_mode == StepBackwards && (dx > 0)) || (m_mode == StepForwards && (dx < 0)) );
108
109 double upper = m_widget->final->value();
110 double lower = m_widget->initial->value();
111
112 if ( lower > upper )
113 qSwap( lower, upper );
114
115 if ( (increasing && (m_currentValue >= upper)) ||
116 (decreasing && (m_currentValue <= lower)) )
117 {
118 stopStepping();
119 return;
120 }
121
122 if ( m_mode == StepForwards )
123 m_currentValue += dx;
124 else
125 m_currentValue -= dx;
126
127 updateUI();
128 updateFunctionParameter();
129 }
130
131
updateFunctionParameter()132 void ParameterAnimator::updateFunctionParameter()
133 {
134 m_function->k = m_currentValue;
135 View::self()->drawPlot();
136 }
137
138
gotoInitial()139 void ParameterAnimator::gotoInitial()
140 {
141 m_currentValue = m_widget->initial->value();
142 updateUI();
143 updateFunctionParameter();
144 }
145
146
gotoFinal()147 void ParameterAnimator::gotoFinal()
148 {
149 m_currentValue = m_widget->final->value();
150 updateUI();
151 updateFunctionParameter();
152 }
153
154
stepBackwards(bool step)155 void ParameterAnimator::stepBackwards( bool step )
156 {
157 if ( !step )
158 {
159 pause();
160 return;
161 }
162
163 m_mode = StepBackwards;
164 startStepping();
165 updateUI();
166 }
167
168
stepForwards(bool step)169 void ParameterAnimator::stepForwards( bool step )
170 {
171 if ( !step )
172 {
173 pause();
174 return;
175 }
176
177 m_mode = StepForwards;
178 startStepping();
179 updateUI();
180 }
181
182
pause()183 void ParameterAnimator::pause()
184 {
185 m_mode = Paused;
186 m_timer->stop();
187 updateUI();
188 }
189
190
updateUI()191 void ParameterAnimator::updateUI()
192 {
193 switch ( m_mode )
194 {
195 case StepBackwards:
196 m_widget->stepBackwards->setChecked( true );
197 m_widget->stepForwards->setChecked( false );
198 break;
199
200 case StepForwards:
201 m_widget->stepBackwards->setChecked( false );
202 m_widget->stepForwards->setChecked( true );
203 break;
204
205 case Paused:
206 m_widget->stepBackwards->setChecked( false );
207 m_widget->stepForwards->setChecked( false );
208 break;
209 }
210
211 m_widget->currentValue->setText( View::self()->posToString( m_currentValue, m_widget->step->value() * 1e-2, View::DecimalFormat ) );
212 }
213
214
updateSpeed()215 void ParameterAnimator::updateSpeed()
216 {
217 if ( m_mode != Paused )
218 startStepping();
219 }
220
221
startStepping() const222 void ParameterAnimator::startStepping() const
223 {
224 double prop = (log( m_widget->speed->value() ) - log( m_widget->speed->minimum() )) / (log( m_widget->speed->maximum()) - log( m_widget->speed->minimum()));
225
226 // prop = 0 ~ slowest
227 // prop = 1 ~ fastest
228
229 int min_ms = 40;
230 int max_ms = 1000;
231
232 int ms = int( prop*min_ms + (1-prop)*max_ms );
233 m_timer->start( ms );
234 }
235
236
stopStepping()237 void ParameterAnimator::stopStepping()
238 {
239 m_timer->stop();
240 m_mode = Paused;
241 updateUI();
242 }
243 //END class ParameterAnimator
244