1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
59
60
61
62
63
64
65
66
67
68
69
70
71
77
78
84
85
91
92
93
97
98
99
100
101
102
103
104
105
106
107
108
109
115
116
123
124
125
126
130
134
135
136
137
138
142
143
144
145
148
149
150
151
152
153
154
160
161
162
163
164
165
166
170
171
172
173
174
175
180
185
186
187
188
189
190
191
196
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
240
241
246
247
251
252
260
261
269
270
271
272
276
277
278
279
280
281
282
283
287
291
292
293
294
295
300
301
327
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
398
399
403
404
405
406
407
408
409
413
417
418
419
/* ... */
#include <gui/graph_screen/PieChart.hpp>
PieChart::PieChart():
minRadius(0),
maxRadius(0),
minAngle(0),
maxAngle(0),
centerX(0),
centerY(0),
animationRunning(false),
selectAnimationSteps(4),
selectionAction(0),
animationEndedAction(0),
animationEndedCallbackActive(false)
{
sliceSum = 0;
for (int i = 0; i < NUM_ITEMS; i++)
{
slice[i] = 0;
displacement[i] = 0;
expand[i] = 0;
selected[i] = false;
circle[i].setCenter(0, 0);
circle[i].setArc(0, 0);
circle[i].setVisible(false);
add(circle[i]);
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
startPieChartAnimation(0, 0, 0, 0, 0);
setTouchable(true);
}{ ... }
void PieChart::setSlices(int newShares[NUM_ITEMS])
{
sliceSum = 0;
for (int i = 0; i < NUM_ITEMS; i++)
{
slice[i] = newShares[i];
sliceSum += slice[i];
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
}{ ... }
#if !defined(USE_BPP) || USE_BPP==16
void PieChart::setPainter(int index, AbstractPainterRGB565& painter)
#elif USE_BPP==24
void PieChart::setPainter(int index, AbstractPainterRGB888& painter)
#elif USE_BPP==4
void PieChart::setPainter(int index, AbstractPainterGRAY4& painter)
#elif USE_BPP==2
void PieChart::setPainter(int index, AbstractPainterGRAY2& painter)
#else
#error Unknown USE_BPP
#endif
{
if (index >= 0 && index < NUM_ITEMS)
{
circle[index].setPainter(painter);
}if (index >= 0 && index < NUM_ITEMS) { ... }
...}
void PieChart::setRadiuses(int innerRadius, int outerRadius)
{
this->minRadius = innerRadius;
this->maxRadius = outerRadius;
recalculatePieChart();
}{ ... }
void PieChart::setAngles(int newMinAngle, int newMaxAngle)
{
minAngle = newMinAngle;
maxAngle = newMaxAngle;
recalculatePieChart();
}{ ... }
void PieChart::getAngles(int& currentMinAngle, int& currentMaxAngle) const
{
currentMinAngle = minAngle;
currentMaxAngle = maxAngle;
...}
void PieChart::setPieChart(int newStartAngle, int newEndAngle, int newMinRadius, int newMaxRadius)
{
setAngles(newStartAngle, newEndAngle);
setRadiuses(newMinRadius, newMaxRadius);
startAngleExit = minAngle;
endAngleExit = maxAngle;
minRadiusExit = newMinRadius;
maxRadiusExit = newMaxRadius;
}{ ... }
void PieChart::setCenter(int newCenterX, int newCenterY)
{
centerX = newCenterX;
centerY = newCenterY;
recalculatePieChart();
}{ ... }
void PieChart::setSelectAnimationSteps(int steps)
{
if (steps >= 0)
{
selectAnimationSteps = steps;
}if (steps >= 0) { ... }
}{ ... }
void PieChart::setSelected(int index, bool value)
{
if (index < 0 || index >= NUM_ITEMS)
{
return;
}if (index < 0 || index >= NUM_ITEMS) { ... }
if (value == selected[index])
{
return;
}if (value == selected[index]) { ... }
selected[index] = value;
expand[index] = value ? 1 : -1;
animateSelected(selectAnimationSteps);
if (selectionAction && selectionAction->isValid())
{
selectionAction->execute(*this, index);
}if (selectionAction && selectionAction->isValid()) { ... }
}{ ... }
bool PieChart::isSelected(int share) const
{
return (share >= 0 && share < NUM_ITEMS) ? selected[share] : false;
...}
void PieChart::unselectAll()
{
animationRunning = false;
for (int i = 0; i < NUM_ITEMS; i++)
{
selected[i] = 0;
expand[i] = 0;
displacement[i] = 0;
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
recalculatePieChart();
}{ ... }
void PieChart::recalculatePieChart()
{
if (sliceSum == 0)
{
return;
}if (sliceSum == 0) { ... }
int accum = 0;
for (int i = 0; i < NUM_ITEMS; i++)
{
int lineWidth = (maxRadius - minRadius);
circle[i].setVisible(lineWidth > 0);
if (minRadius > 0)
{
circle[i].setRadius(minRadius + lineWidth / 2);
circle[i].setLineWidth(lineWidth);
}if (minRadius > 0) { ... }
else
{
circle[i].setRadius(maxRadius);
circle[i].setLineWidth(0);
}else { ... }
int arcStart = minAngle + accum * (maxAngle - minAngle) / sliceSum;
accum += slice[i];
int arcEnd = minAngle + accum * (maxAngle - minAngle) / sliceSum;
circle[i].updateArcStart(arcStart);
circle[i].updateArcEnd(arcEnd);
int middleAngle = (arcStart + arcEnd) / 2;
if (displacement[i] != 0)
{
circle[i].setCenter(centerX + (CWRUtil::toQ5(displacement[i]) * CWRUtil::sine(middleAngle)).to<int>(),
centerY - (CWRUtil::toQ5(displacement[i]) * CWRUtil::cosine(middleAngle)).to<int>());
}if (displacement[i] != 0) { ... }
else
{
circle[i].setCenter(centerX, centerY);
}else { ... }
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
}{ ... }
void PieChart::startPieChartAnimation(int toStartAngle, int toEndAngle, int toMinRadius, int toMaxRadius, int steps, EasingEquation newAngleEquation , EasingEquation newRadiusEquation )
{
startAngleInit = startAngleExit;
endAngleInit = endAngleExit;
minRadiusInit = minRadiusExit;
maxRadiusInit = maxRadiusExit;
startAngleExit = toStartAngle;
endAngleExit = toEndAngle;
minRadiusExit = toMinRadius;
maxRadiusExit = toMaxRadius;
currentStep = 0;
animationSteps = steps;
this->angleEquation = newAngleEquation;
this->radiusEquation = newRadiusEquation;
Application::getInstance()->registerTimerWidget(this);
animationRunning = true;
animationType = CHANGE_PIECHART;
}{ ... }
void PieChart::animateSelected(int steps, EasingEquation progressionEquation)
{
this->currentStep = 0;
this->animationSteps = steps;
angleEquation = progressionEquation;
Application::getInstance()->registerTimerWidget(this);
animationRunning = true;
animationType = SELECT_DESELECT;
}{ ... }
void PieChart::setPieChartSelectionCallback(GenericCallback<const PieChart&, int>& callback)
{
selectionAction = &callback;
}{ ... }
void PieChart::setPieChartAnimationEndedCallback(GenericCallback<const PieChart&>& callback)
{
animationEndedAction = &callback;
animationEndedCallbackActive = true;
}{ ... }
void PieChart::activatePieChartAnimationEndedCallback(bool active)
{
animationEndedCallbackActive = active;
}{ ... }
void PieChart::setWidth(int16_t width)
{
Container::setWidth(width);
for (int i = 0; i < NUM_ITEMS; i++)
{
circle[i].setWidth(width);
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
}{ ... }
void PieChart::setHeight(int16_t height)
{
Container::setHeight(height);
for (int i = 0; i < NUM_ITEMS; i++)
{
circle[i].setHeight(height);
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
}{ ... }
void PieChart::handleClickEvent(const ClickEvent& evt)
{
if (animationRunning)
{
return;
}if (animationRunning) { ... }
if (evt.getType() == ClickEvent::PRESSED)
{
int x = evt.getX() - centerX;
int y = evt.getY() - centerY;
int distance;
int angle = CWRUtil::angle(x, y, distance);
while (angle - minAngle > 360)
{
angle -= 360;
}while (angle - minAngle > 360) { ... }
while (angle - minAngle < 0)
{
angle += 360;
}while (angle - minAngle < 0) { ... }
if (angle >= minAngle && angle <= maxAngle && ((distance >= minRadius && distance <= maxRadius) || distance < 20))
{
bool allExpanded = true;
int selectedCount = 0;
for (int i = 0; i < NUM_ITEMS; i++)
{
allExpanded &= (displacement[i] > 0);
selectedCount += (displacement[i] > 0) ? 1 : 0;
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
if (distance < 20)
{
if (allExpanded)
{
for (int i = 0; i < NUM_ITEMS; i++)
{
if (displacement[i] > 0)
{
setSelected(i, false);
...}
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
...}
else
{
for (int i = 0; i < NUM_ITEMS; i++)
{
if (displacement[i] == 0)
{
setSelected(i, true);
...}
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
}else { ... }
}if (distance < 20) { ... }
else
{
for (int i = 0; i < NUM_ITEMS; i++)
{
expand[i] = 0;
if (angle >= circle[i].getArcStart() && angle < circle[i].getArcEnd())
{
if (displacement[i] > 0)
{
if (selectedCount < 2)
{
setSelected(i, false);
}if (selectedCount < 2) { ... }
}if (displacement[i] > 0) { ... }
else
{
setSelected(i, true);
}else { ... }
}if (angle >= circle[i].getArcStart() && angle < circle[i].getArcEnd()) { ... }
else
{
if (displacement[i] > 0)
{
setSelected(i, false);
}if (displacement[i] > 0) { ... }
}else { ... }
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
}else { ... }
}if (angle >= minAngle && angle <= maxAngle && ((distance >= minRadius && distance <= maxRadius) || distance < 20)) { ... }
}if (evt.getType() == ClickEvent::PRESSED) { ... }
}{ ... }
void PieChart::handleTickEvent()
{
Container::handleTickEvent();
if (animationRunning)
{
switch (animationType)
{
case CHANGE_PIECHART:
{
int newStartAngle = angleEquation(currentStep, startAngleInit, startAngleExit - startAngleInit, animationSteps);
int newEndAngle = angleEquation(currentStep, endAngleInit, endAngleExit - endAngleInit, animationSteps);
int newMinRadius = radiusEquation(currentStep, minRadiusInit, minRadiusExit - minRadiusInit, animationSteps);
int newMaxRadius = radiusEquation(currentStep, maxRadiusInit, maxRadiusExit - maxRadiusInit, animationSteps);
setAngles(newStartAngle, newEndAngle);
setRadiuses(newMinRadius, newMaxRadius);
...}
break;case CHANGE_PIECHART:
case SELECT_DESELECT:
{
int showRadius = angleEquation(currentStep, 0, DISPLACEMENT, animationSteps);
int hideRadius = angleEquation(currentStep, DISPLACEMENT, -DISPLACEMENT, animationSteps);
for (int i = 0; i < NUM_ITEMS; i++)
{
switch (expand[i])
{
case -1:
displacement[i] = hideRadius;
break;case -1:
case 1:
displacement[i] = showRadius;
break;case 1:
}switch (expand[i]) { ... }
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
recalculatePieChart();
...}
break;case SELECT_DESELECT:
}switch (animationType) { ... }
if (isVisible())
{
invalidate();
}if (isVisible()) { ... }
currentStep++;
if (currentStep > animationSteps)
{
Application::getInstance()->unregisterTimerWidget(this);
animationRunning = false;
for (int i = 0; i < NUM_ITEMS; i++)
{
expand[i] = 0;
}for (int i = 0; i < NUM_ITEMS; i++) { ... }
if (animationEndedCallbackActive && animationEndedAction && animationEndedAction->isValid())
{
animationEndedAction->execute(*this);
}if (animationEndedCallbackActive && animationEndedAction && animationEndedAction->isValid()) { ... }
}if (currentStep > animationSteps) { ... }
}if (animationRunning) { ... }
}{ ... }