[FL-1908] New animation update scheme (#737)
* Assets: update desktop animation frame rate and cleanup. * Power: update ViewPort only if changed. * Gui: tie IconAnimation with View, new update event generation scheme. Desktop: update IconAnimation usage. Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
This commit is contained in:
parent
6f346597d2
commit
61aaed8abb
@ -45,7 +45,6 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
void desktop_scene_locked_on_exit(void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
DesktopLockedView* locked_view = desktop->locked_view;
|
||||
desktop_locked_reset_counter(desktop->locked_view);
|
||||
osTimerStop(locked_view->timer);
|
||||
osTimerStop(desktop->locked_view->timer);
|
||||
}
|
||||
|
@ -67,6 +67,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
|
||||
desktop_switch_to_app(desktop, &FLIPPER_ARCHIVE);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case DesktopMainEventOpenFavorite:
|
||||
desktop_settings_load(&desktop->settings);
|
||||
desktop_switch_to_app(desktop, &FLIPPER_APPS[desktop->settings.favorite]);
|
||||
|
@ -20,13 +20,12 @@ void locked_view_timer_callback(void* context) {
|
||||
}
|
||||
|
||||
// temporary locked screen animation managment
|
||||
static void
|
||||
desktop_scene_handler_set_scene(DesktopLockedView* locked_view, const Icon* icon_data) {
|
||||
static void desktop_locked_set_scene(DesktopLockedView* locked_view, const Icon* icon_data) {
|
||||
with_view_model(
|
||||
locked_view->view, (DesktopLockedViewModel * model) {
|
||||
if(model->animation) icon_animation_free(model->animation);
|
||||
model->animation = icon_animation_alloc(icon_data);
|
||||
icon_animation_start(model->animation);
|
||||
view_tie_icon_animation(locked_view->view, model->animation);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@ -148,6 +147,25 @@ bool desktop_locked_input(InputEvent* event, void* context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void desktop_locked_enter(void* context) {
|
||||
DesktopLockedView* locked_view = context;
|
||||
|
||||
with_view_model(
|
||||
locked_view->view, (DesktopLockedViewModel * model) {
|
||||
if(model->animation) icon_animation_start(model->animation);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void desktop_locked_exit(void* context) {
|
||||
DesktopLockedView* locked_view = context;
|
||||
with_view_model(
|
||||
locked_view->view, (DesktopLockedViewModel * model) {
|
||||
if(model->animation) icon_animation_stop(model->animation);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
DesktopLockedView* desktop_locked_alloc() {
|
||||
DesktopLockedView* locked_view = furi_alloc(sizeof(DesktopLockedView));
|
||||
locked_view->view = view_alloc();
|
||||
@ -158,8 +176,10 @@ DesktopLockedView* desktop_locked_alloc() {
|
||||
view_set_context(locked_view->view, locked_view);
|
||||
view_set_draw_callback(locked_view->view, (ViewDrawCallback)desktop_locked_render);
|
||||
view_set_input_callback(locked_view->view, desktop_locked_input);
|
||||
view_set_enter_callback(locked_view->view, desktop_locked_enter);
|
||||
view_set_exit_callback(locked_view->view, desktop_locked_exit);
|
||||
|
||||
desktop_scene_handler_set_scene(locked_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
|
||||
desktop_locked_set_scene(locked_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
|
||||
return locked_view;
|
||||
}
|
||||
|
||||
|
@ -17,17 +17,18 @@ void desktop_main_set_callback(
|
||||
void desktop_main_reset_hint(DesktopMainView* main_view) {
|
||||
with_view_model(
|
||||
main_view->view, (DesktopMainViewModel * model) {
|
||||
model->hint_timeout = 0;
|
||||
model->hint_expire_at = 0;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// temporary main screen animation managment
|
||||
void desktop_scene_handler_set_scene(DesktopMainView* main_view, const Icon* icon_data) {
|
||||
static void desktop_main_set_scene(DesktopMainView* main_view, const Icon* icon_data) {
|
||||
with_view_model(
|
||||
main_view->view, (DesktopMainViewModel * model) {
|
||||
if(model->animation) icon_animation_free(model->animation);
|
||||
model->animation = icon_animation_alloc(icon_data);
|
||||
icon_animation_start(model->animation);
|
||||
view_tie_icon_animation(main_view->view, model->animation);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@ -38,7 +39,6 @@ void desktop_scene_handler_switch_scene(DesktopMainView* main_view) {
|
||||
if(icon_animation_is_last_frame(model->animation)) {
|
||||
if(model->animation) icon_animation_free(model->animation);
|
||||
model->animation = icon_animation_alloc(idle_scenes[model->scene_num]);
|
||||
icon_animation_start(model->animation);
|
||||
model->scene_num = random() % COUNT_OF(idle_scenes);
|
||||
}
|
||||
return true;
|
||||
@ -53,8 +53,7 @@ void desktop_main_render(Canvas* canvas, void* model) {
|
||||
canvas_draw_icon_animation(canvas, 0, -3, m->animation);
|
||||
}
|
||||
|
||||
if(m->unlocked && m->hint_timeout) {
|
||||
m->hint_timeout = CLAMP(m->hint_timeout - 1, 2, 0);
|
||||
if(osKernelGetTickCount() < m->hint_expire_at) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_framed(canvas, 42, 30, "Unlocked");
|
||||
}
|
||||
@ -87,6 +86,25 @@ bool desktop_main_input(InputEvent* event, void* context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void desktop_main_enter(void* context) {
|
||||
DesktopMainView* main_view = context;
|
||||
|
||||
with_view_model(
|
||||
main_view->view, (DesktopMainViewModel * model) {
|
||||
if(model->animation) icon_animation_start(model->animation);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void desktop_main_exit(void* context) {
|
||||
DesktopMainView* main_view = context;
|
||||
with_view_model(
|
||||
main_view->view, (DesktopMainViewModel * model) {
|
||||
if(model->animation) icon_animation_stop(model->animation);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
DesktopMainView* desktop_main_alloc() {
|
||||
DesktopMainView* main_view = furi_alloc(sizeof(DesktopMainView));
|
||||
main_view->view = view_alloc();
|
||||
@ -94,8 +112,10 @@ DesktopMainView* desktop_main_alloc() {
|
||||
view_set_context(main_view->view, main_view);
|
||||
view_set_draw_callback(main_view->view, (ViewDrawCallback)desktop_main_render);
|
||||
view_set_input_callback(main_view->view, desktop_main_input);
|
||||
view_set_enter_callback(main_view->view, desktop_main_enter);
|
||||
view_set_exit_callback(main_view->view, desktop_main_exit);
|
||||
|
||||
desktop_scene_handler_set_scene(main_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
|
||||
desktop_main_set_scene(main_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
|
||||
|
||||
return main_view;
|
||||
}
|
||||
@ -109,8 +129,7 @@ void desktop_main_free(DesktopMainView* main_view) {
|
||||
void desktop_main_unlocked(DesktopMainView* main_view) {
|
||||
with_view_model(
|
||||
main_view->view, (DesktopMainViewModel * model) {
|
||||
model->unlocked = true;
|
||||
model->hint_timeout = 2;
|
||||
model->hint_expire_at = osKernelGetTickCount() + osKernelGetTickFreq();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
@ -28,8 +28,7 @@ struct DesktopMainView {
|
||||
typedef struct {
|
||||
IconAnimation* animation;
|
||||
uint8_t scene_num;
|
||||
uint8_t hint_timeout;
|
||||
bool unlocked;
|
||||
uint32_t hint_expire_at;
|
||||
} DesktopMainViewModel;
|
||||
|
||||
void desktop_main_set_callback(
|
||||
@ -40,4 +39,5 @@ void desktop_main_set_callback(
|
||||
View* desktop_main_get_view(DesktopMainView* main_view);
|
||||
|
||||
DesktopMainView* desktop_main_alloc();
|
||||
|
||||
void desktop_main_free(DesktopMainView* main_view);
|
||||
|
@ -7,26 +7,26 @@ IconAnimation* icon_animation_alloc(const Icon* icon) {
|
||||
furi_assert(icon);
|
||||
IconAnimation* instance = furi_alloc(sizeof(IconAnimation));
|
||||
instance->icon = icon;
|
||||
instance->timer = osTimerNew(icon_animation_timer_callback, osTimerPeriodic, instance, NULL);
|
||||
return instance;
|
||||
}
|
||||
|
||||
void icon_animation_free(IconAnimation* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(osTimerDelete(instance->timer) == osOK);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
const uint8_t* icon_animation_get_data(IconAnimation* instance) {
|
||||
void icon_animation_set_update_callback(
|
||||
IconAnimation* instance,
|
||||
IconAnimationCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
if(instance->tick) {
|
||||
uint32_t now = osKernelGetTickCount();
|
||||
if(now < instance->tick) {
|
||||
instance->tick = now;
|
||||
icon_animation_next_frame(instance);
|
||||
} else if(now - instance->tick > osKernelGetTickFreq() / instance->icon->frame_rate) {
|
||||
instance->tick = now;
|
||||
icon_animation_next_frame(instance);
|
||||
}
|
||||
}
|
||||
instance->callback = callback;
|
||||
instance->callback_context = context;
|
||||
}
|
||||
|
||||
const uint8_t* icon_animation_get_data(IconAnimation* instance) {
|
||||
return instance->icon->frames[instance->frame];
|
||||
}
|
||||
|
||||
@ -35,6 +35,19 @@ void icon_animation_next_frame(IconAnimation* instance) {
|
||||
instance->frame = (instance->frame + 1) % instance->icon->frame_count;
|
||||
}
|
||||
|
||||
void icon_animation_timer_callback(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
IconAnimation* instance = context;
|
||||
|
||||
if(!instance->animating) return;
|
||||
|
||||
icon_animation_next_frame(instance);
|
||||
if(instance->callback) {
|
||||
instance->callback(instance, instance->callback_context);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t icon_animation_get_width(IconAnimation* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->icon->width;
|
||||
@ -45,30 +58,23 @@ uint8_t icon_animation_get_height(IconAnimation* instance) {
|
||||
return instance->icon->height;
|
||||
}
|
||||
|
||||
bool icon_animation_is_animated(IconAnimation* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->icon->frame_count > 1;
|
||||
}
|
||||
|
||||
bool icon_animation_is_animating(IconAnimation* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->tick > 0;
|
||||
}
|
||||
|
||||
void icon_animation_start(IconAnimation* instance) {
|
||||
furi_assert(instance);
|
||||
instance->tick = osKernelGetTickCount();
|
||||
if(!instance->animating) {
|
||||
instance->animating = true;
|
||||
furi_check(
|
||||
osTimerStart(instance->timer, (osKernelGetTickFreq() / instance->icon->frame_rate)) ==
|
||||
osOK);
|
||||
}
|
||||
}
|
||||
|
||||
void icon_animation_stop(IconAnimation* instance) {
|
||||
furi_assert(instance);
|
||||
instance->tick = 0;
|
||||
if(instance->animating) {
|
||||
instance->animating = false;
|
||||
furi_check(osTimerStop(instance->timer) == osOK);
|
||||
instance->frame = 0;
|
||||
}
|
||||
|
||||
uint8_t icon_animation_get_current_frame(IconAnimation* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->frame;
|
||||
}
|
||||
}
|
||||
|
||||
bool icon_animation_is_last_frame(IconAnimation* instance) {
|
||||
|
@ -11,54 +11,41 @@ extern "C" {
|
||||
|
||||
typedef struct IconAnimation IconAnimation;
|
||||
|
||||
/*
|
||||
* Allocate icon animation instance with const icon data.
|
||||
typedef void (*IconAnimationCallback)(IconAnimation* instance, void* context);
|
||||
|
||||
/** Allocate icon animation instance with const icon data.
|
||||
* always returns Icon or stops system if not enough memory
|
||||
*/
|
||||
IconAnimation* icon_animation_alloc(const Icon* icon);
|
||||
|
||||
/*
|
||||
* Release icon animation instance
|
||||
/** Release icon animation instance
|
||||
*/
|
||||
void icon_animation_free(IconAnimation* instance);
|
||||
|
||||
/*
|
||||
* Get icon animation width
|
||||
/** Get icon animation width
|
||||
*/
|
||||
void icon_animation_set_update_callback(
|
||||
IconAnimation* instance,
|
||||
IconAnimationCallback callback,
|
||||
void* context);
|
||||
|
||||
/** Get icon animation width
|
||||
*/
|
||||
uint8_t icon_animation_get_width(IconAnimation* instance);
|
||||
|
||||
/*
|
||||
* Get icon animation height
|
||||
/** Get icon animation height
|
||||
*/
|
||||
uint8_t icon_animation_get_height(IconAnimation* instance);
|
||||
|
||||
/*
|
||||
* Check if icon is animated
|
||||
*/
|
||||
bool icon_animation_is_animated(IconAnimation* instance);
|
||||
|
||||
/*
|
||||
* Check if icon animation is active
|
||||
*/
|
||||
bool icon_animation_is_animating(IconAnimation* instance);
|
||||
|
||||
/*
|
||||
* Start icon animation
|
||||
/** Start icon animation
|
||||
*/
|
||||
void icon_animation_start(IconAnimation* instance);
|
||||
|
||||
/*
|
||||
* Stop icon animation
|
||||
/** Stop icon animation
|
||||
*/
|
||||
void icon_animation_stop(IconAnimation* instance);
|
||||
|
||||
/*
|
||||
* Get current frame
|
||||
*/
|
||||
uint8_t icon_animation_get_current_frame(IconAnimation* instance);
|
||||
|
||||
/*
|
||||
* Returns true if current frame is a last one
|
||||
/** Returns true if current frame is a last one
|
||||
*/
|
||||
bool icon_animation_is_last_frame(IconAnimation* instance);
|
||||
|
||||
|
@ -2,20 +2,22 @@
|
||||
|
||||
#include "icon_animation.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <furi.h>
|
||||
|
||||
struct IconAnimation {
|
||||
const Icon* icon;
|
||||
uint8_t frame;
|
||||
uint32_t tick;
|
||||
bool animating;
|
||||
osTimerId_t timer;
|
||||
IconAnimationCallback callback;
|
||||
void* callback_context;
|
||||
};
|
||||
|
||||
/*
|
||||
* Get pointer to current frame data
|
||||
*/
|
||||
/** Get pointer to current frame data */
|
||||
const uint8_t* icon_animation_get_data(IconAnimation* instance);
|
||||
|
||||
/*
|
||||
* Advance to next frame
|
||||
*/
|
||||
/** Advance to next frame */
|
||||
void icon_animation_next_frame(IconAnimation* instance);
|
||||
|
||||
/** IconAnimation timer callback */
|
||||
void icon_animation_timer_callback(void* context);
|
||||
|
54
applications/gui/modules/menu.c
Executable file → Normal file
54
applications/gui/modules/menu.c
Executable file → Normal file
@ -20,7 +20,7 @@ ARRAY_DEF(MenuItemArray, MenuItem, M_POD_OPLIST);
|
||||
|
||||
typedef struct {
|
||||
MenuItemArray_t items;
|
||||
uint8_t position;
|
||||
size_t position;
|
||||
} MenuModel;
|
||||
|
||||
static void menu_process_up(Menu* menu);
|
||||
@ -32,7 +32,7 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
|
||||
|
||||
canvas_clear(canvas);
|
||||
|
||||
uint8_t position = model->position;
|
||||
size_t position = model->position;
|
||||
size_t items_count = MenuItemArray_size(model->items);
|
||||
if(items_count) {
|
||||
MenuItem* item;
|
||||
@ -43,7 +43,6 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
|
||||
item = MenuItemArray_get(model->items, shift_position);
|
||||
if(item->icon) {
|
||||
canvas_draw_icon_animation(canvas, 4, 3, item->icon);
|
||||
icon_animation_stop(item->icon);
|
||||
}
|
||||
canvas_draw_str(canvas, 22, 14, item->label);
|
||||
// Second line main
|
||||
@ -52,7 +51,6 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
|
||||
item = MenuItemArray_get(model->items, shift_position);
|
||||
if(item->icon) {
|
||||
canvas_draw_icon_animation(canvas, 4, 25, item->icon);
|
||||
icon_animation_start(item->icon);
|
||||
}
|
||||
canvas_draw_str(canvas, 22, 36, item->label);
|
||||
// Third line
|
||||
@ -61,7 +59,6 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
|
||||
item = MenuItemArray_get(model->items, shift_position);
|
||||
if(item->icon) {
|
||||
canvas_draw_icon_animation(canvas, 4, 47, item->icon);
|
||||
icon_animation_stop(item->icon);
|
||||
}
|
||||
canvas_draw_str(canvas, 22, 58, item->label);
|
||||
// Frame and scrollbar
|
||||
@ -93,6 +90,30 @@ static bool menu_input_callback(InputEvent* event, void* context) {
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void menu_enter(void* context) {
|
||||
Menu* menu = context;
|
||||
with_view_model(
|
||||
menu->view, (MenuModel * model) {
|
||||
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
||||
if(item && item->icon) {
|
||||
icon_animation_start(item->icon);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
static void menu_exit(void* context) {
|
||||
Menu* menu = context;
|
||||
with_view_model(
|
||||
menu->view, (MenuModel * model) {
|
||||
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
||||
if(item && item->icon) {
|
||||
icon_animation_stop(item->icon);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
Menu* menu_alloc() {
|
||||
Menu* menu = furi_alloc(sizeof(Menu));
|
||||
menu->view = view_alloc(menu->view);
|
||||
@ -100,6 +121,8 @@ Menu* menu_alloc() {
|
||||
view_allocate_model(menu->view, ViewModelTypeLocking, sizeof(MenuModel));
|
||||
view_set_draw_callback(menu->view, menu_draw_callback);
|
||||
view_set_input_callback(menu->view, menu_input_callback);
|
||||
view_set_enter_callback(menu->view, menu_enter);
|
||||
view_set_exit_callback(menu->view, menu_exit);
|
||||
|
||||
with_view_model(
|
||||
menu->view, (MenuModel * model) {
|
||||
@ -143,6 +166,7 @@ void menu_add_item(
|
||||
item = MenuItemArray_push_new(model->items);
|
||||
item->label = label;
|
||||
item->icon = icon;
|
||||
view_tie_icon_animation(menu->view, item->icon);
|
||||
item->index = index;
|
||||
item->callback = callback;
|
||||
item->callback_context = context;
|
||||
@ -175,11 +199,21 @@ void menu_set_selected_item(Menu* menu, uint32_t index) {
|
||||
static void menu_process_up(Menu* menu) {
|
||||
with_view_model(
|
||||
menu->view, (MenuModel * model) {
|
||||
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
||||
if(item && item->icon) {
|
||||
icon_animation_stop(item->icon);
|
||||
}
|
||||
|
||||
if(model->position > 0) {
|
||||
model->position--;
|
||||
} else {
|
||||
model->position = MenuItemArray_size(model->items) - 1;
|
||||
}
|
||||
|
||||
item = MenuItemArray_get(model->items, model->position);
|
||||
if(item && item->icon) {
|
||||
icon_animation_start(item->icon);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@ -187,11 +221,21 @@ static void menu_process_up(Menu* menu) {
|
||||
static void menu_process_down(Menu* menu) {
|
||||
with_view_model(
|
||||
menu->view, (MenuModel * model) {
|
||||
MenuItem* item = MenuItemArray_get(model->items, model->position);
|
||||
if(item && item->icon) {
|
||||
icon_animation_stop(item->icon);
|
||||
}
|
||||
|
||||
if(model->position < MenuItemArray_size(model->items) - 1) {
|
||||
model->position++;
|
||||
} else {
|
||||
model->position = 0;
|
||||
}
|
||||
|
||||
item = MenuItemArray_get(model->items, model->position);
|
||||
if(item && item->icon) {
|
||||
icon_animation_start(item->icon);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
@ -12,6 +12,11 @@ void view_free(View* view) {
|
||||
free(view);
|
||||
}
|
||||
|
||||
void view_tie_icon_animation(View* view, IconAnimation* icon_animation) {
|
||||
furi_assert(view);
|
||||
icon_animation_set_update_callback(icon_animation, view_icon_animation_callback, view);
|
||||
}
|
||||
|
||||
void view_set_draw_callback(View* view, ViewDrawCallback callback) {
|
||||
furi_assert(view);
|
||||
furi_assert(view->draw_callback == NULL);
|
||||
@ -120,6 +125,14 @@ void view_commit_model(View* view, bool update) {
|
||||
}
|
||||
}
|
||||
|
||||
void view_icon_animation_callback(IconAnimation* instance, void* context) {
|
||||
furi_assert(context);
|
||||
View* view = context;
|
||||
if(view->update_callback) {
|
||||
view->update_callback(view, view->update_callback_context);
|
||||
}
|
||||
}
|
||||
|
||||
void view_unlock_model(View* view) {
|
||||
furi_assert(view);
|
||||
if(view->model_type == ViewModelTypeLocking) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <input/input.h>
|
||||
|
||||
#include "icon_animation.h"
|
||||
#include "canvas.h"
|
||||
|
||||
#include <stddef.h>
|
||||
@ -10,9 +12,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Hides drawing view_port */
|
||||
/** Hides drawing view_port */
|
||||
#define VIEW_NONE 0xFFFFFFFF
|
||||
/* Ignore navigation event */
|
||||
|
||||
/** Ignore navigation event */
|
||||
#define VIEW_IGNORE 0xFFFFFFFE
|
||||
|
||||
typedef enum {
|
||||
@ -20,17 +23,17 @@ typedef enum {
|
||||
ViewOrientationVertical,
|
||||
} ViewOrientation;
|
||||
|
||||
/* View, anonymous type */
|
||||
/** View, anonymous type */
|
||||
typedef struct View View;
|
||||
|
||||
/* View Draw callback
|
||||
/** View Draw callback
|
||||
* @param canvas, pointer to canvas
|
||||
* @param view_model, pointer to context
|
||||
* @warning called from GUI thread
|
||||
*/
|
||||
typedef void (*ViewDrawCallback)(Canvas* canvas, void* model);
|
||||
|
||||
/* View Input callback
|
||||
/** View Input callback
|
||||
* @param event, pointer to input event data
|
||||
* @param context, pointer to context
|
||||
* @return true if event handled, false if event ignored
|
||||
@ -38,27 +41,27 @@ typedef void (*ViewDrawCallback)(Canvas* canvas, void* model);
|
||||
*/
|
||||
typedef bool (*ViewInputCallback)(InputEvent* event, void* context);
|
||||
|
||||
/* View Custom callback
|
||||
/** View Custom callback
|
||||
* @param event, number of custom event
|
||||
* @param context, pointer to context
|
||||
* @return true if event handled, false if event ignored
|
||||
*/
|
||||
typedef bool (*ViewCustomCallback)(uint32_t event, void* context);
|
||||
|
||||
/* View navigation callback
|
||||
/** View navigation callback
|
||||
* @param context, pointer to context
|
||||
* @return next view id
|
||||
* @warning called from GUI thread
|
||||
*/
|
||||
typedef uint32_t (*ViewNavigationCallback)(void* context);
|
||||
|
||||
/* View callback
|
||||
/** View callback
|
||||
* @param context, pointer to context
|
||||
* @warning called from GUI thread
|
||||
*/
|
||||
typedef void (*ViewCallback)(void* context);
|
||||
|
||||
/* View Update Callback
|
||||
/** View Update Callback
|
||||
* Called upon model change, need to be propagated to GUI throw ViewPort update
|
||||
* @param view, pointer to view
|
||||
* @param context, pointer to context
|
||||
@ -66,7 +69,7 @@ typedef void (*ViewCallback)(void* context);
|
||||
*/
|
||||
typedef void (*ViewUpdateCallback)(View* view, void* context);
|
||||
|
||||
/* View model types */
|
||||
/** View model types */
|
||||
typedef enum {
|
||||
/* Model is not allocated */
|
||||
ViewModelTypeNone,
|
||||
@ -80,97 +83,103 @@ typedef enum {
|
||||
ViewModelTypeLocking,
|
||||
} ViewModelType;
|
||||
|
||||
/* Allocate and init View
|
||||
* @return pointer to View
|
||||
/** Allocate and init View
|
||||
* @return View instance
|
||||
*/
|
||||
View* view_alloc();
|
||||
|
||||
/* Free View
|
||||
* @param pointer to View
|
||||
/** Free View
|
||||
* @param View instance
|
||||
*/
|
||||
void view_free(View* view);
|
||||
|
||||
/* Set View Draw callback
|
||||
* @param view, pointer to View
|
||||
/** Tie IconAnimation with View
|
||||
* @param view, View instance
|
||||
* @param icon_animation, IconAnimation instance
|
||||
*/
|
||||
void view_tie_icon_animation(View* view, IconAnimation* icon_animation);
|
||||
|
||||
/** Set View Draw callback
|
||||
* @param view, View instance
|
||||
* @param callback, draw callback
|
||||
*/
|
||||
void view_set_draw_callback(View* view, ViewDrawCallback callback);
|
||||
|
||||
/* Set View Input callback
|
||||
* @param view, pointer to View
|
||||
/** Set View Input callback
|
||||
* @param view, View instance
|
||||
* @param callback, input callback
|
||||
*/
|
||||
void view_set_input_callback(View* view, ViewInputCallback callback);
|
||||
|
||||
/* Set View Custom callback
|
||||
* @param view, pointer to View
|
||||
/** Set View Custom callback
|
||||
* @param view, View instance
|
||||
* @param callback, input callback
|
||||
*/
|
||||
void view_set_custom_callback(View* view, ViewCustomCallback callback);
|
||||
|
||||
/* Set Navigation Previous callback
|
||||
* @param view, pointer to View
|
||||
/** Set Navigation Previous callback
|
||||
* @param view, View instance
|
||||
* @param callback, input callback
|
||||
*/
|
||||
void view_set_previous_callback(View* view, ViewNavigationCallback callback);
|
||||
|
||||
/* Set Enter callback
|
||||
* @param view, pointer to View
|
||||
/** Set Enter callback
|
||||
* @param view, View instance
|
||||
* @param callback, callback
|
||||
*/
|
||||
void view_set_enter_callback(View* view, ViewCallback callback);
|
||||
|
||||
/* Set Exit callback
|
||||
* @param view, pointer to View
|
||||
/** Set Exit callback
|
||||
* @param view, View instance
|
||||
* @param callback, callback
|
||||
*/
|
||||
void view_set_exit_callback(View* view, ViewCallback callback);
|
||||
|
||||
/* Set Update callback
|
||||
* @param view, pointer to View
|
||||
/** Set Update callback
|
||||
* @param view, View instance
|
||||
* @param callback, callback
|
||||
*/
|
||||
void view_set_update_callback(View* view, ViewUpdateCallback callback);
|
||||
|
||||
/* Set View Draw callback
|
||||
* @param view, pointer to View
|
||||
/** Set View Draw callback
|
||||
* @param view, View instance
|
||||
* @param context, context for callbacks
|
||||
*/
|
||||
void view_set_update_callback_context(View* view, void* context);
|
||||
|
||||
/* Set View Draw callback
|
||||
* @param view, pointer to View
|
||||
/** Set View Draw callback
|
||||
* @param view, View instance
|
||||
* @param context, context for callbacks
|
||||
*/
|
||||
void view_set_context(View* view, void* context);
|
||||
|
||||
/* Set View Orientation
|
||||
* @param view, pointer to View
|
||||
/** Set View Orientation
|
||||
* @param view, View instance
|
||||
* @param orientation, either vertical or horizontal
|
||||
*/
|
||||
void view_set_orientation(View* view, ViewOrientation orientation);
|
||||
|
||||
/* Allocate view model.
|
||||
* @param view, pointer to View
|
||||
/** Allocate view model.
|
||||
* @param view, View instance
|
||||
* @param type, View Model Type
|
||||
* @param size, size
|
||||
*/
|
||||
void view_allocate_model(View* view, ViewModelType type, size_t size);
|
||||
|
||||
/* Free view model data memory.
|
||||
* @param view, pointer to View
|
||||
/** Free view model data memory.
|
||||
* @param view, View instance
|
||||
*/
|
||||
void view_free_model(View* view);
|
||||
|
||||
/* Get view model data
|
||||
* @param view, pointer to View
|
||||
/** Get view model data
|
||||
* @param view, View instance
|
||||
* @return pointer to model data
|
||||
* @warning Don't forget to commit model changes
|
||||
*/
|
||||
void* view_get_model(View* view);
|
||||
|
||||
/* Commit view model
|
||||
* @param view, pointer to View
|
||||
/** Commit view model
|
||||
* @param view, View instance
|
||||
* @param update, true if you want to emit view update, false otherwise
|
||||
*/
|
||||
void view_commit_model(View* view, bool update);
|
||||
@ -187,7 +196,7 @@ void view_commit_model(View* view, bool update);
|
||||
view_commit_model(view, update); \
|
||||
}
|
||||
#else
|
||||
/*
|
||||
/**
|
||||
* With clause for view model
|
||||
* @param view, View instance pointer
|
||||
* @param function_body a (){} lambda declaration, executed within you parent function context
|
||||
|
@ -26,6 +26,9 @@ struct View {
|
||||
void* context;
|
||||
};
|
||||
|
||||
/* IconAnimation tie callback */
|
||||
void view_icon_animation_callback(IconAnimation* instance, void* context);
|
||||
|
||||
/* Unlock model */
|
||||
void view_unlock_model(View* view);
|
||||
|
||||
|
@ -14,48 +14,41 @@ typedef enum {
|
||||
ViewPortOrientationVertical,
|
||||
} ViewPortOrientation;
|
||||
|
||||
/*
|
||||
* ViewPort Draw callback
|
||||
/** ViewPort Draw callback
|
||||
* @warning called from GUI thread
|
||||
*/
|
||||
typedef void (*ViewPortDrawCallback)(Canvas* canvas, void* context);
|
||||
|
||||
/*
|
||||
* ViewPort Input callback
|
||||
/** ViewPort Input callback
|
||||
* @warning called from GUI thread
|
||||
*/
|
||||
typedef void (*ViewPortInputCallback)(InputEvent* event, void* context);
|
||||
|
||||
/*
|
||||
* ViewPort allocator
|
||||
/** ViewPort allocator
|
||||
* always returns view_port or stops system if not enough memory.
|
||||
*/
|
||||
ViewPort* view_port_alloc();
|
||||
|
||||
/*
|
||||
* ViewPort deallocator
|
||||
/** ViewPort deallocator
|
||||
* Ensure that view_port was unregistered in GUI system before use.
|
||||
*/
|
||||
void view_port_free(ViewPort* view_port);
|
||||
|
||||
/*
|
||||
* Set view_port width.
|
||||
/** Set view_port width.
|
||||
* Will be used to limit canvas drawing area and autolayout feature.
|
||||
* @param width - wanted width, 0 - auto.
|
||||
*/
|
||||
void view_port_set_width(ViewPort* view_port, uint8_t width);
|
||||
uint8_t view_port_get_width(ViewPort* view_port);
|
||||
|
||||
/*
|
||||
* Set view_port height.
|
||||
/** Set view_port height.
|
||||
* Will be used to limit canvas drawing area and autolayout feature.
|
||||
* @param height - wanted height, 0 - auto.
|
||||
*/
|
||||
void view_port_set_height(ViewPort* view_port, uint8_t height);
|
||||
uint8_t view_port_get_height(ViewPort* view_port);
|
||||
|
||||
/*
|
||||
* Enable or disable view_port rendering.
|
||||
/** Enable or disable view_port rendering.
|
||||
* @param view_port - ViewPort instance
|
||||
* @param enabled
|
||||
* @warning automatically dispatches update event
|
||||
@ -63,8 +56,7 @@ uint8_t view_port_get_height(ViewPort* view_port);
|
||||
void view_port_enabled_set(ViewPort* view_port, bool enabled);
|
||||
bool view_port_is_enabled(ViewPort* view_port);
|
||||
|
||||
/*
|
||||
* ViewPort event callbacks
|
||||
/** ViewPort event callbacks
|
||||
* @param callback - appropriate callback function
|
||||
* @param context - context to pass to callback
|
||||
*/
|
||||
@ -74,14 +66,12 @@ void view_port_input_callback_set(
|
||||
ViewPortInputCallback callback,
|
||||
void* context);
|
||||
|
||||
/*
|
||||
* Emit update signal to GUI system.
|
||||
/** Emit update signal to GUI system.
|
||||
* Rendering will happen later after GUI system process signal.
|
||||
*/
|
||||
void view_port_update(ViewPort* view_port);
|
||||
|
||||
/*
|
||||
* Set ViewPort orientation.
|
||||
/** Set ViewPort orientation.
|
||||
* @param orientation, display orientation, horizontal or vertical.
|
||||
*/
|
||||
void view_port_set_orientation(ViewPort* view_port, ViewPortOrientation orientation);
|
||||
|
38
applications/power/power_service/power.c
Executable file → Normal file
38
applications/power/power_service/power.c
Executable file → Normal file
@ -97,23 +97,27 @@ static void power_check_charging_state(Power* power) {
|
||||
}
|
||||
}
|
||||
|
||||
static void power_update_info(Power* power) {
|
||||
static bool power_update_info(Power* power) {
|
||||
PowerInfo info;
|
||||
|
||||
info.charge = furi_hal_power_get_pct();
|
||||
info.health = furi_hal_power_get_bat_health_pct();
|
||||
info.capacity_remaining = furi_hal_power_get_battery_remaining_capacity();
|
||||
info.capacity_full = furi_hal_power_get_battery_full_capacity();
|
||||
info.current_charger = furi_hal_power_get_battery_current(FuriHalPowerICCharger);
|
||||
info.current_gauge = furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge);
|
||||
info.voltage_charger = furi_hal_power_get_battery_voltage(FuriHalPowerICCharger);
|
||||
info.voltage_gauge = furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge);
|
||||
info.voltage_vbus = furi_hal_power_get_usb_voltage();
|
||||
info.temperature_charger = furi_hal_power_get_battery_temperature(FuriHalPowerICCharger);
|
||||
info.temperature_gauge = furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge);
|
||||
|
||||
osMutexAcquire(power->info_mtx, osWaitForever);
|
||||
PowerInfo* info = &power->info;
|
||||
|
||||
info->charge = furi_hal_power_get_pct();
|
||||
info->health = furi_hal_power_get_bat_health_pct();
|
||||
info->capacity_remaining = furi_hal_power_get_battery_remaining_capacity();
|
||||
info->capacity_full = furi_hal_power_get_battery_full_capacity();
|
||||
info->current_charger = furi_hal_power_get_battery_current(FuriHalPowerICCharger);
|
||||
info->current_gauge = furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge);
|
||||
info->voltage_charger = furi_hal_power_get_battery_voltage(FuriHalPowerICCharger);
|
||||
info->voltage_gauge = furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge);
|
||||
info->voltage_vbus = furi_hal_power_get_usb_voltage();
|
||||
info->temperature_charger = furi_hal_power_get_battery_temperature(FuriHalPowerICCharger);
|
||||
info->temperature_gauge = furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge);
|
||||
|
||||
bool need_refresh = power->info.charge != info.charge;
|
||||
power->info = info;
|
||||
osMutexRelease(power->info_mtx);
|
||||
|
||||
return need_refresh;
|
||||
}
|
||||
|
||||
static void power_check_low_battery(Power* power) {
|
||||
@ -156,7 +160,7 @@ int32_t power_srv(void* p) {
|
||||
|
||||
while(1) {
|
||||
// Update data from gauge and charger
|
||||
power_update_info(power);
|
||||
bool need_refresh = power_update_info(power);
|
||||
|
||||
// Check low battery level
|
||||
power_check_low_battery(power);
|
||||
@ -168,7 +172,7 @@ int32_t power_srv(void* p) {
|
||||
power_check_battery_level_change(power);
|
||||
|
||||
// Update battery view port
|
||||
view_port_update(power->battery_view_port);
|
||||
if(need_refresh) view_port_update(power->battery_view_port);
|
||||
|
||||
osDelay(1000);
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 830 B |
@ -1 +1 @@
|
||||
10
|
||||
1
|
@ -1 +1 @@
|
||||
10
|
||||
1
|
Loading…
Reference in New Issue
Block a user