Skip to content

Commit 6e844ce

Browse files
authored
Merge pull request #1 from JF002/develop
Version 0.2.0
2 parents 1a2ef10 + 25958c3 commit 6e844ce

21 files changed

Lines changed: 1005 additions & 76 deletions

README.md

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,39 @@
11
# cfGUI
22
A simple GUI library for M5Stack (ESP32)
33

4-
This library is intended to run on M5Stack development board (http://www.m5stack.com/). However, it should be easy to port it to any other board.
4+
This library is intended to run on M5Stack development board (http://www.m5stack.com/), base on ESP32.
5+
6+
However, it should be easy to port it to any other board with an LCD screen and 3 physical buttons.
7+
58
It's composed of a simple hierarchy of graphical widget that can be drawn on screen.
69
The following widgets have been created so far:
7-
- Screen
10+
- Screen and AppScreen (screen with a top bar and a bottom bar)
811
- Bar
9-
- StatusBar (with uptime, current time and wifi signal)
10-
- Button
11-
- Mosaic of widge
12-
13-
![Example picture of cfGUI running on a M5Stack board](https://mastodon.codingfield.com/media/oXYl3M6SVqcpn2iefrs)
12+
- StatusBar (Bar with uptime, clock and Wifi signal)
13+
- ButtonInfoBar (display the function of the physical button)
14+
- Button, UpDownButton
15+
- Mosaic of widgets
1416

17+
![Example picture of cfGUI running on a M5Stack board](https://mastodon.codingfield.com/system/media_attachments/files/000/207/740/original/dbacf24f45561e5c.jpg)
18+
19+
# How To (Platform.io)
20+
To use this library with your platform.io project, simply clone or download the library into the directory 'lib' of your project.
21+
Then, you just need to include the headers (e.g. #include <Screen.h>) and write some code.
22+
23+
Look at examples if you need some inspiration ;-)
1524

1625
# Todo
17-
- Remove hard-coded values to make the lib more flexible
26+
- <s>Remove hard-coded values to make the lib more flexible</s>
1827
- Add new widgets
1928
- Better 'focus' management
2029

30+
# Changelog
31+
## 0.2.0
32+
- Change default font (looks better)
33+
- New widgets (AppScreen, StatusBar, ButtonInfoBar, UpDownButton)
34+
- Improved mosaic (the size and position of the widget is not hard-coded anymore)
35+
- Global improvements
36+
37+
## 0.1.0
38+
- First version of the library, with basic functionalities
2139

examples/simpleExample/main.cpp

Lines changed: 116 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,58 @@
11
#include <M5Stack.h>
22

3+
#include <NTPClient.h>
34
#include <Screen.h>
4-
#include <Bar.h>
5+
#include <ButtonInfoBar.h>
56
#include <StatusBar.h>
67
#include <Button.h>
78
#include <WidgetMosaic.h>
9+
#include <string>
10+
#include <time.h>
11+
#include <sys/time.h>
12+
#include <AppScreen.h>
13+
#include <UpDownButton.h>
814

915
using namespace Codingfield::UI;
10-
Screen screen(Size(320, 240), BLACK);
16+
AppScreen* screen;
1117
StatusBar* topBar;
12-
Bar* bottomBar;
13-
Codingfield::UI::Button* button0; // M5STack should really use namespaces to avoid name clashes
18+
ButtonInfoBar* bottomBar;
19+
Codingfield::UI::Button* button0;
1420
Codingfield::UI::Button* button1;
15-
Codingfield::UI::Button* button2;
21+
Codingfield::UI::UpDownButton* button2;
1622
Codingfield::UI::Button* button3;
1723
Codingfield::UI::Button* button4;
1824
Codingfield::UI::Button* button5;
1925
WidgetMosaic* mosaic;
2026
Widget* focus;
2127

28+
int32_t editButtonValue = 0;
29+
int32_t editOldButtonValue = 0;
30+
2231
void setup() {
2332
M5.begin();
2433

25-
topBar = new StatusBar(&screen, Point(0,0), 25);
26-
bottomBar = new Bar(&screen, Point(0, screen.GetSize().height-25), 25);
34+
// Instanciate and configure all widgets
35+
topBar = new StatusBar();
36+
bottomBar = new ButtonInfoBar();
37+
mosaic = new WidgetMosaic(3, 2);
38+
screen = new AppScreen(Size(320, 240), BLACK, topBar, bottomBar, mosaic);
2739

28-
mosaic = new WidgetMosaic(&screen, Point(5,30), Size(320, 190));
29-
focus = mosaic;
40+
// Give the focus to the main screen
41+
focus = screen;
3042

3143
button0 = new Codingfield::UI::Button(mosaic);
3244
button0->SetBackgroundColor(BLUE);
3345
button0->SetTextColor(WHITE);
3446
button0->SetText("16C");
47+
button0->SetTitle("Fridge");
3548
button1 = new Codingfield::UI::Button(mosaic);
3649
button1->SetBackgroundColor(ORANGE);
3750
button1->SetTextColor(BLACK);
3851
button1->SetText("50%");
39-
button2 = new Codingfield::UI::Button(mosaic);
52+
button2 = new Codingfield::UI::UpDownButton(mosaic); // Up/Down button
4053
button2->SetBackgroundColor(YELLOW);
4154
button2->SetTextColor(BLACK);
42-
button2->SetText("3h15");
55+
button2->SetText("0");
4356
button3 = new Codingfield::UI::Button(mosaic);
4457
button3->SetBackgroundColor(PURPLE);
4558
button3->SetTextColor(WHITE);
@@ -56,24 +69,80 @@ void setup() {
5669
topBar->SetUptime(0);
5770
topBar->SetWifiStatus(StatusBar::WifiStatuses::No_signal);
5871

59-
screen.Draw();
72+
bottomBar->SetButtonAText("<");
73+
bottomBar->SetButtonBText("SELECT");
74+
bottomBar->SetButtonCText(">");
75+
76+
// Callback called by the mosaic when it changes mode (mosaic/zoom on 1 widget)
77+
// We use it to update the bottom bar.
78+
mosaic->SetZoomOnSelectedCallback([bottomBar](Widget* widget, bool edit) {
79+
if(edit) {
80+
if(widget->IsEditable()){
81+
bottomBar->SetButtonAText("-");
82+
bottomBar->SetButtonBText("APPLY");
83+
bottomBar->SetButtonCText("+");
84+
} else {
85+
bottomBar->SetButtonAText("");
86+
bottomBar->SetButtonBText("BACK");
87+
bottomBar->SetButtonCText("");
88+
}
89+
} else {
90+
bottomBar->SetButtonAText("<");
91+
bottomBar->SetButtonBText("SELECT");
92+
bottomBar->SetButtonCText(">");
93+
}
94+
});
95+
96+
// Configure callback to be called when the user wants to increment the value
97+
// of button2
98+
button2->SetUpCallback([&editButtonValue](UpDownButton* w) {
99+
editButtonValue++;
100+
w->SetText(String(editButtonValue).c_str());
101+
return true;
102+
});
103+
104+
// Configure callback to be called when the user wants to decrement the value
105+
// of button2
106+
button2->SetDownCallback([&editButtonValue](UpDownButton* w) {
107+
editButtonValue--;
108+
w->SetText(String(editButtonValue).c_str());
109+
return true;
110+
});
111+
112+
// Configure callback to be called when the user wants to apply the value
113+
// of button2
114+
button2->SetApplyCallback([&editButtonValue, &editOldButtonValue](UpDownButton* w) {
115+
editOldButtonValue = editButtonValue;
116+
return false;
117+
});
118+
119+
// Configure callback to be called when the user wants to cancel modification
120+
// of the value of button2
121+
button2->SetCancelCallback([&editButtonValue](UpDownButton* w) {
122+
editButtonValue = editOldButtonValue;
123+
w->SetText(String(editButtonValue).c_str());
124+
return true;
125+
});
126+
127+
// Draw the screen and all its children
128+
screen->Draw();
60129
}
61130

62131
uint32_t loopCount = 0;
63132
uint32_t temperature = 10;
64133
uint32_t percent = 0;
65134
std::string state = "BUSY";
66135
int32_t wifiStatusIndex;
67-
int rssi = -100;
68-
int seconds = 0;
69136
std::vector<StatusBar::WifiStatuses> wifiStatus {StatusBar::WifiStatuses::No_signal,
70137
StatusBar::WifiStatuses::Weak,
71138
StatusBar::WifiStatuses::Medium,
72139
StatusBar::WifiStatuses::Full};
73140
int32_t uptimeHours=0;
141+
bool longPush = false;
74142
void loop() {
75143
M5.update();
76144

145+
// Update values displayd on the screen (status bar, buttons,...)
77146
if((loopCount % 50) == 0) {
78147
if(temperature < 100)
79148
temperature++;
@@ -94,43 +163,53 @@ void loop() {
94163
topBar->SetUptime(uptimeHours);
95164

96165
char strftime_buf[64];
97-
if(seconds < 60)
98-
seconds++;
99-
else
100-
seconds = 0;
101-
snprintf(strftime_buf, 64, "%02d:%02d:%02d", 1, 2, seconds);
166+
snprintf(strftime_buf, 64, "%02d:%02d:%02d", 12, 14, 59);
102167
topBar->SetDateTime(strftime_buf);
103-
104-
if(rssi < 0)
105-
rssi++;
106-
else
107-
rssi = -100;
108-
if(rssi >= -55)
109-
topBar->SetWifiStatus(StatusBar::WifiStatuses::Full);
110-
else if(rssi >= -75)
111-
topBar->SetWifiStatus(StatusBar::WifiStatuses::Medium);
112-
else if(rssi >= -85)
113-
topBar->SetWifiStatus(StatusBar::WifiStatuses::Weak);
114-
else
115-
topBar->SetWifiStatus(StatusBar::WifiStatuses::No_signal);
116168
}
117169

118170
if((loopCount % 100) == 0) {
119171
if(state == "BUSY") state = "IDLE";
120172
else state = "BUSY";
121173
button5->SetText(state);
174+
175+
auto rssi =WiFi.RSSI();
176+
if(rssi >= -55) {
177+
topBar->SetWifiStatus(StatusBar::WifiStatuses::Full);
178+
} else if(rssi >= -75) {
179+
topBar->SetWifiStatus(StatusBar::WifiStatuses::Medium);
180+
} else if(rssi >= -85) {
181+
topBar->SetWifiStatus(StatusBar::WifiStatuses::Weak);
182+
} else {
183+
topBar->SetWifiStatus(StatusBar::WifiStatuses::No_signal);
184+
}
122185
}
123186

124-
if(M5.BtnA.wasPressed())
187+
// Notify the widgets that physical buttons are pressed
188+
if(M5.BtnA.wasPressed()) {
125189
focus->OnButtonAPressed();
190+
}
126191

127-
if(M5.BtnB.wasPressed())
128-
focus->OnButtonBPressed();
192+
if(M5.BtnB.pressedFor(1000)) {
193+
if(!longPush) {
194+
focus->OnButtonBLongPush();
195+
longPush = true;
196+
}
197+
}
198+
else if(M5.BtnB.wasReleased()) {
199+
if(!longPush) {
200+
focus->OnButtonBPressed();
201+
}
202+
else {
203+
longPush = false;
204+
}
205+
}
129206

130-
if(M5.BtnC.wasPressed())
207+
if(M5.BtnC.wasPressed()) {
131208
focus->OnButtonCPressed();
209+
}
132210

133-
screen.Draw();
211+
// Redraw the screen
212+
screen->Draw();
134213

135214
loopCount++;
136215
delay(10);

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=cfGUI
2-
version=0.1
2+
version=0.2.0
33
author=Jean-François Milants <jf@codingfield.com>
44
maintainer=Jean-François Milants <jf@codingfield.com>
55
sentence=cfGUI

src/AppScreen.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include "AppScreen.h"
2+
#include <Bar.h>
3+
4+
using namespace Codingfield::UI;
5+
6+
AppScreen::AppScreen(Size size, Color color) : Screen(size, color) {
7+
8+
}
9+
10+
AppScreen::AppScreen(Size size, Color color, Bar* topBar, Bar* bottomBar, Widget* centreWidget) : Screen(size, color), topBar{topBar}, bottomBar{bottomBar}, centreWidget{centreWidget} {
11+
if(topBar != nullptr) {
12+
topBar->SetParent(this);
13+
topBar->SetPosition(Point(0,0));
14+
topBar->SetSize(Size(this->GetSize().width, barHeight));
15+
AddChild(topBar);
16+
}
17+
18+
if(bottomBar != nullptr) {
19+
bottomBar->SetParent(this);
20+
bottomBar->SetPosition(Point(0, this->GetSize().height-barHeight));
21+
bottomBar->SetSize(Size(this->GetSize().width, barHeight));
22+
AddChild(bottomBar);
23+
}
24+
25+
if(centreWidget != nullptr) {
26+
Point centerPosition;
27+
centerPosition.y = position.y + ((topBar != nullptr) ? topBar->GetSize().height : 0) + padding;
28+
centerPosition.x = position.x + padding;
29+
30+
Size centerSize;
31+
centerSize.height = size.height - (((bottomBar != nullptr) ? bottomBar->GetSize().height : 0) + ((topBar != nullptr) ? topBar->GetSize().height : 0) + padding);
32+
centerSize.width = size.width;
33+
34+
centreWidget->SetParent(this);
35+
centreWidget->SetPosition(centerPosition);
36+
centreWidget->SetSize(centerSize);
37+
AddChild(centreWidget);
38+
}
39+
}
40+
41+
void AppScreen::OnButtonAPressed() {
42+
if(centreWidget != nullptr)
43+
centreWidget->OnButtonAPressed();
44+
}
45+
46+
void AppScreen::OnButtonBPressed() {
47+
if(centreWidget != nullptr)
48+
centreWidget->OnButtonBPressed();
49+
}
50+
51+
void AppScreen::OnButtonBLongPush() {
52+
if(centreWidget != nullptr)
53+
centreWidget->OnButtonBLongPush();
54+
}
55+
56+
void AppScreen::OnButtonCPressed() {
57+
if(centreWidget != nullptr)
58+
centreWidget->OnButtonCPressed();
59+
}

src/AppScreen.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
3+
#include <Screen.h>
4+
5+
namespace Codingfield {
6+
namespace UI {
7+
class Bar;
8+
class AppScreen : public Screen {
9+
public:
10+
AppScreen(Size size, Color color);
11+
AppScreen(Size size, Color color, Bar* topBar, Bar* bottomBar, Widget* centreWidget);
12+
13+
virtual void OnButtonAPressed() override;
14+
virtual void OnButtonBPressed() override;
15+
virtual void OnButtonBLongPush() override;
16+
virtual void OnButtonCPressed() override;
17+
18+
private:
19+
Bar* topBar = nullptr;
20+
Bar* bottomBar = nullptr;
21+
Widget* centreWidget = nullptr;
22+
int32_t padding = 5;
23+
int32_t barHeight = 25;
24+
};
25+
}
26+
}

src/Bar.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using namespace Codingfield::UI;
44

55
void Bar::Draw() {
6+
if(IsHidden()) return;
67
if(isUpdated)
78
M5.Lcd.fillRect(position.x, position.y, size.width, size.height, WHITE);
89

src/Bar.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace Codingfield {
66
namespace UI {
77
class Bar : public Widget {
88
public:
9+
Bar() : Widget(nullptr, Point(), Size()) {}
910
Bar(Widget* parent, Point position, int32_t height) : Widget(parent, position, Size(parent->GetSize().width, height)) {}
1011
void Draw() override;
1112
private:

0 commit comments

Comments
 (0)