nitepone 2 лет назад
Родитель
Сommit
bae9c09959
1 измененных файлов с 303 добавлено и 29 удалено
  1. 303 29
      intervalometer.c

+ 303 - 29
intervalometer.c

@@ -3,7 +3,6 @@
 // author: nitepone <sierra>
 
 #include "intervalometer.h"
-#include <gui/scene_manager.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <furi.h>
@@ -42,10 +41,10 @@ struct flipvalo_config {
 
 // run time states for intervalometer
 enum flipvalo_state {
-    FVDone = 0, // done, 0 so it is default if state struct is zeroed
-    FVWaitInitShot, // waiting for first shot
-    FVWaitContShot, // waiting between "bursts" or "shots"
-    FVWaitBurst, // waiting between shots in a "burst"
+    FVDone = 0,                   // done, 0 so it is default if state struct is zeroed
+    FVWaitInitShot,               // waiting for first shot
+    FVWaitContShot,               // waiting between "bursts" or "shots"
+    FVWaitBurst,                  // waiting between shots in a "burst"
 };
 
 // run time data for intervalometer
@@ -58,9 +57,35 @@ struct flipvalo_run_state {
     int burst_cur;              // current trigger in a burst
 };
 
+enum flipvalo_config_edit_lines {
+    FvConfigEditInitDelay,
+    FvConfigEditMIN = FvConfigEditInitDelay,
+    FvConfigEditShotDelay,
+    FvConfigEditShotCount,
+    FvConfigEditBurstDelay,
+    FvConfigEditBurstCount,
+    FvConfigEditMAX = FvConfigEditBurstCount,
+};
+
+struct flipvalo_config_edit_view {
+    // the `config` that is under edit
+    struct flipvalo_config* config;
+    // the `cur_index` of the selection
+    // (e.g. editing the 3rd value of a number)
+    int cur_index;
+    // the `cur_line` of the selection
+    enum flipvalo_config_edit_lines cur_line;
+    // the current line that is at the top of the scrolled view
+    enum flipvalo_config_edit_lines scroll_pos;
+    // are we editing the selection?
+    // (this is really only needed for number fields)
+    bool edit_mode;
+};
+
 // private data of app
 struct flipvalo_priv {
     struct flipvalo_config config;
+    struct flipvalo_config_edit_view config_edit_view;
     struct flipvalo_run_state run_state;
     enum flipvalo_ui_scene ui_scene;
     FuriTimer* timer;
@@ -78,12 +103,236 @@ struct plugin_event {
     InputEvent input;
 };
 
+
+// XXX(luna) settings experimental ui kludge
+
+enum flipvalo_config_edit_line_type {
+    FvConfigEditTypeTimer,
+    FvConfigEditTypeCount,
+};
+
+
+#define ITEM_H 64 / 3
+#define ITEM_W 128
+#define VALUE_X 100
+#define VALUE_W 100
+static void flipvalo_config_edit_draw(Canvas* canvas, struct flipvalo_config_edit_view* view) {
+    int* line_value;
+    char* line_label = NULL;
+    FuriString* temp_str = furi_string_alloc();
+    enum flipvalo_config_edit_line_type line_type;
+
+    for (size_t line = 0; line < 3; line++) {
+        switch (view->scroll_pos + line) {
+            case FvConfigEditInitDelay:
+                line_value = &view->config->init_delay_msec;
+                line_type = FvConfigEditTypeTimer;
+                line_label = "Init Timer";
+                break;
+            case FvConfigEditShotDelay:
+                line_value = &view->config->interval_delay_msec;
+                line_type = FvConfigEditTypeTimer;
+                line_label = "Seq. Timer";
+                break;
+            case FvConfigEditShotCount:
+                line_value = &view->config->shot_count;
+                line_type = FvConfigEditTypeCount;
+                line_label = "Seq. Count";
+                break;
+            case FvConfigEditBurstDelay:
+                line_value = &view->config->burst_delay_msec;
+                line_type = FvConfigEditTypeTimer;
+                line_label = "Burst Timer";
+                break;
+            case FvConfigEditBurstCount:
+                line_value = &view->config->burst_count;
+                line_type = FvConfigEditTypeCount;
+                line_label = "Burst Count";
+                break;
+            default:
+                continue;
+        };
+
+        canvas_set_color(canvas, ColorBlack);
+        if ((view->scroll_pos + line) == view->cur_line) {
+            elements_slightly_rounded_box(canvas, 0, ITEM_H * line + 1, ITEM_W, ITEM_H - 1);
+            canvas_set_color(canvas, ColorWhite);
+        }
+
+        uint8_t text_y = ITEM_H * line + ITEM_H / 2 + 2;
+
+        canvas_draw_str_aligned(canvas, 6, text_y, AlignLeft, AlignCenter, line_label);
+
+        switch(line_type) {
+            case FvConfigEditTypeTimer:
+                furi_string_printf(
+                        temp_str, "%02d:%02d:%02d:%03d",
+                        *line_value / 3600000,
+                        (*line_value / 60000) % 60,
+                        (*line_value / 1000) % 60,
+                        *line_value % 1000);
+                canvas_set_font(canvas, FontKeyboard);
+                canvas_draw_str_aligned(
+                        canvas, 124, text_y, AlignRight, AlignCenter,
+                        furi_string_get_cstr(temp_str));
+                canvas_set_font(canvas, FontSecondary);
+                if (view->edit_mode) {
+                    //TODO(luna) review positioning.
+                    //uint8_t icon_x = (128) - ((7 - view->cur_index - 1) * 6);
+                    //canvas_draw_icon(canvas, icon_x, text_y - 9, &I_SmallArrowUp_3x5);
+                    //canvas_draw_icon(canvas, icon_x, text_y + 5, &I_SmallArrowDown_3x5);
+                }
+                break;
+            case FvConfigEditTypeCount:
+                furi_string_printf(temp_str, "%d", *line_value);
+                canvas_draw_str_aligned(
+                        canvas, VALUE_X, text_y, AlignCenter, AlignCenter,
+                        furi_string_get_cstr(temp_str));
+                // TODO(luna) 0 values are actually more special for shot count and burst count.
+                // former being infinite, latter being uh.. nothing? not allowed?.. review this logic later.
+                if(*line_value > 0) {
+                    canvas_draw_str_aligned(
+                        canvas, VALUE_X - VALUE_W / 2, text_y, AlignCenter, AlignCenter, "<");
+                }
+                canvas_draw_str_aligned(
+                    canvas, VALUE_X + VALUE_W / 2, text_y, AlignCenter, AlignCenter, ">");
+                break;
+        }
+    }
+
+    furi_string_free(temp_str);
+}
+
+static void flipvalo_config_edit_input_move_cursor(struct flipvalo_config_edit_view* view, int dx, int dy) {
+    enum flipvalo_config_edit_lines new_line = 0;
+
+    int* line_value;
+    enum flipvalo_config_edit_line_type line_type;
+
+    switch (view->cur_line) {
+        case FvConfigEditInitDelay:
+            line_value = &view->config->init_delay_msec;
+            line_type = FvConfigEditTypeTimer;
+            break;
+        case FvConfigEditShotDelay:
+            line_value = &view->config->interval_delay_msec;
+            line_type = FvConfigEditTypeTimer;
+            break;
+        case FvConfigEditShotCount:
+            line_value = &view->config->shot_count;
+            line_type = FvConfigEditTypeCount;
+            break;
+        case FvConfigEditBurstDelay:
+            line_value = &view->config->burst_delay_msec;
+            line_type = FvConfigEditTypeTimer;
+            break;
+        case FvConfigEditBurstCount:
+            line_value = &view->config->burst_count;
+            line_type = FvConfigEditTypeCount;
+            break;
+        default:
+            return;
+    };
+
+    if (!view->edit_mode) {
+        // Do `dy` behaviors
+        new_line = view->cur_line + dy;
+        if (new_line > FvConfigEditMAX) {
+            // Out of bound cursor. No-op.
+            return;
+        }
+        view->cur_line = new_line;
+
+        // Handle moving scroll position.
+        if (new_line < view->scroll_pos) {
+            view->scroll_pos = new_line;
+        }
+        else if (new_line >= (view->scroll_pos + 3)) {
+            view->scroll_pos+=dy;
+        }
+
+        // Do `dx` behavior
+        switch (line_type) {
+            case FvConfigEditTypeCount:
+                if (*line_value + dx >= 0) {
+                    *line_value += dx;
+                }
+                break;
+            case FvConfigEditTypeTimer:
+                // no-op unless edit mode
+                break;
+        }
+    }
+    else /* edit mode */ {
+        switch (line_type) {
+            case FvConfigEditTypeCount:
+                // If current line does not edit mode.. why are we in edit mode?
+                // Reaching this would be a bug, so lets go back to normal mode.
+                view->edit_mode = false;
+                return;
+            case FvConfigEditTypeTimer:
+                // bro the math here is gonna suck.
+                // I'm doing it WRONG for now x3
+                // TODO(luna) REAL MATHS
+                if (*line_value + (dy * -100) >= 0) {
+                    *line_value += (dy * -100);
+                }
+                view->cur_index += dx;
+                if (view->cur_index < 0) {
+                    view->cur_index = 0;
+                }
+                if (view->cur_index > 10) {
+                    view->cur_index = 10;
+                }
+                break;
+        }
+    }
+}
+
+static int flipvalo_config_edit_input(InputEvent* event, struct flipvalo_config_edit_view* view) {
+    // ignore all but short and repeats
+    if (!(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
+        return 0;
+    }
+    switch (event->key) {
+        case InputKeyRight:
+            flipvalo_config_edit_input_move_cursor(view, 1, 0);
+            break;
+        case InputKeyLeft:
+            flipvalo_config_edit_input_move_cursor(view, -1, 0);
+            break;
+        case InputKeyUp:
+            flipvalo_config_edit_input_move_cursor(view, 0, -1);
+            break;
+        case InputKeyDown:
+            flipvalo_config_edit_input_move_cursor(view, 0, 1);
+            break;
+        case InputKeyOk:
+            view->edit_mode = !view->edit_mode;
+            break;
+        case InputKeyBack:
+            if (view->edit_mode) {
+                view->edit_mode = false;
+            } else {
+                // exit config edit view
+                return 1;
+            }
+        default:
+            break;
+    }
+    return 0;
+}
+
+
+// XXX(luna) back to app
+
 static void flipvalo_run_state_init(struct flipvalo_run_state* fv_run_state) {
     fv_run_state->burst_cur = 0;
     fv_run_state->shot_cur = 0;
     fv_run_state->tick_next = 0;
     fv_run_state->state = FVDone;
     fv_run_state->tick_next = 0;
+    fv_run_state->tick_cur = 0;
 }
 
 static int sony_ir_trigger(void* ctx) {
@@ -203,6 +452,9 @@ static void render_callback(Canvas* const canvas, void* ctx) {
             elements_button_center(canvas, "Stop ");
         }
     }
+    else if (fv_priv->ui_scene == FVSceneConfig) {
+        flipvalo_config_edit_draw(canvas, &fv_priv->config_edit_view);
+    }
 
     furi_string_free(temp_str);
     furi_mutex_release(fv_priv->mutex);
@@ -274,32 +526,54 @@ int32_t flipvalo_app() {
         }
 
         // handle input
-        if (event.type == EventTypeKey) {
-            if (event.input.type == InputTypeShort) {
-                switch (event.input.key) {
-                    case InputKeyUp:
-                        break;
-                    case InputKeyDown:
-                        break;
-                    case InputKeyLeft:
-                        break;
-                    case InputKeyRight:
-                        fv_priv->config.send_trigger_fn(fv_priv->config.output_config);
-                        break;
-                    case InputKeyOk:
-                        if (flipvalo_intv_running(fv_priv)) {
-                            flipvalo_intv_stop(fv_priv);
-                        } else {
-                            flipvalo_intv_start(fv_priv);
+        if (
+            event.type == EventTypeKey
+            && event.input.type == InputTypeLong
+            && event.input.key == InputKeyBack
+        ) {
+            goto cleanup;
+        }
+        switch (fv_priv->ui_scene) {
+            case FVSceneMain:
+                if (event.type == EventTypeKey) {
+                    if (event.input.type == InputTypeShort) {
+                        switch (event.input.key) {
+                            case InputKeyUp:
+                                break;
+                            case InputKeyDown:
+                                break;
+                            case InputKeyLeft:
+                                fv_priv->config_edit_view.config = &fv_priv->config;
+                                fv_priv->config_edit_view.cur_index = 0;
+                                fv_priv->config_edit_view.cur_line = 0;
+                                fv_priv->config_edit_view.scroll_pos = 0;
+                                fv_priv->config_edit_view.edit_mode = false;
+                                fv_priv->ui_scene = FVSceneConfig;
+                                break;
+                            case InputKeyRight:
+                                fv_priv->config.send_trigger_fn(fv_priv->config.output_config);
+                                break;
+                            case InputKeyOk:
+                                if (flipvalo_intv_running(fv_priv)) {
+                                    flipvalo_intv_stop(fv_priv);
+                                } else {
+                                    flipvalo_intv_start(fv_priv);
+                                }
+                                break;
+                            case InputKeyMAX:
+                                break;
+                            case InputKeyBack:
+                                break;
                         }
-                        break;
-                    case InputKeyMAX:
-                        break;
-                    case InputKeyBack:
-                        // Exit the app
-                        goto cleanup;
+                    }
                 }
-            }
+                break;
+            case FVSceneConfig:
+                ret = flipvalo_config_edit_input(&event.input, &fv_priv->config_edit_view);
+                if (ret) {
+                    fv_priv->ui_scene = FVSceneMain;
+                }
+                break;
         }
 
 next_event: