mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-22 20:43:07 +00:00
[FL-3471] Infrared: buttons move feature rework (#2949)
This commit is contained in:
parent
c7648eb932
commit
4c771b66dc
11 changed files with 280 additions and 176 deletions
|
@ -165,6 +165,10 @@ static Infrared* infrared_alloc() {
|
|||
view_dispatcher_add_view(
|
||||
view_dispatcher, InfraredViewStack, view_stack_get_view(infrared->view_stack));
|
||||
|
||||
infrared->move_view = infrared_move_view_alloc();
|
||||
view_dispatcher_add_view(
|
||||
view_dispatcher, InfraredViewMove, infrared_move_view_get_view(infrared->move_view));
|
||||
|
||||
if(app_state->is_debug_enabled) {
|
||||
infrared->debug_view = infrared_debug_view_alloc();
|
||||
view_dispatcher_add_view(
|
||||
|
@ -209,6 +213,9 @@ static void infrared_free(Infrared* infrared) {
|
|||
view_dispatcher_remove_view(view_dispatcher, InfraredViewStack);
|
||||
view_stack_free(infrared->view_stack);
|
||||
|
||||
view_dispatcher_remove_view(view_dispatcher, InfraredViewMove);
|
||||
infrared_move_view_free(infrared->move_view);
|
||||
|
||||
if(app_state->is_debug_enabled) {
|
||||
view_dispatcher_remove_view(view_dispatcher, InfraredViewDebugView);
|
||||
infrared_debug_view_free(infrared->debug_view);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "scenes/infrared_scene.h"
|
||||
#include "views/infrared_progress_view.h"
|
||||
#include "views/infrared_debug_view.h"
|
||||
#include "views/infrared_move_view.h"
|
||||
|
||||
#include "rpc/rpc_app.h"
|
||||
|
||||
|
@ -60,8 +61,6 @@ typedef enum {
|
|||
InfraredEditModeNone,
|
||||
InfraredEditModeRename,
|
||||
InfraredEditModeDelete,
|
||||
InfraredEditModeMove,
|
||||
InfraredEditModeMoveSelectDest
|
||||
} InfraredEditMode;
|
||||
|
||||
typedef struct {
|
||||
|
@ -96,6 +95,7 @@ struct Infrared {
|
|||
|
||||
ViewStack* view_stack;
|
||||
InfraredDebugView* debug_view;
|
||||
InfraredMoveView* move_view;
|
||||
|
||||
ButtonPanel* button_panel;
|
||||
Loading* loading;
|
||||
|
@ -116,6 +116,7 @@ typedef enum {
|
|||
InfraredViewPopup,
|
||||
InfraredViewStack,
|
||||
InfraredViewDebugView,
|
||||
InfraredViewMove,
|
||||
} InfraredView;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -108,19 +108,13 @@ bool infrared_remote_delete_button(InfraredRemote* remote, size_t index) {
|
|||
return infrared_remote_store(remote);
|
||||
}
|
||||
|
||||
bool infrared_remote_move_button(InfraredRemote* remote, size_t index_orig, size_t index_dest) {
|
||||
void infrared_remote_move_button(InfraredRemote* remote, size_t index_orig, size_t index_dest) {
|
||||
furi_assert(index_orig < InfraredButtonArray_size(remote->buttons));
|
||||
furi_assert(index_dest <= InfraredButtonArray_size(remote->buttons));
|
||||
if(index_orig == index_dest) {
|
||||
return true;
|
||||
}
|
||||
furi_assert(index_dest < InfraredButtonArray_size(remote->buttons));
|
||||
|
||||
InfraredRemoteButton* button;
|
||||
InfraredButtonArray_pop_at(&button, remote->buttons, index_orig);
|
||||
if(index_orig > index_dest)
|
||||
InfraredButtonArray_push_at(remote->buttons, index_dest, button);
|
||||
else
|
||||
InfraredButtonArray_push_at(remote->buttons, index_dest - 1, button);
|
||||
return infrared_remote_store(remote);
|
||||
InfraredButtonArray_push_at(remote->buttons, index_dest, button);
|
||||
}
|
||||
|
||||
bool infrared_remote_store(InfraredRemote* remote) {
|
||||
|
|
|
@ -23,7 +23,7 @@ bool infrared_remote_find_button_by_name(InfraredRemote* remote, const char* nam
|
|||
bool infrared_remote_add_button(InfraredRemote* remote, const char* name, InfraredSignal* signal);
|
||||
bool infrared_remote_rename_button(InfraredRemote* remote, const char* new_name, size_t index);
|
||||
bool infrared_remote_delete_button(InfraredRemote* remote, size_t index);
|
||||
bool infrared_remote_move_button(InfraredRemote* remote, size_t index_orig, size_t index_dest);
|
||||
void infrared_remote_move_button(InfraredRemote* remote, size_t index_orig, size_t index_dest);
|
||||
|
||||
bool infrared_remote_store(InfraredRemote* remote);
|
||||
bool infrared_remote_load(InfraredRemote* remote, FuriString* path);
|
||||
|
|
|
@ -8,7 +8,6 @@ ADD_SCENE(infrared, edit_button_select, EditButtonSelect)
|
|||
ADD_SCENE(infrared, edit_rename, EditRename)
|
||||
ADD_SCENE(infrared, edit_rename_done, EditRenameDone)
|
||||
ADD_SCENE(infrared, edit_move, EditMove)
|
||||
ADD_SCENE(infrared, edit_move_done, EditMoveDone)
|
||||
ADD_SCENE(infrared, learn, Learn)
|
||||
ADD_SCENE(infrared, learn_done, LearnDone)
|
||||
ADD_SCENE(infrared, learn_enter_name, LearnEnterName)
|
||||
|
|
|
@ -82,9 +82,7 @@ bool infrared_scene_edit_on_event(void* context, SceneManagerEvent event) {
|
|||
scene_manager_next_scene(scene_manager, InfraredSceneEditButtonSelect);
|
||||
consumed = true;
|
||||
} else if(submenu_index == SubmenuIndexMoveButton) {
|
||||
infrared->app_state.edit_target = InfraredEditTargetButton;
|
||||
infrared->app_state.edit_mode = InfraredEditModeMove;
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditButtonSelect);
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditMove);
|
||||
consumed = true;
|
||||
} else if(submenu_index == SubmenuIndexDeleteButton) {
|
||||
infrared->app_state.edit_target = InfraredEditTargetButton;
|
||||
|
|
|
@ -11,23 +11,9 @@ void infrared_scene_edit_button_select_on_enter(void* context) {
|
|||
InfraredRemote* remote = infrared->remote;
|
||||
InfraredAppState* app_state = &infrared->app_state;
|
||||
|
||||
const char* header = NULL;
|
||||
switch(infrared->app_state.edit_mode) {
|
||||
case InfraredEditModeRename:
|
||||
header = "Rename Button:";
|
||||
break;
|
||||
case InfraredEditModeDelete:
|
||||
header = "Delete Button:";
|
||||
break;
|
||||
case InfraredEditModeMove:
|
||||
header = "Select Button to Move:";
|
||||
break;
|
||||
case InfraredEditModeMoveSelectDest:
|
||||
case InfraredEditModeNone:
|
||||
default:
|
||||
header = "Move Button Before:";
|
||||
break;
|
||||
}
|
||||
const char* header = infrared->app_state.edit_mode == InfraredEditModeRename ?
|
||||
"Rename Button:" :
|
||||
"Delete Button:";
|
||||
submenu_set_header(submenu, header);
|
||||
|
||||
const size_t button_count = infrared_remote_get_button_count(remote);
|
||||
|
@ -40,14 +26,6 @@ void infrared_scene_edit_button_select_on_enter(void* context) {
|
|||
infrared_scene_edit_button_select_submenu_callback,
|
||||
context);
|
||||
}
|
||||
if(infrared->app_state.edit_mode == InfraredEditModeMoveSelectDest) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"-- Move to the end --",
|
||||
button_count,
|
||||
infrared_scene_edit_button_select_submenu_callback,
|
||||
context);
|
||||
}
|
||||
if(button_count && app_state->current_button_index != InfraredButtonIndexNone) {
|
||||
submenu_set_selected_item(submenu, app_state->current_button_index);
|
||||
app_state->current_button_index = InfraredButtonIndexNone;
|
||||
|
@ -69,12 +47,6 @@ bool infrared_scene_edit_button_select_on_event(void* context, SceneManagerEvent
|
|||
scene_manager_next_scene(scene_manager, InfraredSceneEditRename);
|
||||
} else if(edit_mode == InfraredEditModeDelete) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditDelete);
|
||||
} else if(edit_mode == InfraredEditModeMove) {
|
||||
app_state->current_button_index_move_orig = event.event;
|
||||
app_state->edit_mode = InfraredEditModeMoveSelectDest;
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditButtonSelect);
|
||||
} else if(edit_mode == InfraredEditModeMoveSelectDest) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditMove);
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
|
|
|
@ -1,103 +1,44 @@
|
|||
#include "../infrared_i.h"
|
||||
|
||||
static void infrared_scene_edit_move_dialog_result_callback(DialogExResult result, void* context) {
|
||||
Infrared* infrared = context;
|
||||
view_dispatcher_send_custom_event(infrared->view_dispatcher, result);
|
||||
static void infrared_scene_move_button(uint32_t index_old, uint32_t index_new, void* context) {
|
||||
InfraredRemote* remote = context;
|
||||
furi_assert(remote);
|
||||
infrared_remote_move_button(remote, index_old, index_new);
|
||||
}
|
||||
|
||||
static const char* infrared_scene_get_btn_name(uint32_t index, void* context) {
|
||||
InfraredRemote* remote = context;
|
||||
furi_assert(remote);
|
||||
InfraredRemoteButton* button = infrared_remote_get_button(remote, index);
|
||||
return (infrared_remote_button_get_name(button));
|
||||
}
|
||||
|
||||
void infrared_scene_edit_move_on_enter(void* context) {
|
||||
Infrared* infrared = context;
|
||||
DialogEx* dialog_ex = infrared->dialog_ex;
|
||||
InfraredRemote* remote = infrared->remote;
|
||||
|
||||
const InfraredEditTarget edit_target = infrared->app_state.edit_target;
|
||||
if(edit_target == InfraredEditTargetButton) {
|
||||
int32_t current_button_index = infrared->app_state.current_button_index_move_orig;
|
||||
furi_assert(current_button_index != InfraredButtonIndexNone);
|
||||
infrared_move_view_set_callback(infrared->move_view, infrared_scene_move_button);
|
||||
|
||||
dialog_ex_set_header(dialog_ex, "Move Button?", 64, 0, AlignCenter, AlignTop);
|
||||
InfraredRemoteButton* current_button =
|
||||
infrared_remote_get_button(remote, current_button_index);
|
||||
InfraredSignal* signal = infrared_remote_button_get_signal(current_button);
|
||||
uint32_t btn_count = infrared_remote_get_button_count(remote);
|
||||
infrared_move_view_list_init(
|
||||
infrared->move_view, btn_count, infrared_scene_get_btn_name, remote);
|
||||
infrared_move_view_list_update(infrared->move_view);
|
||||
|
||||
if(infrared_signal_is_raw(signal)) {
|
||||
const InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
||||
infrared_text_store_set(
|
||||
infrared,
|
||||
0,
|
||||
"%s\nRAW\n%ld samples",
|
||||
infrared_remote_button_get_name(current_button),
|
||||
raw->timings_size);
|
||||
|
||||
} else {
|
||||
const InfraredMessage* message = infrared_signal_get_message(signal);
|
||||
infrared_text_store_set(
|
||||
infrared,
|
||||
0,
|
||||
"%s\n%s\nA=0x%0*lX C=0x%0*lX",
|
||||
infrared_remote_button_get_name(current_button),
|
||||
infrared_get_protocol_name(message->protocol),
|
||||
ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4),
|
||||
message->address,
|
||||
ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4),
|
||||
message->command);
|
||||
}
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
|
||||
dialog_ex_set_text(dialog_ex, infrared->text_store[0], 64, 31, AlignCenter, AlignCenter);
|
||||
dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Cancel");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "Move");
|
||||
dialog_ex_set_result_callback(dialog_ex, infrared_scene_edit_move_dialog_result_callback);
|
||||
dialog_ex_set_context(dialog_ex, context);
|
||||
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx);
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewMove);
|
||||
}
|
||||
|
||||
bool infrared_scene_edit_move_on_event(void* context, SceneManagerEvent event) {
|
||||
Infrared* infrared = context;
|
||||
SceneManager* scene_manager = infrared->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == DialogExResultLeft) {
|
||||
scene_manager_previous_scene(scene_manager);
|
||||
consumed = true;
|
||||
} else if(event.event == DialogExResultRight) {
|
||||
bool success = false;
|
||||
InfraredRemote* remote = infrared->remote;
|
||||
InfraredAppState* app_state = &infrared->app_state;
|
||||
const InfraredEditTarget edit_target = app_state->edit_target;
|
||||
|
||||
if(edit_target == InfraredEditTargetButton) {
|
||||
furi_assert(app_state->current_button_index != InfraredButtonIndexNone);
|
||||
success = infrared_remote_move_button(
|
||||
remote,
|
||||
app_state->current_button_index_move_orig,
|
||||
app_state->current_button_index);
|
||||
app_state->current_button_index_move_orig = InfraredButtonIndexNone;
|
||||
app_state->current_button_index = InfraredButtonIndexNone;
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
|
||||
if(success) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditMoveDone);
|
||||
} else {
|
||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
UNUSED(event);
|
||||
UNUSED(infrared);
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void infrared_scene_edit_move_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
UNUSED(infrared);
|
||||
InfraredRemote* remote = infrared->remote;
|
||||
infrared_remote_store(remote);
|
||||
}
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
#include "../infrared_i.h"
|
||||
|
||||
void infrared_scene_edit_move_done_on_enter(void* context) {
|
||||
Infrared* infrared = context;
|
||||
Popup* popup = infrared->popup;
|
||||
|
||||
popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62);
|
||||
popup_set_header(popup, "Moved", 83, 19, AlignLeft, AlignBottom);
|
||||
|
||||
popup_set_callback(popup, infrared_popup_closed_callback);
|
||||
popup_set_context(popup, context);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_enable_timeout(popup);
|
||||
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup);
|
||||
}
|
||||
|
||||
bool infrared_scene_edit_move_done_on_event(void* context, SceneManagerEvent event) {
|
||||
Infrared* infrared = context;
|
||||
SceneManager* scene_manager = infrared->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == InfraredCustomEventTypePopupClosed) {
|
||||
const InfraredEditTarget edit_target = infrared->app_state.edit_target;
|
||||
if(edit_target == InfraredEditTargetButton) {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
scene_manager, InfraredSceneRemote);
|
||||
} else if(edit_target == InfraredEditTargetRemote) {
|
||||
const uint32_t possible_scenes[] = {InfraredSceneStart, InfraredSceneRemoteList};
|
||||
if(!scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes))) {
|
||||
view_dispatcher_stop(infrared->view_dispatcher);
|
||||
}
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void infrared_scene_edit_move_done_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
UNUSED(infrared);
|
||||
}
|
215
applications/main/infrared/views/infrared_move_view.c
Normal file
215
applications/main/infrared/views/infrared_move_view.c
Normal file
|
@ -0,0 +1,215 @@
|
|||
#include "infrared_move_view.h"
|
||||
|
||||
#include <gui/canvas.h>
|
||||
#include <gui/elements.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LIST_ITEMS 4U
|
||||
#define LIST_LINE_H 13U
|
||||
#define HEADER_H 12U
|
||||
#define MOVE_X_OFFSET 5U
|
||||
|
||||
struct InfraredMoveView {
|
||||
View* view;
|
||||
InfraredMoveCallback move_cb;
|
||||
void* cb_context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char** btn_names;
|
||||
uint32_t btn_number;
|
||||
int32_t list_offset;
|
||||
int32_t item_idx;
|
||||
bool is_moving;
|
||||
|
||||
InfraredMoveGetItemCallback get_item_cb;
|
||||
} InfraredMoveViewModel;
|
||||
|
||||
static void infrared_move_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
InfraredMoveViewModel* model = _model;
|
||||
|
||||
UNUSED(model);
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(
|
||||
canvas, canvas_width(canvas) / 2, 0, AlignCenter, AlignTop, "Select a button to move");
|
||||
|
||||
bool show_scrollbar = model->btn_number > LIST_ITEMS;
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
for(uint32_t i = 0; i < MIN(model->btn_number, LIST_ITEMS); i++) {
|
||||
int32_t idx = CLAMP((uint32_t)(i + model->list_offset), model->btn_number, 0u);
|
||||
uint8_t x_offset = (model->is_moving && model->item_idx == idx) ? MOVE_X_OFFSET : 0;
|
||||
uint8_t y_offset = HEADER_H + i * LIST_LINE_H;
|
||||
uint8_t box_end_x = canvas_width(canvas) - (show_scrollbar ? 6 : 1);
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
if(model->item_idx == idx) {
|
||||
canvas_draw_box(canvas, x_offset, y_offset, box_end_x - x_offset, LIST_LINE_H);
|
||||
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_dot(canvas, x_offset, y_offset);
|
||||
canvas_draw_dot(canvas, x_offset + 1, y_offset);
|
||||
canvas_draw_dot(canvas, x_offset, y_offset + 1);
|
||||
canvas_draw_dot(canvas, x_offset, y_offset + LIST_LINE_H - 1);
|
||||
canvas_draw_dot(canvas, box_end_x - 1, y_offset);
|
||||
canvas_draw_dot(canvas, box_end_x - 1, y_offset + LIST_LINE_H - 1);
|
||||
}
|
||||
canvas_draw_str_aligned(
|
||||
canvas, x_offset + 3, y_offset + 3, AlignLeft, AlignTop, model->btn_names[idx]);
|
||||
}
|
||||
|
||||
if(show_scrollbar) {
|
||||
elements_scrollbar_pos(
|
||||
canvas,
|
||||
canvas_width(canvas),
|
||||
HEADER_H,
|
||||
canvas_height(canvas) - HEADER_H,
|
||||
model->item_idx,
|
||||
model->btn_number);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_list_offset(InfraredMoveViewModel* model) {
|
||||
int32_t bounds = model->btn_number > (LIST_ITEMS - 1) ? 2 : model->btn_number;
|
||||
|
||||
if((model->btn_number > (LIST_ITEMS - 1)) &&
|
||||
(model->item_idx >= ((int32_t)model->btn_number - 1))) {
|
||||
model->list_offset = model->item_idx - (LIST_ITEMS - 1);
|
||||
} else if(model->list_offset < model->item_idx - bounds) {
|
||||
model->list_offset = CLAMP(
|
||||
model->item_idx - (int32_t)(LIST_ITEMS - 2), (int32_t)model->btn_number - bounds, 0);
|
||||
} else if(model->list_offset > model->item_idx - bounds) {
|
||||
model->list_offset = CLAMP(model->item_idx - 1, (int32_t)model->btn_number - bounds, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static bool infrared_move_view_input_callback(InputEvent* event, void* context) {
|
||||
InfraredMoveView* move_view = context;
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
if(((event->type == InputTypeShort || event->type == InputTypeRepeat)) &&
|
||||
((event->key == InputKeyUp) || (event->key == InputKeyDown))) {
|
||||
bool is_moving = false;
|
||||
uint32_t index_old = 0;
|
||||
uint32_t index_new = 0;
|
||||
with_view_model(
|
||||
move_view->view,
|
||||
InfraredMoveViewModel * model,
|
||||
{
|
||||
is_moving = model->is_moving;
|
||||
index_old = model->item_idx;
|
||||
if(event->key == InputKeyUp) {
|
||||
if(model->item_idx <= 0) {
|
||||
model->item_idx = model->btn_number;
|
||||
}
|
||||
model->item_idx--;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
model->item_idx++;
|
||||
if(model->item_idx >= (int32_t)(model->btn_number)) {
|
||||
model->item_idx = 0;
|
||||
}
|
||||
}
|
||||
index_new = model->item_idx;
|
||||
update_list_offset(model);
|
||||
},
|
||||
!is_moving);
|
||||
if((is_moving) && (move_view->move_cb)) {
|
||||
move_view->move_cb(index_old, index_new, move_view->cb_context);
|
||||
infrared_move_view_list_update(move_view);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
if((event->key == InputKeyOk) && (event->type == InputTypeShort)) {
|
||||
with_view_model(
|
||||
move_view->view,
|
||||
InfraredMoveViewModel * model,
|
||||
{ model->is_moving = !(model->is_moving); },
|
||||
true);
|
||||
consumed = true;
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
static void infrared_move_view_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
InfraredMoveView* move_view = context;
|
||||
|
||||
with_view_model(
|
||||
move_view->view,
|
||||
InfraredMoveViewModel * model,
|
||||
{
|
||||
if(model->btn_names) {
|
||||
free(model->btn_names);
|
||||
model->btn_names = NULL;
|
||||
}
|
||||
model->btn_number = 0;
|
||||
model->get_item_cb = NULL;
|
||||
},
|
||||
false);
|
||||
move_view->cb_context = NULL;
|
||||
}
|
||||
|
||||
void infrared_move_view_set_callback(InfraredMoveView* move_view, InfraredMoveCallback callback) {
|
||||
furi_assert(move_view);
|
||||
move_view->move_cb = callback;
|
||||
}
|
||||
|
||||
void infrared_move_view_list_init(
|
||||
InfraredMoveView* move_view,
|
||||
uint32_t item_count,
|
||||
InfraredMoveGetItemCallback load_cb,
|
||||
void* context) {
|
||||
furi_assert(move_view);
|
||||
move_view->cb_context = context;
|
||||
with_view_model(
|
||||
move_view->view,
|
||||
InfraredMoveViewModel * model,
|
||||
{
|
||||
furi_assert(model->btn_names == NULL);
|
||||
model->btn_names = malloc(sizeof(char*) * item_count);
|
||||
model->btn_number = item_count;
|
||||
model->get_item_cb = load_cb;
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
void infrared_move_view_list_update(InfraredMoveView* move_view) {
|
||||
furi_assert(move_view);
|
||||
with_view_model(
|
||||
move_view->view,
|
||||
InfraredMoveViewModel * model,
|
||||
{
|
||||
for(uint32_t i = 0; i < model->btn_number; i++) {
|
||||
if(!model->get_item_cb) break;
|
||||
model->btn_names[i] = model->get_item_cb(i, move_view->cb_context);
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
InfraredMoveView* infrared_move_view_alloc(void) {
|
||||
InfraredMoveView* move_view = malloc(sizeof(InfraredMoveView));
|
||||
move_view->view = view_alloc();
|
||||
view_allocate_model(move_view->view, ViewModelTypeLocking, sizeof(InfraredMoveViewModel));
|
||||
view_set_draw_callback(move_view->view, infrared_move_view_draw_callback);
|
||||
view_set_input_callback(move_view->view, infrared_move_view_input_callback);
|
||||
view_set_exit_callback(move_view->view, infrared_move_view_on_exit);
|
||||
view_set_context(move_view->view, move_view);
|
||||
return move_view;
|
||||
}
|
||||
|
||||
void infrared_move_view_free(InfraredMoveView* move_view) {
|
||||
view_free(move_view->view);
|
||||
free(move_view);
|
||||
}
|
||||
|
||||
View* infrared_move_view_get_view(InfraredMoveView* move_view) {
|
||||
return move_view->view;
|
||||
}
|
25
applications/main/infrared/views/infrared_move_view.h
Normal file
25
applications/main/infrared/views/infrared_move_view.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct InfraredMoveView InfraredMoveView;
|
||||
|
||||
typedef void (*InfraredMoveCallback)(uint32_t index_old, uint32_t index_new, void* context);
|
||||
|
||||
typedef const char* (*InfraredMoveGetItemCallback)(uint32_t index, void* context);
|
||||
|
||||
InfraredMoveView* infrared_move_view_alloc(void);
|
||||
|
||||
void infrared_move_view_free(InfraredMoveView* debug_view);
|
||||
|
||||
View* infrared_move_view_get_view(InfraredMoveView* debug_view);
|
||||
|
||||
void infrared_move_view_set_callback(InfraredMoveView* move_view, InfraredMoveCallback callback);
|
||||
|
||||
void infrared_move_view_list_init(
|
||||
InfraredMoveView* move_view,
|
||||
uint32_t item_count,
|
||||
InfraredMoveGetItemCallback load_cb,
|
||||
void* context);
|
||||
|
||||
void infrared_move_view_list_update(InfraredMoveView* move_view);
|
Loading…
Reference in a new issue