Skip to content

Commit

Permalink
[FL-1549] Gui Widget module (#598)
Browse files Browse the repository at this point in the history
* gui_widget: rework with mlib container
* widget: rename gui_widget-> widget; gui_element->widget_element
* gui: move widget from nfc to gui/modules
* nfc: rework widget usage
* nfc: return to ReadEmvAppSuccess scene after ReadEmvDataSuccess exit

Co-authored-by: あく <[email protected]>
  • Loading branch information
gornekich and skotopes authored Jul 23, 2021
1 parent ad421a8 commit 3f640e8
Show file tree
Hide file tree
Showing 18 changed files with 326 additions and 388 deletions.
152 changes: 152 additions & 0 deletions applications/gui/modules/widget.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#include <furi.h>
#include "widget.h"
#include <m-array.h>

ARRAY_DEF(ElementArray, WidgetElement*, M_PTR_OPLIST);

struct Widget {
View* view;
void* context;
};

typedef struct {
ElementArray_t element;
} GuiWidgetModel;

static void gui_widget_view_draw_callback(Canvas* canvas, void* _model) {
GuiWidgetModel* model = _model;
canvas_clear(canvas);

// Draw all elements
ElementArray_it_t it;
ElementArray_it(it, model->element);
while(!ElementArray_end_p(it)) {
WidgetElement* element = *ElementArray_ref(it);
if(element->draw != NULL) {
element->draw(canvas, element);
}
ElementArray_next(it);
}
}

static bool gui_widget_view_input_callback(InputEvent* event, void* context) {
Widget* widget = context;
bool consumed = false;

// Call all Widget Elements input handlers
with_view_model(
widget->view, (GuiWidgetModel * model) {
ElementArray_it_t it;
ElementArray_it(it, model->element);
while(!ElementArray_end_p(it)) {
WidgetElement* element = *ElementArray_ref(it);
if(element->input != NULL) {
consumed |= element->input(event, element);
}
ElementArray_next(it);
}
return true;
});

return consumed;
}

Widget* widget_alloc() {
Widget* widget = furi_alloc(sizeof(Widget));
widget->view = view_alloc();
view_set_context(widget->view, widget);
view_allocate_model(widget->view, ViewModelTypeLocking, sizeof(GuiWidgetModel));
view_set_draw_callback(widget->view, gui_widget_view_draw_callback);
view_set_input_callback(widget->view, gui_widget_view_input_callback);

with_view_model(
widget->view, (GuiWidgetModel * model) {
ElementArray_init(model->element);
return true;
});

return widget;
}

void widget_clear(Widget* widget) {
furi_assert(widget);

with_view_model(
widget->view, (GuiWidgetModel * model) {
ElementArray_it_t it;
ElementArray_it(it, model->element);
while(!ElementArray_end_p(it)) {
WidgetElement* element = *ElementArray_ref(it);
furi_assert(element->free);
element->free(element);
ElementArray_next(it);
}
ElementArray_clean(model->element);
return true;
});
}

void widget_free(Widget* widget) {
furi_assert(widget);
// Free all elements
widget_clear(widget);
// Free elements container
with_view_model(
widget->view, (GuiWidgetModel * model) {
ElementArray_clear(model->element);
return true;
});

view_free(widget->view);
free(widget);
}

View* widget_get_view(Widget* widget) {
furi_assert(widget);
return widget->view;
}

static void widget_add_element(Widget* widget, WidgetElement* element) {
furi_assert(widget);
furi_assert(element);

with_view_model(
widget->view, (GuiWidgetModel * model) {
element->parent = widget;
ElementArray_push_back(model->element, element);
return true;
});
}

void widget_add_string_element(
Widget* widget,
uint8_t x,
uint8_t y,
Align horizontal,
Align vertical,
Font font,
const char* text) {
furi_assert(widget);
WidgetElement* string_element =
widget_element_string_create(x, y, horizontal, vertical, font, text);
widget_add_element(widget, string_element);
}

void widget_add_button_element(
Widget* widget,
GuiButtonType button_type,
const char* text,
ButtonCallback callback,
void* context) {
furi_assert(widget);
WidgetElement* button_element =
widget_element_button_create(button_type, text, callback, context);
widget_add_element(widget, button_element);
}

void widget_add_icon_element(Widget* widget, uint8_t x, uint8_t y, const Icon* icon) {
furi_assert(widget);
furi_assert(icon);
WidgetElement* icon_element = widget_element_icon_create(x, y, icon);
widget_add_element(widget, icon_element);
}
66 changes: 66 additions & 0 deletions applications/gui/modules/widget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#pragma once
#include "widget_elements/widget_element_i.h"

typedef struct Widget Widget;
typedef struct WidgetElement WidgetElement;

/** Allocate Widget that holds Widget Elements
* @return Widget instance
*/
Widget* widget_alloc();

/** Free Widget
* @note this function free allocated Widget Elements
* @param widget Widget instance
*/
void widget_free(Widget* widget);

/** Clear Widget
* @param widget Widget instance
*/
void widget_clear(Widget* widget);

/** Get Widget view
* @param widget Widget instance
* @return View instance
*/
View* widget_get_view(Widget* widget);

/** Add String Element
* @param widget Widget instance
* @param x - x coordinate
* @param y - y coordinate
* @param horizontal - Align instance
* @param vertical - Align instance
* @param font Font instance
*/
void widget_add_string_element(
Widget* widget,
uint8_t x,
uint8_t y,
Align horizontal,
Align vertical,
Font font,
const char* text);

/** Add Button Element
* @param widget Widget instance
* @param button_type GuiButtonType instance
* @param text text on allocated button
* @param callback ButtonCallback instance
* @param context pointer to context
*/
void widget_add_button_element(
Widget* widget,
GuiButtonType button_type,
const char* text,
ButtonCallback callback,
void* context);

/** Add Icon Element
* @param widget Widget instance
* @param x - x coordinate
* @param y - y coordinate
* @param icon Icon instance
*/
void widget_add_icon_element(Widget* widget, uint8_t x, uint8_t y, const Icon* icon);
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#include "gui_element_i.h"
#include "gui_element_button.h"
#include "gui_widget.h"
#include "widget_element_i.h"
#include <gui/elements.h>
#include <m-string.h>

Expand All @@ -11,7 +9,7 @@ typedef struct {
void* context;
} GuiButtonModel;

static void gui_button_draw(Canvas* canvas, GuiElement* element) {
static void gui_button_draw(Canvas* canvas, WidgetElement* element) {
furi_assert(canvas);
furi_assert(element);
GuiButtonModel* model = element->model;
Expand All @@ -28,7 +26,7 @@ static void gui_button_draw(Canvas* canvas, GuiElement* element) {
}
}

static bool gui_button_input(InputEvent* event, GuiElement* element) {
static bool gui_button_input(InputEvent* event, WidgetElement* element) {
GuiButtonModel* model = element->model;
bool consumed = false;

Expand All @@ -48,19 +46,16 @@ static bool gui_button_input(InputEvent* event, GuiElement* element) {
return consumed;
}

static void gui_button_free(GuiElement* gui_button) {
static void gui_button_free(WidgetElement* gui_button) {
furi_assert(gui_button);

GuiButtonModel* model = gui_button->model;
if(gui_button->parent != NULL) {
// TODO deattach element
}
string_clear(model->text);
free(gui_button->model);
free(gui_button);
}

GuiElement* gui_button_create(
WidgetElement* widget_element_button_create(
GuiButtonType button_type,
const char* text,
ButtonCallback callback,
Expand All @@ -73,7 +68,7 @@ GuiElement* gui_button_create(
string_init_set_str(model->text, text);

// Allocate and init Element
GuiElement* gui_button = furi_alloc(sizeof(GuiElement));
WidgetElement* gui_button = furi_alloc(sizeof(WidgetElement));
gui_button->parent = NULL;
gui_button->input = gui_button_input;
gui_button->draw = gui_button_draw;
Expand Down
48 changes: 48 additions & 0 deletions applications/gui/modules/widget_elements/widget_element_i.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#pragma once
#include <furi.h>
#include <gui/view.h>

typedef enum {
GuiButtonTypeLeft,
GuiButtonTypeCenter,
GuiButtonTypeRight,
} GuiButtonType;

typedef void (*ButtonCallback)(GuiButtonType result, void* context);

typedef struct WidgetElement WidgetElement;
typedef struct Widget Widget;

struct WidgetElement {
// generic draw and input callbacks
void (*draw)(Canvas* canvas, WidgetElement* element);
bool (*input)(InputEvent* event, WidgetElement* element);

// free callback
void (*free)(WidgetElement* element);

// generic model holder
void* model;

// pointer to widget that hold our element
Widget* parent;
};

/* Create string element */
WidgetElement* widget_element_string_create(
uint8_t x,
uint8_t y,
Align horizontal,
Align vertical,
Font font,
const char* text);

/* Create button element */
WidgetElement* widget_element_button_create(
GuiButtonType button_type,
const char* text,
ButtonCallback callback,
void* context);

/* Create icon element element */
WidgetElement* widget_element_icon_create(uint8_t x, uint8_t y, const Icon* icon);
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
#include "gui_element_i.h"
#include "gui_element_icon.h"
#include "gui_widget.h"

#include "widget_element_i.h"
#include <m-string.h>

typedef struct {
Expand All @@ -10,7 +7,7 @@ typedef struct {
const Icon* icon;
} GuiIconModel;

static void gui_icon_draw(Canvas* canvas, GuiElement* element) {
static void gui_icon_draw(Canvas* canvas, WidgetElement* element) {
furi_assert(canvas);
furi_assert(element);
GuiIconModel* model = element->model;
Expand All @@ -20,17 +17,14 @@ static void gui_icon_draw(Canvas* canvas, GuiElement* element) {
}
}

static void gui_icon_free(GuiElement* gui_icon) {
static void gui_icon_free(WidgetElement* gui_icon) {
furi_assert(gui_icon);

if(gui_icon->parent != NULL) {
// TODO deattach element
}
free(gui_icon->model);
free(gui_icon);
}

GuiElement* gui_icon_create(uint8_t x, uint8_t y, const Icon* icon) {
WidgetElement* widget_element_icon_create(uint8_t x, uint8_t y, const Icon* icon) {
furi_assert(icon);

// Allocate and init model
Expand All @@ -40,7 +34,7 @@ GuiElement* gui_icon_create(uint8_t x, uint8_t y, const Icon* icon) {
model->icon = icon;

// Allocate and init Element
GuiElement* gui_icon = furi_alloc(sizeof(GuiElement));
WidgetElement* gui_icon = furi_alloc(sizeof(WidgetElement));
gui_icon->parent = NULL;
gui_icon->input = NULL;
gui_icon->draw = gui_icon_draw;
Expand Down
Loading

0 comments on commit 3f640e8

Please sign in to comment.