From b6ca9ff68debea050f22e2ea6cb893352f4de242 Mon Sep 17 00:00:00 2001 From: Arceveti Date: Tue, 22 Aug 2023 14:13:35 -0700 Subject: [PATCH] Add expand/collapse all for settings --- src/crash_screen/crash_settings.c | 24 ++- src/crash_screen/crash_settings.h | 25 +-- src/crash_screen/pages/page_settings.c | 211 ++++++++++++++----------- 3 files changed, 155 insertions(+), 105 deletions(-) diff --git a/src/crash_screen/crash_settings.c b/src/crash_screen/crash_settings.c index 84131cfc6..9642af40a 100644 --- a/src/crash_screen/crash_settings.c +++ b/src/crash_screen/crash_settings.c @@ -43,12 +43,14 @@ const char* sValNames_branch_arrow[] = { #define DISASM_ARROW_MODE_DEFAULT DISASM_ARROW_MODE_SELECTION #endif -#define SECTION_EXPANDED_DEFAULT TRUE +#define SECTION_EXPANDED_DEFAULT FALSE struct CSSettingsEntry gCSSettings[NUM_CS_OPTS] = { //! TODO: Callback functions. //! TODO: Collapsible(?) page name non-setting entries (A+B to reset only that page to default) + [CS_OPT_EXPAND_ALL ] = { .name = "expand all", .valNames = &sValNames_bool, .val = FALSE, .defaultVal = FALSE, .lowerBound = FALSE, .upperBound = TRUE, }, + [CS_OPT_COLLAPSE_ALL ] = { .name = "collapse all", .valNames = &sValNames_bool, .val = FALSE, .defaultVal = FALSE, .lowerBound = FALSE, .upperBound = TRUE, }, [CS_OPT_RESET_TO_DEFAULTS ] = { .name = "reset all to defaults", .valNames = &sValNames_bool, .val = FALSE, .defaultVal = FALSE, .lowerBound = FALSE, .upperBound = TRUE, }, // GLOBAL: - [CS_OPT_HEADER_GLOBAL ] = { .name = "GLOBAL", .valNames = &sIsSettingHeader, .val = SECTION_EXPANDED_DEFAULT, .defaultVal = SECTION_EXPANDED_DEFAULT, .lowerBound = FALSE, .upperBound = TRUE, }, + [CS_OPT_HEADER_GLOBAL ] = { .name = "GLOBAL", .valNames = &sIsSettingHeader, .val = SECTION_EXPANDED_DEFAULT, .defaultVal = SECTION_EXPANDED_DEFAULT, .lowerBound = FALSE, .upperBound = TRUE, }, [CS_OPT_DRAW_SCREENSHOT ] = { .name = "Show screenshot background", .valNames = &sValNames_bool, .val = TRUE, .defaultVal = TRUE, .lowerBound = FALSE, .upperBound = TRUE, }, #ifdef INCLUDE_DEBUG_MAP [CS_OPT_SYMBOL_NAMES ] = { .name = "Print symbol names", .valNames = &sValNames_bool, .val = SHOW_FUNC_NAMES_DEFAULT, .defaultVal = SHOW_FUNC_NAMES_DEFAULT, .lowerBound = FALSE, .upperBound = TRUE, }, @@ -133,3 +135,21 @@ _Bool crash_screen_check_for_changed_settings(void) { return FALSE; } + +_Bool crash_screen_settings_check_for_header_state(_Bool expand) { + for (enum CSSettings settingID = 0; settingID < ARRAY_COUNT(gCSSettings); settingID++) { + if (crash_screen_setting_is_header(settingID) && gCSSettings[settingID].val == expand) { + return TRUE; + } + } + + return FALSE; +} + +void crash_screen_settings_set_all_headers(_Bool expand) { + for (enum CSSettings settingID = 0; settingID < ARRAY_COUNT(gCSSettings); settingID++) { + if (crash_screen_setting_is_header(settingID)) { + gCSSettings[settingID].val = expand; + } + } +} diff --git a/src/crash_screen/crash_settings.h b/src/crash_screen/crash_settings.h index 934739667..6b9630411 100644 --- a/src/crash_screen/crash_settings.h +++ b/src/crash_screen/crash_settings.h @@ -28,17 +28,9 @@ enum CSDisasmBranchArrowModes { DISASM_ARROW_MODE_OVERSCAN, }; -//! TODO: shown flag + enabled flag + callback func(old, new) -struct CSSettingsEntry { - /*0x00*/ const char* name; - /*0x20*/ const char* (*valNames)[]; - /*0x24*/ SettingsType val; - /*0x28*/ SettingsType defaultVal; - /*0x2C*/ SettingsType lowerBound; - /*0x30*/ SettingsType upperBound; -}; /*0x34*/ - enum CSSettings { + CS_OPT_EXPAND_ALL, + CS_OPT_COLLAPSE_ALL, CS_OPT_RESET_TO_DEFAULTS, // GLOBAL: CS_OPT_HEADER_GLOBAL, @@ -77,6 +69,17 @@ enum CSSettings { }; +//! TODO: shown flag + enabled flag + callback func(old, new) + draw func(x, y, text, opt) +struct CSSettingsEntry { + /*0x00*/ const char* name; + /*0x20*/ const char* (*valNames)[]; + /*0x24*/ SettingsType val; + /*0x28*/ SettingsType defaultVal; + /*0x2C*/ SettingsType lowerBound; + /*0x30*/ SettingsType upperBound; +}; /*0x40*/ + + extern struct CSSettingsEntry gCSSettings[NUM_CS_OPTS]; @@ -86,3 +89,5 @@ void crash_screen_reset_setting(enum CSSettings settingID); void crash_screen_reset_settings_section(enum CSSettings settingID); void crash_screen_reset_all_settings(void); _Bool crash_screen_check_for_changed_settings(void); +_Bool crash_screen_settings_check_for_header_state(_Bool expand); +void crash_screen_settings_set_all_headers(_Bool expand); diff --git a/src/crash_screen/pages/page_settings.c b/src/crash_screen/pages/page_settings.c index 0565029c5..bfcf196ab 100644 --- a/src/crash_screen/pages/page_settings.c +++ b/src/crash_screen/pages/page_settings.c @@ -71,7 +71,7 @@ void print_settings_list(u32 line, u32 numLines) { const u32 section_indent = STRLEN("> "); // Print - for (u32 i = 0; i < numLines; i++) { + for (u32 i = 0; i < numLines; i++, currViewIndex++) { u32 currSettingIndex = gCSDisplayedSettingIDs[currViewIndex]; const struct CSSettingsEntry* setting = &gCSSettings[currSettingIndex]; @@ -89,90 +89,106 @@ void print_settings_list(u32 line, u32 numLines) { crash_screen_draw_row_selection_box(y); } - // Print the "RESET TO DEFAULTS" and header options differently: - if (currViewIndex == CS_OPT_RESET_TO_DEFAULTS) { // Reset all to defaults entry. - s32 centeredDefaultsStartX = TEXT_X((CRASH_SCREEN_NUM_CHARS_X / 2) - (STRLEN("") / 2)); - // "<[setting name]>" - if (crash_screen_check_for_changed_settings()) { - crash_screen_print( - centeredDefaultsStartX, y, - STR_COLOR_PREFIX"<"STR_COLOR_PREFIX"%s"STR_COLOR_PREFIX">", - COLOR_RGBA32_CRASH_SELECT_ARROW, - COLOR_RGBA32_CRASH_NO, setting->name, - COLOR_RGBA32_CRASH_SELECT_ARROW - ); - } else { + s32 centeredDefaultsStartX = TEXT_X((CRASH_SCREEN_NUM_CHARS_X / 2) - ((STRLEN("<") + strlen(setting->name) + STRLEN(">")) / 2)); + + // Print certain header options differently: + switch (currViewIndex) { + case CS_OPT_RESET_TO_DEFAULTS: + // "<[setting name]>" + if (crash_screen_check_for_changed_settings()) { + crash_screen_print( + centeredDefaultsStartX, y, + STR_COLOR_PREFIX"<"STR_COLOR_PREFIX"%s"STR_COLOR_PREFIX">", + COLOR_RGBA32_CRASH_SELECT_ARROW, + COLOR_RGBA32_CRASH_NO, setting->name, + COLOR_RGBA32_CRASH_SELECT_ARROW + ); + } else { + crash_screen_print( + centeredDefaultsStartX, y, + STR_COLOR_PREFIX"<%s>", + COLOR_RGBA32_CRASH_SETTINGS_DISABLED, setting->name + ); + } + continue; + case CS_OPT_EXPAND_ALL: + case CS_OPT_COLLAPSE_ALL: crash_screen_print( centeredDefaultsStartX, y, STR_COLOR_PREFIX"<%s>", - COLOR_RGBA32_CRASH_SETTINGS_DISABLED, setting->name + (crash_screen_settings_check_for_header_state(currViewIndex == CS_OPT_COLLAPSE_ALL) ? COLOR_RGBA32_CRASH_SETTINGS_DESCRIPTION : COLOR_RGBA32_CRASH_SETTINGS_DISABLED), setting->name ); - } - } else if (crash_screen_setting_is_header(currSettingIndex)) { // Header entry. - crash_screen_draw_triangle(TEXT_X(0), y, TEXT_WIDTH(1), TEXT_WIDTH(1), COLOR_RGBA32_CRASH_PAGE_NAME, (setting->val ? CS_TRI_DOWN : CS_TRI_RIGHT)); - crash_screen_print( - TEXT_X(section_indent), y, - STR_COLOR_PREFIX"%s", - COLOR_RGBA32_CRASH_PAGE_NAME, setting->name - ); - // Translucent divider. - crash_screen_draw_divider_translucent(DIVIDER_Y((line + i) + 1)); - } else { // Setting entry. - // Maximum description print size. - u32 charX = (CRASH_SCREEN_NUM_CHARS_X - (STRLEN("*<") + VALUE_NAME_SIZE + STRLEN(">"))); - - crash_screen_print_scroll( - TEXT_X(section_indent), y, (charX - section_indent), - STR_COLOR_PREFIX"%s", - COLOR_RGBA32_CRASH_SETTINGS_DESCRIPTION, setting->name - ); - - // "<" - charX += crash_screen_print(TEXT_X(charX), y, - (STR_COLOR_PREFIX"<"), - COLOR_RGBA32_CRASH_SELECT_ARROW - ); - - // Print the current setting. - if (setting->valNames != NULL) { - RGBA32 nameColor = COLOR_RGBA32_CRASH_SETTINGS_NAMED; - - // Booleans color. - if (setting->valNames == &sValNames_bool) { - nameColor = (setting->val ? COLOR_RGBA32_CRASH_YES : COLOR_RGBA32_CRASH_NO); + continue; + default: + if (crash_screen_setting_is_header(currSettingIndex)) { // Header entry. + crash_screen_draw_triangle(TEXT_X(0), y, TEXT_WIDTH(1), TEXT_WIDTH(1), COLOR_RGBA32_CRASH_PAGE_NAME, (setting->val ? CS_TRI_DOWN : CS_TRI_RIGHT)); + crash_screen_print( + TEXT_X(section_indent), y, + STR_COLOR_PREFIX"%s", + COLOR_RGBA32_CRASH_PAGE_NAME, setting->name + ); + // Translucent divider. + crash_screen_draw_divider_translucent(DIVIDER_Y((line + i) + 1)); + continue; + } else { // Normal Setting entry. + break; } - - // "[setting value (string)]" - crash_screen_print(TEXT_X(charX), y, - (STR_COLOR_PREFIX"%s"), - nameColor, (*setting->valNames)[setting->val] - ); - } else { - // "[setting value (number)]" - crash_screen_print(TEXT_X(charX), y, - (STR_COLOR_PREFIX"%-d"), - COLOR_RGBA32_CRASH_SETTINGS_NUMERIC, setting->val - ); - } - charX += VALUE_NAME_SIZE; - - // ">" - charX += crash_screen_print(TEXT_X(charX), y, - (STR_COLOR_PREFIX">"), - COLOR_RGBA32_CRASH_SELECT_ARROW - ); - - // Print an asterisk if the setting has been changed from the default value. - if (setting->val != setting->defaultVal) { - // "*" - crash_screen_print(TEXT_X(charX), y, - (STR_COLOR_PREFIX"*"), - COLOR_RGBA32_CRASH_SETTINGS_DESCRIPTION - ); - } } - currViewIndex++; + // Normal setting + + // Maximum description print size. + u32 charX = (CRASH_SCREEN_NUM_CHARS_X - (STRLEN("*<") + VALUE_NAME_SIZE + STRLEN(">"))); + + crash_screen_print_scroll( + TEXT_X(section_indent), y, (charX - section_indent), + STR_COLOR_PREFIX"%s", + COLOR_RGBA32_CRASH_SETTINGS_DESCRIPTION, setting->name + ); + + // "<" + charX += crash_screen_print(TEXT_X(charX), y, + (STR_COLOR_PREFIX"<"), + COLOR_RGBA32_CRASH_SELECT_ARROW + ); + + // Print the current setting. + if (setting->valNames != NULL) { + RGBA32 nameColor = COLOR_RGBA32_CRASH_SETTINGS_NAMED; + + // Booleans color. + if (setting->valNames == &sValNames_bool) { + nameColor = (setting->val ? COLOR_RGBA32_CRASH_YES : COLOR_RGBA32_CRASH_NO); + } + + // "[setting value (string)]" + crash_screen_print(TEXT_X(charX), y, + (STR_COLOR_PREFIX"%s"), + nameColor, (*setting->valNames)[setting->val] + ); + } else { + // "[setting value (number)]" + crash_screen_print(TEXT_X(charX), y, + (STR_COLOR_PREFIX"%-d"), + COLOR_RGBA32_CRASH_SETTINGS_NUMERIC, setting->val + ); + } + charX += VALUE_NAME_SIZE; + + // ">" + charX += crash_screen_print(TEXT_X(charX), y, + (STR_COLOR_PREFIX">"), + COLOR_RGBA32_CRASH_SELECT_ARROW + ); + + // Print an asterisk if the setting has been changed from the default value. + if (setting->val != setting->defaultVal) { + // "*" + crash_screen_print(TEXT_X(charX), y, + (STR_COLOR_PREFIX"*"), + COLOR_RGBA32_CRASH_SETTINGS_DESCRIPTION + ); + } } } @@ -203,22 +219,31 @@ void settings_input(void) { u16 buttonPressed = gCSCompositeController->buttonPressed; // Handle the reset to defaults entry differently. - if (selectedSettingIndex == CS_OPT_RESET_TO_DEFAULTS) { - if (buttonPressed & (A_BUTTON | B_BUTTON)) { - crash_screen_reset_all_settings(); - } - } else { - if ((gCSCompositeController->buttonDown & (A_BUTTON | B_BUTTON)) == (A_BUTTON | B_BUTTON)) { - if (crash_screen_setting_is_header(selectedSettingIndex)) { - // Resetting a header resets the whole section. - crash_screen_reset_settings_section(selectedSettingIndex); - } else { - crash_screen_reset_setting(selectedSettingIndex); + switch (selectedSettingIndex) { + case CS_OPT_RESET_TO_DEFAULTS: + if (buttonPressed & (A_BUTTON | B_BUTTON)) { + crash_screen_reset_all_settings(); } - } else { - if (gCSDirectionFlags.pressed.left || (buttonPressed & B_BUTTON)) crash_screen_inc_setting(selectedSettingIndex, -1); // Decrement + wrap. - if (gCSDirectionFlags.pressed.right || (buttonPressed & A_BUTTON)) crash_screen_inc_setting(selectedSettingIndex, +1); // Increment + wrap. - } + break; + case CS_OPT_EXPAND_ALL: + case CS_OPT_COLLAPSE_ALL: + if (buttonPressed & (A_BUTTON | B_BUTTON)) { + crash_screen_settings_set_all_headers(selectedSettingIndex == CS_OPT_EXPAND_ALL); + } + break; + default: + if ((gCSCompositeController->buttonDown & (A_BUTTON | B_BUTTON)) == (A_BUTTON | B_BUTTON)) { // Reset combo + if (crash_screen_setting_is_header(selectedSettingIndex)) { + // Resetting a header resets the whole section. + crash_screen_reset_settings_section(selectedSettingIndex); + } else { + crash_screen_reset_setting(selectedSettingIndex); + } + } else { + if (gCSDirectionFlags.pressed.left || (buttonPressed & B_BUTTON)) crash_screen_inc_setting(selectedSettingIndex, -1); // Decrement + wrap. + if (gCSDirectionFlags.pressed.right || (buttonPressed & A_BUTTON)) crash_screen_inc_setting(selectedSettingIndex, +1); // Increment + wrap. + } + break; } update_displayed_settings();