1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 12:42:30 +04:00

submenu merge all changes

by WillyJL
This commit is contained in:
MX
2025-06-30 19:48:34 +03:00
parent 91a235b395
commit 1382a6af46
3 changed files with 64 additions and 48 deletions

View File

@@ -7,6 +7,7 @@
struct Submenu {
View* view;
FuriTimer* locked_timer;
};
@@ -19,6 +20,7 @@ typedef struct {
};
void* callback_context;
bool has_extended_events;
bool locked;
FuriString* locked_message;
} SubmenuItem;
@@ -68,6 +70,7 @@ typedef struct {
FuriString* header;
size_t position;
size_t window_position;
bool locked_message_visible;
bool is_vertical;
} SubmenuModel;
@@ -76,9 +79,9 @@ static void submenu_process_up(Submenu* submenu);
static void submenu_process_down(Submenu* submenu);
static void submenu_process_ok(Submenu* submenu, InputType input_type);
static size_t submenu_items_on_screen(bool header, bool vertical) {
size_t res = (vertical) ? 8 : 4;
return (header) ? res - 1 : res;
static size_t submenu_items_on_screen(SubmenuModel* model) {
size_t res = (model->is_vertical) ? 8 : 4;
return (furi_string_empty(model->header)) ? res : res - 1;
}
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);
SubmenuItemArray_next(it)) {
const size_t item_position = position - model->window_position;
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;
const size_t items_on_screen = submenu_items_on_screen(model);
uint8_t y_offset = furi_string_empty(model->header) ? 0 : item_height;
bool is_locked = SubmenuItemArray_cref(it)->locked;
if(item_position < items_on_screen) {
if(position == model->position) {
@@ -119,7 +122,7 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
canvas_set_color(canvas, ColorBlack);
}
if(SubmenuItemArray_cref(it)->locked) {
if(is_locked) {
canvas_draw_icon(
canvas,
item_width - 10,
@@ -127,10 +130,8 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) {
&I_Lock_7x8);
}
FuriString* disp_str;
disp_str = furi_string_alloc_set(SubmenuItemArray_cref(it)->label);
elements_string_fit_width(
canvas, disp_str, item_width - (SubmenuItemArray_cref(it)->locked ? 21 : 11));
FuriString* disp_str = furi_string_alloc_set(SubmenuItemArray_cref(it)->label);
elements_string_fit_width(canvas, disp_str, item_width - (is_locked ? 21 : 11));
canvas_draw_str(
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 + 1, frame_y + 1, frame_width - 2, frame_height - 2, 2);
if(model->is_vertical) {
elements_multiline_text_aligned(
canvas,
32,
42,
(model->is_vertical) ? 32 : 84,
(model->is_vertical) ? 42 : 32,
AlignCenter,
AlignCenter,
furi_string_get_cstr(
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; },
false);
if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) &&
locked_message_visible) {
if(locked_message_visible && (event->type == InputTypeShort || event->type == InputTypeLong)) {
with_view_model(
submenu->view, SubmenuModel * model, { model->locked_message_visible = false; }, true);
consumed = true;
@@ -303,6 +292,9 @@ void submenu_add_lockable_item(
SubmenuItem* item = NULL;
furi_check(label);
furi_check(submenu);
if(locked) {
furi_check(locked_message);
}
with_view_model(
submenu->view,
@@ -366,6 +358,25 @@ void submenu_change_item_label(Submenu* submenu, uint32_t index, const char* lab
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) {
furi_check(submenu);
view_set_orientation(submenu->view, ViewOrientationHorizontal);
@@ -431,8 +442,7 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index) {
model->window_position -= 1;
}
const size_t items_on_screen =
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
const size_t items_on_screen = submenu_items_on_screen(model);
if(items_size <= items_on_screen) {
model->window_position = 0;
@@ -451,8 +461,7 @@ void submenu_process_up(Submenu* submenu) {
submenu->view,
SubmenuModel * model,
{
const size_t items_on_screen =
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
const size_t items_on_screen = submenu_items_on_screen(model);
const size_t items_size = SubmenuItemArray_size(model->items);
if(model->position > 0) {
@@ -475,8 +484,7 @@ void submenu_process_down(Submenu* submenu) {
submenu->view,
SubmenuModel * model,
{
const size_t items_on_screen =
submenu_items_on_screen(!furi_string_empty(model->header), model->is_vertical);
const size_t items_on_screen = submenu_items_on_screen(model);
const size_t items_size = SubmenuItemArray_size(model->items);
if(model->position < items_size - 1) {
@@ -504,7 +512,8 @@ void submenu_process_ok(Submenu* submenu, InputType input_type) {
if(model->position < items_size) {
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;
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) {
furi_assert(submenu);
const bool is_vertical =
(orientation == ViewOrientationVertical || orientation == ViewOrientationVerticalFlip) ?
true :
false;
furi_check(submenu);
const bool is_vertical = orientation == ViewOrientationVertical ||
orientation == ViewOrientationVerticalFlip;
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
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);
const size_t items_on_screen = submenu_items_on_screen(model);
if(position >= items_size) {
position = 0;

View File

@@ -98,6 +98,14 @@ void submenu_add_item_ex(
*/
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
*
* @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);
/** 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 header header to set
*/
void submenu_set_header(Submenu* submenu, const char* header);
/** Set Orientation
/** Set submenu orientation
*
* @param submenu Submenu instance
* @param orientation either vertical or horizontal

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,86.1,,
Version,+,86.0,,
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_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_get_selected_item,uint32_t,Submenu*
Function,+,submenu_get_view,View*,Submenu*
Function,+,submenu_remove_item,void,"Submenu*, uint32_t"
Function,+,submenu_reset,void,Submenu*
Function,+,submenu_set_header,void,"Submenu*, const char*"
Function,+,submenu_set_orientation,void,"Submenu*, ViewOrientation"
1 entry status name type params
2 Version + 86.1 86.0
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/bt/bt_service/bt_keys_storage.h
3660 Function + submenu_free void Submenu*
3661 Function + submenu_get_selected_item uint32_t Submenu*
3662 Function + submenu_get_view View* Submenu*
3663 Function + submenu_remove_item void Submenu*, uint32_t
3664 Function + submenu_reset void Submenu*
3665 Function + submenu_set_header void Submenu*, const char*
3666 Function + submenu_set_orientation void Submenu*, ViewOrientation