GUI: status bar rendering. Power: battery indicator. (#207)
* Menu: animation. Irukagotchi: idle image. * Power: battery, usb activity widget * Power: tune battery max voltage and clamp overshoot * get initial charge state Co-authored-by: Aleksandr Kutuzov <aku@plooks.com> Co-authored-by: aanper <mail@s3f.ru>
This commit is contained in:
@@ -64,6 +64,12 @@ void canvas_api_free(CanvasApi* api) {
|
||||
free(api);
|
||||
}
|
||||
|
||||
void canvas_reset(CanvasApi* api) {
|
||||
assert(api);
|
||||
canvas_color_set(api, ColorBlack);
|
||||
canvas_font_set(api, FontSecondary);
|
||||
}
|
||||
|
||||
void canvas_commit(CanvasApi* api) {
|
||||
furi_assert(api);
|
||||
Canvas* canvas = (Canvas*)api;
|
||||
@@ -144,23 +150,33 @@ void canvas_icon_draw(CanvasApi* api, uint8_t x, uint8_t y, Icon* icon) {
|
||||
void canvas_dot_draw(CanvasApi* api, uint8_t x, uint8_t y) {
|
||||
furi_assert(api);
|
||||
Canvas* canvas = (Canvas*)api;
|
||||
x += canvas->offset_x;
|
||||
y += canvas->offset_y;
|
||||
u8g2_DrawPixel(&canvas->fb, x, y);
|
||||
}
|
||||
|
||||
void canvas_box_draw(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
|
||||
furi_assert(api);
|
||||
Canvas* canvas = (Canvas*)api;
|
||||
x += canvas->offset_x;
|
||||
y += canvas->offset_y;
|
||||
u8g2_DrawBox(&canvas->fb, x, y, width, height);
|
||||
}
|
||||
|
||||
void canvas_draw_frame(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
|
||||
furi_assert(api);
|
||||
Canvas* canvas = (Canvas*)api;
|
||||
x += canvas->offset_x;
|
||||
y += canvas->offset_y;
|
||||
u8g2_DrawFrame(&canvas->fb, x, y, width, height);
|
||||
}
|
||||
|
||||
void canvas_draw_line(CanvasApi* api, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
|
||||
furi_assert(api);
|
||||
Canvas* canvas = (Canvas*)api;
|
||||
x1 += canvas->offset_x;
|
||||
y1 += canvas->offset_y;
|
||||
x2 += canvas->offset_x;
|
||||
y2 += canvas->offset_y;
|
||||
u8g2_DrawLine(&canvas->fb, x1, y1, x2, y2);
|
||||
}
|
||||
|
@@ -4,6 +4,8 @@ CanvasApi* canvas_api_init();
|
||||
|
||||
void canvas_api_free(CanvasApi* api);
|
||||
|
||||
void canvas_reset(CanvasApi* api);
|
||||
|
||||
void canvas_commit(CanvasApi* api);
|
||||
|
||||
void canvas_frame_set(
|
||||
|
@@ -41,7 +41,7 @@ void gui_update(Gui* gui) {
|
||||
}
|
||||
|
||||
bool gui_redraw_fs(Gui* gui) {
|
||||
canvas_frame_set(gui->canvas_api, 0, 0, 128, 64);
|
||||
canvas_frame_set(gui->canvas_api, 0, 0, GUI_DISPLAY_WIDTH, GUI_DISPLAY_HEIGHT);
|
||||
Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerFullscreen]);
|
||||
if(widget) {
|
||||
widget_draw(widget, gui->canvas_api);
|
||||
@@ -51,18 +51,48 @@ bool gui_redraw_fs(Gui* gui) {
|
||||
}
|
||||
}
|
||||
|
||||
bool gui_redraw_status_bar(Gui* gui) {
|
||||
canvas_frame_set(gui->canvas_api, 0, 0, 128, 64);
|
||||
Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerStatusBar]);
|
||||
if(widget) {
|
||||
widget_draw(widget, gui->canvas_api);
|
||||
return true;
|
||||
void gui_redraw_status_bar(Gui* gui) {
|
||||
WidgetArray_it_t it;
|
||||
uint8_t x;
|
||||
uint8_t x_used = 0;
|
||||
uint8_t width;
|
||||
Widget* widget;
|
||||
// Right side
|
||||
x = 128;
|
||||
WidgetArray_it(it, gui->layers[GuiLayerStatusBarRight]);
|
||||
while(!WidgetArray_end_p(it) && x_used < GUI_STATUS_BAR_WIDTH) {
|
||||
// Render widget;
|
||||
widget = *WidgetArray_ref(it);
|
||||
if(widget_is_enabled(widget)) {
|
||||
width = widget_get_width(widget);
|
||||
if(!width) width = 8;
|
||||
x_used += width;
|
||||
x -= width;
|
||||
canvas_frame_set(gui->canvas_api, x, GUI_STATUS_BAR_Y, width, GUI_STATUS_BAR_HEIGHT);
|
||||
widget_draw(widget, gui->canvas_api);
|
||||
}
|
||||
WidgetArray_next(it);
|
||||
}
|
||||
// Left side
|
||||
x = 0;
|
||||
WidgetArray_it(it, gui->layers[GuiLayerStatusBarLeft]);
|
||||
while(!WidgetArray_end_p(it) && x_used < GUI_STATUS_BAR_WIDTH) {
|
||||
// Render widget;
|
||||
widget = *WidgetArray_ref(it);
|
||||
if(widget_is_enabled(widget)) {
|
||||
width = widget_get_width(widget);
|
||||
if(!width) width = 8;
|
||||
x_used += width;
|
||||
canvas_frame_set(gui->canvas_api, x, GUI_STATUS_BAR_Y, width, GUI_STATUS_BAR_HEIGHT);
|
||||
widget_draw(widget, gui->canvas_api);
|
||||
x += width;
|
||||
}
|
||||
WidgetArray_next(it);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gui_redraw_normal(Gui* gui) {
|
||||
canvas_frame_set(gui->canvas_api, 0, 9, 128, 55);
|
||||
canvas_frame_set(gui->canvas_api, GUI_MAIN_X, GUI_MAIN_Y, GUI_MAIN_WIDTH, GUI_MAIN_HEIGHT);
|
||||
Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerMain]);
|
||||
if(widget) {
|
||||
widget_draw(widget, gui->canvas_api);
|
||||
@@ -72,7 +102,7 @@ bool gui_redraw_normal(Gui* gui) {
|
||||
}
|
||||
|
||||
bool gui_redraw_none(Gui* gui) {
|
||||
canvas_frame_set(gui->canvas_api, 0, 9, 118, 44);
|
||||
canvas_frame_set(gui->canvas_api, GUI_MAIN_X, GUI_MAIN_Y, GUI_MAIN_WIDTH, GUI_MAIN_HEIGHT);
|
||||
Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerNone]);
|
||||
if(widget) {
|
||||
widget_draw(widget, gui->canvas_api);
|
||||
@@ -86,6 +116,8 @@ void gui_redraw(Gui* gui) {
|
||||
furi_assert(gui);
|
||||
gui_lock(gui);
|
||||
|
||||
canvas_reset(gui->canvas_api);
|
||||
|
||||
if(!gui_redraw_fs(gui)) {
|
||||
if(!gui_redraw_normal(gui)) {
|
||||
gui_redraw_none(gui);
|
||||
|
@@ -3,10 +3,24 @@
|
||||
#include "widget.h"
|
||||
#include "canvas.h"
|
||||
|
||||
#define GUI_DISPLAY_WIDTH 128
|
||||
#define GUI_DISPLAY_HEIGHT 64
|
||||
|
||||
#define GUI_STATUS_BAR_X 0
|
||||
#define GUI_STATUS_BAR_Y 0
|
||||
#define GUI_STATUS_BAR_WIDTH GUI_DISPLAY_WIDTH
|
||||
#define GUI_STATUS_BAR_HEIGHT 8
|
||||
|
||||
#define GUI_MAIN_X 0
|
||||
#define GUI_MAIN_Y 9
|
||||
#define GUI_MAIN_WIDTH GUI_DISPLAY_WIDTH
|
||||
#define GUI_MAIN_HEIGHT (GUI_DISPLAY_HEIGHT - GUI_MAIN_Y)
|
||||
|
||||
typedef enum {
|
||||
GuiLayerNone, /* Special layer for internal use only */
|
||||
|
||||
GuiLayerStatusBar, /* Status bar widget layer */
|
||||
GuiLayerStatusBarLeft, /* Status bar left-side widget layer, auto-layout */
|
||||
GuiLayerStatusBarRight, /* Status bar right-side widget layer, auto-layout */
|
||||
GuiLayerMain, /* Main widget layer, status bar is shown */
|
||||
GuiLayerFullscreen, /* Fullscreen widget layer */
|
||||
|
||||
|
@@ -6,9 +6,20 @@
|
||||
|
||||
struct GuiEvent {
|
||||
PubSub* input_event_record;
|
||||
osTimerId_t timer;
|
||||
osMessageQueueId_t mqueue;
|
||||
};
|
||||
|
||||
void gui_event_timer_callback(void* arg) {
|
||||
assert(arg);
|
||||
GuiEvent* gui_event = arg;
|
||||
|
||||
GuiMessage message;
|
||||
message.type = GuiMessageTypeRedraw;
|
||||
|
||||
osMessageQueuePut(gui_event->mqueue, &message, 0, osWaitForever);
|
||||
}
|
||||
|
||||
void gui_event_input_events_callback(const void* value, void* ctx) {
|
||||
furi_assert(value);
|
||||
furi_assert(ctx);
|
||||
@@ -29,6 +40,10 @@ GuiEvent* gui_event_alloc() {
|
||||
gui_event->mqueue = osMessageQueueNew(GUI_EVENT_MQUEUE_SIZE, sizeof(GuiMessage), NULL);
|
||||
furi_check(gui_event->mqueue);
|
||||
|
||||
gui_event->timer = osTimerNew(gui_event_timer_callback, osTimerPeriodic, gui_event, NULL);
|
||||
assert(gui_event->timer);
|
||||
osTimerStart(gui_event->timer, 1000 / 10);
|
||||
|
||||
// Input
|
||||
gui_event->input_event_record = furi_open("input_events");
|
||||
furi_check(gui_event->input_event_record != NULL);
|
||||
|
@@ -10,15 +10,6 @@
|
||||
|
||||
// TODO add mutex to widget ops
|
||||
|
||||
struct Widget {
|
||||
Gui* gui;
|
||||
bool is_enabled;
|
||||
WidgetDrawCallback draw_callback;
|
||||
void* draw_callback_context;
|
||||
WidgetInputCallback input_callback;
|
||||
void* input_callback_context;
|
||||
};
|
||||
|
||||
Widget* widget_alloc(WidgetDrawCallback callback, void* callback_context) {
|
||||
Widget* widget = furi_alloc(sizeof(Widget));
|
||||
widget->is_enabled = true;
|
||||
@@ -31,6 +22,26 @@ void widget_free(Widget* widget) {
|
||||
free(widget);
|
||||
}
|
||||
|
||||
void widget_set_width(Widget* widget, uint8_t width) {
|
||||
assert(widget);
|
||||
widget->width = width;
|
||||
}
|
||||
|
||||
uint8_t widget_get_width(Widget* widget) {
|
||||
assert(widget);
|
||||
return widget->width;
|
||||
}
|
||||
|
||||
void widget_set_height(Widget* widget, uint8_t height) {
|
||||
assert(widget);
|
||||
widget->height = height;
|
||||
}
|
||||
|
||||
uint8_t widget_get_height(Widget* widget) {
|
||||
assert(widget);
|
||||
return widget->height;
|
||||
}
|
||||
|
||||
void widget_enabled_set(Widget* widget, bool enabled) {
|
||||
furi_assert(widget);
|
||||
if(widget->is_enabled != enabled) {
|
||||
@@ -80,7 +91,9 @@ void widget_draw(Widget* widget, CanvasApi* canvas_api) {
|
||||
void widget_input(Widget* widget, InputEvent* event) {
|
||||
furi_assert(widget);
|
||||
furi_assert(event);
|
||||
|
||||
furi_check(widget->gui);
|
||||
if(widget->input_callback) widget->input_callback(event, widget->input_callback_context);
|
||||
|
||||
if(widget->input_callback) {
|
||||
widget->input_callback(event, widget->input_callback_context);
|
||||
}
|
||||
}
|
||||
|
@@ -8,14 +8,51 @@ typedef struct Widget Widget;
|
||||
typedef void (*WidgetDrawCallback)(CanvasApi* api, void* context);
|
||||
typedef void (*WidgetInputCallback)(InputEvent* event, void* context);
|
||||
|
||||
/*
|
||||
* Widget allocator
|
||||
* always returns widget or stops system if not enough memory.
|
||||
*/
|
||||
Widget* widget_alloc();
|
||||
|
||||
/*
|
||||
* Widget deallocator
|
||||
* Ensure that widget was unregistered in GUI system before use.
|
||||
*/
|
||||
void widget_free(Widget* widget);
|
||||
|
||||
/*
|
||||
* Set widget width.
|
||||
* Will be used to limit canvas drawing area and autolayout feature.
|
||||
* @param width - wanted width, 0 - auto.
|
||||
*/
|
||||
void widget_set_width(Widget* widget, uint8_t width);
|
||||
uint8_t widget_get_width(Widget* widget);
|
||||
|
||||
/*
|
||||
* Set widget height.
|
||||
* Will be used to limit canvas drawing area and autolayout feature.
|
||||
* @param height - wanted height, 0 - auto.
|
||||
*/
|
||||
void widget_set_height(Widget* widget, uint8_t height);
|
||||
uint8_t widget_get_height(Widget* widget);
|
||||
|
||||
/*
|
||||
* Enable or disable widget rendering.
|
||||
* @param enabled.
|
||||
*/
|
||||
void widget_enabled_set(Widget* widget, bool enabled);
|
||||
bool widget_is_enabled(Widget* widget);
|
||||
|
||||
/*
|
||||
* Widget event callbacks
|
||||
* @param callback - appropriate callback function
|
||||
* @param context - context to pass to callback
|
||||
*/
|
||||
void widget_draw_callback_set(Widget* widget, WidgetDrawCallback callback, void* context);
|
||||
void widget_input_callback_set(Widget* widget, WidgetInputCallback callback, void* context);
|
||||
|
||||
// emit update signal
|
||||
/*
|
||||
* Emit update signal to GUI system.
|
||||
* Rendering will happen later after GUI system process signal.
|
||||
*/
|
||||
void widget_update(Widget* widget);
|
||||
|
@@ -2,8 +2,31 @@
|
||||
|
||||
#include "gui_i.h"
|
||||
|
||||
struct Widget {
|
||||
Gui* gui;
|
||||
bool is_enabled;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
WidgetDrawCallback draw_callback;
|
||||
void* draw_callback_context;
|
||||
WidgetInputCallback input_callback;
|
||||
void* input_callback_context;
|
||||
};
|
||||
|
||||
/*
|
||||
* Set GUI referenec.
|
||||
* @param gui - gui instance pointer.
|
||||
*/
|
||||
void widget_gui_set(Widget* widget, Gui* gui);
|
||||
|
||||
/*
|
||||
* Process draw call. Calls draw callback.
|
||||
* @param canvas_api - canvas to draw at.
|
||||
*/
|
||||
void widget_draw(Widget* widget, CanvasApi* canvas_api);
|
||||
|
||||
/*
|
||||
* Process input. Calls input callback.
|
||||
* @param event - pointer to input event.
|
||||
*/
|
||||
void widget_input(Widget* widget, InputEvent* event);
|
||||
|
Reference in New Issue
Block a user