Added entry context menu in browser view

This commit is contained in:
Mateusz Faderewski 2023-08-20 14:11:17 +02:00
parent d5485a2f12
commit 65a578c571
9 changed files with 183 additions and 22 deletions

View File

@ -32,6 +32,7 @@ SRCS = \
menu/components/background.c \
menu/components/boxart.c \
menu/components/common.c \
menu/components/context_menu.c \
menu/components/file_list.c \
menu/fonts.c \
menu/menu.c \

View File

@ -15,7 +15,7 @@ static void actions_clear (menu_t *menu) {
menu->actions.fast = false;
menu->actions.enter = false;
menu->actions.back = false;
menu->actions.file_info = false;
menu->actions.options = false;
menu->actions.system_info = false;
menu->actions.settings = false;
}
@ -103,7 +103,7 @@ void actions_update (menu_t *menu) {
} else if (down.c[0].B) {
menu->actions.back = true;
} else if (down.c[0].R) {
menu->actions.file_info = true;
menu->actions.options = true;
} else if (down.c[0].L) {
menu->actions.system_info = true;
} else if (down.c[0].start) {

View File

@ -47,15 +47,10 @@ char *cart_load_convert_error_message (cart_load_err_t err) {
}
cart_load_err_t cart_load_n64_rom_and_save (menu_t *menu, rom_header_t *header, flashcart_progress_callback_t progress) {
if (menu->settings.use_saves_folder) {
if (create_saves_subdirectory(menu)) {
return CART_LOAD_ERR_SAVES_SUBDIR;
}
}
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
bool byte_swap = (header->config_flags == ROM_MID_BIG_ENDIAN);
flashcart_save_type_t save_type = convert_save_type(header);
menu->flashcart_error = flashcart_load_rom(path_get(path), byte_swap, progress);
if (menu->flashcart_error != FLASHCART_OK) {
path_free(path);
@ -65,9 +60,13 @@ cart_load_err_t cart_load_n64_rom_and_save (menu_t *menu, rom_header_t *header,
path_ext_replace(path, "sav");
if (menu->settings.use_saves_folder) {
path_push_subdir(path, SAVES_SUBDIRECTORY);
if ((save_type != FLASHCART_SAVE_TYPE_NONE) && create_saves_subdirectory(menu)) {
path_free(path);
return CART_LOAD_ERR_SAVES_SUBDIR;
}
}
menu->flashcart_error = flashcart_load_save(path_get(path), convert_save_type(header));
menu->flashcart_error = flashcart_load_save(path_get(path), save_type);
if (menu->flashcart_error != FLASHCART_OK) {
path_free(path);
return CART_LOAD_ERR_SAVE;
@ -79,12 +78,6 @@ cart_load_err_t cart_load_n64_rom_and_save (menu_t *menu, rom_header_t *header,
}
cart_load_err_t cart_load_emulator (menu_t *menu, cart_load_emu_type_t emu_type, flashcart_progress_callback_t progress) {
if (menu->settings.use_saves_folder) {
if (create_saves_subdirectory(menu)) {
return CART_LOAD_ERR_SAVES_SUBDIR;
}
}
path_t *path = path_init("sd:/", EMU_LOCATION);
flashcart_save_type_t save_type = FLASHCART_SAVE_TYPE_NONE;
uint32_t emulated_rom_offset = 0x200000;
@ -128,6 +121,10 @@ cart_load_err_t cart_load_emulator (menu_t *menu, cart_load_emu_type_t emu_type,
path_ext_replace(path, "sav");
if (menu->settings.use_saves_folder) {
path_push_subdir(path, SAVES_SUBDIRECTORY);
if ((save_type != FLASHCART_SAVE_TYPE_NONE) && create_saves_subdirectory(menu)) {
path_free(path);
return CART_LOAD_ERR_SAVES_SUBDIR;
}
}
menu->flashcart_error = flashcart_load_save(path_get(path), save_type);

View File

@ -37,6 +37,22 @@ void component_background_draw (void);
void component_file_list_draw (entry_t *list, int entries, int selected);
typedef struct {
int count;
int selected;
struct {
const char *text;
void (*action) (menu_t *menu);
} list[];
} component_context_menu_t;
#define COMPONENT_CONTEXT_MENU_LIST_END { .text = NULL }
void component_context_menu_init (component_context_menu_t *cm);
void component_context_menu_show (component_context_menu_t *cm);
bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm);
void component_context_menu_draw (component_context_menu_t *cm);
typedef struct {
bool loading;
surface_t *image;

View File

@ -79,5 +79,7 @@
#define FILE_LIST_HIGHLIGHT_COLOR RGBA32(0x3F, 0x3F, 0x3F, 0xFF)
#define CONTEXT_MENU_HIGHLIGHT_COLOR RGBA32(0x3F, 0x3F, 0x3F, 0xFF)
#endif

View File

@ -0,0 +1,92 @@
#include "../components.h"
#include "../fonts.h"
#include "constants.h"
void component_context_menu_init (component_context_menu_t *cm) {
cm->selected = -1;
cm->count = 0;
for (int i = 0; (cm->list[i].text) != NULL; i++) {
cm->count += 1;
}
}
void component_context_menu_show (component_context_menu_t *cm) {
cm->selected = 0;
}
bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm) {
if (!cm || (cm->selected < 0)) {
return false;
}
if (menu->actions.back) {
cm->selected = -1;
} else if (menu->actions.enter) {
if (cm->list[cm->selected].action) {
cm->list[cm->selected].action(menu);
cm->selected = -1;
}
} else if (menu->actions.go_up) {
cm->selected -= 1;
if (cm->selected < 0) {
cm->selected = 0;
}
} else if (menu->actions.go_down) {
cm->selected += 1;
if (cm->selected >= cm->count) {
cm->selected = (cm->count - 1);
}
}
return true;
}
void component_context_menu_draw (component_context_menu_t *cm) {
if (!cm || (cm->selected < 0)) {
return;
}
rdpq_paragraph_builder_begin(
&(rdpq_textparms_t) {
.width = VISIBLE_AREA_WIDTH,
.height = VISIBLE_AREA_HEIGHT,
.align = ALIGN_CENTER,
.valign = VALIGN_CENTER,
},
FNT_DEFAULT,
NULL
);
for (int i = 0; i < cm->count; i++) {
const char *text = cm->list[i].text;
rdpq_paragraph_builder_span(text, strlen(text));
if (cm->list[i + 1].text != NULL) {
rdpq_paragraph_builder_newline();
}
}
rdpq_paragraph_t *layout = rdpq_paragraph_builder_end();
int width = layout->bbox[2] - layout->bbox[0] + MESSAGEBOX_MARGIN;
int height = layout->bbox[3] - layout->bbox[1] + MESSAGEBOX_MARGIN;
component_dialog_draw(width, height);
int highlight_x0 = DISPLAY_CENTER_X - (width / 2);
int highlight_x1 = DISPLAY_CENTER_X + (width / 2);
int highlight_height = (layout->bbox[3] - layout->bbox[1]) / layout->nlines;
int highlight_y = VISIBLE_AREA_Y0 + layout->bbox[1] + ((cm->selected) * highlight_height);
component_box_draw(
highlight_x0,
highlight_y,
highlight_x1,
highlight_y + highlight_height,
CONTEXT_MENU_HIGHLIGHT_COLOR
);
rdpq_paragraph_render(layout, VISIBLE_AREA_X0, VISIBLE_AREA_Y0);
rdpq_paragraph_free(layout);
}

View File

@ -78,7 +78,7 @@ typedef struct {
bool enter;
bool back;
bool file_info;
bool options;
bool system_info;
bool settings;
} actions;

View File

@ -168,8 +168,57 @@ static bool pop_directory (menu_t *menu) {
return false;
}
void show_properties (menu_t *menu) {
menu->next_mode = MENU_MODE_FILE_INFO;
}
void delete_entry (menu_t *menu) {
int selected = menu->browser.selected;
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
if (menu->browser.entry->type == ENTRY_TYPE_DIR) {
if (directory_delete(path_get(path))) {
menu_show_error(menu, "Couldn't delete directory\nDirectory might not be empty");
path_free(path);
return;
}
} else {
if (file_delete(path_get(path))) {
menu_show_error(menu, "Couldn't delete file");
path_free(path);
return;
}
}
path_free(path);
if (load_directory(menu)) {
menu->browser.valid = false;
menu_show_error(menu, "Couldn't refresh directory contents after delete operation");
return;
}
menu->browser.selected = selected;
if (menu->browser.selected >= menu->browser.entries) {
menu->browser.selected = menu->browser.entries - 1;
}
menu->browser.entry = menu->browser.selected >= 0 ? &menu->browser.list[menu->browser.selected] : NULL;
}
static component_context_menu_t entry_context_menu = {
.list = {
{ .text = "Properties", .action = show_properties },
{ .text = "Delete", .action = delete_entry },
COMPONENT_CONTEXT_MENU_LIST_END,
}
};
static void process (menu_t *menu) {
if (component_context_menu_process(menu, &entry_context_menu)) {
return;
}
int scroll_speed = menu->actions.fast ? 10 : 1;
if (menu->browser.entries > 1) {
@ -216,8 +265,8 @@ static void process (menu_t *menu) {
menu->browser.valid = false;
menu_show_error(menu, "Couldn't open last directory");
}
} else if (menu->actions.file_info && menu->browser.entry) {
menu->next_mode = MENU_MODE_FILE_INFO;
} else if (menu->actions.options && menu->browser.entry) {
component_context_menu_show(&entry_context_menu);
} else if (menu->actions.system_info) {
menu->next_mode = MENU_MODE_SYSTEM_INFO;
} else if (menu->actions.settings) {
@ -259,7 +308,7 @@ static void draw (menu_t *menu, surface_t *d) {
ALIGN_RIGHT, VALIGN_TOP,
"%s\n"
"L: Settings",
menu->browser.entries == 0 ? "" : "R: Info"
menu->browser.entries == 0 ? "" : "R: Options"
);
if (menu->current_time >= 0) {
@ -271,12 +320,15 @@ static void draw (menu_t *menu, surface_t *d) {
);
}
component_context_menu_draw(&entry_context_menu);
rdpq_detach_show();
}
void view_browser_init (menu_t *menu) {
if (!menu->browser.valid) {
component_context_menu_init(&entry_context_menu);
if (load_directory(menu)) {
path_free(menu->browser.directory);
menu->browser.directory = path_init("sd:/", "");

View File

@ -165,8 +165,9 @@ bool directory_create (char *path) {
*separator++ = '\0';
}
if ((strlen(directory) > 0) && (!directory_exists(directory))) {
if (f_mkdir(directory) != FR_OK) {
if (directory[0] != '\0') {
FRESULT res = f_mkdir(directory);
if ((res != FR_OK) && (res != FR_EXIST)) {
error = true;
break;
}