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

Implemented horizontal view support for all pages

Sandro Kalatozishvili 2 лет назад
Родитель
Сommit
a5bfd17635

+ 2 - 1
.vscode/settings.json

@@ -8,6 +8,7 @@
         "xremote_saved_view.h": "c",
         "xremote_saved_view.h": "c",
         "infrared_remote.h": "c",
         "infrared_remote.h": "c",
         "xremote_navigation_view.h": "c",
         "xremote_navigation_view.h": "c",
-        "xremote_settings_view.h": "c"
+        "xremote_settings_view.h": "c",
+        "xremote_learn_view.h": "c"
     }
     }
 }
 }

+ 2 - 3
README.md

@@ -43,7 +43,7 @@ Button name | Description
 
 
 - [x] Application menu
 - [x] Application menu
 - [ ] Learn new remote
 - [ ] Learn new remote
-- [ ] IR signal analyzer
+- [ ] Signal analyzer
 - [x] Use saved remote
 - [x] Use saved remote
     - [x] General button page
     - [x] General button page
     - [x] Control buttons page
     - [x] Control buttons page
@@ -53,12 +53,11 @@ Button name | Description
     - [ ] Full button list
     - [ ] Full button list
     - [ ] Edit remote file
     - [ ] Edit remote file
     - [ ] Delete remote file
     - [ ] Delete remote file
-    - [ ] Horizontal view for all pages
 - [x] Application settings
 - [x] Application settings
     - [x] GUI to change settings
     - [x] GUI to change settings
     - [x] Load settings from the file
     - [x] Load settings from the file
     - [x] Store settings to the file
     - [x] Store settings to the file
-    - [x] Vertical/Horizontal view
+    - [x] Vertical/horizontal view
     - [x] IR command repeat count
     - [x] IR command repeat count
     - [x] Exit button behavior
     - [x] Exit button behavior
 
 

+ 53 - 10
views/xremote_about_view.c

@@ -9,32 +9,75 @@
 #include "xremote_about_view.h"
 #include "xremote_about_view.h"
 #include "../xremote.h"
 #include "../xremote.h"
 
 
-static void xremote_about_view_draw_callback(Canvas* canvas, void* context)
+static void xremote_about_view_draw_vertical(Canvas* canvas, XRemoteViewModel* model)
 {
 {
-    (void)context;
+    UNUSED(model);
     char version[32];
     char version[32];
 
 
-    xremote_canvas_draw_header(canvas, "About");
     canvas_set_font(canvas, FontSecondary);
     canvas_set_font(canvas, FontSecondary);
-
     xremote_get_version(version, sizeof(version));
     xremote_get_version(version, sizeof(version));
+
     canvas_draw_str_aligned(canvas, 0, 30, AlignLeft, AlignTop, "Version:");
     canvas_draw_str_aligned(canvas, 0, 30, AlignLeft, AlignTop, "Version:");
     canvas_draw_str_aligned(canvas, 35, 30, AlignLeft, AlignTop, version);
     canvas_draw_str_aligned(canvas, 35, 30, AlignLeft, AlignTop, version);
 
 
     canvas_draw_str_aligned(canvas, 0, 40, AlignLeft, AlignTop, "License: GPLv3");
     canvas_draw_str_aligned(canvas, 0, 40, AlignLeft, AlignTop, "License: GPLv3");
     canvas_draw_str_aligned(canvas, 0, 50, AlignLeft, AlignTop, "Author: kala13x");
     canvas_draw_str_aligned(canvas, 0, 50, AlignLeft, AlignTop, "Author: kala13x");
 
 
+    elements_slightly_rounded_frame(canvas, 9, 78, 45, 33);
     canvas_draw_str_aligned(canvas, 0, 69, AlignLeft, AlignTop, "Contact:");
     canvas_draw_str_aligned(canvas, 0, 69, AlignLeft, AlignTop, "Contact:");
     canvas_draw_str_aligned(canvas, 13, 80, AlignLeft, AlignTop, "s.kalatoz");
     canvas_draw_str_aligned(canvas, 13, 80, AlignLeft, AlignTop, "s.kalatoz");
-    canvas_draw_str_aligned(canvas, 29, 90, AlignLeft, AlignTop, "@");
+    canvas_draw_str_aligned(canvas, 28, 91, AlignLeft, AlignTop, "@");
     canvas_draw_str_aligned(canvas, 11, 100, AlignLeft, AlignTop, "gmail.com");
     canvas_draw_str_aligned(canvas, 11, 100, AlignLeft, AlignTop, "gmail.com");
+}
 
 
-    elements_slightly_rounded_frame(canvas, 9, 78, 45, 33);
-    xremote_canvas_draw_exit_footer(canvas, "Press to exit");
+static void xremote_about_view_draw_horizontal(Canvas* canvas, XRemoteViewModel* model)
+{
+    UNUSED(model);
+    char version[32];
+
+    canvas_set_font(canvas, FontSecondary);
+    xremote_get_version(version, sizeof(version));
+
+    canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Version:");
+    canvas_draw_str_aligned(canvas, 35, 0, AlignLeft, AlignTop, version);
+
+    canvas_draw_str_aligned(canvas, 0, 10, AlignLeft, AlignTop, "License: GPLv3");
+    canvas_draw_str_aligned(canvas, 0, 20, AlignLeft, AlignTop, "Author: kala13x");
+
+    elements_slightly_rounded_frame(canvas, 8, 30, 45, 33);
+    canvas_draw_str_aligned(canvas, 0, 69, AlignLeft, AlignTop, "Contact:");
+    canvas_draw_str_aligned(canvas, 12, 32, AlignLeft, AlignTop, "s.kalatoz");
+    canvas_draw_str_aligned(canvas, 27, 43, AlignLeft, AlignTop, "@");
+    canvas_draw_str_aligned(canvas, 10, 52, AlignLeft, AlignTop, "gmail.com");
 }
 }
 
 
-XRemoteView* xremote_about_view_alloc(void *app_ctx)
+static void xremote_about_view_draw_callback(Canvas* canvas, void* context)
 {
 {
-    return xremote_view_alloc(app_ctx, NULL,
-        xremote_about_view_draw_callback);
+    furi_assert(context);
+    XRemoteViewModel* model = context;
+    XRemoteAppContext *app_ctx = model->context;
+    XRemoteViewDrawFunction xremote_about_view_draw_body;
+
+    ViewOrientation orientation = app_ctx->app_settings->orientation;
+    xremote_about_view_draw_body = orientation == ViewOrientationVertical ?
+        xremote_about_view_draw_vertical : xremote_about_view_draw_horizontal;
+
+    xremote_canvas_draw_header(canvas, orientation, "About");
+    xremote_about_view_draw_body(canvas, model);
+    xremote_canvas_draw_exit_footer(canvas, orientation, "Press to exit");
+}
+
+XRemoteView* xremote_about_view_alloc(void* app_ctx)
+{
+    XRemoteView *view = xremote_view_alloc(app_ctx,
+        NULL, xremote_about_view_draw_callback);
+
+    with_view_model(
+        xremote_view_get_view(view),
+        XRemoteViewModel* model,
+        { model->context = app_ctx; },
+        true
+    );
+
+    return view;
 }
 }

+ 42 - 7
views/xremote_common_view.c

@@ -34,7 +34,7 @@ XRemoteView* xremote_view_alloc(void* app_ctx, ViewInputCallback input_cb, ViewD
     remote_view->context = NULL;
     remote_view->context = NULL;
     remote_view->on_clear = NULL;
     remote_view->on_clear = NULL;
 
 
-    view_set_orientation(remote_view->view, ViewOrientationVertical);
+    view_set_orientation(remote_view->view, ((XRemoteAppContext*)app_ctx)->app_settings->orientation);
     view_allocate_model(remote_view->view, ViewModelTypeLocking, sizeof(XRemoteViewModel));
     view_allocate_model(remote_view->view, ViewModelTypeLocking, sizeof(XRemoteViewModel));
 
 
     view_set_input_callback(remote_view->view, input_cb);
     view_set_input_callback(remote_view->view, input_cb);
@@ -198,19 +198,38 @@ void xremote_canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, XRemoteIcon
     }
     }
 }
 }
 
 
-void xremote_canvas_draw_header(Canvas* canvas, const char* section)
+void xremote_canvas_draw_header(Canvas* canvas, ViewOrientation orient, const char* section)
 {
 {
+    Align align = AlignLeft;
+    uint8_t x = 0;
+
+    if (orient == ViewOrientationHorizontal)
+    {
+        align = AlignRight;
+        x = 128;
+    }
+
     canvas_set_font(canvas, FontPrimary);
     canvas_set_font(canvas, FontPrimary);
-    elements_multiline_text_aligned(canvas, 0, 0, AlignLeft, AlignTop, "XRemote");
+    elements_multiline_text_aligned(canvas, x, 0, align, AlignTop, "XRemote");
+
     canvas_set_font(canvas, FontSecondary);
     canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str(canvas, 0, 20, section);
+    elements_multiline_text_aligned(canvas, x, 12, align, AlignTop, section);
 }
 }
 
 
-void xremote_canvas_draw_exit_footer(Canvas* canvas, const char *text)
+void xremote_canvas_draw_exit_footer(Canvas* canvas, ViewOrientation orient, const char *text)
 {
 {
     canvas_set_font(canvas, FontSecondary);
     canvas_set_font(canvas, FontSecondary);
-    xremote_canvas_draw_icon(canvas, 6, 124, XRemoteIconBack);
-    canvas_draw_str(canvas, 12, 128, text);
+
+    if (orient == ViewOrientationVertical)
+    {
+        xremote_canvas_draw_icon(canvas, 6, 124, XRemoteIconBack);
+        elements_multiline_text_aligned(canvas, 12, 128, AlignLeft, AlignBottom, text);
+    }
+    else
+    {
+        xremote_canvas_draw_icon(canvas, 71, 60, XRemoteIconBack);
+        elements_multiline_text_aligned(canvas, 128, 64, AlignRight, AlignBottom, text);
+    }
 }
 }
 
 
 void xremote_canvas_draw_button(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, XRemoteIcon icon)
 void xremote_canvas_draw_button(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, XRemoteIcon icon)
@@ -243,6 +262,22 @@ void xremote_canvas_draw_button_wide(Canvas* canvas, bool pressed, uint8_t x, ui
     canvas_set_color(canvas, ColorBlack);
     canvas_set_color(canvas, ColorBlack);
 }
 }
 
 
+void xremote_canvas_draw_button_size(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, uint8_t xy, char* text, XRemoteIcon icon)
+{
+    (void)icon;
+    elements_slightly_rounded_frame(canvas, x + 4, y, xy, 15);
+
+    if (pressed)
+    {
+        elements_slightly_rounded_box(canvas, x + 6, y + 2, xy - 4, 11);
+        canvas_set_color(canvas, ColorWhite);
+    }
+
+    xremote_canvas_draw_icon(canvas, x + 15, y + 7, icon);
+    elements_multiline_text_aligned(canvas, x + 22, y + 10, AlignLeft, AlignBottom, text);
+    canvas_set_color(canvas, ColorBlack);
+}
+
 void xremote_canvas_draw_frame(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, uint8_t xl, const char *text)
 void xremote_canvas_draw_frame(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, uint8_t xl, const char *text)
 {
 {
     elements_slightly_rounded_frame(canvas, x, y, xl, 15);
     elements_slightly_rounded_frame(canvas, x, y, xl, 15);

+ 4 - 2
views/xremote_common_view.h

@@ -97,13 +97,15 @@ typedef enum {
 
 
 typedef struct XRemoteView XRemoteView;
 typedef struct XRemoteView XRemoteView;
 typedef void (*XRemoteViewClearCallback)(void *context);
 typedef void (*XRemoteViewClearCallback)(void *context);
+typedef void (*XRemoteViewDrawFunction)(Canvas*, XRemoteViewModel*);
 
 
-void xremote_canvas_draw_header(Canvas* canvas, const char* section);
-void xremote_canvas_draw_exit_footer(Canvas* canvas, const char *text);
+void xremote_canvas_draw_header(Canvas* canvas, ViewOrientation orient, const char* section);
+void xremote_canvas_draw_exit_footer(Canvas* canvas, ViewOrientation orient, const char *text);
 
 
 void xremote_canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, XRemoteIcon icon);
 void xremote_canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, XRemoteIcon icon);
 void xremote_canvas_draw_button(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, XRemoteIcon icon);
 void xremote_canvas_draw_button(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, XRemoteIcon icon);
 void xremote_canvas_draw_button_wide(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, char* text, XRemoteIcon icon);
 void xremote_canvas_draw_button_wide(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, char* text, XRemoteIcon icon);
+void xremote_canvas_draw_button_size(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, uint8_t xy, char* text, XRemoteIcon icon);
 void xremote_canvas_draw_frame(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, uint8_t xl, const char *text);
 void xremote_canvas_draw_frame(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, uint8_t xl, const char *text);
 
 
 XRemoteView* xremote_view_alloc(void *app_ctx, ViewInputCallback input_cb, ViewDrawCallback draw_cb);
 XRemoteView* xremote_view_alloc(void *app_ctx, ViewInputCallback input_cb, ViewDrawCallback draw_cb);

+ 47 - 7
views/xremote_control_view.c

@@ -7,19 +7,40 @@
  */
  */
 
 
 #include "xremote_control_view.h"
 #include "xremote_control_view.h"
+#include "../xremote_app.h"
 
 
-static void xremote_control_view_draw_callback(Canvas* canvas, void* context)
+static void xremote_control_view_draw_vertical(Canvas* canvas, XRemoteViewModel* model)
 {
 {
-    furi_assert(context);
-    XRemoteViewModel* model = context;
-
-    xremote_canvas_draw_header(canvas, "Control");
     xremote_canvas_draw_frame(canvas, model->up_pressed, 17, 30, 31, "VOL +");
     xremote_canvas_draw_frame(canvas, model->up_pressed, 17, 30, 31, "VOL +");
     xremote_canvas_draw_frame(canvas, model->left_pressed, 4, 50, 23, "< CH");
     xremote_canvas_draw_frame(canvas, model->left_pressed, 4, 50, 23, "< CH");
     xremote_canvas_draw_frame(canvas, model->right_pressed, 37, 50, 23, "CH >");
     xremote_canvas_draw_frame(canvas, model->right_pressed, 37, 50, 23, "CH >");
     xremote_canvas_draw_frame(canvas, model->down_pressed, 17, 70, 31, "VOL -");
     xremote_canvas_draw_frame(canvas, model->down_pressed, 17, 70, 31, "VOL -");
     xremote_canvas_draw_button_wide(canvas, model->ok_pressed, 0, 95, "Mute", XRemoteIconEnter);
     xremote_canvas_draw_button_wide(canvas, model->ok_pressed, 0, 95, "Mute", XRemoteIconEnter);
-    xremote_canvas_draw_exit_footer(canvas, "Press to exit");
+}
+
+static void xremote_control_view_draw_horizontal(Canvas* canvas, XRemoteViewModel* model)
+{
+    xremote_canvas_draw_frame(canvas, model->up_pressed, 17, 5, 31, "VOL +");
+    xremote_canvas_draw_frame(canvas, model->left_pressed, 4, 25, 23, "< CH");
+    xremote_canvas_draw_frame(canvas, model->right_pressed, 37, 25, 23, "CH >");
+    xremote_canvas_draw_frame(canvas, model->down_pressed, 17, 45, 31, "VOL -");
+    xremote_canvas_draw_button_size(canvas, model->ok_pressed, 70, 29, 44, "Mute", XRemoteIconEnter);
+}
+
+static void xremote_control_view_draw_callback(Canvas* canvas, void* context)
+{
+    furi_assert(context);
+    XRemoteViewModel* model = context;
+    XRemoteAppContext *app_ctx = model->context;
+    XRemoteViewDrawFunction xremote_control_view_draw_body;
+
+    ViewOrientation orientation = app_ctx->app_settings->orientation;
+    xremote_control_view_draw_body = orientation == ViewOrientationVertical ?
+        xremote_control_view_draw_vertical : xremote_control_view_draw_horizontal;
+
+    xremote_canvas_draw_header(canvas, orientation, "Control");
+    xremote_control_view_draw_body(canvas, model);
+    xremote_canvas_draw_exit_footer(canvas, orientation, "Press to exit");
 }
 }
 
 
 static void xremote_control_view_process(XRemoteView* view, InputEvent* event)
 static void xremote_control_view_process(XRemoteView* view, InputEvent* event)
@@ -28,6 +49,8 @@ static void xremote_control_view_process(XRemoteView* view, InputEvent* event)
         xremote_view_get_view(view),
         xremote_view_get_view(view),
         XRemoteViewModel* model,
         XRemoteViewModel* model,
         {
         {
+            model->context = xremote_view_get_app_context(view);
+
             if (event->type == InputTypePress)
             if (event->type == InputTypePress)
             {
             {
                 if (event->key == InputKeyOk)
                 if (event->key == InputKeyOk)
@@ -80,7 +103,24 @@ static bool xremote_control_view_input_callback(InputEvent* event, void* context
 
 
 XRemoteView* xremote_control_view_alloc(void *app_ctx)
 XRemoteView* xremote_control_view_alloc(void *app_ctx)
 {
 {
-    return xremote_view_alloc(app_ctx,
+    XRemoteView *view = xremote_view_alloc(app_ctx,
         xremote_control_view_input_callback,
         xremote_control_view_input_callback,
         xremote_control_view_draw_callback);
         xremote_control_view_draw_callback);
+
+    with_view_model(
+        xremote_view_get_view(view),
+        XRemoteViewModel* model,
+        {
+            model->context = app_ctx;
+            model->up_pressed = false;
+            model->down_pressed = false;
+            model->left_pressed = false;
+            model->right_pressed = false;
+            model->back_pressed = false;
+            model->ok_pressed = false;
+        },
+        true
+    );
+
+    return view;
 }
 }

+ 22 - 6
views/xremote_custom_view.c

@@ -7,18 +7,34 @@
  */
  */
 
 
 #include "xremote_custom_view.h"
 #include "xremote_custom_view.h"
+#include "../xremote_app.h"
 
 
 static void xremote_custom_view_draw_callback(Canvas* canvas, void* context)
 static void xremote_custom_view_draw_callback(Canvas* canvas, void* context)
 {
 {
-    (void)context;
-    xremote_canvas_draw_header(canvas, "Custom");
+    furi_assert(context);
+    XRemoteViewModel* model = context;
+    XRemoteAppContext *app_ctx = model->context;
+
+    ViewOrientation orientation = app_ctx->app_settings->orientation;
+    uint64_t x = orientation == ViewOrientationVertical ? 70 : 34;
+
+    xremote_canvas_draw_header(canvas, orientation, "Custom");
     canvas_set_font(canvas, FontSecondary);
     canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str(canvas, 0, 70, "Coming Soon");
-    xremote_canvas_draw_exit_footer(canvas, "Press to exit");
+    canvas_draw_str(canvas, 0, x, "Coming Soon.");
+    xremote_canvas_draw_exit_footer(canvas, orientation, "Press to exit");
 }
 }
 
 
 XRemoteView* xremote_custom_view_alloc(void* app_ctx)
 XRemoteView* xremote_custom_view_alloc(void* app_ctx)
 {
 {
-    return xremote_view_alloc(app_ctx, NULL,
-        xremote_custom_view_draw_callback);
+    XRemoteView *view = xremote_view_alloc(app_ctx,
+        NULL, xremote_custom_view_draw_callback);
+
+    with_view_model(
+        xremote_view_get_view(view),
+        XRemoteViewModel* model,
+        { model->context = app_ctx; },
+        true
+    );
+
+    return view;
 }
 }

+ 47 - 7
views/xremote_general_view.c

@@ -7,19 +7,40 @@
  */
  */
 
 
 #include "xremote_general_view.h"
 #include "xremote_general_view.h"
+#include "../xremote_app.h"
 
 
-static void xremote_general_view_draw_callback(Canvas* canvas, void* context)
+static void xremote_general_view_draw_vertical(Canvas* canvas, XRemoteViewModel* model)
 {
 {
-    furi_assert(context);
-    XRemoteViewModel* model = context;
-
-    xremote_canvas_draw_header(canvas, "General");
     xremote_canvas_draw_button_wide(canvas, model->ok_pressed, 0, 27, "Power", XRemoteIconEnter);
     xremote_canvas_draw_button_wide(canvas, model->ok_pressed, 0, 27, "Power", XRemoteIconEnter);
     xremote_canvas_draw_button_wide(canvas, model->up_pressed, 0, 45, "Input", XRemoteIconArrowUp);
     xremote_canvas_draw_button_wide(canvas, model->up_pressed, 0, 45, "Input", XRemoteIconArrowUp);
     xremote_canvas_draw_button_wide(canvas, model->down_pressed, 0, 63, "Setup", XRemoteIconArrowDown);
     xremote_canvas_draw_button_wide(canvas, model->down_pressed, 0, 63, "Setup", XRemoteIconArrowDown);
     xremote_canvas_draw_button_wide(canvas, model->left_pressed, 0, 81, "Menu", XRemoteIconArrowLeft);
     xremote_canvas_draw_button_wide(canvas, model->left_pressed, 0, 81, "Menu", XRemoteIconArrowLeft);
     xremote_canvas_draw_button_wide(canvas, model->right_pressed, 0, 99, "List", XRemoteIconArrowRight);
     xremote_canvas_draw_button_wide(canvas, model->right_pressed, 0, 99, "List", XRemoteIconArrowRight);
-    xremote_canvas_draw_exit_footer(canvas, "Press to exit");
+}
+
+static void xremote_general_view_draw_horizontal(Canvas* canvas, XRemoteViewModel* model)
+{
+    xremote_canvas_draw_button_wide(canvas, model->ok_pressed, 0, 7, "Power", XRemoteIconEnter);
+    xremote_canvas_draw_button_wide(canvas, model->up_pressed, 0, 25, "Input", XRemoteIconArrowUp);
+    xremote_canvas_draw_button_wide(canvas, model->down_pressed, 0, 43, "Setup", XRemoteIconArrowDown);
+    xremote_canvas_draw_button_wide(canvas, model->left_pressed, 64, 21, "Menu", XRemoteIconArrowLeft);
+    xremote_canvas_draw_button_wide(canvas, model->right_pressed, 64, 39, "List", XRemoteIconArrowRight);
+}
+
+static void xremote_general_view_draw_callback(Canvas* canvas, void* context)
+{
+    furi_assert(context);
+    XRemoteViewModel* model = context;
+    XRemoteAppContext *app_ctx = model->context;
+    XRemoteViewDrawFunction xremote_general_view_draw_body;
+
+    ViewOrientation orientation = app_ctx->app_settings->orientation;
+    xremote_general_view_draw_body = orientation == ViewOrientationVertical ?
+        xremote_general_view_draw_vertical : xremote_general_view_draw_horizontal;
+
+    xremote_canvas_draw_header(canvas, orientation, "General");
+    xremote_general_view_draw_body(canvas, model);
+    xremote_canvas_draw_exit_footer(canvas, orientation, "Press to exit");
 }
 }
 
 
 static void xremote_general_view_process(XRemoteView* view, InputEvent* event)
 static void xremote_general_view_process(XRemoteView* view, InputEvent* event)
@@ -30,6 +51,8 @@ static void xremote_general_view_process(XRemoteView* view, InputEvent* event)
         {
         {
             if (event->type == InputTypePress)
             if (event->type == InputTypePress)
             {
             {
+                model->context = xremote_view_get_app_context(view);
+
                 if (event->key == InputKeyOk)
                 if (event->key == InputKeyOk)
                 {
                 {
                     model->ok_pressed = true;
                     model->ok_pressed = true;
@@ -80,7 +103,24 @@ static bool xremote_general_view_input_callback(InputEvent* event, void* context
 
 
 XRemoteView* xremote_general_view_alloc(void* app_ctx)
 XRemoteView* xremote_general_view_alloc(void* app_ctx)
 {
 {
-    return xremote_view_alloc(app_ctx,
+    XRemoteView *view = xremote_view_alloc(app_ctx,
         xremote_general_view_input_callback,
         xremote_general_view_input_callback,
         xremote_general_view_draw_callback);
         xremote_general_view_draw_callback);
+
+    with_view_model(
+        xremote_view_get_view(view),
+        XRemoteViewModel* model,
+        {
+            model->context = app_ctx;
+            model->up_pressed = false;
+            model->down_pressed = false;
+            model->left_pressed = false;
+            model->right_pressed = false;
+            model->back_pressed = false;
+            model->ok_pressed = false;
+        },
+        true
+    );
+
+    return view;
 }
 }

+ 22 - 6
views/xremote_learn_view.c

@@ -7,18 +7,34 @@
  */
  */
 
 
 #include "xremote_learn_view.h"
 #include "xremote_learn_view.h"
+#include "../xremote_app.h"
 
 
 static void xremote_learn_view_draw_callback(Canvas* canvas, void* context)
 static void xremote_learn_view_draw_callback(Canvas* canvas, void* context)
 {
 {
-    (void)context;
-    xremote_canvas_draw_header(canvas, "Learn");
+    furi_assert(context);
+    XRemoteViewModel* model = context;
+    XRemoteAppContext *app_ctx = model->context;
+
+    ViewOrientation orientation = app_ctx->app_settings->orientation;
+    uint64_t x = orientation == ViewOrientationVertical ? 70 : 34;
+
+    xremote_canvas_draw_header(canvas, orientation, "Learn");
     canvas_set_font(canvas, FontSecondary);
     canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str(canvas, 0, 70, "Coming Soon");
-    xremote_canvas_draw_exit_footer(canvas, "Press to exit");
+    canvas_draw_str(canvas, 0, x, "Coming Soon.");
+    xremote_canvas_draw_exit_footer(canvas, orientation, "Press to exit");
 }
 }
 
 
 XRemoteView* xremote_learn_view_alloc(void* app_ctx)
 XRemoteView* xremote_learn_view_alloc(void* app_ctx)
 {
 {
-    return xremote_view_alloc(app_ctx, NULL,
-        xremote_learn_view_draw_callback);
+    XRemoteView *view = xremote_view_alloc(app_ctx,
+        NULL, xremote_learn_view_draw_callback);
+
+    with_view_model(
+        xremote_view_get_view(view),
+        XRemoteViewModel* model,
+        { model->context = app_ctx; },
+        true
+    );
+
+    return view;
 }
 }

+ 42 - 13
views/xremote_navigation_view.c

@@ -9,13 +9,11 @@
 #include "xremote_navigation_view.h"
 #include "xremote_navigation_view.h"
 #include "../xremote_app.h"
 #include "../xremote_app.h"
 
 
-static void xremote_navigation_view_draw_callback(Canvas* canvas, void* context)
+
+static void xremote_navigation_view_draw_vertical(Canvas* canvas, XRemoteViewModel* model)
 {
 {
-    furi_assert(context);
-    XRemoteViewModel* model = context;
     XRemoteAppContext *app_ctx = model->context;
     XRemoteAppContext *app_ctx = model->context;
 
 
-    xremote_canvas_draw_header(canvas, "Navigation");
     xremote_canvas_draw_button(canvas, model->up_pressed, 23, 30, XRemoteIconArrowUp);
     xremote_canvas_draw_button(canvas, model->up_pressed, 23, 30, XRemoteIconArrowUp);
     xremote_canvas_draw_button(canvas, model->down_pressed, 23, 72, XRemoteIconArrowDown);
     xremote_canvas_draw_button(canvas, model->down_pressed, 23, 72, XRemoteIconArrowDown);
     xremote_canvas_draw_button(canvas, model->left_pressed, 2, 51, XRemoteIconArrowLeft);
     xremote_canvas_draw_button(canvas, model->left_pressed, 2, 51, XRemoteIconArrowLeft);
@@ -25,8 +23,38 @@ static void xremote_navigation_view_draw_callback(Canvas* canvas, void* context)
 
 
     if (app_ctx->app_settings->exit_behavior == XRemoteAppExitPress)
     if (app_ctx->app_settings->exit_behavior == XRemoteAppExitPress)
         canvas_draw_icon(canvas, 22, 107, &I_Hold_Text_17x4);
         canvas_draw_icon(canvas, 22, 107, &I_Hold_Text_17x4);
+}
+
+static void xremote_navigation_view_draw_horizontal(Canvas* canvas, XRemoteViewModel* model)
+{
+    XRemoteAppContext *app_ctx = model->context;
+
+    xremote_canvas_draw_button(canvas, model->up_pressed, 23, 2, XRemoteIconArrowUp);
+    xremote_canvas_draw_button(canvas, model->down_pressed, 23, 44, XRemoteIconArrowDown);
+    xremote_canvas_draw_button(canvas, model->left_pressed, 2, 23, XRemoteIconArrowLeft);
+    xremote_canvas_draw_button(canvas, model->right_pressed, 44, 23, XRemoteIconArrowRight);
+    xremote_canvas_draw_button(canvas, model->ok_pressed, 23, 23, XRemoteIconOk);
+    xremote_canvas_draw_button(canvas, model->back_pressed, 70, 33, XRemoteIconBack);
+
+    if (app_ctx->app_settings->exit_behavior == XRemoteAppExitPress)
+        canvas_draw_icon(canvas, 90, 45, &I_Hold_Text_17x4);
+}
+
+static void xremote_navigation_view_draw_callback(Canvas* canvas, void* context)
+{
+    furi_assert(context);
+    XRemoteViewModel* model = context;
+    XRemoteAppContext *app_ctx = model->context;
+    ViewOrientation orientation = app_ctx->app_settings->orientation;
+    const char *exit_str = xremote_app_context_get_exit_str(app_ctx);
+
+    XRemoteViewDrawFunction xremote_navigation_view_draw_body;
+    xremote_navigation_view_draw_body = orientation == ViewOrientationVertical ?
+        xremote_navigation_view_draw_vertical : xremote_navigation_view_draw_horizontal;
 
 
-    xremote_canvas_draw_exit_footer(canvas, xremote_app_context_get_exit_str(app_ctx));
+    xremote_canvas_draw_header(canvas, orientation, "Navigation");
+    xremote_navigation_view_draw_body(canvas, model);
+    xremote_canvas_draw_exit_footer(canvas, orientation, exit_str);
 }
 }
 
 
 static void xremote_navigation_view_process(XRemoteView* view, InputEvent* event)
 static void xremote_navigation_view_process(XRemoteView* view, InputEvent* event)
@@ -74,13 +102,12 @@ static void xremote_navigation_view_process(XRemoteView* view, InputEvent* event
                 model->back_pressed = true;
                 model->back_pressed = true;
                 xremote_view_send_ir(view, XREMOTE_COMMAND_BACK);
                 xremote_view_send_ir(view, XREMOTE_COMMAND_BACK);
             }
             }
-            else if (event->type == InputTypeLong)
+            else if (event->type == InputTypeLong &&
+                    event->key == InputKeyBack &&
+                    exit == XRemoteAppExitPress)
             {
             {
-                if (event->key == InputKeyBack && exit == XRemoteAppExitPress)
-                {
-                    model->back_pressed = true;
-                    xremote_view_send_ir(view, XREMOTE_COMMAND_BACK);
-                }
+                model->back_pressed = true;
+                xremote_view_send_ir(view, XREMOTE_COMMAND_BACK);
             }
             }
             else if (event->type == InputTypeRelease)
             else if (event->type == InputTypeRelease)
             {
             {
@@ -123,14 +150,16 @@ XRemoteView* xremote_navigation_view_alloc(void* app_ctx)
         xremote_view_get_view(view),
         xremote_view_get_view(view),
         XRemoteViewModel* model,
         XRemoteViewModel* model,
         {
         {
-            model->context = xremote_view_get_app_context(view);
+            model->context = app_ctx;
             model->up_pressed = false;
             model->up_pressed = false;
             model->down_pressed = false;
             model->down_pressed = false;
             model->left_pressed = false;
             model->left_pressed = false;
             model->right_pressed = false;
             model->right_pressed = false;
             model->back_pressed = false;
             model->back_pressed = false;
             model->ok_pressed = false;
             model->ok_pressed = false;
-        }, true);
+        },
+        true
+    );
 
 
     return view;
     return view;
 }
 }

+ 42 - 14
views/xremote_player_view.c

@@ -9,24 +9,51 @@
 #include "xremote_player_view.h"
 #include "xremote_player_view.h"
 #include "../xremote_app.h"
 #include "../xremote_app.h"
 
 
-static void xremote_player_view_draw_callback(Canvas* canvas, void* context)
+static void xremote_player_view_draw_vertical(Canvas* canvas, XRemoteViewModel* model)
 {
 {
-    furi_assert(context);
-    XRemoteViewModel* model = context;
     XRemoteAppContext *app_ctx = model->context;
     XRemoteAppContext *app_ctx = model->context;
 
 
-    xremote_canvas_draw_header(canvas, "Playback");
     xremote_canvas_draw_button(canvas, model->up_pressed, 23, 30, XRemoteIconJumpForward);
     xremote_canvas_draw_button(canvas, model->up_pressed, 23, 30, XRemoteIconJumpForward);
     xremote_canvas_draw_button(canvas, model->down_pressed, 23, 72, XRemoteIconJumpBackward);
     xremote_canvas_draw_button(canvas, model->down_pressed, 23, 72, XRemoteIconJumpBackward);
-    xremote_canvas_draw_button(canvas, model->ok_pressed, 23, 51, XRemoteIconPlayPause);
     xremote_canvas_draw_button(canvas, model->left_pressed, 2, 51, XRemoteIconFastBackward);
     xremote_canvas_draw_button(canvas, model->left_pressed, 2, 51, XRemoteIconFastBackward);
     xremote_canvas_draw_button(canvas, model->right_pressed, 44, 51, XRemoteIconFastForward);
     xremote_canvas_draw_button(canvas, model->right_pressed, 44, 51, XRemoteIconFastForward);
+    xremote_canvas_draw_button(canvas, model->ok_pressed, 23, 51, XRemoteIconPlayPause);
     xremote_canvas_draw_button(canvas, model->back_pressed, 2, 95, XRemoteIconStop);
     xremote_canvas_draw_button(canvas, model->back_pressed, 2, 95, XRemoteIconStop);
 
 
     if (app_ctx->app_settings->exit_behavior == XRemoteAppExitPress)
     if (app_ctx->app_settings->exit_behavior == XRemoteAppExitPress)
         canvas_draw_icon(canvas, 22, 107, &I_Hold_Text_17x4);
         canvas_draw_icon(canvas, 22, 107, &I_Hold_Text_17x4);
+}
+
+static void xremote_player_view_draw_horizontal(Canvas* canvas, XRemoteViewModel* model)
+{
+    XRemoteAppContext *app_ctx = model->context;
 
 
-    xremote_canvas_draw_exit_footer(canvas, xremote_app_context_get_exit_str(app_ctx));
+    xremote_canvas_draw_button(canvas, model->up_pressed, 23, 2, XRemoteIconJumpForward);
+    xremote_canvas_draw_button(canvas, model->down_pressed, 23, 44, XRemoteIconJumpBackward);
+    xremote_canvas_draw_button(canvas, model->left_pressed, 2, 23, XRemoteIconFastBackward);
+    xremote_canvas_draw_button(canvas, model->right_pressed, 44, 23, XRemoteIconFastForward);
+    xremote_canvas_draw_button(canvas, model->ok_pressed, 23, 23, XRemoteIconPlayPause);
+    xremote_canvas_draw_button(canvas, model->back_pressed, 70, 33, XRemoteIconStop);
+
+    if (app_ctx->app_settings->exit_behavior == XRemoteAppExitPress)
+        canvas_draw_icon(canvas, 90, 45, &I_Hold_Text_17x4);
+}
+
+static void xremote_player_view_draw_callback(Canvas* canvas, void* context)
+{
+    furi_assert(context);
+    XRemoteViewModel* model = context;
+    XRemoteAppContext *app_ctx = model->context;
+    ViewOrientation orientation = app_ctx->app_settings->orientation;
+    const char *exit_str = xremote_app_context_get_exit_str(app_ctx);
+
+    XRemoteViewDrawFunction xremote_player_view_draw_body;
+    xremote_player_view_draw_body = orientation == ViewOrientationVertical ?
+        xremote_player_view_draw_vertical : xremote_player_view_draw_horizontal;
+
+    xremote_canvas_draw_header(canvas, orientation, "Playback");
+    xremote_player_view_draw_body(canvas, model);
+    xremote_canvas_draw_exit_footer(canvas, orientation, exit_str);
 }
 }
 
 
 static void xremote_player_view_process(XRemoteView* view, InputEvent* event)
 static void xremote_player_view_process(XRemoteView* view, InputEvent* event)
@@ -74,13 +101,12 @@ static void xremote_player_view_process(XRemoteView* view, InputEvent* event)
                 model->back_pressed = true;
                 model->back_pressed = true;
                 xremote_view_send_ir(view, XREMOTE_COMMAND_STOP);
                 xremote_view_send_ir(view, XREMOTE_COMMAND_STOP);
             }
             }
-            else if (event->type == InputTypeLong)
+            else if (event->type == InputTypeLong &&
+                    event->key == InputKeyBack &&
+                    exit == XRemoteAppExitPress)
             {
             {
-                if (event->key == InputKeyBack && exit == XRemoteAppExitPress)
-                {
-                    model->back_pressed = true;
-                    xremote_view_send_ir(view, XREMOTE_COMMAND_STOP);
-                }
+                model->back_pressed = true;
+                xremote_view_send_ir(view, XREMOTE_COMMAND_STOP);
             }
             }
             else if (event->type == InputTypeRelease)
             else if (event->type == InputTypeRelease)
             {
             {
@@ -123,14 +149,16 @@ XRemoteView* xremote_player_view_alloc(void* app_ctx)
         xremote_view_get_view(view),
         xremote_view_get_view(view),
         XRemoteViewModel* model,
         XRemoteViewModel* model,
         {
         {
-            model->context = xremote_view_get_app_context(view);
+            model->context = app_ctx;
             model->up_pressed = false;
             model->up_pressed = false;
             model->down_pressed = false;
             model->down_pressed = false;
             model->left_pressed = false;
             model->left_pressed = false;
             model->right_pressed = false;
             model->right_pressed = false;
             model->back_pressed = false;
             model->back_pressed = false;
             model->ok_pressed = false;
             model->ok_pressed = false;
-        }, true);
+        },
+        true
+    );
 
 
     return view;
     return view;
 }
 }

+ 1 - 1
xremote.h

@@ -10,6 +10,6 @@
 
 
 #define XREMOTE_VERSION_MAJOR  0
 #define XREMOTE_VERSION_MAJOR  0
 #define XREMOTE_VERSION_MINOR  9
 #define XREMOTE_VERSION_MINOR  9
-#define XREMOTE_BUILD_NUMBER   20
+#define XREMOTE_BUILD_NUMBER   21
 
 
 void xremote_get_version(char *version, size_t length);
 void xremote_get_version(char *version, size_t length);

+ 8 - 4
xremote_app.c

@@ -17,7 +17,7 @@ XRemoteAppSettings* xremote_app_settings_alloc()
     XRemoteAppSettings* settings = malloc(sizeof(XRemoteAppSettings));
     XRemoteAppSettings* settings = malloc(sizeof(XRemoteAppSettings));
     settings->orientation = ViewOrientationHorizontal;
     settings->orientation = ViewOrientationHorizontal;
     settings->exit_behavior = XRemoteAppExitPress;
     settings->exit_behavior = XRemoteAppExitPress;
-    settings->repeat_count = 1;
+    settings->repeat_count = 2;
     return settings;
     return settings;
 }
 }
 
 
@@ -63,6 +63,7 @@ bool xremote_app_settings_load(XRemoteAppSettings* settings)
 
 
     FURI_LOG_I(TAG, "load config file: \'%s\'", XREMOTE_APP_SETTINGS);
     FURI_LOG_I(TAG, "load config file: \'%s\'", XREMOTE_APP_SETTINGS);
     uint32_t version = 0;
     uint32_t version = 0;
+    uint32_t value = 0;
     bool success = false;
     bool success = false;
 
 
     do {
     do {
@@ -72,9 +73,12 @@ bool xremote_app_settings_load(XRemoteAppSettings* settings)
         if (!furi_string_equal(header, "XRemote settings file") || (version != 1)) break;
         if (!furi_string_equal(header, "XRemote settings file") || (version != 1)) break;
 
 
         /* Parse config data from the buffer */
         /* Parse config data from the buffer */
-        if (!flipper_format_read_uint32(ff, "orientation", (uint32_t*)&settings->orientation, 1)) break;
-        if (!flipper_format_read_uint32(ff, "repeat", (uint32_t*)&settings->repeat_count, 1)) break;
-        if (!flipper_format_read_uint32(ff, "exit", (uint32_t*)&settings->exit_behavior, 1)) break;
+        if (!flipper_format_read_uint32(ff, "orientation", &value, 1)) break;
+        settings->orientation = value;
+        if (!flipper_format_read_uint32(ff, "repeat", &value, 1)) break;
+        settings->repeat_count = value;
+        if (!flipper_format_read_uint32(ff, "exit", &value, 1)) break;
+        settings->exit_behavior = value;
 
 
         success = true;
         success = true;
     } while(false);
     } while(false);