Просмотр исходного кода

[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.
あく 4 лет назад
Родитель
Сommit
37131dbe12

+ 12 - 9
applications/gui/view.c

@@ -11,13 +11,6 @@ void view_free(View* 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) {
     furi_assert(view);
     furi_assert(view->draw_callback == NULL);
@@ -50,6 +43,16 @@ void view_set_exit_callback(View* view, ViewCallback 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) {
     furi_assert(view);
     furi_assert(context);
@@ -105,8 +108,8 @@ void* view_get_model(View* view) {
 void view_commit_model(View* view, bool update) {
     furi_assert(view);
     view_unlock_model(view);
-    if(update && view->dispatcher) {
-        view_dispatcher_update(view->dispatcher, view);
+    if(update && view->update_callback) {
+        view->update_callback(view, view->update_callback_context);
     }
 }
 

+ 23 - 2
applications/gui/view.h

@@ -20,6 +20,9 @@ extern "C" {
  */
 #define VIEW_DESTROY 0xFFFFFFFA
 
+/* View, anonymous type */
+typedef struct View View;
+
 /* View Draw callback
  * @param canvas, pointer to canvas
  * @param view_model, pointer to context
@@ -48,6 +51,14 @@ typedef uint32_t (*ViewNavigationCallback)(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 */
 typedef enum {
     /* Model is not allocated */
@@ -62,8 +73,6 @@ typedef enum {
     ViewModelTypeLocking,
 } ViewModelType;
 
-typedef struct View View;
-
 /* Allocate and init 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);
 
+/* 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
  * @param view, pointer to View
  * @param context, context for callbacks

+ 12 - 4
applications/gui/view_dispatcher.c

@@ -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);
-    view_set_dispatcher(view, view_dispatcher);
+    view_set_update_callback(view, view_dispatcher_update);
+    view_set_update_callback_context(view, view_dispatcher);
 
     // Unlock gui
     if(view_dispatcher->gui) {
@@ -63,14 +64,19 @@ void view_dispatcher_remove_view(ViewDispatcher* view_dispatcher, uint32_t view_
     if(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
-    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);
     }
     // Remove view
     ViewDict_erase(view_dispatcher->views, view_id);
 
+    view_set_update_callback(view, NULL);
+    view_set_update_callback_context(view, NULL);
+
     // Unlock gui
     if(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) {
-    furi_assert(view_dispatcher);
+void view_dispatcher_update(View* view, void* context) {
     furi_assert(view);
+    furi_assert(context);
+
+    ViewDispatcher* view_dispatcher = context;
 
     if(view_dispatcher->current_view == view) {
         view_port_update(view_dispatcher->view_port);

+ 2 - 2
applications/gui/view_dispatcher_i.h

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

+ 5 - 5
applications/gui/view_i.h

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

+ 20 - 0
applications/sd-filesystem/view_holder.c

@@ -45,7 +45,17 @@ void view_holder_free(ViewHolder* view_holder) {
 
 void view_holder_set_view(ViewHolder* view_holder, View* view) {
     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;
+
+    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(
@@ -85,6 +95,16 @@ void view_holder_stop(ViewHolder* view_holder) {
     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) {
     ViewHolder* view_holder = context;
     if(view_holder->view) {

+ 6 - 0
applications/sd-filesystem/view_holder.h

@@ -87,6 +87,12 @@ void view_holder_start(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
 }
 #endif