From 9416ec5ac025406ef92571eec4011aa797571550 Mon Sep 17 00:00:00 2001 From: Pk11 Date: Fri, 14 Oct 2022 21:59:06 -0500 Subject: [PATCH] Make select prompt scroll if too many options Also a little cleanup to the file browse one for consistency --- arm9/source/common/ui.c | 85 +++++++++++++++++++++++++++++------------ arm9/source/common/ui.h | 4 +- 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/arm9/source/common/ui.c b/arm9/source/common/ui.c index f8fc1e4..3b61c35 100644 --- a/arm9/source/common/ui.c +++ b/arm9/source/common/ui.c @@ -839,10 +839,11 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...) { } #endif -u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...) { +u32 ShowSelectPrompt(int n, const char** options, const char *format, ...) { u32 str_width, str_height; u32 x, y, yopt; - u32 sel = 0; + int sel = 0, scroll = 0; + int n_show = min(n, 10); char str[STRBUF_SIZE]; va_list va; @@ -854,30 +855,64 @@ u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...) { // else if (n == 1) return ShowPrompt(true, "%s\n%s?", str, options[0]) ? 1 : 0; str_width = GetDrawStringWidth(str); - str_height = GetDrawStringHeight(str) + (n * (line_height + 2)) + (3 * line_height); + str_height = GetDrawStringHeight(str) + (n_show * (line_height + 2)) + (3 * line_height); if (str_width < 24 * font_width) str_width = 24 * font_width; - for (u32 i = 0; i < n; i++) if (str_width < GetDrawStringWidth(options[i])) - str_width = GetDrawStringWidth(options[i]); + for (int i = 0; i < n; i++) if (str_width < GetDrawStringWidth(options[i]) + (3 * font_width)) + str_width = GetDrawStringWidth(options[i]) + (3 * font_width); x = (str_width >= SCREEN_WIDTH_MAIN) ? 0 : (SCREEN_WIDTH_MAIN - str_width) / 2; y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - str_height) / 2; yopt = y + GetDrawStringHeight(str) + 8; ClearScreenF(true, false, COLOR_STD_BG); DrawStringF(MAIN_SCREEN, x, y, COLOR_STD_FONT, COLOR_STD_BG, "%s", str); - DrawStringF(MAIN_SCREEN, x, yopt + (n*(line_height+2)) + line_height, COLOR_STD_FONT, COLOR_STD_BG, "( select, cancel)"); + DrawStringF(MAIN_SCREEN, x, yopt + (n_show*(line_height+2)) + line_height, COLOR_STD_FONT, COLOR_STD_BG, "( select, cancel)"); while (true) { - for (u32 i = 0; i < n; i++) { - DrawStringF(MAIN_SCREEN, x, yopt + ((line_height+2)*i), (sel == i) ? COLOR_STD_FONT : COLOR_LIGHTGREY, COLOR_STD_BG, "%2.2s %s", + for (int i = scroll; i < scroll+n_show; i++) { + DrawStringF(MAIN_SCREEN, x, yopt + ((line_height+2)*(i-scroll)), (sel == i) ? COLOR_STD_FONT : COLOR_LIGHTGREY, COLOR_STD_BG, "%2.2s %s", (sel == i) ? "->" : "", options[i]); } + + // show [n more] + if (n - n_show - scroll > 0) { + char more_str[UTF_BUFFER_BYTESIZE(str_width / font_width)], temp_str[64]; + snprintf(temp_str, 64, " [%d more]", (n - (n_show-1) - scroll)); + ResizeString(more_str, temp_str, str_width / font_width, 8, false); + DrawString(MAIN_SCREEN, more_str, x, yopt + (line_height+2)*(n_show-1), COLOR_LIGHTGREY, COLOR_STD_BG); + } + // show scroll bar + u32 bar_x = x + str_width + 2; + const u32 flist_height = (n_show * (line_height + 2)); + const u32 bar_width = 2; + if (n > n_show) { // draw position bar at the right + const u32 bar_height_min = 32; + u32 bar_height = (n_show * flist_height) / n; + if (bar_height < bar_height_min) bar_height = bar_height_min; + const u32 bar_y = ((u64) scroll * (flist_height - bar_height)) / (n - n_show) + yopt; + + DrawRectangle(MAIN_SCREEN, bar_x, bar_y, bar_width, bar_height, COLOR_SIDE_BAR); + } + u32 pad_state = InputWait(0); if (pad_state & BUTTON_DOWN) sel = (sel+1) % n; else if (pad_state & BUTTON_UP) sel = (sel+n-1) % n; + else if (pad_state & BUTTON_RIGHT) sel += n_show; + else if (pad_state & BUTTON_LEFT) sel -= n_show; else if (pad_state & BUTTON_A) break; else if (pad_state & BUTTON_B) { sel = n; break; } + if (sel < 0) sel = 0; + else if (sel >= n) sel = n-1; + + int prev_scroll = scroll; + if (sel < scroll) scroll = sel; + else if (sel == n-1 && sel >= (scroll + n_show - 1)) scroll = sel - n_show + 1; + else if (sel >= (scroll + (n_show-1) - 1)) scroll = sel - (n_show-1) + 1; + + if (scroll != prev_scroll) { + DrawRectangle(MAIN_SCREEN, x + font_width * 3, yopt, str_width + 4, (n_show * (line_height + 2)), COLOR_STD_BG); + } } ClearScreenF(true, false, COLOR_STD_BG); @@ -885,12 +920,12 @@ u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...) { return (sel >= n) ? 0 : sel + 1; } -u32 ShowFileScrollPrompt(u32 n, const DirEntry** options, bool hide_ext, const char *format, ...) { +u32 ShowFileScrollPrompt(int n, const DirEntry** options, bool hide_ext, const char *format, ...) { u32 str_height, fname_len; u32 x, y, yopt; const u32 item_width = SCREEN_WIDTH(MAIN_SCREEN) - 40; int sel = 0, scroll = 0; - u32 n_show = min(n, 10); + int n_show = min(n, 10); char str[STRBUF_SIZE]; va_list va; @@ -911,7 +946,7 @@ u32 ShowFileScrollPrompt(u32 n, const DirEntry** options, bool hide_ext, const c DrawStringF(MAIN_SCREEN, x, y, COLOR_STD_FONT, COLOR_STD_BG, "%s", str); DrawStringF(MAIN_SCREEN, x, yopt + (n_show*(line_height+2)) + line_height, COLOR_STD_FONT, COLOR_STD_BG, "( select, cancel)"); while (true) { - for (u32 i = scroll; i < scroll+n_show; i++) { + for (int i = scroll; i < scroll+n_show; i++) { char bytestr[16]; FormatBytes(bytestr, options[i]->size); @@ -925,19 +960,19 @@ u32 ShowFileScrollPrompt(u32 n, const DirEntry** options, bool hide_ext, const c ResizeString(content_str, temp_str, fname_len, 8, false); DrawStringF(MAIN_SCREEN, x, yopt + ((line_height+2)*(i-scroll)), - (sel == (int)i) ? COLOR_STD_FONT : COLOR_ENTRY(options[i]), COLOR_STD_BG, "%2.2s %s", - (sel == (int)i) ? "->" : "", content_str); + (sel == i) ? COLOR_STD_FONT : COLOR_ENTRY(options[i]), COLOR_STD_BG, "%2.2s %s", + (sel == i) ? "->" : "", content_str); DrawStringF(MAIN_SCREEN, x + item_width - font_width * 11, yopt + ((line_height+2)*(i-scroll)), - (sel == (int)i) ? COLOR_STD_FONT : COLOR_ENTRY(options[i]), COLOR_STD_BG, "%10.10s", + (sel == i) ? COLOR_STD_FONT : COLOR_ENTRY(options[i]), COLOR_STD_BG, "%10.10s", (options[i]->type == T_DIR) ? "(dir)" : (options[i]->type == T_DOTDOT) ? "(..)" : bytestr); } // show [n more] - if (n - n_show - scroll) { - char more_str[64 + 1]; - snprintf(more_str, 64, " [%d more]", (int)(n - (n_show-1) - scroll)); - DrawStringF(MAIN_SCREEN, x, yopt + (line_height+2)*(n_show-1), COLOR_LIGHTGREY, COLOR_STD_BG, - "%-*s", (int) (item_width / font_width), more_str); + if (n - n_show - scroll > 0) { + char more_str[UTF_BUFFER_BYTESIZE(item_width / font_width)], temp_str[64]; + snprintf(temp_str, 64, " [%d more]", (n - (n_show-1) - scroll)); + ResizeString(more_str, temp_str, item_width / font_width, 8, false); + DrawString(MAIN_SCREEN, more_str, x, yopt + (line_height+2)*(n_show-1), COLOR_LIGHTGREY, COLOR_STD_BG); } // show scroll bar u32 bar_x = x + item_width + 2; @@ -955,8 +990,8 @@ u32 ShowFileScrollPrompt(u32 n, const DirEntry** options, bool hide_ext, const c } else DrawRectangle(MAIN_SCREEN, bar_x, yopt, bar_width, flist_height, COLOR_STD_BG); u32 pad_state = InputWait(0); - if (pad_state & BUTTON_DOWN) sel++; - else if (pad_state & BUTTON_UP) sel--; + if (pad_state & BUTTON_DOWN) sel = (sel+1) % n; + else if (pad_state & BUTTON_UP) sel = (sel+n-1) % n; else if (pad_state & BUTTON_RIGHT) sel += n_show; else if (pad_state & BUTTON_LEFT) sel -= n_show; else if (pad_state & BUTTON_A) break; @@ -965,15 +1000,15 @@ u32 ShowFileScrollPrompt(u32 n, const DirEntry** options, bool hide_ext, const c break; } if (sel < 0) sel = 0; - else if (sel >= (int)n) sel = n-1; + else if (sel >= n) sel = n-1; if (sel < scroll) scroll = sel; - else if (sel == (int) n-1 && sel >= (int)(scroll + n_show - 1)) scroll = sel - n_show + 1; - else if (sel >= (int)(scroll + (n_show-1) - 1)) scroll = sel - (n_show-1) + 1; + else if (sel == n-1 && sel >= (scroll + n_show - 1)) scroll = sel - n_show + 1; + else if (sel >= (scroll + (n_show-1) - 1)) scroll = sel - (n_show-1) + 1; } ClearScreenF(true, false, COLOR_STD_BG); - return (sel >= (int)n) ? 0 : sel + 1; + return (sel >= n) ? 0 : sel + 1; } u32 ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...) { diff --git a/arm9/source/common/ui.h b/arm9/source/common/ui.h index ef9361c..ee20da8 100644 --- a/arm9/source/common/ui.h +++ b/arm9/source/common/ui.h @@ -88,8 +88,8 @@ void PRINTF_ARGS(2) ShowStringF(u16* screen, const char *format, ...); void PRINTF_ARGS(4) ShowIconString(u16* icon, int w, int h, const char *format, ...); void PRINTF_ARGS(5) ShowIconStringF(u16* screen, u16* icon, int w, int h, const char *format, ...); bool PRINTF_ARGS(2) ShowPrompt(bool ask, const char *format, ...); -u32 PRINTF_ARGS(3) ShowSelectPrompt(u32 n, const char** options, const char *format, ...); -u32 PRINTF_ARGS(4) ShowFileScrollPrompt(u32 n, const DirEntry** entries, bool hide_ext, const char *format, ...); +u32 PRINTF_ARGS(3) ShowSelectPrompt(int n, const char** options, const char *format, ...); +u32 PRINTF_ARGS(4) ShowFileScrollPrompt(int n, const DirEntry** entries, bool hide_ext, const char *format, ...); u32 PRINTF_ARGS(4) ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...); bool PRINTF_ARGS(3) ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...); u64 PRINTF_ARGS(3) ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...);