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
48
49
52
53
59
60
61
65
66
70
71
72
73
74
75
76
87
88
89
90
91
102
103
104
105
106
110
111
112
113
114
119
120
121
122
123
131
132
133
134
135
136
137
138
139
150
151
152
153
158
159
160
161
162
163
164
165
166
167
168
169
170
174
175
176
177
178
182
183
184
185
186
187
188
193
194
195
196
197
198
202
203
211
227
228
229
230
231
232
233
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
273
274
275
276
281
286
290
291
295
296
297
298
299
300
305
306
311
321
327
328
329
336
337
344
345
346
350
351
356
357
368
369
373
374
/* ... */
#include <gui/common/CollapsibleMenu.hpp>
#include <BitmapDatabase.hpp>
#include <assert.h>
CollapsibleMenu::CollapsibleMenu() :
currentAnimationState(NO_ANIMATION),
size(0),
isExpanded(false),
elementSpace(0),
expandDirection(RIGHT),
fadedOut(false),
timeout(0),
timeoutCounter(0),
selectedElementIndex(0),
onButtonPressed(this, &CollapsibleMenu::buttonPressedHandler),
menuElementMoveAnimationEndedCallback(this, &CollapsibleMenu::menuElementMoveAnimationEndedHandler),
menuElementFadeAnimationEndedCallback(this, &CollapsibleMenu::menuElementFadeAnimationEndedHandler),
stateChangedAction(0)
{
for (int i = MAX_NUMBER_OF_ELEMENTS - 1; i >= 0; i--)
{
menuElements[i].setVisible(false);
menuElements[i].setAction(onButtonPressed);
menuElements[i].setFadeAnimationEndedAction(menuElementFadeAnimationEndedCallback);
menuElements[i].setMoveAnimationEndedAction(menuElementMoveAnimationEndedCallback);
add(menuElements[i]);
}for (int i = MAX_NUMBER_OF_ELEMENTS - 1; i >= 0; i--) { ... }
}{ ... }
CollapsibleMenu::~CollapsibleMenu()
{
}{ ... }
void CollapsibleMenu::addMenuElement(const Bitmap& elementBitmap, const Bitmap& elementPressedBitmap)
{
menuElements[size].setBitmaps(elementBitmap, elementPressedBitmap);
menuElements[size].setVisible(true);
size++;
}{ ... }
void CollapsibleMenu::setElementSpace(uint16_t space)
{
elementSpace = space;
}{ ... }
void CollapsibleMenu::setExpandDirection(ExpandDirection direction)
{
expandDirection = direction;
}{ ... }
void CollapsibleMenu::finilizeInitialization()
{
int newWidth = 0;
int newHeight = 0;
for (int i = 0; i < size; i++)
{
newWidth += menuElements[i].getWidth();
if (i < size - 1)
{
newWidth += elementSpace;
}if (i < size - 1) { ... }
newHeight = (menuElements[i].getHeight() > newHeight) ? menuElements[i].getHeight() : newHeight;
}for (int i = 0; i < size; i++) { ... }
setWidth(newWidth);
setHeight(newHeight);
for (int i = 0; i < size; i++)
{
if (expandDirection == LEFT)
{
menuElements[i].setXY(getWidth() - menuElements[i].getWidth(), 0);
}if (expandDirection == LEFT) { ... }
else
{
menuElements[i].setXY(0, 0);
}else { ... }
}for (int i = 0; i < size; i++) { ... }
}{ ... }
void CollapsibleMenu::buttonPressedHandler(const AbstractButton& button)
{
if (currentAnimationState != NO_ANIMATION)
{
return;
}if (currentAnimationState != NO_ANIMATION) { ... }
if (isExpanded)
{
if (selectedElementIndex > 0)
{
remove(menuElements[selectedElementIndex]);
insert(&menuElements[selectedElementIndex - 1], menuElements[selectedElementIndex]);
}if (selectedElementIndex > 0) { ... }
uint8_t oldSelectedElementIndex = selectedElementIndex;
for (int i = 0; i < size; i++)
{
if (&button == &menuElements[i])
{
selectedElementIndex = i;
break;
}if (&button == &menuElements[i]) { ... }
}for (int i = 0; i < size; i++) { ... }
remove(menuElements[selectedElementIndex]);
add(menuElements[selectedElementIndex]);
int duration = 20;
int delayCounter = 0;
for (int i = 0; i < size; i++)
{
if (i != oldSelectedElementIndex)
{
int endPosition = (expandDirection == LEFT) ? getWidth() - menuElements[i].getWidth() : 0;
menuElements[i].setMoveAnimationDelay(2 * delayCounter++);
menuElements[i].startMoveAnimation(endPosition, menuElements[i].getY(), duration, EasingEquations::cubicEaseOut);
}if (i != oldSelectedElementIndex) { ... }
}for (int i = 0; i < size; i++) { ... }
currentAnimationState = ANIMATE_TO_COLLAPSED;
if (timeout > 0)
{
Application::getInstance()->unregisterTimerWidget(this);
}if (timeout > 0) { ... }
}if (isExpanded) { ... }
else
{
int duration = 20;
int delayCounter = 0;
int posX = (expandDirection == LEFT) ? getWidth() - menuElements[selectedElementIndex].getWidth() : menuElements[selectedElementIndex].getWidth() + elementSpace;
for (int i = 0; i < size; i++)
{
if (i != selectedElementIndex)
{
if (expandDirection == LEFT)
{
posX -= menuElements[i].getWidth() + elementSpace;
}if (expandDirection == LEFT) { ... }
menuElements[i].setMoveAnimationDelay(2 * delayCounter++);
menuElements[i].startMoveAnimation(posX, menuElements[i].getY(), duration, EasingEquations::cubicEaseOut);
if (expandDirection == RIGHT)
{
posX += menuElements[i].getWidth() + elementSpace;
}if (expandDirection == RIGHT) { ... }
}if (i != selectedElementIndex) { ... }
}for (int i = 0; i < size; i++) { ... }
currentAnimationState = ANIMATE_TO_EXPANDED;
if (timeout > 0)
{
Application::getInstance()->registerTimerWidget(this);
timeoutCounter = 0;
}if (timeout > 0) { ... }
}else { ... }
}{ ... }
void CollapsibleMenu::fadeIn(int duration)
{
for (int i = 0; i < size; i++)
{
menuElements[i].setVisible(true);
}for (int i = 0; i < size; i++) { ... }
if (isExpanded)
{
for (int i = 0; i < size; i++)
{
menuElements[i].setFadeAnimationDelay(0);
menuElements[i].startFadeAnimation(255, duration);
}for (int i = 0; i < size; i++) { ... }
}if (isExpanded) { ... }
else
{
for (int i = 0; i < size; i++)
{
if (i == selectedElementIndex)
{
menuElements[i].setFadeAnimationDelay(0);
menuElements[i].startFadeAnimation(255, duration);
}if (i == selectedElementIndex) { ... }
else
{
menuElements[i].setFadeAnimationDelay(duration);
menuElements[i].startFadeAnimation(255, 1);
}else { ... }
}for (int i = 0; i < size; i++) { ... }
}else { ... }
currentAnimationState = FADE_IN;
}{ ... }
void CollapsibleMenu::fadeOut(int duration)
{
for (int i = 0; i < size; i++)
{
menuElements[i].setVisible(false);
menuElements[i].invalidate();
}for (int i = 0; i < size; i++) { ... }
fadedOut = true;
/* ... */
}{ ... }
bool CollapsibleMenu::isFadedOut()
{
return fadedOut;
}{ ... }
void CollapsibleMenu::menuElementMoveAnimationEndedHandler(const MoveAnimator<Button>& element)
{
if (currentAnimationState == ANIMATE_TO_COLLAPSED)
{
currentAnimationState = NO_ANIMATION;
isExpanded = false;
}if (currentAnimationState == ANIMATE_TO_COLLAPSED) { ... }
else if (currentAnimationState == ANIMATE_TO_EXPANDED)
{
currentAnimationState = NO_ANIMATION;
isExpanded = true;
}else if (currentAnimationState == ANIMATE_TO_EXPANDED) { ... }
else
{
return;
}else { ... }
if (stateChangedAction && stateChangedAction->isValid())
{
stateChangedAction->execute(*this, isExpanded);
}if (stateChangedAction && stateChangedAction->isValid()) { ... }
}{ ... }
void CollapsibleMenu::menuElementFadeAnimationEndedHandler(const FadeAnimator<MoveAnimator<Button> >& element)
{
if (anyFadeAnimationRunning())
{
return;
}if (anyFadeAnimationRunning()) { ... }
if (currentAnimationState == FADE_IN)
{
currentAnimationState = NO_ANIMATION;
fadedOut = false;
}if (currentAnimationState == FADE_IN) { ... }
else if (currentAnimationState == FADE_OUT)
{
currentAnimationState = NO_ANIMATION;
fadedOut = true;
for (int i = 0; i < size; i++)
{
menuElements[i].setVisible(false);
menuElements[i].invalidate();
}for (int i = 0; i < size; i++) { ... }
}else if (currentAnimationState == FADE_OUT) { ... }
else if (currentAnimationState == FADE_IN_AND_EXPAND)
{
currentAnimationState = NO_ANIMATION;
fadedOut = false;
expandMenu();
}else if (currentAnimationState == FADE_IN_AND_EXPAND) { ... }
}{ ... }
void CollapsibleMenu::collapseMenu()
{
if (isExpanded)
{
buttonPressedHandler(menuElements[selectedElementIndex]);
}if (isExpanded) { ... }
}{ ... }
void CollapsibleMenu::expandMenu()
{
if (!isExpanded)
{
buttonPressedHandler(menuElements[selectedElementIndex]);
}if (!isExpanded) { ... }
}{ ... }
void CollapsibleMenu::setTimeout(int newTimeout)
{
timeout = newTimeout;
}{ ... }
void CollapsibleMenu::fadeInAndExpand(int duration)
{
fadeIn(duration);
currentAnimationState = FADE_IN_AND_EXPAND;
}{ ... }
bool CollapsibleMenu::anyFadeAnimationRunning()
{
for (int i = 0; i < size; i++)
{
if (menuElements[i].isRunning())
{
return true;
}if (menuElements[i].isRunning()) { ... }
}for (int i = 0; i < size; i++) { ... }
return false;
}{ ... }
uint8_t CollapsibleMenu::getSelectedElementIndex()
{
return selectedElementIndex;
}{ ... }
void CollapsibleMenu::handleTickEvent()
{
timeoutCounter++;
if (timeoutCounter >= timeout)
{
collapseMenu();
}if (timeoutCounter >= timeout) { ... }
}{ ... }