|
|
|
@@ -1,5 +1,4 @@
|
|
|
|
#include "submenu.h"
|
|
|
|
#include "submenu.h"
|
|
|
|
#include <gui/canvas_i.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <assets_icons.h>
|
|
|
|
#include <assets_icons.h>
|
|
|
|
#include <gui/elements.h>
|
|
|
|
#include <gui/elements.h>
|
|
|
|
@@ -66,22 +65,23 @@ typedef struct {
|
|
|
|
size_t position;
|
|
|
|
size_t position;
|
|
|
|
size_t window_position;
|
|
|
|
size_t window_position;
|
|
|
|
bool locked_message_visible;
|
|
|
|
bool locked_message_visible;
|
|
|
|
|
|
|
|
bool is_vertical;
|
|
|
|
} SubmenuModel;
|
|
|
|
} SubmenuModel;
|
|
|
|
|
|
|
|
|
|
|
|
static void submenu_process_up(Submenu* submenu);
|
|
|
|
static void submenu_process_up(Submenu* submenu);
|
|
|
|
static void submenu_process_down(Submenu* submenu);
|
|
|
|
static void submenu_process_down(Submenu* submenu);
|
|
|
|
static void submenu_process_ok(Submenu* submenu);
|
|
|
|
static void submenu_process_ok(Submenu* submenu);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static size_t submenu_items_on_screen(bool header, bool vertical) {
|
|
|
|
|
|
|
|
size_t res = (vertical) ? 8 : 4;
|
|
|
|
|
|
|
|
return (header) ? res - 1 : res;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
|
|
|
static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
|
|
|
SubmenuModel* model = _model;
|
|
|
|
SubmenuModel* model = _model;
|
|
|
|
|
|
|
|
|
|
|
|
const uint8_t item_height = 16;
|
|
|
|
const uint8_t item_height = 16;
|
|
|
|
uint8_t item_width = 123;
|
|
|
|
uint8_t item_width = canvas_width(canvas) - 5;
|
|
|
|
|
|
|
|
|
|
|
|
if(canvas->orientation == CanvasOrientationVertical ||
|
|
|
|
|
|
|
|
canvas->orientation == CanvasOrientationVerticalFlip) {
|
|
|
|
|
|
|
|
item_width = 60;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
canvas_clear(canvas);
|
|
|
|
canvas_clear(canvas);
|
|
|
|
|
|
|
|
|
|
|
|
@@ -97,7 +97,8 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
|
|
|
for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it);
|
|
|
|
for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it);
|
|
|
|
SubmenuItemArray_next(it)) {
|
|
|
|
SubmenuItemArray_next(it)) {
|
|
|
|
const size_t item_position = position - model->window_position;
|
|
|
|
const size_t item_position = position - model->window_position;
|
|
|
|
const size_t items_on_screen = furi_string_empty(model->header) ? 4 : 3;
|
|
|
|
const size_t items_on_screen =
|
|
|
|
|
|
|
|
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
|
|
|
|
uint8_t y_offset = furi_string_empty(model->header) ? 0 : 16;
|
|
|
|
uint8_t y_offset = furi_string_empty(model->header) ? 0 : 16;
|
|
|
|
|
|
|
|
|
|
|
|
if(item_position < items_on_screen) {
|
|
|
|
if(item_position < items_on_screen) {
|
|
|
|
@@ -117,7 +118,7 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
|
|
|
if(SubmenuItemArray_cref(it)->locked) {
|
|
|
|
if(SubmenuItemArray_cref(it)->locked) {
|
|
|
|
canvas_draw_icon(
|
|
|
|
canvas_draw_icon(
|
|
|
|
canvas,
|
|
|
|
canvas,
|
|
|
|
110,
|
|
|
|
item_width - 10,
|
|
|
|
y_offset + (item_position * item_height) + item_height - 12,
|
|
|
|
y_offset + (item_position * item_height) + item_height - 12,
|
|
|
|
&I_Lock_7x8);
|
|
|
|
&I_Lock_7x8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -125,7 +126,7 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
|
|
|
FuriString* disp_str;
|
|
|
|
FuriString* disp_str;
|
|
|
|
disp_str = furi_string_alloc_set(SubmenuItemArray_cref(it)->label);
|
|
|
|
disp_str = furi_string_alloc_set(SubmenuItemArray_cref(it)->label);
|
|
|
|
elements_string_fit_width(
|
|
|
|
elements_string_fit_width(
|
|
|
|
canvas, disp_str, item_width - (SubmenuItemArray_cref(it)->locked ? 25 : 11));
|
|
|
|
canvas, disp_str, item_width - (SubmenuItemArray_cref(it)->locked ? 21 : 11));
|
|
|
|
|
|
|
|
|
|
|
|
canvas_draw_str(
|
|
|
|
canvas_draw_str(
|
|
|
|
canvas,
|
|
|
|
canvas,
|
|
|
|
@@ -142,12 +143,30 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
|
|
|
elements_scrollbar(canvas, model->position, SubmenuItemArray_size(model->items));
|
|
|
|
elements_scrollbar(canvas, model->position, SubmenuItemArray_size(model->items));
|
|
|
|
|
|
|
|
|
|
|
|
if(model->locked_message_visible) {
|
|
|
|
if(model->locked_message_visible) {
|
|
|
|
|
|
|
|
const uint8_t frame_x = 7;
|
|
|
|
|
|
|
|
const uint8_t frame_width = canvas_width(canvas) - frame_x * 2;
|
|
|
|
|
|
|
|
const uint8_t frame_y = 7;
|
|
|
|
|
|
|
|
const uint8_t frame_height = canvas_height(canvas) - frame_y * 2;
|
|
|
|
|
|
|
|
|
|
|
|
canvas_set_color(canvas, ColorWhite);
|
|
|
|
canvas_set_color(canvas, ColorWhite);
|
|
|
|
canvas_draw_box(canvas, 8, 10, 110, 48);
|
|
|
|
canvas_draw_box(canvas, frame_x + 2, frame_y + 2, frame_width - 4, frame_height - 4);
|
|
|
|
|
|
|
|
|
|
|
|
canvas_set_color(canvas, ColorBlack);
|
|
|
|
canvas_set_color(canvas, ColorBlack);
|
|
|
|
canvas_draw_icon(canvas, 10, 14, &I_WarningDolphin_45x42);
|
|
|
|
canvas_draw_icon(
|
|
|
|
canvas_draw_rframe(canvas, 8, 8, 112, 50, 3);
|
|
|
|
canvas, frame_x + 2, canvas_height(canvas) - frame_y - 2 - 42, &I_WarningDolphin_45x42);
|
|
|
|
canvas_draw_rframe(canvas, 9, 9, 110, 48, 2);
|
|
|
|
|
|
|
|
|
|
|
|
canvas_draw_rframe(canvas, frame_x, frame_y, frame_width, frame_height, 3);
|
|
|
|
|
|
|
|
canvas_draw_rframe(canvas, frame_x + 1, frame_y + 1, frame_width - 2, frame_height - 2, 2);
|
|
|
|
|
|
|
|
if(model->is_vertical) {
|
|
|
|
|
|
|
|
elements_multiline_text_aligned(
|
|
|
|
|
|
|
|
canvas,
|
|
|
|
|
|
|
|
32,
|
|
|
|
|
|
|
|
42,
|
|
|
|
|
|
|
|
AlignCenter,
|
|
|
|
|
|
|
|
AlignCenter,
|
|
|
|
|
|
|
|
furi_string_get_cstr(
|
|
|
|
|
|
|
|
SubmenuItemArray_get(model->items, model->position)->locked_message));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
elements_multiline_text_aligned(
|
|
|
|
elements_multiline_text_aligned(
|
|
|
|
canvas,
|
|
|
|
canvas,
|
|
|
|
84,
|
|
|
|
84,
|
|
|
|
@@ -157,6 +176,7 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
|
|
|
furi_string_get_cstr(
|
|
|
|
furi_string_get_cstr(
|
|
|
|
SubmenuItemArray_get(model->items, model->position)->locked_message));
|
|
|
|
SubmenuItemArray_get(model->items, model->position)->locked_message));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool submenu_view_input_callback(InputEvent* event, void* context) {
|
|
|
|
static bool submenu_view_input_callback(InputEvent* event, void* context) {
|
|
|
|
@@ -303,6 +323,7 @@ void submenu_add_lockable_item(
|
|
|
|
|
|
|
|
|
|
|
|
void submenu_reset(Submenu* submenu) {
|
|
|
|
void submenu_reset(Submenu* submenu) {
|
|
|
|
furi_assert(submenu);
|
|
|
|
furi_assert(submenu);
|
|
|
|
|
|
|
|
view_set_orientation(submenu->view, ViewOrientationHorizontal);
|
|
|
|
|
|
|
|
|
|
|
|
with_view_model(
|
|
|
|
with_view_model(
|
|
|
|
submenu->view,
|
|
|
|
submenu->view,
|
|
|
|
@@ -311,6 +332,7 @@ void submenu_reset(Submenu* submenu) {
|
|
|
|
SubmenuItemArray_reset(model->items);
|
|
|
|
SubmenuItemArray_reset(model->items);
|
|
|
|
model->position = 0;
|
|
|
|
model->position = 0;
|
|
|
|
model->window_position = 0;
|
|
|
|
model->window_position = 0;
|
|
|
|
|
|
|
|
model->is_vertical = false;
|
|
|
|
furi_string_reset(model->header);
|
|
|
|
furi_string_reset(model->header);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
true);
|
|
|
|
true);
|
|
|
|
@@ -344,7 +366,8 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index) {
|
|
|
|
model->window_position -= 1;
|
|
|
|
model->window_position -= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const size_t items_on_screen = furi_string_empty(model->header) ? 4 : 3;
|
|
|
|
const size_t items_on_screen =
|
|
|
|
|
|
|
|
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
|
|
|
|
|
|
|
|
|
|
|
|
if(items_size <= items_on_screen) {
|
|
|
|
if(items_size <= items_on_screen) {
|
|
|
|
model->window_position = 0;
|
|
|
|
model->window_position = 0;
|
|
|
|
@@ -363,7 +386,8 @@ void submenu_process_up(Submenu* submenu) {
|
|
|
|
submenu->view,
|
|
|
|
submenu->view,
|
|
|
|
SubmenuModel * model,
|
|
|
|
SubmenuModel * model,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const size_t items_on_screen = furi_string_empty(model->header) ? 4 : 3;
|
|
|
|
const size_t items_on_screen =
|
|
|
|
|
|
|
|
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
|
|
|
|
const size_t items_size = SubmenuItemArray_size(model->items);
|
|
|
|
const size_t items_size = SubmenuItemArray_size(model->items);
|
|
|
|
|
|
|
|
|
|
|
|
if(model->position > 0) {
|
|
|
|
if(model->position > 0) {
|
|
|
|
@@ -386,7 +410,8 @@ void submenu_process_down(Submenu* submenu) {
|
|
|
|
submenu->view,
|
|
|
|
submenu->view,
|
|
|
|
SubmenuModel * model,
|
|
|
|
SubmenuModel * model,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const size_t items_on_screen = furi_string_empty(model->header) ? 4 : 3;
|
|
|
|
const size_t items_on_screen =
|
|
|
|
|
|
|
|
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
|
|
|
|
const size_t items_size = SubmenuItemArray_size(model->items);
|
|
|
|
const size_t items_size = SubmenuItemArray_size(model->items);
|
|
|
|
|
|
|
|
|
|
|
|
if(model->position < items_size - 1) {
|
|
|
|
if(model->position < items_size - 1) {
|
|
|
|
@@ -441,3 +466,48 @@ void submenu_set_header(Submenu* submenu, const char* header) {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
true);
|
|
|
|
true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void submenu_set_orientation(Submenu* submenu, ViewOrientation orientation) {
|
|
|
|
|
|
|
|
furi_assert(submenu);
|
|
|
|
|
|
|
|
const bool is_vertical =
|
|
|
|
|
|
|
|
(orientation == ViewOrientationVertical || orientation == ViewOrientationVerticalFlip) ?
|
|
|
|
|
|
|
|
true :
|
|
|
|
|
|
|
|
false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
view_set_orientation(submenu->view, orientation);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with_view_model(
|
|
|
|
|
|
|
|
submenu->view,
|
|
|
|
|
|
|
|
SubmenuModel * model,
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
model->is_vertical = is_vertical;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Recalculating the position
|
|
|
|
|
|
|
|
// Need if _set_orientation is called after _set_selected_item
|
|
|
|
|
|
|
|
size_t position = model->position;
|
|
|
|
|
|
|
|
const size_t items_size = SubmenuItemArray_size(model->items);
|
|
|
|
|
|
|
|
const size_t items_on_screen =
|
|
|
|
|
|
|
|
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(position >= items_size) {
|
|
|
|
|
|
|
|
position = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model->position = position;
|
|
|
|
|
|
|
|
model->window_position = position;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(model->window_position > 0) {
|
|
|
|
|
|
|
|
model->window_position -= 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(items_size <= items_on_screen) {
|
|
|
|
|
|
|
|
model->window_position = 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
const size_t pos = items_size - items_on_screen;
|
|
|
|
|
|
|
|
if(model->window_position > pos) {
|
|
|
|
|
|
|
|
model->window_position = pos;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|