[FL-1092] Make View reusable outside of dispatcher (#396)

* View: replace direct View to ViewDispatcher link with callback. ViewDispatcher: update View usage. ViewHandler: update View usage, handle update signal.
This commit is contained in:
あく 2021-04-01 15:03:02 +03:00 committed by GitHub
parent 41c3b95f6d
commit 37131dbe12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 80 additions and 22 deletions

View File

@ -11,13 +11,6 @@ void view_free(View* view) {
free(view); free(view);
} }
void view_set_dispatcher(View* view, ViewDispatcher* view_dispatcher) {
furi_assert(view);
furi_assert(view_dispatcher);
furi_assert(view->dispatcher == NULL);
view->dispatcher = view_dispatcher;
}
void view_set_draw_callback(View* view, ViewDrawCallback callback) { void view_set_draw_callback(View* view, ViewDrawCallback callback) {
furi_assert(view); furi_assert(view);
furi_assert(view->draw_callback == NULL); furi_assert(view->draw_callback == NULL);
@ -50,6 +43,16 @@ void view_set_exit_callback(View* view, ViewCallback callback) {
view->exit_callback = callback; view->exit_callback = callback;
} }
void view_set_update_callback(View* view, ViewUpdateCallback callback) {
furi_assert(view);
view->update_callback = callback;
}
void view_set_update_callback_context(View* view, void* context) {
furi_assert(view);
view->update_callback_context = context;
}
void view_set_context(View* view, void* context) { void view_set_context(View* view, void* context) {
furi_assert(view); furi_assert(view);
furi_assert(context); furi_assert(context);
@ -105,8 +108,8 @@ void* view_get_model(View* view) {
void view_commit_model(View* view, bool update) { void view_commit_model(View* view, bool update) {
furi_assert(view); furi_assert(view);
view_unlock_model(view); view_unlock_model(view);
if(update && view->dispatcher) { if(update && view->update_callback) {
view_dispatcher_update(view->dispatcher, view); view->update_callback(view, view->update_callback_context);
} }
} }

View File

@ -20,6 +20,9 @@ extern "C" {
*/ */
#define VIEW_DESTROY 0xFFFFFFFA #define VIEW_DESTROY 0xFFFFFFFA
/* View, anonymous type */
typedef struct View View;
/* View Draw callback /* View Draw callback
* @param canvas, pointer to canvas * @param canvas, pointer to canvas
* @param view_model, pointer to context * @param view_model, pointer to context
@ -48,6 +51,14 @@ typedef uint32_t (*ViewNavigationCallback)(void* context);
*/ */
typedef void (*ViewCallback)(void* context); typedef void (*ViewCallback)(void* context);
/* 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
* @warning called from GUI thread
*/
typedef void (*ViewUpdateCallback)(View* view, void* context);
/* View model types */ /* View model types */
typedef enum { typedef enum {
/* Model is not allocated */ /* Model is not allocated */
@ -62,8 +73,6 @@ typedef enum {
ViewModelTypeLocking, ViewModelTypeLocking,
} ViewModelType; } ViewModelType;
typedef struct View View;
/* Allocate and init View /* Allocate and init View
* @return pointer to View * @return pointer to View
*/ */
@ -110,6 +119,18 @@ void view_set_enter_callback(View* view, ViewCallback callback);
*/ */
void view_set_exit_callback(View* view, ViewCallback callback); void view_set_exit_callback(View* view, ViewCallback callback);
/* Set Update callback
* @param view, pointer to View
* @param callback, callback
*/
void view_set_update_callback(View* view, ViewUpdateCallback callback);
/* Set View Draw callback
* @param view, pointer to View
* @param context, context for callbacks
*/
void view_set_update_callback_context(View* view, void* context);
/* Set View Draw callback /* Set View Draw callback
* @param view, pointer to View * @param view, pointer to View
* @param context, context for callbacks * @param context, context for callbacks

View File

@ -48,7 +48,8 @@ void view_dispatcher_add_view(ViewDispatcher* view_dispatcher, uint32_t view_id,
} }
ViewDict_set_at(view_dispatcher->views, view_id, view); ViewDict_set_at(view_dispatcher->views, view_id, view);
view_set_dispatcher(view, view_dispatcher); view_set_update_callback(view, view_dispatcher_update);
view_set_update_callback_context(view, view_dispatcher);
// Unlock gui // Unlock gui
if(view_dispatcher->gui) { if(view_dispatcher->gui) {
@ -63,14 +64,19 @@ void view_dispatcher_remove_view(ViewDispatcher* view_dispatcher, uint32_t view_
if(view_dispatcher->gui) { if(view_dispatcher->gui) {
gui_lock(view_dispatcher->gui); gui_lock(view_dispatcher->gui);
} }
// Get View by ID
View* view = *ViewDict_get(view_dispatcher->views, view_id);
// Disable the view if it is active // Disable the view if it is active
if(view_dispatcher->current_view == *ViewDict_get(view_dispatcher->views, view_id)) { if(view_dispatcher->current_view == view) {
view_dispatcher_set_current_view(view_dispatcher, NULL); view_dispatcher_set_current_view(view_dispatcher, NULL);
} }
// Remove view // Remove view
ViewDict_erase(view_dispatcher->views, view_id); ViewDict_erase(view_dispatcher->views, view_id);
view_set_update_callback(view, NULL);
view_set_update_callback_context(view, NULL);
// Unlock gui // Unlock gui
if(view_dispatcher->gui) { if(view_dispatcher->gui) {
gui_unlock(view_dispatcher->gui); gui_unlock(view_dispatcher->gui);
@ -153,9 +159,11 @@ void view_dispatcher_set_current_view(ViewDispatcher* view_dispatcher, View* vie
} }
} }
void view_dispatcher_update(ViewDispatcher* view_dispatcher, View* view) { void view_dispatcher_update(View* view, void* context) {
furi_assert(view_dispatcher);
furi_assert(view); furi_assert(view);
furi_assert(context);
ViewDispatcher* view_dispatcher = context;
if(view_dispatcher->current_view == view) { if(view_dispatcher->current_view == view) {
view_port_update(view_dispatcher->view_port); view_port_update(view_dispatcher->view_port);

View File

@ -23,5 +23,5 @@ void view_dispatcher_input_callback(InputEvent* event, void* context);
/* Set current view, dispatches view enter and exit */ /* Set current view, dispatches view enter and exit */
void view_dispatcher_set_current_view(ViewDispatcher* view_dispatcher, View* view); void view_dispatcher_set_current_view(ViewDispatcher* view_dispatcher, View* view);
/* View to ViewDispatcher update event */ /* ViewDispatcher update event */
void view_dispatcher_update(ViewDispatcher* view_dispatcher, View* view); void view_dispatcher_update(View* view, void* context);

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "view.h" #include "view.h"
#include "view_dispatcher_i.h"
#include <furi.h> #include <furi.h>
typedef struct { typedef struct {
@ -10,21 +9,22 @@ typedef struct {
} ViewModelLocking; } ViewModelLocking;
struct View { struct View {
ViewDispatcher* dispatcher;
ViewDrawCallback draw_callback; ViewDrawCallback draw_callback;
ViewInputCallback input_callback; ViewInputCallback input_callback;
ViewModelType model_type; ViewModelType model_type;
ViewNavigationCallback previous_callback; ViewNavigationCallback previous_callback;
ViewNavigationCallback next_callback; ViewNavigationCallback next_callback;
ViewCallback enter_callback; ViewCallback enter_callback;
ViewCallback exit_callback; ViewCallback exit_callback;
ViewUpdateCallback update_callback;
void* update_callback_context;
void* model; void* model;
void* context; void* context;
}; };
/* Set View dispatcher */
void view_set_dispatcher(View* view, ViewDispatcher* view_dispatcher);
/* Unlock model */ /* Unlock model */
void view_unlock_model(View* view); void view_unlock_model(View* view);

View File

@ -45,7 +45,17 @@ void view_holder_free(ViewHolder* view_holder) {
void view_holder_set_view(ViewHolder* view_holder, View* view) { void view_holder_set_view(ViewHolder* view_holder, View* view) {
furi_assert(view_holder); furi_assert(view_holder);
if(view_holder->view) {
view_set_update_callback(view_holder->view, NULL);
view_set_update_callback_context(view_holder->view, NULL);
}
view_holder->view = view; view_holder->view = view;
if(view_holder->view) {
view_set_update_callback(view_holder->view, view_holder_update);
view_set_update_callback_context(view_holder->view, view_holder);
}
} }
void view_holder_set_free_callback( void view_holder_set_free_callback(
@ -85,6 +95,16 @@ void view_holder_stop(ViewHolder* view_holder) {
view_port_enabled_set(view_holder->view_port, false); view_port_enabled_set(view_holder->view_port, false);
} }
void view_holder_update(View* view, void* context) {
furi_assert(view);
furi_assert(context);
ViewHolder* view_holder = context;
if(view == view_holder->view) {
view_port_update(view_holder->view_port);
}
}
static void view_holder_draw_callback(Canvas* canvas, void* context) { static void view_holder_draw_callback(Canvas* canvas, void* context) {
ViewHolder* view_holder = context; ViewHolder* view_holder = context;
if(view_holder->view) { if(view_holder->view) {

View File

@ -87,6 +87,12 @@ void view_holder_start(ViewHolder* view_holder);
*/ */
void view_holder_stop(ViewHolder* view_holder); void view_holder_stop(ViewHolder* view_holder);
/** View Update Handler
* @param view, View Instance
* @param context, ViewHolder instance
*/
void view_holder_update(View* view, void* context);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif