GUI: abolish API injection into instances. (#265)

* GUI: abolish API injection into instances. Update usage by 3rd party apps.
* GUI: update documentation. Cleanup api usage. Adjust status bar item spacing.
This commit is contained in:
あく 2020-12-14 13:50:32 +03:00 committed by GitHub
parent ff7ce6f00f
commit d3ff787864
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 486 additions and 422 deletions

View file

@ -19,16 +19,16 @@ typedef struct {
// TODO add mutex for contex
static void render_callback(CanvasApi* canvas, void* _ctx) {
static void render_callback(Canvas* canvas, void* _ctx) {
AppLoaderState* ctx = (AppLoaderState*)_ctx;
canvas->clear(canvas);
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
canvas->draw_str(canvas, 2, 32, ctx->current_app->name);
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 2, 32, ctx->current_app->name);
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 44, "press back to exit");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 44, "press back to exit");
}
static void input_callback(InputEvent* input_event, void* _ctx) {
@ -92,12 +92,12 @@ void app_loader(void* p) {
Cli* cli = furi_open("cli");
// Open GUI and register widget
GuiApi* gui = furi_open("gui");
Gui* gui = furi_open("gui");
if(gui == NULL) {
printf("gui is not available\n");
furiac_exit(NULL);
}
gui->add_widget(gui, state.widget, GuiLayerFullscreen);
gui_add_widget(gui, state.widget, GuiLayerFullscreen);
// FURI startup
const size_t flipper_app_count = sizeof(FLIPPER_APPS) / sizeof(FLIPPER_APPS[0]);

View file

@ -229,8 +229,6 @@ const FlipperStartupApp FLIPPER_APPS[] = {
.icon = A_iButton_14},
#endif
{.app = NULL, .name = "Bluetooth", .libs = {0}, .icon = A_Bluetooth_14},
#ifdef BUILD_GPIO_DEMO
{.app = app_gpio_test, .name = "GPIO", .libs = {1, FURI_LIB{"gui_task"}}, .icon = A_GPIO_14},
#endif

View file

@ -6,17 +6,20 @@ Bt* bt_alloc() {
bt->statusbar_icon = assets_icons_get(I_Bluetooth_5x8);
bt->statusbar_widget = widget_alloc();
widget_set_width(bt->statusbar_widget, icon_get_width(bt->statusbar_icon) + 2);
widget_set_width(bt->statusbar_widget, icon_get_width(bt->statusbar_icon));
widget_draw_callback_set(bt->statusbar_widget, bt_draw_statusbar_callback, bt);
widget_enabled_set(bt->statusbar_widget, false);
bt->menu_icon = assets_icons_get(A_Bluetooth_14);
bt->menu_item = menu_item_alloc_menu("Bluetooth", bt->menu_icon);
return bt;
}
void bt_draw_statusbar_callback(CanvasApi* canvas, void* context) {
void bt_draw_statusbar_callback(Canvas* canvas, void* context) {
assert(context);
Bt* bt = context;
canvas->draw_icon(canvas, 0, 0, bt->statusbar_icon);
canvas_draw_icon(canvas, 0, 0, bt->statusbar_icon);
}
void bt_cli_info(string_t args, void* context) {
@ -40,12 +43,11 @@ void bt_task() {
furiac_exit(NULL);
}
FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL);
furi_assert(gui_record);
GuiApi* gui = furi_take(gui_record);
furi_assert(gui);
gui->add_widget(gui, bt->statusbar_widget, GuiLayerStatusBarLeft);
furi_commit(gui_record);
Gui* gui = furi_open("gui");
gui_add_widget(gui, bt->statusbar_widget, GuiLayerStatusBarLeft);
with_value_mutex(
furi_open("menu"), (Menu * menu) { menu_item_add(menu, bt->menu_item); });
furiac_ready();

View file

@ -3,17 +3,26 @@
#include "bt.h"
#include <cli/cli.h>
#include <flipper.h>
#include <flipper_v2.h>
#include <gui/gui.h>
#include <gui/widget.h>
#include <menu/menu.h>
#include <menu/menu_item.h>
typedef struct {
Cli* cli;
// Status bar
Icon* statusbar_icon;
Widget* statusbar_widget;
// Menu
Icon* menu_icon;
MenuItem* menu_item;
} Bt;
Bt* bt_alloc();
void bt_draw_statusbar_callback(CanvasApi* canvas, void* context);
void bt_draw_statusbar_callback(Canvas* canvas, void* context);

View file

@ -329,15 +329,15 @@ typedef struct {
bool need_cc1101_conf;
} State;
static void render_callback(CanvasApi* canvas, void* ctx) {
static void render_callback(Canvas* canvas, void* ctx) {
State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25);
if(!state) return;
canvas->clear(canvas);
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
canvas->draw_str(canvas, 2, 12, "cc1101 workaround");
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 2, 12, "cc1101 workaround");
{
char buf[24];
@ -345,21 +345,21 @@ static void render_callback(CanvasApi* canvas, void* ctx) {
float freq = conf.band->base_freq + CHAN_SPA * conf.channel;
sprintf(buf, "freq: %ld.%02ld MHz", (uint32_t)freq, (uint32_t)(freq * 100.) % 100);
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 25, buf);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 25, buf);
}
{
canvas->set_font(canvas, FontSecondary);
canvas_set_font(canvas, FontSecondary);
if(state->need_cc1101_conf) {
canvas->draw_str(canvas, 2, 36, "mode: configuring...");
canvas_draw_str(canvas, 2, 36, "mode: configuring...");
} else if(state->mode == ModeRx) {
canvas->draw_str(canvas, 2, 36, "mode: RX");
canvas_draw_str(canvas, 2, 36, "mode: RX");
} else if(state->mode == ModeTx) {
canvas->draw_str(canvas, 2, 36, "mode: TX");
canvas_draw_str(canvas, 2, 36, "mode: TX");
} else {
canvas->draw_str(canvas, 2, 36, "mode: unknown");
canvas_draw_str(canvas, 2, 36, "mode: unknown");
}
}
@ -368,8 +368,8 @@ static void render_callback(CanvasApi* canvas, void* ctx) {
char buf[24];
sprintf(buf, "RSSI: %d dBm", state->last_rssi);
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 48, buf);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 48, buf);
}
}
@ -377,8 +377,8 @@ static void render_callback(CanvasApi* canvas, void* ctx) {
char buf[24];
sprintf(buf, "tx level: %d dBm", TX_LEVELS[state->tx_level].dbm);
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 63, buf);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 63, buf);
}
release_mutex((ValueMutex*)ctx, state);
@ -416,12 +416,12 @@ extern "C" void cc1101_workaround(void* p) {
widget_input_callback_set(widget, input_callback, event_queue);
// Open GUI and register widget
GuiApi* gui = (GuiApi*)furi_open("gui");
Gui* gui = (Gui*)furi_open("gui");
if(gui == NULL) {
printf("[cc1101] gui is not available\n");
furiac_exit(NULL);
}
gui->add_widget(gui, widget, GuiLayerFullscreen);
gui_add_widget(gui, widget, GuiLayerFullscreen);
gpio_init(&debug_0, GpioModeOutputPushPull);
gpio_write((GpioPin*)&debug_0, false);

@ -1 +1 @@
Subproject commit 2039949856df06d7f6fa7698897acc48f4714976
Subproject commit 4adfd876167429ff9280db8e8b286b6c880e0c0a

View file

@ -33,15 +33,15 @@ typedef struct {
uint8_t gpio_index;
} State;
static void render_callback(CanvasApi* canvas, void* ctx) {
static void render_callback(Canvas* canvas, void* ctx) {
State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25);
canvas->clear(canvas);
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
canvas->draw_str(canvas, 2, 10, "GPIO demo");
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 25, GPIO_PINS[state->gpio_index].name);
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 2, 10, "GPIO demo");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 25, GPIO_PINS[state->gpio_index].name);
release_mutex((ValueMutex*)ctx, state);
}
@ -74,12 +74,12 @@ void app_gpio_test(void* p) {
widget_input_callback_set(widget, input_callback, event_queue);
// Open GUI and register widget
GuiApi* gui = (GuiApi*)furi_open("gui");
Gui* gui = (Gui*)furi_open("gui");
if(gui == NULL) {
printf("[gpio-tester] gui is not available\n");
furiac_exit(NULL);
}
gui->add_widget(gui, widget, GuiLayerFullscreen);
gui_add_widget(gui, widget, GuiLayerFullscreen);
// configure pin
for(uint8_t i = 0; i < sizeof(GPIO_PINS) / sizeof(GPIO_PINS[0]); i++) {

View file

@ -1,4 +1,3 @@
#include "canvas.h"
#include "canvas_i.h"
#include "icon.h"
#include "icon_i.h"
@ -6,40 +5,18 @@
#include <flipper.h>
#include <flipper_v2.h>
typedef struct {
CanvasApi api;
struct Canvas {
u8g2_t fb;
uint8_t offset_x;
uint8_t offset_y;
uint8_t width;
uint8_t height;
} Canvas;
uint8_t canvas_width(CanvasApi* api);
uint8_t canvas_height(CanvasApi* api);
void canvas_clear(CanvasApi* api);
void canvas_color_set(CanvasApi* api, uint8_t color);
void canvas_font_set(CanvasApi* api, Font font);
void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str);
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);
void canvas_box_draw(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
void canvas_draw_frame(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
void canvas_draw_line(CanvasApi* api, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);
void canvas_draw_xbm(
CanvasApi* canvas,
uint8_t x,
uint8_t y,
uint8_t w,
uint8_t h,
const uint8_t* bitmap);
void canvas_draw_glyph(CanvasApi* canvas, uint8_t x, uint8_t y, uint16_t ch);
};
uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr);
uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr);
CanvasApi* canvas_api_init() {
Canvas* canvas_init() {
Canvas* canvas = furi_alloc(sizeof(Canvas));
u8g2_Setup_st7565_erc12864_alt_f(
@ -48,86 +25,65 @@ CanvasApi* canvas_api_init() {
// send init sequence to the display, display is in sleep mode after this
u8g2_InitDisplay(&canvas->fb);
u8g2_SetContrast(&canvas->fb, 36);
u8g2_SetPowerSave(&canvas->fb, 0); // wake up display
// wake up display
u8g2_SetPowerSave(&canvas->fb, 0);
u8g2_SendBuffer(&canvas->fb);
canvas->api.width = canvas_width;
canvas->api.height = canvas_height;
canvas->api.clear = canvas_clear;
canvas->api.set_color = canvas_color_set;
canvas->api.set_font = canvas_font_set;
canvas->api.draw_str = canvas_str_draw;
canvas->api.draw_icon = canvas_icon_draw;
canvas->api.draw_dot = canvas_dot_draw;
canvas->api.draw_box = canvas_box_draw;
canvas->api.draw_frame = canvas_draw_frame;
canvas->api.draw_line = canvas_draw_line;
canvas->api.draw_xbm = canvas_draw_xbm;
canvas->api.draw_glyph = canvas_draw_glyph;
return (CanvasApi*)canvas;
return canvas;
}
void canvas_api_free(CanvasApi* api) {
furi_assert(api);
free(api);
void canvas_free(Canvas* canvas) {
furi_assert(canvas);
free(canvas);
}
void canvas_reset(CanvasApi* api) {
assert(api);
canvas_color_set(api, ColorBlack);
canvas_font_set(api, FontSecondary);
void canvas_reset(Canvas* canvas) {
furi_assert(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
}
void canvas_commit(CanvasApi* api) {
furi_assert(api);
Canvas* canvas = (Canvas*)api;
void canvas_commit(Canvas* canvas) {
furi_assert(canvas);
u8g2_SetPowerSave(&canvas->fb, 0); // wake up display
u8g2_SendBuffer(&canvas->fb);
}
void canvas_frame_set(
CanvasApi* api,
Canvas* canvas,
uint8_t offset_x,
uint8_t offset_y,
uint8_t width,
uint8_t height) {
furi_assert(api);
Canvas* canvas = (Canvas*)api;
furi_assert(canvas);
canvas->offset_x = offset_x;
canvas->offset_y = offset_y;
canvas->width = width;
canvas->height = height;
}
uint8_t canvas_width(CanvasApi* api) {
furi_assert(api);
Canvas* canvas = (Canvas*)api;
uint8_t canvas_width(Canvas* canvas) {
furi_assert(canvas);
return canvas->width;
}
uint8_t canvas_height(CanvasApi* api) {
furi_assert(api);
Canvas* canvas = (Canvas*)api;
uint8_t canvas_height(Canvas* canvas) {
furi_assert(canvas);
return canvas->height;
}
void canvas_clear(CanvasApi* api) {
furi_assert(api);
Canvas* canvas = (Canvas*)api;
void canvas_clear(Canvas* canvas) {
furi_assert(canvas);
u8g2_ClearBuffer(&canvas->fb);
}
void canvas_color_set(CanvasApi* api, Color color) {
furi_assert(api);
Canvas* canvas = (Canvas*)api;
void canvas_set_color(Canvas* canvas, Color color) {
furi_assert(canvas);
u8g2_SetDrawColor(&canvas->fb, color);
}
void canvas_font_set(CanvasApi* api, Font font) {
furi_assert(api);
Canvas* canvas = (Canvas*)api;
void canvas_set_font(Canvas* canvas, Font font) {
furi_assert(canvas);
u8g2_SetFontMode(&canvas->fb, 1);
if(font == FontPrimary) {
u8g2_SetFont(&canvas->fb, u8g2_font_helvB08_tf);
@ -140,52 +96,46 @@ void canvas_font_set(CanvasApi* api, Font font) {
}
}
void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str) {
furi_assert(api);
void canvas_draw_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str) {
furi_assert(canvas);
if(!str) return;
Canvas* canvas = (Canvas*)api;
x += canvas->offset_x;
y += canvas->offset_y;
u8g2_DrawStr(&canvas->fb, x, y, str);
}
void canvas_icon_draw(CanvasApi* api, uint8_t x, uint8_t y, Icon* icon) {
furi_assert(api);
void canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, Icon* icon) {
furi_assert(canvas);
if(!icon) return;
Canvas* canvas = (Canvas*)api;
x += canvas->offset_x;
y += canvas->offset_y;
u8g2_DrawXBM(
&canvas->fb, x, y, icon_get_width(icon), icon_get_height(icon), icon_get_data(icon));
}
void canvas_dot_draw(CanvasApi* api, uint8_t x, uint8_t y) {
furi_assert(api);
Canvas* canvas = (Canvas*)api;
void canvas_draw_dot(Canvas* canvas, uint8_t x, uint8_t y) {
furi_assert(canvas);
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;
void canvas_draw_box(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
furi_assert(canvas);
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;
void canvas_draw_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
furi_assert(canvas);
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;
void canvas_draw_line(Canvas* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
furi_assert(canvas);
x1 += canvas->offset_x;
y1 += canvas->offset_y;
x2 += canvas->offset_x;
@ -194,22 +144,20 @@ void canvas_draw_line(CanvasApi* api, uint8_t x1, uint8_t y1, uint8_t x2, uint8_
}
void canvas_draw_xbm(
CanvasApi* api,
Canvas* canvas,
uint8_t x,
uint8_t y,
uint8_t w,
uint8_t h,
const uint8_t* bitmap) {
furi_assert(api);
Canvas* canvas = (Canvas*)api;
furi_assert(canvas);
x += canvas->offset_x;
y += canvas->offset_y;
u8g2_DrawXBM(&canvas->fb, x, y, w, h, bitmap);
}
void canvas_draw_glyph(CanvasApi* api, uint8_t x, uint8_t y, uint16_t ch) {
furi_assert(api);
Canvas* canvas = (Canvas*)api;
void canvas_draw_glyph(Canvas* canvas, uint8_t x, uint8_t y, uint16_t ch) {
furi_assert(canvas);
x += canvas->offset_x;
y += canvas->offset_y;
u8g2_DrawGlyph(&canvas->fb, x, y, ch);

View file

@ -11,28 +11,77 @@ typedef enum {
typedef enum { FontPrimary = 0x00, FontSecondary = 0x01, FontGlyph = 0x02 } Font;
typedef struct CanvasApi CanvasApi;
struct CanvasApi {
uint8_t (*width)(CanvasApi* canvas);
uint8_t (*height)(CanvasApi* canvas);
typedef struct Canvas Canvas;
void (*clear)(CanvasApi* canvas);
/*
* Canvas width
* @return width in pixels.
*/
uint8_t canvas_width(Canvas* canvas);
void (*set_color)(CanvasApi* canvas, Color color);
void (*set_font)(CanvasApi* canvas, Font font);
/*
* Canvas height
* @return height in pixels.
*/
uint8_t canvas_height(Canvas* canvas);
void (*draw_str)(CanvasApi* canvas, uint8_t x, uint8_t y, const char* str);
void (*draw_icon)(CanvasApi* canvas, uint8_t x, uint8_t y, Icon* icon);
void (*draw_xbm)(
CanvasApi* canvas,
/*
* Clear canvas, clear rendering buffer
*/
void canvas_clear(Canvas* canvas);
/*
* Set drawing color
*/
void canvas_set_color(Canvas* canvas, Color color);
/*
* Set drawing font
*/
void canvas_set_font(Canvas* canvas, Font font);
/*
* Draw string at position of baseline defined by x, y.
*/
void canvas_draw_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str);
/*
* Draw icon at position defined by x,y.
*/
void canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, Icon* icon);
/*
* Draw xbm icon of width, height at position defined by x,y.
*/
void canvas_draw_xbm(
Canvas* canvas,
uint8_t x,
uint8_t y,
uint8_t w,
uint8_t h,
const uint8_t* bitmap);
void (*draw_dot)(CanvasApi* canvas, uint8_t x, uint8_t y);
void (*draw_box)(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
void (*draw_frame)(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
void (*draw_line)(CanvasApi* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);
void (*draw_glyph)(CanvasApi* canvas, uint8_t x, uint8_t y, uint16_t ch);
};
/*
* Draw dot at x,y
*/
void canvas_draw_dot(Canvas* canvas, uint8_t x, uint8_t y);
/*
* Draw box of width, height at x,y
*/
void canvas_draw_box(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
/*
* Draw frame of width, height at x,y
*/
void canvas_draw_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
/*
* Draw line from x1,y1 to x2,y2
*/
void canvas_draw_line(Canvas* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);
/*
* Draw glyph
*/
void canvas_draw_glyph(Canvas* canvas, uint8_t x, uint8_t y, uint16_t ch);

View file

@ -1,15 +1,32 @@
#pragma once
CanvasApi* canvas_api_init();
#include "canvas.h"
void canvas_api_free(CanvasApi* api);
/*
* Allocate memory and initialize canvas
*/
Canvas* canvas_init();
void canvas_reset(CanvasApi* api);
/*
* Free canvas memory
*/
void canvas_free(Canvas* canvas);
void canvas_commit(CanvasApi* api);
/*
* Reset canvas drawing tools configuration
*/
void canvas_reset(Canvas* canvas);
/*
* Commit canvas. Send buffer to display
*/
void canvas_commit(Canvas* canvas);
/*
* Set drawing region relative to real screen buffer
*/
void canvas_frame_set(
CanvasApi* api,
Canvas* canvas,
uint8_t offset_x,
uint8_t offset_y,
uint8_t width,

View file

@ -1,31 +1,31 @@
#include "elements.h"
void elements_scrollbar(CanvasApi* canvas, uint8_t pos, uint8_t total) {
uint8_t width = canvas->width(canvas);
uint8_t height = canvas->height(canvas);
void elements_scrollbar(Canvas* canvas, uint8_t pos, uint8_t total) {
uint8_t width = canvas_width(canvas);
uint8_t height = canvas_height(canvas);
// prevent overflows
canvas->set_color(canvas, ColorWhite);
canvas->draw_box(canvas, width - 3, 0, 3, height);
canvas_set_color(canvas, ColorWhite);
canvas_draw_box(canvas, width - 3, 0, 3, height);
// dot line
canvas->set_color(canvas, ColorBlack);
canvas_set_color(canvas, ColorBlack);
for(uint8_t i = 0; i < height; i += 2) {
canvas->draw_dot(canvas, width - 2, i);
canvas_draw_dot(canvas, width - 2, i);
}
// Position block
if(total) {
uint8_t block_h = ((float)height) / total;
canvas->draw_box(canvas, width - 3, block_h * pos, 3, block_h);
canvas_draw_box(canvas, width - 3, block_h * pos, 3, block_h);
}
}
void elements_frame(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
canvas->draw_line(canvas, x + 2, y, x + width - 2, y);
canvas->draw_line(canvas, x + 1, y + height - 1, x + width, y + height - 1);
canvas->draw_line(canvas, x + 2, y + height, x + width - 1, y + height);
void elements_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
canvas_draw_line(canvas, x + 2, y, x + width - 2, y);
canvas_draw_line(canvas, x + 1, y + height - 1, x + width, y + height - 1);
canvas_draw_line(canvas, x + 2, y + height, x + width - 1, y + height);
canvas->draw_line(canvas, x, y + 2, x, y + height - 2);
canvas->draw_line(canvas, x + width - 1, y + 1, x + width - 1, y + height - 2);
canvas->draw_line(canvas, x + width, y + 2, x + width, y + height - 2);
canvas_draw_line(canvas, x, y + 2, x, y + height - 2);
canvas_draw_line(canvas, x + width - 1, y + 1, x + width - 1, y + height - 2);
canvas_draw_line(canvas, x + width, y + 2, x + width, y + height - 2);
canvas->draw_dot(canvas, x + 1, y + 1);
canvas_draw_dot(canvas, x + 1, y + 1);
}

View file

@ -3,6 +3,17 @@
#include <stdint.h>
#include "canvas.h"
void elements_scrollbar(CanvasApi* canvas, uint8_t pos, uint8_t total);
/*
* Draw scrollbar on canvas.
* width 3px, height equal to canvas height
* @param pos - current element of total elements
* @param total - total elements
*/
void elements_scrollbar(Canvas* canvas, uint8_t pos, uint8_t total);
void elements_frame(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
/*
* Draw rounded frame
* @param x, y - top left corner coordinates
* @param width, height - frame width and height
*/
void elements_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height);

View file

@ -15,9 +15,8 @@
ARRAY_DEF(WidgetArray, Widget*, M_PTR_OPLIST);
struct Gui {
GuiApi api;
GuiEvent* event;
CanvasApi* canvas_api;
Canvas* canvas;
WidgetArray_t layers[GuiLayerMAX];
osMutexId_t mutex;
};
@ -41,10 +40,10 @@ void gui_update(Gui* gui) {
}
bool gui_redraw_fs(Gui* gui) {
canvas_frame_set(gui->canvas_api, 0, 0, GUI_DISPLAY_WIDTH, GUI_DISPLAY_HEIGHT);
canvas_frame_set(gui->canvas, 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);
widget_draw(widget, gui->canvas);
return true;
} else {
return false;
@ -67,9 +66,9 @@ void gui_redraw_status_bar(Gui* gui) {
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);
x -= (width + 2);
canvas_frame_set(gui->canvas, x, GUI_STATUS_BAR_Y, width, GUI_STATUS_BAR_HEIGHT);
widget_draw(widget, gui->canvas);
}
WidgetArray_next(it);
}
@ -83,29 +82,29 @@ void gui_redraw_status_bar(Gui* gui) {
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;
canvas_frame_set(gui->canvas, x, GUI_STATUS_BAR_Y, width, GUI_STATUS_BAR_HEIGHT);
widget_draw(widget, gui->canvas);
x += (width + 2);
}
WidgetArray_next(it);
}
}
bool gui_redraw_normal(Gui* gui) {
canvas_frame_set(gui->canvas_api, GUI_MAIN_X, GUI_MAIN_Y, GUI_MAIN_WIDTH, GUI_MAIN_HEIGHT);
canvas_frame_set(gui->canvas, 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);
widget_draw(widget, gui->canvas);
return true;
}
return false;
}
bool gui_redraw_none(Gui* gui) {
canvas_frame_set(gui->canvas_api, GUI_MAIN_X, GUI_MAIN_Y, GUI_MAIN_WIDTH, GUI_MAIN_HEIGHT);
canvas_frame_set(gui->canvas, 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);
widget_draw(widget, gui->canvas);
return true;
}
@ -116,7 +115,7 @@ void gui_redraw(Gui* gui) {
furi_assert(gui);
gui_lock(gui);
canvas_reset(gui->canvas_api);
canvas_reset(gui->canvas);
if(!gui_redraw_fs(gui)) {
if(!gui_redraw_normal(gui)) {
@ -125,7 +124,7 @@ void gui_redraw(Gui* gui) {
gui_redraw_status_bar(gui);
}
canvas_commit(gui->canvas_api);
canvas_commit(gui->canvas);
gui_unlock(gui);
}
@ -156,11 +155,10 @@ void gui_unlock(Gui* gui) {
furi_check(osMutexRelease(gui->mutex) == osOK);
}
void gui_add_widget(GuiApi* gui_api, Widget* widget, GuiLayer layer) {
furi_assert(gui_api);
void gui_add_widget(Gui* gui, Widget* widget, GuiLayer layer) {
furi_assert(gui);
furi_assert(widget);
furi_check(layer < GuiLayerMAX);
Gui* gui = (Gui*)gui_api;
gui_lock(gui);
WidgetArray_push_back(gui->layers[layer], widget);
@ -169,10 +167,9 @@ void gui_add_widget(GuiApi* gui_api, Widget* widget, GuiLayer layer) {
gui_update(gui);
}
void gui_remove_widget(GuiApi* gui_api, Widget* widget) {
furi_assert(gui_api);
void gui_remove_widget(Gui* gui, Widget* widget) {
furi_assert(gui);
furi_assert(widget);
Gui* gui = (Gui*)gui_api;
gui_lock(gui);
@ -193,16 +190,13 @@ void gui_remove_widget(GuiApi* gui_api, Widget* widget) {
Gui* gui_alloc() {
Gui* gui = furi_alloc(sizeof(Gui));
// Set API functions
gui->api.add_widget = gui_add_widget;
gui->api.remove_widget = gui_remove_widget;
// Allocate mutex
gui->mutex = osMutexNew(NULL);
furi_check(gui->mutex);
// Event dispatcher
gui->event = gui_event_alloc();
// Drawing canvas api
gui->canvas_api = canvas_api_init();
// Drawing canvas
gui->canvas = canvas_init();
// Compose Layers
for(size_t i = 0; i < GuiLayerMAX; i++) {
WidgetArray_init(gui->layers[i]);

View file

@ -27,8 +27,16 @@ typedef enum {
GuiLayerMAX /* Don't use or move, special value */
} GuiLayer;
typedef struct GuiApi GuiApi;
struct GuiApi {
void (*add_widget)(GuiApi* gui_api, Widget* widget, GuiLayer layer);
void (*remove_widget)(GuiApi* gui_api, Widget* widget);
};
typedef struct Gui Gui;
/*
* Add widget to widget tree
* @remarks thread safe
*/
void gui_add_widget(Gui* gui, Widget* widget, GuiLayer layer);
/*
* Remove widget from rendering tree
* @remarks thread safe
*/
void gui_remove_widget(Gui* gui, Widget* widget);

View file

@ -1,4 +1,3 @@
#include "icon.h"
#include "icon_i.h"
#include <cmsis_os2.h>

View file

@ -6,16 +6,38 @@
typedef struct IconData IconData;
typedef struct Icon Icon;
/*
* Allocate icon instance with const icon data.
* always returns Icon or stops system if not enough memory
*/
Icon* icon_alloc(const IconData* data);
/*
* Release icon instance
*/
void icon_free(Icon* icon);
/*
* Get icon width
*/
uint8_t icon_get_width(Icon* icon);
/*
* Get icon height
*/
uint8_t icon_get_height(Icon* icon);
/*
* Check if icon is animated
*/
bool icon_is_animated(Icon* icon);
/*
* Start icon animation
*/
void icon_start_animation(Icon* icon);
/*
* Stop icon animation
*/
void icon_stop_animation(Icon* icon);

View file

@ -1,5 +1,7 @@
#pragma once
#include "icon.h"
#include <stdint.h>
struct IconData {
@ -16,6 +18,12 @@ struct Icon {
uint32_t tick;
};
/*
* Get pointer to current frame data
*/
const uint8_t* icon_get_data(Icon* icon);
/*
* Advance to next frame
*/
void icon_next_frame(Icon* icon);

View file

@ -1,4 +1,3 @@
#include "widget.h"
#include "widget_i.h"
#include <cmsis_os.h>
@ -75,16 +74,17 @@ void widget_update(Widget* widget) {
void widget_gui_set(Widget* widget, Gui* gui) {
furi_assert(widget);
furi_assert(gui);
widget->gui = gui;
}
void widget_draw(Widget* widget, CanvasApi* canvas_api) {
void widget_draw(Widget* widget, Canvas* canvas) {
furi_assert(widget);
furi_assert(canvas_api);
furi_assert(canvas);
furi_check(widget->gui);
if(widget->draw_callback) {
widget->draw_callback(canvas_api, widget->draw_callback_context);
widget->draw_callback(canvas, widget->draw_callback_context);
}
}

View file

@ -5,7 +5,16 @@
typedef struct Widget Widget;
typedef void (*WidgetDrawCallback)(CanvasApi* api, void* context);
/*
* Widget Draw callback
* @warning called from GUI thread
*/
typedef void (*WidgetDrawCallback)(Canvas* api, void* context);
/*
* Widget Input callback
* @warning called from GUI thread
*/
typedef void (*WidgetInputCallback)(InputEvent* event, void* context);
/*

View file

@ -1,32 +1,39 @@
#pragma once
#include "gui_i.h"
#include "widget.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.
* Set GUI reference.
* To be used by GUI, called upon widget tree insert
* @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.
* To be used by GUI, called on tree redraw.
* @param canvas - canvas to draw at.
*/
void widget_draw(Widget* widget, CanvasApi* canvas_api);
void widget_draw(Widget* widget, Canvas* canvas);
/*
* Process input. Calls input callback.
* Process input. Calls input callbac
* To be used by GUI, called on input dispatch.
* @param event - pointer to input event.
*/
void widget_input(Widget* widget, InputEvent* event);

View file

@ -56,15 +56,15 @@ void AppiButton::run() {
}
// render app
void AppiButton::render(CanvasApi* canvas) {
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
canvas->draw_str(canvas, 2, 12, "iButton");
void AppiButton::render(Canvas* canvas) {
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 2, 12, "iButton");
mode[state.mode_index]->render(canvas, &state);
}
void AppiButton::render_dallas_list(CanvasApi* canvas, AppiButtonState* state) {
void AppiButton::render_dallas_list(Canvas* canvas, AppiButtonState* state) {
const uint8_t buffer_size = 50;
char buf[buffer_size];
for(uint8_t i = 0; i < state->dallas_address_count; i++) {
@ -82,11 +82,11 @@ void AppiButton::render_dallas_list(CanvasApi* canvas, AppiButtonState* state) {
state->dallas_address[i][5],
state->dallas_address[i][6],
state->dallas_address[i][7]);
canvas->draw_str(canvas, 2, 37 + i * 12, buf);
canvas_draw_str(canvas, 2, 37 + i * 12, buf);
}
}
void AppiButton::render_cyfral_list(CanvasApi* canvas, AppiButtonState* state) {
void AppiButton::render_cyfral_list(Canvas* canvas, AppiButtonState* state) {
const uint8_t buffer_size = 50;
char buf[buffer_size];
for(uint8_t i = 0; i < state->cyfral_address_count; i++) {
@ -100,7 +100,7 @@ void AppiButton::render_cyfral_list(CanvasApi* canvas, AppiButtonState* state) {
state->cyfral_address[i][1],
state->cyfral_address[i][2],
state->cyfral_address[i][3]);
canvas->draw_str(canvas, 2, 37 + i * 12, buf);
canvas_draw_str(canvas, 2, 37 + i * 12, buf);
}
}

View file

@ -60,9 +60,9 @@ public:
AppTemplateMode<AppiButtonState, AppiButtonEvent>* mode[modes_count];
void run();
void render(CanvasApi* canvas);
void render_dallas_list(CanvasApi* canvas, AppiButtonState* state);
void render_cyfral_list(CanvasApi* canvas, AppiButtonState* state);
void render(Canvas* canvas);
void render_dallas_list(Canvas* canvas, AppiButtonState* state);
void render_cyfral_list(Canvas* canvas, AppiButtonState* state);
void blink_red();
void blink_green();

View file

@ -9,7 +9,7 @@ public:
CyfralEmulator* cyfral_emulator;
void event(AppiButtonEvent* event, AppiButtonState* state);
void render(CanvasApi* canvas, AppiButtonState* state);
void render(Canvas* canvas, AppiButtonState* state);
void acquire();
void release();
@ -39,9 +39,9 @@ void AppiButtonModeCyfralEmulate::event(AppiButtonEvent* event, AppiButtonState*
}
}
void AppiButtonModeCyfralEmulate::render(CanvasApi* canvas, AppiButtonState* state) {
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 25, "< Cyfral emulate");
void AppiButtonModeCyfralEmulate::render(Canvas* canvas, AppiButtonState* state) {
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 25, "< Cyfral emulate");
app->render_cyfral_list(canvas, state);
}

View file

@ -9,7 +9,7 @@ public:
CyfralReader* reader;
void event(AppiButtonEvent* event, AppiButtonState* state);
void render(CanvasApi* canvas, AppiButtonState* state);
void render(Canvas* canvas, AppiButtonState* state);
void acquire();
void release();
@ -37,9 +37,9 @@ void AppiButtonModeCyfralRead::event(AppiButtonEvent* event, AppiButtonState* st
}
}
void AppiButtonModeCyfralRead::render(CanvasApi* canvas, AppiButtonState* state) {
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 25, "< Cyfral read >");
void AppiButtonModeCyfralRead::render(Canvas* canvas, AppiButtonState* state) {
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 25, "< Cyfral read >");
app->render_cyfral_list(canvas, state);
}

View file

@ -11,7 +11,7 @@ public:
DS1990 key;
void event(AppiButtonEvent* event, AppiButtonState* state);
void render(CanvasApi* canvas, AppiButtonState* state);
void render(Canvas* canvas, AppiButtonState* state);
void acquire();
void release();
@ -46,9 +46,9 @@ void AppiButtonModeDallasEmulate::event(AppiButtonEvent* event, AppiButtonState*
}
}
void AppiButtonModeDallasEmulate::render(CanvasApi* canvas, AppiButtonState* state) {
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 25, "< Dallas emulate >");
void AppiButtonModeDallasEmulate::render(Canvas* canvas, AppiButtonState* state) {
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 25, "< Dallas emulate >");
app->render_dallas_list(canvas, state);
}

View file

@ -10,7 +10,7 @@ public:
OneWireGpio* onewire;
void event(AppiButtonEvent* event, AppiButtonState* state);
void render(CanvasApi* canvas, AppiButtonState* state);
void render(Canvas* canvas, AppiButtonState* state);
void acquire();
void release();
@ -69,9 +69,9 @@ void AppiButtonModeDallasRead::event(AppiButtonEvent* event, AppiButtonState* st
}
}
void AppiButtonModeDallasRead::render(CanvasApi* canvas, AppiButtonState* state) {
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 25, "Dallas read >");
void AppiButtonModeDallasRead::render(Canvas* canvas, AppiButtonState* state) {
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 25, "Dallas read >");
app->render_dallas_list(canvas, state);
}

View file

@ -5,7 +5,7 @@ template <class TState, class TEvents> class AppTemplateMode {
public:
const char* name;
virtual void event(TEvents* event, TState* state) = 0;
virtual void render(CanvasApi* canvas, TState* state) = 0;
virtual void render(Canvas* canvas, TState* state) = 0;
virtual void acquire() = 0;
virtual void release() = 0;
};

View file

@ -27,15 +27,15 @@ typedef struct {
} State;
typedef void (*ModeInput)(AppEvent*, State*);
typedef void (*ModeRender)(CanvasApi*, State*);
typedef void (*ModeRender)(Canvas*, State*);
void input_carrier(AppEvent* event, State* state);
void render_carrier(CanvasApi* canvas, State* state);
void render_carrier(Canvas* canvas, State* state);
void input_nec(AppEvent* event, State* state);
void render_nec(CanvasApi* canvas, State* state);
void render_carrier(CanvasApi* canvas, State* state);
void render_nec(Canvas* canvas, State* state);
void render_carrier(Canvas* canvas, State* state);
void input_samsung(AppEvent* event, State* state);
void render_samsung(CanvasApi* canvas, State* state);
void render_samsung(Canvas* canvas, State* state);
typedef struct {
ModeRender render;
@ -76,24 +76,24 @@ const SamsungPacket samsung_packets[] = {
const float duty_cycles[] = {0.1, 0.25, 0.333, 0.5, 1.0};
void render_carrier(CanvasApi* canvas, State* state) {
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 25, "carrier mode >");
canvas->draw_str(canvas, 2, 37, "? /\\ freq | \\/ duty cycle");
void render_carrier(Canvas* canvas, State* state) {
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 25, "carrier mode >");
canvas_draw_str(canvas, 2, 37, "? /\\ freq | \\/ duty cycle");
{
char buf[24];
sprintf(buf, "frequency: %u Hz", state->carrier_freq);
canvas->draw_str(canvas, 2, 50, buf);
canvas_draw_str(canvas, 2, 50, buf);
sprintf(
buf, "duty cycle: %d/1000", (int)(duty_cycles[state->carrier_duty_cycle_id] * 1000));
canvas->draw_str(canvas, 2, 62, buf);
canvas_draw_str(canvas, 2, 62, buf);
}
}
void render_nec(CanvasApi* canvas, State* state) {
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 25, "< nec mode >");
canvas->draw_str(canvas, 2, 37, "? /\\ \\/ packet");
void render_nec(Canvas* canvas, State* state) {
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 25, "< nec mode >");
canvas_draw_str(canvas, 2, 37, "? /\\ \\/ packet");
{
char buf[24];
sprintf(
@ -101,14 +101,14 @@ void render_nec(CanvasApi* canvas, State* state) {
"packet: %02X %02X",
nec_packets[state->nec_packet_id].addr,
nec_packets[state->nec_packet_id].data);
canvas->draw_str(canvas, 2, 50, buf);
canvas_draw_str(canvas, 2, 50, buf);
}
}
void render_samsung(CanvasApi* canvas, State* state) {
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 25, "< samsung32 mode");
canvas->draw_str(canvas, 2, 37, "? /\\ \\/ packet");
void render_samsung(Canvas* canvas, State* state) {
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 25, "< samsung32 mode");
canvas_draw_str(canvas, 2, 37, "? /\\ \\/ packet");
{
char buf[24];
sprintf(
@ -116,7 +116,7 @@ void render_samsung(CanvasApi* canvas, State* state) {
"packet: %02X %02X",
samsung_packets[state->samsung_packet_id].addr,
samsung_packets[state->samsung_packet_id].data);
canvas->draw_str(canvas, 2, 50, buf);
canvas_draw_str(canvas, 2, 50, buf);
}
}
@ -206,13 +206,13 @@ void input_samsung(AppEvent* event, State* state) {
}
}
static void render_callback(CanvasApi* canvas, void* ctx) {
static void render_callback(Canvas* canvas, void* ctx) {
State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25);
canvas->clear(canvas);
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
canvas->draw_str(canvas, 2, 12, "irda test");
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 2, 12, "irda test");
modes[state->mode_id].render(canvas, state);
@ -256,12 +256,12 @@ void irda(void* p) {
widget_input_callback_set(widget, input_callback, event_queue);
// Open GUI and register widget
GuiApi* gui = (GuiApi*)furi_open("gui");
Gui* gui = (Gui*)furi_open("gui");
if(gui == NULL) {
printf("gui is not available\n");
furiac_exit(NULL);
}
gui->add_widget(gui, widget, GuiLayerFullscreen);
gui_add_widget(gui, widget, GuiLayerFullscreen);
// Red LED
// TODO open record

View file

@ -15,17 +15,17 @@ struct Irukagotchi {
ValueMutex* menu_vm;
};
void irukagotchi_draw_callback(CanvasApi* canvas, void* context) {
void irukagotchi_draw_callback(Canvas* canvas, void* context) {
Irukagotchi* irukagotchi = context;
canvas->clear(canvas);
canvas->set_color(canvas, ColorBlack);
canvas->draw_icon(canvas, 128 - 80, 0, irukagotchi->icon);
canvas->set_font(canvas, FontSecondary);
canvas->draw_str(canvas, 2, 10, TARGET " " BUILD_DATE);
canvas->draw_str(canvas, 2, 22, GIT_BRANCH);
canvas->draw_str(canvas, 2, 34, GIT_BRANCH_NUM);
canvas->draw_str(canvas, 2, 46, GIT_COMMIT);
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_draw_icon(canvas, 128 - 80, 0, irukagotchi->icon);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 10, TARGET " " BUILD_DATE);
canvas_draw_str(canvas, 2, 22, GIT_BRANCH);
canvas_draw_str(canvas, 2, 34, GIT_BRANCH_NUM);
canvas_draw_str(canvas, 2, 46, GIT_COMMIT);
}
void irukagotchi_input_callback(InputEvent* event, void* context) {
@ -56,12 +56,8 @@ Irukagotchi* irukagotchi_alloc() {
void irukagotchi_task() {
Irukagotchi* irukagotchi = irukagotchi_alloc();
FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL);
furi_check(gui_record);
GuiApi* gui = furi_take(gui_record);
furi_check(gui);
gui->add_widget(gui, irukagotchi->widget, GuiLayerNone);
furi_commit(gui_record);
Gui* gui = furi_open("gui");
gui_add_widget(gui, irukagotchi->widget, GuiLayerNone);
furiac_ready();

View file

@ -22,24 +22,24 @@ typedef struct {
uint32_t em_data;
} State;
static void render_callback(CanvasApi* canvas, void* ctx) {
static void render_callback(Canvas* canvas, void* ctx) {
State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25);
canvas->clear(canvas);
canvas_clear(canvas);
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
canvas->draw_str(canvas, 2, 12, "LF RFID");
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 2, 12, "LF RFID");
canvas->draw_str(canvas, 2, 24, state->on ? "Reading" : "Emulating");
canvas_draw_str(canvas, 2, 24, state->on ? "Reading" : "Emulating");
char buf[14];
sprintf(buf, "%d kHz", (int)state->freq_khz);
canvas->draw_str(canvas, 2, 36, buf);
canvas_draw_str(canvas, 2, 36, buf);
sprintf(buf, "%02d:%010ld", state->customer_id, state->em_data);
canvas->draw_str(canvas, 2, 45, buf);
canvas_draw_str(canvas, 2, 45, buf);
release_mutex((ValueMutex*)ctx, state);
}
@ -202,12 +202,12 @@ void lf_rfid_workaround(void* p) {
widget_input_callback_set(widget, input_callback, event_queue);
// Open GUI and register widget
GuiApi* gui = (GuiApi*)furi_open("gui");
Gui* gui = (Gui*)furi_open("gui");
if(gui == NULL) {
printf("gui is not available\n");
furiac_exit(NULL);
}
gui->add_widget(gui, widget, GuiLayerFullscreen);
gui_add_widget(gui, widget, GuiLayerFullscreen);
AppEvent event;
uint32_t prev_dwt;

View file

@ -24,7 +24,7 @@ struct Menu {
MenuItem* current;
};
void menu_widget_callback(CanvasApi* canvas, void* context);
void menu_widget_callback(Canvas* canvas, void* context);
ValueMutex* menu_init() {
Menu* menu = furi_alloc(sizeof(Menu));
@ -42,9 +42,9 @@ ValueMutex* menu_init() {
menu->widget = widget_alloc();
// Open GUI and register fullscreen widget
GuiApi* gui = furi_open("gui");
Gui* gui = furi_open("gui");
furi_check(gui);
gui->add_widget(gui, menu->widget, GuiLayerFullscreen);
gui_add_widget(gui, menu->widget, GuiLayerFullscreen);
widget_enabled_set(menu->widget, false);
widget_draw_callback_set(menu->widget, menu_widget_callback, menu_mutex);
@ -57,11 +57,6 @@ void menu_build_main(Menu* menu) {
furi_assert(menu);
// Root point
menu->root = menu_item_alloc_menu(NULL, NULL);
Icon* icon = assets_icons_get(A_Bluetooth_14);
menu->settings = menu_item_alloc_menu("Setting", icon);
// menu_item_add(menu, menu->settings);
}
void menu_item_add(Menu* menu, MenuItem* item) {
@ -72,13 +67,13 @@ void menu_settings_item_add(Menu* menu, MenuItem* item) {
menu_item_subitem_add(menu->settings, item);
}
void menu_draw_primary(Menu* menu, CanvasApi* canvas) {
void menu_draw_primary(Menu* menu, Canvas* canvas) {
}
void menu_draw_secondary(Menu* menu, CanvasApi* canvas) {
void menu_draw_secondary(Menu* menu, Canvas* canvas) {
}
void menu_widget_callback(CanvasApi* canvas, void* context) {
void menu_widget_callback(Canvas* canvas, void* context) {
furi_assert(canvas);
furi_assert(context);
@ -87,8 +82,8 @@ void menu_widget_callback(CanvasApi* canvas, void* context) {
furi_assert(menu->current);
canvas->clear(canvas);
canvas->set_color(canvas, ColorBlack);
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
size_t position = menu_item_get_position(menu->current);
MenuItemArray_t* items = menu_item_get_subitems(menu->current);
@ -97,30 +92,30 @@ void menu_widget_callback(CanvasApi* canvas, void* context) {
MenuItem* item;
size_t shift_position;
// First line
canvas->set_font(canvas, FontSecondary);
canvas_set_font(canvas, FontSecondary);
shift_position = (0 + position + items_count - 1) % (MenuItemArray_size(*items));
item = *MenuItemArray_get(*items, shift_position);
canvas->draw_icon(canvas, 4, 3, menu_item_get_icon(item));
canvas->draw_str(canvas, 22, 14, menu_item_get_label(item));
canvas_draw_icon(canvas, 4, 3, menu_item_get_icon(item));
canvas_draw_str(canvas, 22, 14, menu_item_get_label(item));
// Second line main
canvas->set_font(canvas, FontPrimary);
canvas_set_font(canvas, FontPrimary);
shift_position = (1 + position + items_count - 1) % (MenuItemArray_size(*items));
item = *MenuItemArray_get(*items, shift_position);
canvas->draw_icon(canvas, 4, 25, menu_item_get_icon(item));
canvas->draw_str(canvas, 22, 36, menu_item_get_label(item));
canvas_draw_icon(canvas, 4, 25, menu_item_get_icon(item));
canvas_draw_str(canvas, 22, 36, menu_item_get_label(item));
// Third line
canvas->set_font(canvas, FontSecondary);
canvas_set_font(canvas, FontSecondary);
shift_position = (2 + position + items_count - 1) % (MenuItemArray_size(*items));
item = *MenuItemArray_get(*items, shift_position);
canvas->draw_icon(canvas, 4, 47, menu_item_get_icon(item));
canvas->draw_str(canvas, 22, 58, menu_item_get_label(item));
canvas_draw_icon(canvas, 4, 47, menu_item_get_icon(item));
canvas_draw_str(canvas, 22, 58, menu_item_get_label(item));
// Frame and scrollbar
// elements_frame(canvas, 0, 0, 128 - 5, 21);
elements_frame(canvas, 0, 21, 128 - 5, 21);
// elements_frame(canvas, 0, 42, 128 - 5, 21);
elements_scrollbar(canvas, position, items_count);
} else {
canvas->draw_str(canvas, 2, 32, "Empty");
canvas_draw_str(canvas, 2, 32, "Empty");
elements_scrollbar(canvas, 0, 0);
}

View file

@ -226,13 +226,13 @@ const char* get_note_len_name(const MelodyEventRecord* note_record) {
}
}
static void render_callback(CanvasApi* canvas, void* ctx) {
static void render_callback(Canvas* canvas, void* ctx) {
State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25);
canvas->clear(canvas);
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
canvas->draw_str(canvas, 0, 12, "MusicPlayer");
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 0, 12, "MusicPlayer");
uint8_t x_pos = 0;
uint8_t y_pos = 24;
@ -247,24 +247,24 @@ static void render_callback(CanvasApi* canvas, void* ctx) {
// white keys
for(size_t i = 0; i < 7; i++) {
if(is_white_note(state->note_record, i)) {
canvas->draw_box(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h);
canvas_draw_box(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h);
} else {
canvas->draw_frame(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h);
canvas_draw_frame(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h);
}
}
// black keys
for(size_t i = 0; i < 7; i++) {
if(i != 2 && i != 6) {
canvas->set_color(canvas, ColorWhite);
canvas->draw_box(
canvas_set_color(canvas, ColorWhite);
canvas_draw_box(
canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h);
canvas->set_color(canvas, ColorBlack);
canvas_set_color(canvas, ColorBlack);
if(is_black_note(state->note_record, i)) {
canvas->draw_box(
canvas_draw_box(
canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h);
} else {
canvas->draw_frame(
canvas_draw_frame(
canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h);
}
}
@ -274,28 +274,28 @@ static void render_callback(CanvasApi* canvas, void* ctx) {
x_pos = 124;
y_pos = 0;
const uint8_t volume_h = (64 / (state->volume_id_max - 1)) * state->volume_id;
canvas->draw_frame(canvas, x_pos, y_pos, 4, 64);
canvas->draw_box(canvas, x_pos, y_pos + (64 - volume_h), 4, volume_h);
canvas_draw_frame(canvas, x_pos, y_pos, 4, 64);
canvas_draw_box(canvas, x_pos, y_pos + (64 - volume_h), 4, volume_h);
// note stack widget
x_pos = 73;
y_pos = 0;
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
canvas->draw_frame(canvas, x_pos, y_pos, 49, 64);
canvas->draw_line(canvas, x_pos + 28, 0, x_pos + 28, 64);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
canvas_draw_frame(canvas, x_pos, y_pos, 49, 64);
canvas_draw_line(canvas, x_pos + 28, 0, x_pos + 28, 64);
for(uint8_t i = 0; i < note_stack_size; i++) {
if(i == 0) {
canvas->draw_box(canvas, x_pos, y_pos + 48, 49, 16);
canvas->set_color(canvas, ColorWhite);
canvas_draw_box(canvas, x_pos, y_pos + 48, 49, 16);
canvas_set_color(canvas, ColorWhite);
} else {
canvas->set_color(canvas, ColorBlack);
canvas_set_color(canvas, ColorBlack);
}
canvas->draw_str(canvas, x_pos + 4, 64 - 16 * i - 3, get_note_name(state->note_stack[i]));
canvas->draw_str(
canvas_draw_str(canvas, x_pos + 4, 64 - 16 * i - 3, get_note_name(state->note_stack[i]));
canvas_draw_str(
canvas, x_pos + 31, 64 - 16 * i - 3, get_note_len_name(state->note_stack[i]));
canvas->draw_line(canvas, x_pos, 64 - 16 * i, x_pos + 48, 64 - 16 * i);
canvas_draw_line(canvas, x_pos, 64 - 16 * i, x_pos + 48, 64 - 16 * i);
}
release_mutex((ValueMutex*)ctx, state);
@ -376,12 +376,12 @@ void music_player(void* p) {
widget_input_callback_set(widget, input_callback, event_queue);
// Open GUI and register widget
GuiApi* gui = (GuiApi*)furi_open("gui");
Gui* gui = (Gui*)furi_open("gui");
if(gui == NULL) {
printf("gui is not available\n");
furiac_exit(NULL);
}
gui->add_widget(gui, widget, GuiLayerFullscreen);
gui_add_widget(gui, widget, GuiLayerFullscreen);
// open input record
PubSub* input_events_record = furi_open("input_events");

View file

@ -2,37 +2,37 @@
#include "nfc_i.h"
#include "nfc_worker.h"
void nfc_draw_callback(CanvasApi* canvas, void* context) {
void nfc_draw_callback(Canvas* canvas, void* context) {
furi_assert(canvas);
furi_assert(context);
Nfc* nfc = context;
dispatcher_lock(nfc->dispatcher);
canvas->clear(canvas);
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
if(nfc->screen == 0) {
char status[128 / 8];
if(nfc->ret == ERR_WRONG_STATE)
canvas->draw_str(canvas, 2, 16, "NFC Wrong State");
canvas_draw_str(canvas, 2, 16, "NFC Wrong State");
else if(nfc->ret == ERR_PARAM)
canvas->draw_str(canvas, 2, 16, "NFC Wrong Param");
canvas_draw_str(canvas, 2, 16, "NFC Wrong Param");
else if(nfc->ret == ERR_IO)
canvas->draw_str(canvas, 2, 16, "NFC IO Error");
canvas_draw_str(canvas, 2, 16, "NFC IO Error");
else if(nfc->ret == ERR_NONE)
canvas->draw_str(canvas, 2, 16, "NFC Device Found");
canvas_draw_str(canvas, 2, 16, "NFC Device Found");
else if(nfc->ret == ERR_TIMEOUT)
canvas->draw_str(canvas, 2, 16, "NFC Timeout");
canvas_draw_str(canvas, 2, 16, "NFC Timeout");
else
canvas->draw_str(canvas, 2, 16, "NFC error");
canvas_draw_str(canvas, 2, 16, "NFC error");
canvas->set_font(canvas, FontSecondary);
canvas_set_font(canvas, FontSecondary);
snprintf(status, sizeof(status), "Found: %d", nfc->devCnt);
if(nfc->devCnt > 0) {
canvas->draw_str(canvas, 2, 32, status);
canvas->draw_str(canvas, 2, 42, nfc->current);
canvas_draw_str(canvas, 2, 32, status);
canvas_draw_str(canvas, 2, 42, nfc->current);
snprintf(
status,
@ -40,10 +40,10 @@ void nfc_draw_callback(CanvasApi* canvas, void* context) {
"ATQA:%d SAK:%d",
nfc->first_atqa.anticollisionInfo,
nfc->first_sak.sak);
canvas->draw_str(canvas, 2, 52, status);
canvas_draw_str(canvas, 2, 52, status);
}
} else {
canvas->draw_str(canvas, 2, 16, "Not implemented");
canvas_draw_str(canvas, 2, 16, "Not implemented");
}
dispatcher_unlock(nfc->dispatcher);
@ -166,13 +166,9 @@ Nfc* nfc_alloc() {
void nfc_task(void* p) {
Nfc* nfc = nfc_alloc();
FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL);
furi_check(gui_record);
GuiApi* gui = furi_take(gui_record);
furi_check(gui);
Gui* gui = furi_open("gui");
widget_enabled_set(nfc->widget, false);
gui->add_widget(gui, nfc->widget, GuiLayerFullscreen);
furi_commit(gui_record);
gui_add_widget(gui, nfc->widget, GuiLayerFullscreen);
with_value_mutex(
nfc->menu_vm, (Menu * menu) { menu_item_add(menu, nfc->menu); });

View file

@ -24,18 +24,18 @@ struct Power {
uint8_t charge;
};
void power_draw_usb_callback(CanvasApi* canvas, void* context) {
void power_draw_usb_callback(Canvas* canvas, void* context) {
assert(context);
Power* power = context;
canvas->draw_icon(canvas, 0, 0, power->usb_icon);
canvas_draw_icon(canvas, 0, 0, power->usb_icon);
}
void power_draw_battery_callback(CanvasApi* canvas, void* context) {
void power_draw_battery_callback(Canvas* canvas, void* context) {
assert(context);
Power* power = context;
canvas->draw_icon(canvas, 0, 0, power->battery_icon);
canvas->draw_box(canvas, 2, 2, (float)power->charge / 100 * 14, 4);
canvas_draw_icon(canvas, 0, 0, power->battery_icon);
canvas_draw_box(canvas, 2, 2, (float)power->charge / 100 * 14, 4);
}
void power_off_callback(void* context) {
@ -134,13 +134,9 @@ void power_task(void* p) {
cli_add_command(power->cli, "power_otg_off", power_cli_otg_off, power);
}
FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL);
assert(gui_record);
GuiApi* gui = furi_take(gui_record);
assert(gui);
gui->add_widget(gui, power->usb_widget, GuiLayerStatusBarLeft);
gui->add_widget(gui, power->battery_widget, GuiLayerStatusBarRight);
furi_commit(gui_record);
Gui* gui = furi_open("gui");
gui_add_widget(gui, power->usb_widget, GuiLayerStatusBarLeft);
gui_add_widget(gui, power->battery_widget, GuiLayerStatusBarRight);
with_value_mutex(
power->menu_vm, (Menu * menu) { menu_item_add(menu, power->menu); });

View file

@ -50,7 +50,7 @@ public:
// funcs
void run();
void render(CanvasApi* canvas);
void render(Canvas* canvas);
template <class T> void set_text(std::initializer_list<T> list);
template <class T> void set_error(std::initializer_list<T> list);
const char* fatfs_error_desc(FRESULT res);
@ -833,11 +833,11 @@ template <class T> void SdTest::set_text(std::initializer_list<T> list) {
}
// render app
void SdTest::render(CanvasApi* canvas) {
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontSecondary);
void SdTest::render(Canvas* canvas) {
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
for(uint8_t i = 0; i < state.lines_count; i++) {
canvas->draw_str(canvas, 0, (i + 1) * 10, state.line[i]);
canvas_draw_str(canvas, 0, (i + 1) * 10, state.line[i]);
}
}

View file

@ -51,7 +51,7 @@ public:
GpioPin* green_led_record;
void run();
void render(CanvasApi* canvas);
void render(Canvas* canvas);
void set_error(const char* text);
void set_text(const char* text);
void light_red();
@ -117,10 +117,10 @@ void AppSdNFC::run() {
}
// render app
void AppSdNFC::render(CanvasApi* canvas) {
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
canvas->draw_str(canvas, 2, 12, state.name);
void AppSdNFC::render(Canvas* canvas) {
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 2, 12, state.name);
}
void AppSdNFC::set_error(const char* text) {

View file

@ -18,10 +18,10 @@ typedef struct {
// describe state here
} State;
static void render_callback(CanvasApi* canvas, void* ctx) {
static void render_callback(Canvas* canvas, void* ctx) {
State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25);
canvas->clear(canvas);
canvas_clear(canvas);
// draw your app
@ -54,12 +54,12 @@ void template_app(void* p) {
widget_input_callback_set(widget, input_callback, event_queue);
// Open GUI and register widget
GuiApi* gui = (GuiApi*)furi_open("gui");
Gui* gui = (Gui*)furi_open("gui");
if(gui == NULL) {
printf("gui is not available\n");
furiac_exit(NULL);
}
gui->add_widget(gui, widget, /* specify UI layer */);
gui_add_widget(gui, widget, /* specify UI layer */);
Event event;
while(1) {

View file

@ -46,7 +46,7 @@ public:
class AppExample : public AppTemplate<AppExampleState, AppExampleEvent> {
public:
void run();
void render(CanvasApi* canvas);
void render(Canvas* canvas);
};
// start app
@ -87,12 +87,12 @@ void AppExample::run() {
}
// render app
void AppExample::render(CanvasApi* canvas) {
void AppExample::render(Canvas* canvas) {
// here you dont need to call acquire_state or release_state
// to read or write app state, that already handled by caller
canvas->set_color(canvas, ColorBlack);
canvas->set_font(canvas, FontPrimary);
canvas->draw_str(canvas, 2, state.example_data, "Example app");
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 2, state.example_data, "Example app");
}
// app enter function

View file

@ -10,13 +10,13 @@ public:
osMessageQueueId_t event_queue;
TState state;
ValueMutex state_mutex;
GuiApi* gui;
Gui* gui;
AppTemplate();
~AppTemplate();
void input_callback(InputEvent* input_event, void* ctx);
void draw_callback(CanvasApi* canvas, void* ctx);
virtual void render(CanvasApi* canvas) = 0;
void draw_callback(Canvas* canvas, void* ctx);
virtual void render(Canvas* canvas) = 0;
void acquire_state(void);
void release_state(void);
bool get_event(TEvent* event, uint32_t timeout);
@ -37,7 +37,7 @@ template <class TState, class TEvent> AppTemplate<TState, TEvent>::AppTemplate()
}
// open gui
gui = (GuiApi*)furi_open("gui");
gui = (Gui*)furi_open("gui");
if(gui == NULL) {
printf("gui is not available\n");
furiac_exit(NULL);
@ -63,11 +63,11 @@ void AppTemplate<TState, TEvent>::input_callback(InputEvent* input_event, void*
// generic draw callback
template <class TState, class TEvent>
void AppTemplate<TState, TEvent>::draw_callback(CanvasApi* canvas, void* ctx) {
void AppTemplate<TState, TEvent>::draw_callback(Canvas* canvas, void* ctx) {
AppTemplate* app = static_cast<AppTemplate*>(ctx);
app->acquire_state();
canvas->clear(canvas);
canvas_clear(canvas);
app->render(canvas);
app->release_state();
@ -100,7 +100,7 @@ template <class TState, class TEvent> void AppTemplate<TState, TEvent>::app_read
widget_draw_callback_set(widget, draw_cb_ref, this);
// add widget
gui->add_widget(gui, widget, GuiLayerFullscreen);
gui_add_widget(gui, widget, GuiLayerFullscreen);
// signal that our app ready to work
furiac_ready();