mirror of
https://github.com/Polprzewodnikowy/N64FlashcartMenu.git
synced 2024-11-24 19:46:54 +01:00
Added entry context menu in browser view
This commit is contained in:
parent
d5485a2f12
commit
65a578c571
1
Makefile
1
Makefile
@ -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 \
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
92
src/menu/components/context_menu.c
Normal file
92
src/menu/components/context_menu.c
Normal 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);
|
||||
}
|
@ -78,7 +78,7 @@ typedef struct {
|
||||
|
||||
bool enter;
|
||||
bool back;
|
||||
bool file_info;
|
||||
bool options;
|
||||
bool system_info;
|
||||
bool settings;
|
||||
} actions;
|
||||
|
@ -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:/", "");
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user