[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:
parent
41c3b95f6d
commit
37131dbe12
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user