mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 04:34:43 +04:00
submenu merge all changes
by WillyJL
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
struct Submenu {
|
struct Submenu {
|
||||||
View* view;
|
View* view;
|
||||||
|
|
||||||
FuriTimer* locked_timer;
|
FuriTimer* locked_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ typedef struct {
|
|||||||
};
|
};
|
||||||
void* callback_context;
|
void* callback_context;
|
||||||
bool has_extended_events;
|
bool has_extended_events;
|
||||||
|
|
||||||
bool locked;
|
bool locked;
|
||||||
FuriString* locked_message;
|
FuriString* locked_message;
|
||||||
} SubmenuItem;
|
} SubmenuItem;
|
||||||
@@ -68,6 +70,7 @@ typedef struct {
|
|||||||
FuriString* header;
|
FuriString* header;
|
||||||
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;
|
bool is_vertical;
|
||||||
} SubmenuModel;
|
} SubmenuModel;
|
||||||
@@ -76,9 +79,9 @@ 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, InputType input_type);
|
static void submenu_process_ok(Submenu* submenu, InputType input_type);
|
||||||
|
|
||||||
static size_t submenu_items_on_screen(bool header, bool vertical) {
|
static size_t submenu_items_on_screen(SubmenuModel* model) {
|
||||||
size_t res = (vertical) ? 8 : 4;
|
size_t res = (model->is_vertical) ? 8 : 4;
|
||||||
return (header) ? res - 1 : res;
|
return (furi_string_empty(model->header)) ? res : res - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
||||||
@@ -101,9 +104,9 @@ 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 =
|
const size_t items_on_screen = submenu_items_on_screen(model);
|
||||||
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
|
uint8_t y_offset = furi_string_empty(model->header) ? 0 : item_height;
|
||||||
uint8_t y_offset = furi_string_empty(model->header) ? 0 : 16;
|
bool is_locked = SubmenuItemArray_cref(it)->locked;
|
||||||
|
|
||||||
if(item_position < items_on_screen) {
|
if(item_position < items_on_screen) {
|
||||||
if(position == model->position) {
|
if(position == model->position) {
|
||||||
@@ -119,7 +122,7 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SubmenuItemArray_cref(it)->locked) {
|
if(is_locked) {
|
||||||
canvas_draw_icon(
|
canvas_draw_icon(
|
||||||
canvas,
|
canvas,
|
||||||
item_width - 10,
|
item_width - 10,
|
||||||
@@ -127,10 +130,8 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
&I_Lock_7x8);
|
&I_Lock_7x8);
|
||||||
}
|
}
|
||||||
|
|
||||||
FuriString* disp_str;
|
FuriString* disp_str = furi_string_alloc_set(SubmenuItemArray_cref(it)->label);
|
||||||
disp_str = furi_string_alloc_set(SubmenuItemArray_cref(it)->label);
|
elements_string_fit_width(canvas, disp_str, item_width - (is_locked ? 21 : 11));
|
||||||
elements_string_fit_width(
|
|
||||||
canvas, disp_str, item_width - (SubmenuItemArray_cref(it)->locked ? 21 : 11));
|
|
||||||
|
|
||||||
canvas_draw_str(
|
canvas_draw_str(
|
||||||
canvas,
|
canvas,
|
||||||
@@ -161,25 +162,14 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
|
|
||||||
canvas_draw_rframe(canvas, frame_x, frame_y, frame_width, frame_height, 3);
|
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);
|
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(
|
elements_multiline_text_aligned(
|
||||||
canvas,
|
canvas,
|
||||||
32,
|
(model->is_vertical) ? 32 : 84,
|
||||||
42,
|
(model->is_vertical) ? 42 : 32,
|
||||||
AlignCenter,
|
AlignCenter,
|
||||||
AlignCenter,
|
AlignCenter,
|
||||||
furi_string_get_cstr(
|
furi_string_get_cstr(
|
||||||
SubmenuItemArray_get(model->items, model->position)->locked_message));
|
SubmenuItemArray_get(model->items, model->position)->locked_message));
|
||||||
} else {
|
|
||||||
elements_multiline_text_aligned(
|
|
||||||
canvas,
|
|
||||||
84,
|
|
||||||
32,
|
|
||||||
AlignCenter,
|
|
||||||
AlignCenter,
|
|
||||||
furi_string_get_cstr(
|
|
||||||
SubmenuItemArray_get(model->items, model->position)->locked_message));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,8 +185,7 @@ static bool submenu_view_input_callback(InputEvent* event, void* context) {
|
|||||||
{ locked_message_visible = model->locked_message_visible; },
|
{ locked_message_visible = model->locked_message_visible; },
|
||||||
false);
|
false);
|
||||||
|
|
||||||
if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) &&
|
if(locked_message_visible && (event->type == InputTypeShort || event->type == InputTypeLong)) {
|
||||||
locked_message_visible) {
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
submenu->view, SubmenuModel * model, { model->locked_message_visible = false; }, true);
|
submenu->view, SubmenuModel * model, { model->locked_message_visible = false; }, true);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
@@ -303,6 +292,9 @@ void submenu_add_lockable_item(
|
|||||||
SubmenuItem* item = NULL;
|
SubmenuItem* item = NULL;
|
||||||
furi_check(label);
|
furi_check(label);
|
||||||
furi_check(submenu);
|
furi_check(submenu);
|
||||||
|
if(locked) {
|
||||||
|
furi_check(locked_message);
|
||||||
|
}
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
submenu->view,
|
submenu->view,
|
||||||
@@ -366,6 +358,25 @@ void submenu_change_item_label(Submenu* submenu, uint32_t index, const char* lab
|
|||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void submenu_remove_item(Submenu* submenu, uint32_t index) {
|
||||||
|
furi_check(submenu);
|
||||||
|
|
||||||
|
with_view_model(
|
||||||
|
submenu->view,
|
||||||
|
SubmenuModel * model,
|
||||||
|
{
|
||||||
|
SubmenuItemArray_it_t it;
|
||||||
|
for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it);
|
||||||
|
SubmenuItemArray_next(it)) {
|
||||||
|
if(index == SubmenuItemArray_cref(it)->index) {
|
||||||
|
SubmenuItemArray_remove(model->items, it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
void submenu_reset(Submenu* submenu) {
|
void submenu_reset(Submenu* submenu) {
|
||||||
furi_check(submenu);
|
furi_check(submenu);
|
||||||
view_set_orientation(submenu->view, ViewOrientationHorizontal);
|
view_set_orientation(submenu->view, ViewOrientationHorizontal);
|
||||||
@@ -431,8 +442,7 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index) {
|
|||||||
model->window_position -= 1;
|
model->window_position -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t items_on_screen =
|
const size_t items_on_screen = submenu_items_on_screen(model);
|
||||||
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;
|
||||||
@@ -451,8 +461,7 @@ void submenu_process_up(Submenu* submenu) {
|
|||||||
submenu->view,
|
submenu->view,
|
||||||
SubmenuModel * model,
|
SubmenuModel * model,
|
||||||
{
|
{
|
||||||
const size_t items_on_screen =
|
const size_t items_on_screen = submenu_items_on_screen(model);
|
||||||
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) {
|
||||||
@@ -475,8 +484,7 @@ void submenu_process_down(Submenu* submenu) {
|
|||||||
submenu->view,
|
submenu->view,
|
||||||
SubmenuModel * model,
|
SubmenuModel * model,
|
||||||
{
|
{
|
||||||
const size_t items_on_screen =
|
const size_t items_on_screen = submenu_items_on_screen(model);
|
||||||
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) {
|
||||||
@@ -504,7 +512,8 @@ void submenu_process_ok(Submenu* submenu, InputType input_type) {
|
|||||||
if(model->position < items_size) {
|
if(model->position < items_size) {
|
||||||
item = SubmenuItemArray_get(model->items, model->position);
|
item = SubmenuItemArray_get(model->items, model->position);
|
||||||
}
|
}
|
||||||
if(item && item->locked) {
|
if(item && item->locked &&
|
||||||
|
(input_type == InputTypeShort || input_type == InputTypeLong)) {
|
||||||
model->locked_message_visible = true;
|
model->locked_message_visible = true;
|
||||||
furi_timer_start(submenu->locked_timer, furi_kernel_get_tick_frequency() * 3);
|
furi_timer_start(submenu->locked_timer, furi_kernel_get_tick_frequency() * 3);
|
||||||
}
|
}
|
||||||
@@ -540,11 +549,9 @@ void submenu_set_header(Submenu* submenu, const char* header) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void submenu_set_orientation(Submenu* submenu, ViewOrientation orientation) {
|
void submenu_set_orientation(Submenu* submenu, ViewOrientation orientation) {
|
||||||
furi_assert(submenu);
|
furi_check(submenu);
|
||||||
const bool is_vertical =
|
const bool is_vertical = orientation == ViewOrientationVertical ||
|
||||||
(orientation == ViewOrientationVertical || orientation == ViewOrientationVerticalFlip) ?
|
orientation == ViewOrientationVerticalFlip;
|
||||||
true :
|
|
||||||
false;
|
|
||||||
|
|
||||||
view_set_orientation(submenu->view, orientation);
|
view_set_orientation(submenu->view, orientation);
|
||||||
|
|
||||||
@@ -558,8 +565,7 @@ void submenu_set_orientation(Submenu* submenu, ViewOrientation orientation) {
|
|||||||
// Need if _set_orientation is called after _set_selected_item
|
// Need if _set_orientation is called after _set_selected_item
|
||||||
size_t position = model->position;
|
size_t position = model->position;
|
||||||
const size_t items_size = SubmenuItemArray_size(model->items);
|
const size_t items_size = SubmenuItemArray_size(model->items);
|
||||||
const size_t items_on_screen =
|
const size_t items_on_screen = submenu_items_on_screen(model);
|
||||||
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
|
|
||||||
|
|
||||||
if(position >= items_size) {
|
if(position >= items_size) {
|
||||||
position = 0;
|
position = 0;
|
||||||
|
|||||||
@@ -98,6 +98,14 @@ void submenu_add_item_ex(
|
|||||||
*/
|
*/
|
||||||
void submenu_change_item_label(Submenu* submenu, uint32_t index, const char* label);
|
void submenu_change_item_label(Submenu* submenu, uint32_t index, const char* label);
|
||||||
|
|
||||||
|
/** Remove item from submenu
|
||||||
|
*
|
||||||
|
* @param submenu Submenu instance
|
||||||
|
* @param index menu item index, used for callback, may be
|
||||||
|
* the same with other items, first one is removed
|
||||||
|
*/
|
||||||
|
void submenu_remove_item(Submenu* submenu, uint32_t index);
|
||||||
|
|
||||||
/** Remove all items from submenu
|
/** Remove all items from submenu
|
||||||
*
|
*
|
||||||
* @param submenu Submenu instance
|
* @param submenu Submenu instance
|
||||||
@@ -120,13 +128,14 @@ uint32_t submenu_get_selected_item(Submenu* submenu);
|
|||||||
void submenu_set_selected_item(Submenu* submenu, uint32_t index);
|
void submenu_set_selected_item(Submenu* submenu, uint32_t index);
|
||||||
|
|
||||||
/** Set optional header for submenu
|
/** Set optional header for submenu
|
||||||
|
* Must be called before adding items OR after adding items and before set_selected_item()
|
||||||
*
|
*
|
||||||
* @param submenu Submenu instance
|
* @param submenu Submenu instance
|
||||||
* @param header header to set
|
* @param header header to set
|
||||||
*/
|
*/
|
||||||
void submenu_set_header(Submenu* submenu, const char* header);
|
void submenu_set_header(Submenu* submenu, const char* header);
|
||||||
|
|
||||||
/** Set Orientation
|
/** Set submenu orientation
|
||||||
*
|
*
|
||||||
* @param submenu Submenu instance
|
* @param submenu Submenu instance
|
||||||
* @param orientation either vertical or horizontal
|
* @param orientation either vertical or horizontal
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,86.1,,
|
Version,+,86.0,,
|
||||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
||||||
@@ -3660,6 +3660,7 @@ Function,+,submenu_change_item_label,void,"Submenu*, uint32_t, const char*"
|
|||||||
Function,+,submenu_free,void,Submenu*
|
Function,+,submenu_free,void,Submenu*
|
||||||
Function,+,submenu_get_selected_item,uint32_t,Submenu*
|
Function,+,submenu_get_selected_item,uint32_t,Submenu*
|
||||||
Function,+,submenu_get_view,View*,Submenu*
|
Function,+,submenu_get_view,View*,Submenu*
|
||||||
|
Function,+,submenu_remove_item,void,"Submenu*, uint32_t"
|
||||||
Function,+,submenu_reset,void,Submenu*
|
Function,+,submenu_reset,void,Submenu*
|
||||||
Function,+,submenu_set_header,void,"Submenu*, const char*"
|
Function,+,submenu_set_header,void,"Submenu*, const char*"
|
||||||
Function,+,submenu_set_orientation,void,"Submenu*, ViewOrientation"
|
Function,+,submenu_set_orientation,void,"Submenu*, ViewOrientation"
|
||||||
|
|||||||
|
Reference in New Issue
Block a user