forked from lovyan03/M5DropMenuSample
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MenuContainer.h
129 lines (120 loc) · 4 KB
/
MenuContainer.h
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#ifndef _MenuContainer_H_
#define _MenuContainer_H_
#include "MenuItem.h"
class MenuContainer : public MenuItem {
private:
Rect _cursorRect;
bool _moving = true;
bool _force = true;
void ScrollSubitemArea(MenuItem* mi) {
int scroll = 0;
for (uint16_t i = 0; i != mi->subItems.size(); ++i) {
if (mi->subItems[i]->destRect.h * 2 + mi->subItems[i]->destRect.y > TFT_WIDTH) {
scroll = mi->subItems[i]->destRect.h * 2 + mi->subItems[i]->destRect.y - TFT_WIDTH;
}
}
if (scroll > 0) {
DestRectYScroll(-scroll);
}
}
public:
MenuContainer() : MenuItem() {};
MenuContainer(const String& t, const std::vector<MenuItem*> &sub)
: MenuItem(t, sub) {};
void begin() {
selectedItem = subItems[0];
for (uint16_t i = 0; i != subItems.size(); ++i) {
subItems[i]->visible = true;
}
destRect.w = 0; // root item hidden
destRect.h = itemHeight/2;
UpdateDestRect();
}
void moveUp() {
_moving = true;
if (selectedItem->parentItem != this) {
selectedItem->OnExit();
selectedItem = selectedItem->parentItem;
for (uint16_t i = 0; i != selectedItem->subItems.size(); ++i) {
selectedItem->subItems[i]->Hide();
}
UpdateDestRect();
ScrollSubitemArea(selectedItem->parentItem);
}
}
void moveNext() {
_moving = true;
MenuItem *parent = selectedItem->parentItem;
for (uint16_t i = 0; i != parent->subItems.size(); ++i) {
if (parent->subItems[i] != selectedItem) continue;
selectedItem = parent->subItems[(i+1) % parent->subItems.size()];
break;
}
if (selectedItem->destRect.h * 2 + selectedItem->destRect.y > TFT_WIDTH) {
DestRectYScroll(-(selectedItem->destRect.h * 2 + selectedItem->destRect.y - TFT_WIDTH));
}
}
void movePrev() {
_moving = true;
MenuItem *parent = selectedItem->parentItem;
for (uint16_t i = 0; i != parent->subItems.size(); ++i) {
if (parent->subItems[i] != selectedItem) continue;
selectedItem = parent->subItems[(i > 0) ? i - 1 : parent->subItems.size() - 1];
break;
}
if (selectedItem->destRect.h * 2 + selectedItem->destRect.y > TFT_WIDTH) {
DestRectYScroll(-(selectedItem->destRect.h * 2 + selectedItem->destRect.y - TFT_WIDTH));
}
}
void selectItem() {
selectedItem->OnEnter();
if (!selectedItem->subItems.empty())
{ // サブアイテムを展開
MenuItem* mi = selectedItem;
selectedItem = selectedItem->subItems[0];
_moving = true;
// _force = true;
UpdateDestRect();
ScrollSubitemArea(mi);
} else {
MenuItem* mi = selectedItem;
while (mi && mi != this && !mi->callback) {
mi = mi->parentItem;
}
if (mi->callback) {
mi->callback(selectedItem);
_force = true;
}
}
}
bool loop() {
if (_moving || _force) {
if (selectedItem->destRect.y < itemHeight/2) {
DestRectYScroll(-selectedItem->destRect.y + itemHeight );
}
_moving = Move();
if (!_cursorRect.equal(selectedItem->destRect)) { // カーソル移動
const Rect& c = _cursorRect;
Rect r = c.mixRect(selectedItem->destRect);
if (c.y < r.y ) M5.Lcd.fillRect( c.x , c.y , c.w, r.y - c.y , backgroundColor);
if (c.y+c.h > r.y+r.h) M5.Lcd.fillRect( c.x , r.y+r.h, c.w, (c.y+c.h)-(r.y+r.h), backgroundColor);
if (c.x < r.x ) M5.Lcd.fillRect( c.x , c.y , r.x-c.x ,c.h , backgroundColor);
if (c.x+c.w > r.x+r.w) M5.Lcd.fillRect( r.x+r.w, c.y , (c.x+c.w)-(r.x+r.w),c.h , backgroundColor);
Draw(_force, selectedItem, &_cursorRect);
_cursorRect = r;
_moving = true;
M5.Lcd.fillRect( _cursorRect.x+1, _cursorRect.y+1, _cursorRect.w-2, _cursorRect.h-2, cursorColor);
if (destRect.h > 0) {
selectedItem->DrawTitle();
selectedItem->OnAfterDraw();
}
} else {
Draw(_force, selectedItem);
}
_force = false;
return true;
}
return false;
}
};
#endif