/** * GUI framework * * Created on 2020/01/03. */ #ifndef REFLOWER_LIQUID_H #define REFLOWER_LIQUID_H #include #include struct Liquid; enum InputEvent_Kind { InputEventKind_Wheel, InputEventKind_Button, }; struct InputEvent { enum InputEvent_Kind kind; union { struct { // Wheel delta int8_t delta; } wheel; struct { // Button state bool state; } button; }; }; #define InputEvent_Wheel(delta_) ((struct InputEvent) { \ .kind = InputEventKind_Wheel, \ .wheel = { .delta = delta_ } \ }) #define InputEvent_Button(state_) ((struct InputEvent) { \ .kind = InputEventKind_Button, \ .button = { .state = state_ }, \ }) enum SceneEvent_Kind { // Close this scene. // The scene is responsible for cleaning up 'private'. // 'options' and the scene itself will be freed by the GUI engine. SceneEventKind_Close, SceneEventKind_OpenChild, SceneEventKind_RequestRepaint, SceneEventKind_None, }; struct SceneEvent { enum SceneEvent_Kind kind; union { struct { // Status code uint32_t status; // Return data on heap void *data; } close; struct { // Scene (initialized, with options loaded in through the constructor) void *scene; // Tag used by parent to identify the open child uint32_t tag; } open; }; }; struct Scene; #define SceneEvent_None() ((struct SceneEvent) { \ .kind = SceneEventKind_None\ }) #define SceneEvent_Repaint() ((struct SceneEvent) { \ .kind = SceneEventKind_RequestRepaint\ }) #define SceneEvent_OpenChild(child_, tag_) ((struct SceneEvent) { \ .kind = SceneEventKind_OpenChild,\ .open = { .scene = (child_), .tag=tag_ }, \ }) #define SceneEvent_Close(status_, data_) ((struct SceneEvent) { \ .kind = SceneEventKind_Close,\ .close = { .status = (status_), .data=(data_) }, \ }) typedef struct SceneEvent (*Scene_onInput_t)(struct Scene *scene, struct InputEvent event); typedef struct SceneEvent (*Scene_onChildReturn_t)(struct Scene *scene, uint32_t tag, uint32_t status, void *data); typedef struct SceneEvent (*Scene_onTick_t)(struct Scene *scene); typedef void (*Scene_repaint_t)(struct Scene *scene); struct Scene { uint32_t tag; void *options; void *private; /** Handle input */ Scene_onInput_t onInput; /** Handle child scene return */ Scene_onChildReturn_t onChildReturn; /** Periodic tick */ Scene_onTick_t onTick; /** Periodic tick */ Scene_repaint_t paint; }; /** * Allocate scene and the inner private type. * * Requires * * Must be used like: * * struct Scene *scene = SCENE_SAFE_ALLOC(struct private); * scene->onInput = ... * return scene; */ #define SCENE_SAFE_ALLOC(private_type) \ calloc(1, sizeof(struct Scene)); \ if (!scene) return NULL; \ scene->private = calloc(1, sizeof(private_type)); \ if (!scene->private) return NULL; /** return 1 if repaint requested */ bool Liquid_handleInput(struct Liquid *container, struct InputEvent event); /** return 1 if repaint requested */ bool Liquid_handleTick(struct Liquid *container); void Liquid_paint(struct Liquid *container); struct Liquid *Liquid_start(); #endif //REFLOWER_LIQUID_H