implement number input
This commit is contained in:
@@ -9,6 +9,7 @@ set(COMPONENT_SRCS
|
||||
"scenes/scene_demo.c"
|
||||
"scenes/scene_bootanim.c"
|
||||
"scenes/scene_menu.c"
|
||||
"scenes/scene_number.c"
|
||||
"scenes/scene_test_menu.c"
|
||||
"graphics/nokia.c"
|
||||
"graphics/utf8.c"
|
||||
|
||||
@@ -56,8 +56,8 @@ static struct SceneEvent handleSceneEvent(struct Liquid *container, struct Scene
|
||||
SLIST_REMOVE_HEAD(&container->stack, next);
|
||||
tag = topmost->scene->tag;
|
||||
|
||||
if (topmost->scene->free) {
|
||||
topmost->scene->free(topmost->scene);
|
||||
if (topmost->scene->deinit) {
|
||||
topmost->scene->deinit(topmost->scene);
|
||||
}
|
||||
free(topmost->scene);
|
||||
free(topmost);
|
||||
|
||||
@@ -56,13 +56,13 @@ typedef struct SceneEvent (*Scene_init_t)(struct Scene *scene);
|
||||
typedef void (*Scene_paint_t)(struct Scene *scene);
|
||||
|
||||
/**
|
||||
* Scene::free fp type.
|
||||
* Scene::deinit fp type.
|
||||
* Release internally allocated resources.
|
||||
* This is called by the GUI engine when the scene is closed.
|
||||
*
|
||||
* @param scene - self
|
||||
*/
|
||||
typedef void (*Scene_free_t)(struct Scene *scene);
|
||||
typedef void (*Scene_deinit_t)(struct Scene *scene);
|
||||
|
||||
/**
|
||||
* Scene instance in the framework
|
||||
@@ -112,7 +112,7 @@ struct Scene {
|
||||
* Release internally allocated resources, if any. Called on close.
|
||||
* Nullable field.
|
||||
*/
|
||||
Scene_free_t free;
|
||||
Scene_deinit_t deinit;
|
||||
};
|
||||
|
||||
#endif //LIQUID_SCENE_TYPE_H
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "scenes.h"
|
||||
#include "liquid.h"
|
||||
#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;
|
||||
|
||||
@@ -55,11 +55,18 @@ static struct SceneEvent onInput(struct MenuScene *self, struct InputEvent event
|
||||
}
|
||||
}
|
||||
|
||||
static void deinit(struct MenuScene *self)
|
||||
{
|
||||
free(self->items);
|
||||
self->items = NULL;
|
||||
}
|
||||
|
||||
struct MenuScene *NewScene_Menu(struct MenuItem *items, size_t items_len) {
|
||||
struct MenuScene *scene = calloc(1, sizeof(struct MenuScene));
|
||||
|
||||
scene->base.paint = (Scene_paint_t) paint;
|
||||
scene->base.onInput = (Scene_onInput_t) onInput;
|
||||
scene->base.deinit = (Scene_deinit_t) deinit;
|
||||
|
||||
scene->items = items;
|
||||
scene->items_len = items_len;
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#ifndef REFLOWER_SCENE_MENU_H
|
||||
#define REFLOWER_SCENE_MENU_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define MENUITEM_LABEL_LEN 30
|
||||
|
||||
struct MenuItem {
|
||||
@@ -30,6 +33,8 @@ struct MenuScene {
|
||||
int32_t selected;
|
||||
// selection handler
|
||||
MenuScene_onSelect_t onSelect;
|
||||
// Extra field for the instance's private use.
|
||||
void *private;
|
||||
};
|
||||
|
||||
struct MenuScene *NewScene_Menu(struct MenuItem *items, size_t items_len);
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "scenes.h"
|
||||
#include "liquid.h"
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include "graphics/nokia.h"
|
||||
#include "graphics/drawing.h"
|
||||
#include "scene_number.h"
|
||||
|
||||
struct NumberScene {
|
||||
struct Scene base;
|
||||
struct NumberSceneOpts *opts;
|
||||
};
|
||||
|
||||
static struct SceneEvent onInput(struct NumberScene *self, struct InputEvent event) {
|
||||
struct NumberSceneOpts *opts = self->opts;
|
||||
switch (event.kind) {
|
||||
case InputEventKind_Wheel:
|
||||
opts->value += event.wheel.delta;
|
||||
|
||||
if (opts->value < opts->min) {
|
||||
opts->value = opts->min;
|
||||
}
|
||||
else if (opts->value > opts->max) {
|
||||
opts->value = opts->max;
|
||||
}
|
||||
|
||||
return SceneEvent_Repaint();
|
||||
|
||||
case InputEventKind_Button:
|
||||
if (event.button.state) {
|
||||
return SceneEvent_Close(opts->value, NULL);
|
||||
}
|
||||
// fall through
|
||||
default:
|
||||
return SceneEvent_None();
|
||||
}
|
||||
}
|
||||
|
||||
static void paint(struct NumberScene *self)
|
||||
{
|
||||
struct NumberSceneOpts *opts = self->opts;
|
||||
|
||||
LCD_clearDisplay(0);
|
||||
LCD_setStrEx(opts->label, 1, 1, BLACK, FONT_BOLD);
|
||||
|
||||
char buf[10];
|
||||
snprintf(buf, 10, "%d%s", opts->value, opts->unit);
|
||||
LCD_setStrEx(buf, 1, 9, BLACK, FONT_DOUBLE);
|
||||
}
|
||||
|
||||
static void deinit(struct NumberScene *self)
|
||||
{
|
||||
free(self->opts);
|
||||
self->opts = NULL;
|
||||
}
|
||||
|
||||
struct Scene *NewScene_Number(struct NumberSceneOpts *opts) {
|
||||
struct NumberScene *scene = calloc(1, sizeof(struct NumberScene));
|
||||
if (!scene) return NULL;
|
||||
|
||||
scene->opts = opts;
|
||||
scene->base.onInput = (Scene_onInput_t) onInput;
|
||||
scene->base.paint = (Scene_paint_t) paint;
|
||||
scene->base.deinit = (Scene_deinit_t) deinit;
|
||||
return (struct Scene *) scene;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* TODO file description
|
||||
*
|
||||
* Created on 2020/01/05.
|
||||
*/
|
||||
|
||||
#ifndef REFLOWER_SCENE_NUMBER_H
|
||||
#define REFLOWER_SCENE_NUMBER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct NumberSceneOpts {
|
||||
char label[15];
|
||||
char unit[8];
|
||||
int32_t value;
|
||||
int32_t min;
|
||||
int32_t max;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create number picker.
|
||||
*
|
||||
* The result is passed back as status.
|
||||
*
|
||||
* "opts" must be on heap and will be internally mutated.
|
||||
*
|
||||
* @param opts
|
||||
* @return
|
||||
*/
|
||||
struct Scene *NewScene_Number(struct NumberSceneOpts *opts);
|
||||
|
||||
#endif //REFLOWER_SCENE_NUMBER_H
|
||||
@@ -21,7 +21,7 @@ static struct SceneEvent init(struct RootScene *self)
|
||||
return SceneEvent_OpenChild(NewScene_Boot(), 1);
|
||||
}
|
||||
|
||||
struct SceneEvent onChildReturn(struct RootScene *self, uint32_t tag, int32_t status, void *data)
|
||||
static struct SceneEvent onChildReturn(struct RootScene *self, uint32_t tag, int32_t status, void *data)
|
||||
{
|
||||
if (tag == 1) {
|
||||
return SceneEvent_OpenChild(NewScene_MenuTest(), 0);
|
||||
|
||||
@@ -10,8 +10,14 @@
|
||||
#include "scenes.h"
|
||||
#include "scene_menu.h"
|
||||
|
||||
struct Priv {
|
||||
int32_t number;
|
||||
Scene_deinit_t parent_deinit;
|
||||
};
|
||||
|
||||
static struct SceneEvent onSelect(struct MenuScene *self) {
|
||||
struct Priv *priv = self->private;
|
||||
|
||||
if (self->selected == 0) {
|
||||
return SceneEvent_Close(0, NULL);
|
||||
}
|
||||
@@ -22,24 +28,55 @@ static struct SceneEvent onSelect(struct MenuScene *self) {
|
||||
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, "Count = %d", 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 deinit(struct MenuScene *self)
|
||||
{
|
||||
struct Priv *priv = self->private;
|
||||
if (priv->parent_deinit) {
|
||||
priv->parent_deinit((struct Scene *) self);
|
||||
}
|
||||
free(self->private);
|
||||
self->private = NULL;
|
||||
}
|
||||
|
||||
static struct SceneEvent onChildReturn(struct MenuScene *self, uint32_t tag, int32_t status, void *data)
|
||||
{
|
||||
struct Priv *priv = self->private;
|
||||
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, "▶#2", 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, "Count = 0", 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);
|
||||
@@ -48,5 +85,14 @@ struct Scene *NewScene_MenuTest() {
|
||||
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;
|
||||
priv->parent_deinit = scene->base.deinit;
|
||||
scene->private = priv;
|
||||
|
||||
scene->base.deinit = (Scene_deinit_t) deinit;
|
||||
scene->base.onChildReturn = (Scene_onChildReturn_t) onChildReturn;
|
||||
|
||||
return (struct Scene *) scene;
|
||||
}
|
||||
|
||||
@@ -7,11 +7,15 @@
|
||||
#ifndef REFLOWER_SCENES_H
|
||||
#define REFLOWER_SCENES_H
|
||||
|
||||
#include "scene_type.h"
|
||||
|
||||
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"
|
||||
#include "scene_number.h"
|
||||
|
||||
#endif //REFLOWER_SCENES_H
|
||||
|
||||
Reference in New Issue
Block a user