add manual controls menu, remove demu screens
This commit is contained in:
+1
-3
@@ -5,12 +5,10 @@ set(COMPONENT_SRCS
|
||||
"analog.c"
|
||||
"liquid/liquid.c"
|
||||
"scenes/scene_root.c"
|
||||
"scenes/scene_car.c"
|
||||
"scenes/scene_demo.c"
|
||||
"scenes/scene_bootanim.c"
|
||||
"scenes/scene_menu.c"
|
||||
"scenes/scene_number.c"
|
||||
"scenes/scene_test_menu.c"
|
||||
"scenes/scene_manual_menu.c"
|
||||
"graphics/nokia.c"
|
||||
"graphics/utf8.c"
|
||||
"graphics/font.c"
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#ifndef REFLOWER_ANALOG_H
|
||||
#define REFLOWER_ANALOG_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ANALOG_SAMPLE_TIME_MS 1000
|
||||
|
||||
#define REG_HISTORY_LEN 241
|
||||
|
||||
+19
-9
@@ -242,27 +242,37 @@ void LCD_setStrEx(const char *dString, int x, int y, enum Color color, struct Te
|
||||
int spacingy = style.spacing_y;
|
||||
|
||||
struct Utf8Char uchar;
|
||||
int limit = style.max_chars;
|
||||
int limit = style.limit;
|
||||
int skip = style.skip;
|
||||
bool wrap;
|
||||
while ((uchar = Utf8Iterator_Next(&iter)).uint) {
|
||||
LCD_setCharEx(uchar, x, y, color, style);
|
||||
if (skip > 0) {
|
||||
skip -= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
wrap = uchar.bytes[0] == '\n';
|
||||
|
||||
if (!wrap) LCD_setCharEx(uchar, x, y, color, style);
|
||||
|
||||
if (limit > 0) {
|
||||
limit -= 1;
|
||||
if (limit == 0) return;
|
||||
}
|
||||
|
||||
x += charw;
|
||||
|
||||
if (style.bg) {
|
||||
for (int i = y; i < y + charh; i++) {
|
||||
for (int j = x; j < x + spacingx; j++) {
|
||||
LCD_setPixel(j, i, !color);
|
||||
if (!wrap) {
|
||||
x += charw;
|
||||
if (style.bg) {
|
||||
for (int i = y; i < y + charh; i++) {
|
||||
for (int j = x; j < x + spacingx; j++) {
|
||||
LCD_setPixel(j, i, !color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x += spacingx;
|
||||
if (x > (LCD_WIDTH - charw)) {
|
||||
if (wrap || x > (LCD_WIDTH - charw)) {
|
||||
if (style.nowrap) break;
|
||||
if (style.wrap_to_0) {
|
||||
x = 0;
|
||||
|
||||
@@ -51,9 +51,10 @@ enum TextSize {
|
||||
};
|
||||
|
||||
struct TextStyle {
|
||||
bool bg; //!< Fill the characters background with the opposite color
|
||||
bool bg; //!< Fill the characters background with the opposite color
|
||||
enum TextSize size; //!< Character size
|
||||
int max_chars; //!< Number of characters to print from the string, if > 0
|
||||
int limit; //!< Number of characters to print from the string, if > 0
|
||||
int skip; //!< Characters to skip before printing
|
||||
int spacing_x; //!< Additional X spacing
|
||||
int spacing_y; //!< Additional Y spacing
|
||||
bool nowrap; //!< Stop painting when the right edge of the screen is reached
|
||||
|
||||
@@ -21,6 +21,17 @@ const struct Utf8Char EMPTY_CHAR = (struct Utf8Char) {.uint = 0};
|
||||
// U+40000 - U+FFFFF F1 - F3 80 - BF 80 - BF 80 - BF
|
||||
// U+100000 - U+10FFFF F4 80 - *8F 80 - BF 80 - BF
|
||||
|
||||
size_t utf8_strlen(const char *text)
|
||||
{
|
||||
// TODO optimize
|
||||
struct Utf8Iterator iter;
|
||||
Utf8Iterator_Init(&iter, text);
|
||||
size_t num = 0;
|
||||
while ((Utf8Iterator_Next(&iter)).uint) {
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a received character
|
||||
|
||||
@@ -63,6 +63,8 @@ static inline void Utf8Iterator_Init(struct Utf8Iterator *self, const char *sour
|
||||
self->source = source;
|
||||
}
|
||||
|
||||
size_t utf8_strlen(const char *text);
|
||||
|
||||
/**
|
||||
* Get the next character from the iterator; Returns empty character if there are no more characters to parse.
|
||||
*
|
||||
|
||||
+1
-18
@@ -8,10 +8,8 @@
|
||||
#include "drawing.h"
|
||||
|
||||
static void gui_thread(void *arg);
|
||||
static void gui_tick(TimerHandle_t xTimer);
|
||||
|
||||
TaskHandle_t hGuiThread = NULL;
|
||||
static TimerHandle_t hTicker = NULL;
|
||||
|
||||
void gui_init() {
|
||||
printf("GUI init\n");
|
||||
@@ -20,20 +18,6 @@ void gui_init() {
|
||||
|
||||
int rv = xTaskCreate(gui_thread, "gui", 4096, NULL, 6, &hGuiThread);
|
||||
assert (rv == pdPASS);
|
||||
|
||||
hTicker = xTimerCreate(
|
||||
"gui_tick", /* name */
|
||||
pdMS_TO_TICKS(10), /* period/time */
|
||||
pdTRUE, /* auto reload */
|
||||
(void*)0, /* timer ID */
|
||||
gui_tick); /* callback */
|
||||
assert(hTicker != NULL);
|
||||
|
||||
xTimerStart(hTicker, portMAX_DELAY);
|
||||
}
|
||||
|
||||
static void gui_tick(TimerHandle_t xTimer) {
|
||||
xTaskNotify(hGuiThread, 0b10000, eSetBits);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,8 +43,7 @@ static void __attribute__((noreturn)) gui_thread(void *arg) {
|
||||
xTaskNotifyWait(0, ULONG_MAX, &value, pdMS_TO_TICKS(10));
|
||||
uint32_t time = xTaskGetTickCount();
|
||||
|
||||
if (value & 0b10000) {
|
||||
// TICK
|
||||
if (time - last_time >= pdMS_TO_TICKS(2)) {
|
||||
want_repaint |= Liquid_handleTick(liquid, time - last_time);
|
||||
last_time = time;
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
#include <malloc.h>
|
||||
#include <inttypes.h>
|
||||
#include "graphics/nokia.h"
|
||||
#include "graphics/drawing.h"
|
||||
#include "scenes.h"
|
||||
#include "liquid.h"
|
||||
|
||||
struct CarScene {
|
||||
struct Scene base;
|
||||
int32_t pos;
|
||||
};
|
||||
|
||||
static struct SceneEvent onInput(struct CarScene *self, struct InputEvent event) {
|
||||
switch (event.kind) {
|
||||
case InputEventKind_Wheel:
|
||||
self->pos += event.wheel.delta;
|
||||
if (self->pos < 0) self->pos = 0;
|
||||
if (self->pos > LCD_WIDTH-21) self->pos = LCD_WIDTH-21;
|
||||
return SceneEvent_Repaint();
|
||||
|
||||
case InputEventKind_Button:
|
||||
if (event.button.state) {
|
||||
return SceneEvent_Close(0, NULL);
|
||||
}
|
||||
// fall through
|
||||
default:
|
||||
return SceneEvent_None();
|
||||
}
|
||||
}
|
||||
|
||||
static void paint(struct CarScene *self)
|
||||
{
|
||||
LCD_clearDisplay(0);
|
||||
LCD_setRect(self->pos, LCD_HEIGHT/2-10, self->pos+20,LCD_HEIGHT/2+10,0,1);
|
||||
LCD_updateDisplay();
|
||||
}
|
||||
|
||||
struct Scene *NewScene_Car(void) {
|
||||
struct CarScene *scene = calloc(1, sizeof(struct CarScene));
|
||||
if (!scene) return NULL;
|
||||
|
||||
scene->base.onInput = (Scene_onInput_t) onInput;
|
||||
scene->base.paint = (Scene_paint_t) paint;
|
||||
return (struct Scene *) scene;
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <graphics/bitmaps.h>
|
||||
|
||||
#include "scenes.h"
|
||||
#include "liquid.h"
|
||||
#include "analog.h"
|
||||
#include "graphics/nokia.h"
|
||||
#include "graphics/drawing.h"
|
||||
|
||||
/**
|
||||
* The struct is allocated bigger than 'Scene' to accommodate private fields.
|
||||
* Since the base struct is located at the beginning, it can be cast and passed around as Scene.
|
||||
*/
|
||||
struct DemoScene {
|
||||
struct Scene base;
|
||||
int32_t pos;
|
||||
uint32_t timer_phase;
|
||||
uint32_t timer_prescale;
|
||||
};
|
||||
|
||||
static struct SceneEvent onInput(struct DemoScene *self, struct InputEvent event) {
|
||||
switch (event.kind) {
|
||||
case InputEventKind_Wheel:
|
||||
self->pos += event.wheel.delta;
|
||||
break;
|
||||
|
||||
case InputEventKind_Button:
|
||||
if (event.button.state) {
|
||||
return SceneEvent_OpenChild(NewScene_Car(), 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return SceneEvent_Repaint();
|
||||
}
|
||||
|
||||
static struct SceneEvent onTick(struct DemoScene *self, uint32_t millis) {
|
||||
// top text anim
|
||||
self->timer_prescale += millis;
|
||||
|
||||
if (self->timer_prescale == 1000) {
|
||||
self->timer_prescale = 0;
|
||||
self->timer_phase += 1;
|
||||
self->timer_phase = self->timer_phase & 0b11; // 0..3
|
||||
|
||||
return SceneEvent_Repaint();
|
||||
}
|
||||
|
||||
return SceneEvent_None();
|
||||
}
|
||||
|
||||
static void paint(struct DemoScene *self)
|
||||
{
|
||||
LCD_clearDisplay(0);
|
||||
|
||||
const char *header = "???";
|
||||
switch (self->timer_phase) {
|
||||
case 0:
|
||||
header = "Drink water";
|
||||
break;
|
||||
case 1:
|
||||
header = " Drink water";
|
||||
break;
|
||||
case 2:
|
||||
header = " Drink water";
|
||||
break;
|
||||
case 3:
|
||||
header = " Drink water";
|
||||
break;
|
||||
}
|
||||
|
||||
LCD_setStrEx(header, 3, 1, BLACK, (struct TextStyle) {.size = FONT_BOLD});
|
||||
|
||||
LCD_setRect(0, 12, 83, 31, true, BLACK);
|
||||
char buf[10];
|
||||
// sprintf(buf, "%3d", priv->pos);
|
||||
// LCD_setStr(buf, 2, 15, 0);
|
||||
sprintf(buf, "🌡%.0f°C", analog_read());
|
||||
LCD_setStrEx(buf, 2, 14, WHITE, (struct TextStyle) {.size = FONT_DOUBLE});
|
||||
|
||||
LCD_setStr("×↑↓←→⏰⌛☸⏎🌡°🔙▶◀", 2, 33, BLACK);
|
||||
}
|
||||
|
||||
struct Scene *NewScene_Demo(void) {
|
||||
struct DemoScene *scene = calloc(1, sizeof(struct DemoScene));
|
||||
|
||||
scene->base.onInput = (Scene_onInput_t) onInput;
|
||||
scene->base.paint = (Scene_paint_t) paint;
|
||||
scene->base.onTick = (Scene_onTick_t) onTick;
|
||||
scene->base.onInput = (Scene_onInput_t) onInput;
|
||||
return (struct Scene *) scene;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <analog.h>
|
||||
#include <firehazard.h>
|
||||
|
||||
#include "liquid.h"
|
||||
#include "graphics/drawing.h"
|
||||
#include "graphics/display_spec.h"
|
||||
|
||||
#include "scenes.h"
|
||||
#include "scene_menu.h"
|
||||
|
||||
struct Priv {
|
||||
Scene_paint_t basePaint;
|
||||
};
|
||||
|
||||
static struct SceneEvent onSelect(struct MenuScene *self) {
|
||||
if (self->selected == 0) {
|
||||
struct NumberSceneOpts *opts = calloc(1, sizeof(struct NumberSceneOpts));
|
||||
strcpy(opts->unit, "°C");
|
||||
strcpy(opts->label, "Setpoint");
|
||||
opts->value = (int) roundf(fire_get_setpoint(false));
|
||||
opts->min = 0;
|
||||
opts->max = 350;
|
||||
return SceneEvent_OpenChild(NewScene_Number(opts), 0);
|
||||
}
|
||||
|
||||
if (self->selected == 1) {
|
||||
fire_enable(!fire_enabled());
|
||||
return SceneEvent_Repaint();
|
||||
}
|
||||
|
||||
return SceneEvent_None();
|
||||
}
|
||||
|
||||
static void priv_deinit(struct MenuScene *self)
|
||||
{
|
||||
free(self->extra);
|
||||
self->extra = NULL;
|
||||
}
|
||||
|
||||
static struct SceneEvent onChildReturn(struct MenuScene *self, uint32_t tag, int32_t status, void *data)
|
||||
{
|
||||
if (tag == 0) {
|
||||
fire_setlevel((float) status);
|
||||
}
|
||||
|
||||
return SceneEvent_Repaint();
|
||||
}
|
||||
|
||||
#define XLINE 38
|
||||
|
||||
void print_labels(struct MenuItem *items) {
|
||||
snprintf(items[0].label, MENUITEM_LABEL_LEN, "▶%.0f°C", fire_get_setpoint(false));
|
||||
if (fire_enabled()) {
|
||||
strncpy(items[1].label, "▶STOP", MENUITEM_LABEL_LEN);
|
||||
} else {
|
||||
strncpy(items[1].label, "▶START", MENUITEM_LABEL_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
static void paint(struct MenuScene *self)
|
||||
{
|
||||
struct Priv *priv = self->extra;
|
||||
|
||||
print_labels(self->items);
|
||||
|
||||
LCD_clearDisplay(0);
|
||||
|
||||
LCD_setLine(XLINE-1, 0, XLINE-1, LCD_HEIGHT, BLACK);
|
||||
|
||||
char buf[10];
|
||||
sprintf(buf, "%.0f", analog_read());
|
||||
// TODO centering
|
||||
LCD_setStrEx(buf, 0, 0, BLACK, (struct TextStyle) {.size = FONT_DOUBLE});
|
||||
LCD_setStrEx("°C", 0, 17, BLACK, (struct TextStyle) {.size = FONT_BOLD});
|
||||
|
||||
if (fire_enabled()) {
|
||||
strcpy(buf, "RUN");
|
||||
} else {
|
||||
strcpy(buf, "Off");
|
||||
}
|
||||
LCD_setStrEx(buf, 0, 30, BLACK, (struct TextStyle) {.size = FONT_BOLD});
|
||||
|
||||
priv->basePaint((struct Scene *) self);
|
||||
}
|
||||
|
||||
struct Scene *NewScene_MenuTest() {
|
||||
struct MenuItem *items = calloc(2, sizeof(struct MenuItem));
|
||||
|
||||
print_labels(items);
|
||||
|
||||
struct MenuScene * scene = NewScene_Menu(items, 2);
|
||||
scene->onSelect = onSelect;
|
||||
|
||||
scene->x = XLINE;
|
||||
scene->ncols = 8;
|
||||
|
||||
// private data added by the subclass
|
||||
struct Priv *priv = calloc(1, sizeof(struct Priv));
|
||||
priv->basePaint = scene->base.paint;
|
||||
scene->base.paint = (Scene_paint_t) paint;
|
||||
scene->extra = priv;
|
||||
scene->extra_deinit = (Scene_deinit_t) priv_deinit;
|
||||
|
||||
// add a child return handler (base does not use this)
|
||||
scene->base.onChildReturn = (Scene_onChildReturn_t) onChildReturn;
|
||||
|
||||
return (struct Scene *) scene;
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
#include <graphics/bitmaps.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <liquid/input_event.h>
|
||||
|
||||
#include "liquid.h"
|
||||
@@ -23,17 +25,29 @@ static void paint(struct MenuScene *self)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HSCROLL_START_MS 750
|
||||
#define HSCROLL_MS 250
|
||||
|
||||
static void paint(struct MenuScene *self)
|
||||
{
|
||||
LCD_clearDisplay(0);
|
||||
LCD_setRect(self->x, self->y, self->x + self->ncols*6, self->y + self->nlines*9, 1, WHITE);
|
||||
|
||||
int row = 0;
|
||||
for (int i = self->scroll_up; i < MIN(self->items_len, self->scroll_up + self->visible_lines); i++, row++) {
|
||||
for (int i = self->scroll_up; i < MIN(self->items_len, self->scroll_up + self->nlines); i++, row++) {
|
||||
bool selected = self->selected==i;
|
||||
if (selected) LCD_setRect(0, row*9, LCD_WIDTH-1, row*9 + 8, 1, 1);
|
||||
LCD_setStrEx(self->items[i].label, 1, row * 9 + 1, !selected, (struct TextStyle) {
|
||||
if (selected) LCD_setRect(self->x, self->y + row*9, self->x + self->ncols*6, self->y + row*9 + 8, 1, 1);
|
||||
size_t shift = 0;
|
||||
if (selected) {
|
||||
size_t len = utf8_strlen(self->items[i].label);
|
||||
shift = self->hscroll;
|
||||
if (shift > len - self->ncols) {
|
||||
shift = len - self->ncols;
|
||||
}
|
||||
}
|
||||
LCD_setStrEx(self->items[i].label, self->x + 1, self->y + row * 9 + 1, !selected, (struct TextStyle) {
|
||||
.bg = selected,
|
||||
.max_chars = 13,
|
||||
.nowrap = 1,
|
||||
.skip = shift,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -54,10 +68,15 @@ static struct SceneEvent onInput(struct MenuScene *self, struct InputEvent event
|
||||
self->scroll_up--;
|
||||
}
|
||||
|
||||
while (self->selected - self->scroll_up >= (self->visible_lines - 1) && self->scroll_up < self->items_len - self->visible_lines) {
|
||||
while (self->selected - self->scroll_up >= (self->nlines - 1) &&
|
||||
self->scroll_up < self->items_len - self->nlines) {
|
||||
self->scroll_up++;
|
||||
}
|
||||
|
||||
// reset hscroll
|
||||
self->hscroll_cnt = 0;
|
||||
self->hscroll = 0;
|
||||
|
||||
return SceneEvent_Repaint();
|
||||
|
||||
case InputEventKind_Button:
|
||||
@@ -73,6 +92,35 @@ static struct SceneEvent onInput(struct MenuScene *self, struct InputEvent event
|
||||
}
|
||||
}
|
||||
|
||||
static struct SceneEvent onTick(struct MenuScene *self, uint32_t millis) {
|
||||
size_t len = utf8_strlen(self->items[self->selected].label);
|
||||
self->hscroll_cnt += millis;
|
||||
|
||||
if (len > self->ncols) {
|
||||
size_t limit = (self->hscroll == 0 ? HSCROLL_START_MS : HSCROLL_MS);
|
||||
|
||||
if (self->hscroll_cnt >= limit) {
|
||||
self->hscroll_cnt -= limit;
|
||||
self->hscroll++;
|
||||
|
||||
if (self->hscroll > len - self->ncols + 2/* trailing delay */) {
|
||||
self->hscroll = 0;
|
||||
}
|
||||
|
||||
return SceneEvent_Repaint();
|
||||
}
|
||||
} else {
|
||||
self->hscroll = 0;
|
||||
|
||||
// ensure periodic repaint (for parent)
|
||||
if (self->hscroll_cnt > 20) {
|
||||
return SceneEvent_Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
return SceneEvent_None();
|
||||
}
|
||||
|
||||
static void deinit(struct MenuScene *self)
|
||||
{
|
||||
free(self->items);
|
||||
@@ -90,14 +138,19 @@ struct MenuScene *NewScene_Menu(struct MenuItem *items, size_t items_len) {
|
||||
scene->base.paint = (Scene_paint_t) paint;
|
||||
scene->base.onInput = (Scene_onInput_t) onInput;
|
||||
scene->base.deinit = (Scene_deinit_t) deinit;
|
||||
scene->base.onTick = (Scene_onTick_t) onTick;
|
||||
|
||||
// onChildReturn is free to set by subclass
|
||||
|
||||
// TODO long selected label scrolling on tick
|
||||
|
||||
scene->visible_lines = 5;
|
||||
scene->items = items;
|
||||
scene->items_len = items_len;
|
||||
|
||||
scene->nlines = 5;
|
||||
scene->ncols = 14;
|
||||
scene->x = 0;
|
||||
scene->y = 0;
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
@@ -40,12 +40,22 @@ struct MenuScene {
|
||||
struct MenuItem *items;
|
||||
// items count
|
||||
size_t items_len;
|
||||
// number of visible characters in a line at a time
|
||||
uint8_t ncols;
|
||||
// Vertical scroll offset (how many steps is the topmost item moved above the screen)
|
||||
int32_t scroll_up;
|
||||
// Start X
|
||||
int x;
|
||||
// Start Y
|
||||
int y;
|
||||
// Selected item number
|
||||
int32_t selected;
|
||||
// Horizontal scroll count
|
||||
int32_t hscroll;
|
||||
// Horizontal scroll timer
|
||||
int32_t hscroll_cnt;
|
||||
// Number of lines visible at a time
|
||||
uint8_t visible_lines;
|
||||
uint8_t nlines;
|
||||
// selection handler
|
||||
MenuScene_onSelect_t onSelect;
|
||||
// Extra field for the subclass's private use.
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
#include <malloc.h>
|
||||
#include <graphics/bitmaps.h>
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "liquid.h"
|
||||
#include "graphics/drawing.h"
|
||||
|
||||
#include "scenes.h"
|
||||
#include "scene_menu.h"
|
||||
|
||||
struct Priv {
|
||||
int32_t number;
|
||||
};
|
||||
|
||||
static struct SceneEvent onSelect(struct MenuScene *self) {
|
||||
struct Priv *priv = self->extra;
|
||||
|
||||
if (self->selected == 0) {
|
||||
return SceneEvent_Close(0, NULL);
|
||||
}
|
||||
|
||||
if (self->selected == 8) {
|
||||
return SceneEvent_OpenChild(NewScene_Car(), 0);
|
||||
}
|
||||
if (self->selected == 9) {
|
||||
return SceneEvent_OpenChild(NewScene_Demo(), 0);
|
||||
}
|
||||
if (self->selected == 2) {
|
||||
struct NumberSceneOpts *opts = calloc(1, sizeof(struct NumberSceneOpts));
|
||||
strcpy(opts->unit, "°C");
|
||||
strcpy(opts->label, "Setpoint");
|
||||
opts->value = priv->number;
|
||||
opts->min = 0;
|
||||
opts->max = 350;
|
||||
return SceneEvent_OpenChild(NewScene_Number(opts), 99);
|
||||
}
|
||||
if (self->selected == 5) {
|
||||
self->items[5].tag++;
|
||||
snprintf(self->items[5].label, MENUITEM_LABEL_LEN, "Clicked %dx", self->items[5].tag);
|
||||
return SceneEvent_Repaint();
|
||||
}
|
||||
|
||||
return SceneEvent_None();
|
||||
}
|
||||
|
||||
static void priv_deinit(struct MenuScene *self)
|
||||
{
|
||||
free(self->extra);
|
||||
self->extra = NULL;
|
||||
}
|
||||
|
||||
static struct SceneEvent onChildReturn(struct MenuScene *self, uint32_t tag, int32_t status, void *data)
|
||||
{
|
||||
struct Priv *priv = self->extra;
|
||||
if (tag == 99) {
|
||||
priv->number = status;
|
||||
snprintf(self->items[2].label, MENUITEM_LABEL_LEN, "Set=%d°C", priv->number);
|
||||
}
|
||||
|
||||
// this should be unreachable
|
||||
return SceneEvent_None();
|
||||
}
|
||||
|
||||
struct Scene *NewScene_MenuTest() {
|
||||
struct MenuItem *items = calloc(10, sizeof(struct MenuItem));
|
||||
|
||||
strncpy(items[0].label, "🔙Back", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[1].label, "▶#1", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[2].label, "Set=0°C", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[3].label, "▶#3", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[4].label, "▶#4", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[5].label, "Clicked 0x", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[6].label, "▶#6", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[7].label, "▶#7", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[8].label, "Car", MENUITEM_LABEL_LEN);
|
||||
strncpy(items[9].label, "Demo Scene", MENUITEM_LABEL_LEN);
|
||||
|
||||
struct MenuScene * scene = NewScene_Menu(items, 10);
|
||||
scene->onSelect = onSelect;
|
||||
|
||||
// private data added by the subclass
|
||||
struct Priv *priv = calloc(1, sizeof(struct Priv));
|
||||
priv->number = 0;
|
||||
scene->extra = priv;
|
||||
scene->extra_deinit = (Scene_deinit_t) priv_deinit;
|
||||
|
||||
// add a child return handler (base does not use this)
|
||||
scene->base.onChildReturn = (Scene_onChildReturn_t) onChildReturn;
|
||||
|
||||
return (struct Scene *) scene;
|
||||
}
|
||||
@@ -11,8 +11,6 @@
|
||||
|
||||
struct Scene *NewScene_Root(void);
|
||||
struct Scene *NewScene_Boot(void);
|
||||
struct Scene *NewScene_Demo(void);
|
||||
struct Scene *NewScene_Car(void);
|
||||
struct Scene *NewScene_MenuTest(void);
|
||||
|
||||
#include "scene_menu.h"
|
||||
|
||||
Reference in New Issue
Block a user