Implemented new file selector

This commit is contained in:
windows-server-2003 2018-09-08 17:31:54 +09:00 committed by d0k3
parent d50e6b88ae
commit 732165153b
9 changed files with 119 additions and 21 deletions

View File

@ -44,6 +44,7 @@
#define COLOR_FILE COLOR_TINTEDGREEN #define COLOR_FILE COLOR_TINTEDGREEN
#define COLOR_DIR COLOR_TINTEDBLUE #define COLOR_DIR COLOR_TINTEDBLUE
#define COLOR_ROOT COLOR_GREY #define COLOR_ROOT COLOR_GREY
#define COLOR_ENTRY(e) (((e)->marked) ? COLOR_MARKED : ((e)->type == T_DIR) ? COLOR_DIR : ((e)->type == T_FILE) ? COLOR_FILE : ((e)->type == T_ROOT) ? COLOR_ROOT : COLOR_GREY)
// hex viewer colors // hex viewer colors
#define COLOR_HVOFFS RGB(0x40, 0x60, 0x50) #define COLOR_HVOFFS RGB(0x40, 0x60, 0x50)

View File

@ -598,6 +598,96 @@ u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...) {
return (sel >= n) ? 0 : sel + 1; return (sel >= n) ? 0 : sel + 1;
} }
u32 ShowFileScrollPrompt(u32 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);
char str[STRBUF_SIZE] = { 0 };
va_list va;
va_start(va, format);
vsnprintf(str, STRBUF_SIZE, format, va);
va_end(va);
if (n == 0) return 0; // check for low number of options
// else if (n == 1) return ShowPrompt(true, "%s\n%s?", str, options[0]) ? 1 : 0;
str_height = GetDrawStringHeight(str) + (n_show * (line_height + 2)) + (4 * line_height);
x = (SCREEN_WIDTH_MAIN - item_width) / 2;
y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - str_height) / 2;
yopt = y + GetDrawStringHeight(str) + 8;
fname_len = min(64, item_width / FONT_WIDTH_EXT - 14);
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_show*(line_height+2)) + line_height, COLOR_STD_FONT, COLOR_STD_BG, "(<A> select, <B> cancel)");
while (true) {
for (u32 i = scroll; i < scroll+n_show; i++) {
char bytestr[16];
FormatBytes(bytestr, options[i]->size);
char content_str[64 + 1];
char temp_str[256];
strncpy(temp_str, options[i]->name, 255);
char* dot = strrchr(temp_str, '.');
if (hide_ext && dot) *dot = '\0';
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);
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",
(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", item_width / font_width, more_str);
}
// show scroll bar
u32 bar_x = x + item_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, yopt, bar_width, (bar_y - yopt), COLOR_STD_BG);
DrawRectangle(MAIN_SCREEN, bar_x, bar_y + bar_height, bar_width, SCREEN_HEIGHT - (bar_y + bar_height), COLOR_STD_BG);
DrawRectangle(MAIN_SCREEN, bar_x, bar_y, bar_width, bar_height, COLOR_SIDE_BAR);
} 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--;
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 >= (int)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;
}
ClearScreenF(true, false, COLOR_STD_BG);
return (sel >= (int)n) ? 0 : sel + 1;
}
u32 ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...) { u32 ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...) {
char str[STRBUF_SIZE] = { 0 }; char str[STRBUF_SIZE] = { 0 };
char* ptr = str; char* ptr = str;

View File

@ -7,6 +7,7 @@
#include <vram.h> #include <vram.h>
#include "common.h" #include "common.h"
#include "colors.h" #include "colors.h"
#include "fsdir.h" // only required for ShowFileScrollPrompt
#define BYTES_PER_PIXEL 3 #define BYTES_PER_PIXEL 3
@ -73,6 +74,7 @@ void ShowString(const char *format, ...);
void ShowIconString(u8* icon, int w, int h, const char *format, ...); void ShowIconString(u8* icon, int w, int h, const char *format, ...);
bool ShowPrompt(bool ask, const char *format, ...); bool ShowPrompt(bool ask, const char *format, ...);
u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...); u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...);
u32 ShowFileScrollPrompt(u32 n, const DirEntry** entries, bool hide_ext, const char *format, ...);
u32 ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...); u32 ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...);
bool ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...); bool ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...);
u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...); u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...);

View File

@ -794,7 +794,7 @@ bool PathAttr(const char* path, u8 attr, u8 mask) {
return (f_chmod(path, attr, mask) == FR_OK); return (f_chmod(path, attr, mask) == FR_OK);
} }
bool FileSelectorWorker(char* result, const char* text, const char* path, const char* pattern, u32 flags, void* buffer) { bool FileSelectorWorker(char* result, const char* text, const char* path, const char* pattern, u32 flags, void* buffer, bool new_style) {
DirStruct* contents = (DirStruct*) buffer; DirStruct* contents = (DirStruct*) buffer;
char path_local[256]; char path_local[256];
strncpy(path_local, path, 256); strncpy(path_local, path, 256);
@ -813,7 +813,7 @@ bool FileSelectorWorker(char* result, const char* text, const char* path, const
while (pos < contents->n_entries) { while (pos < contents->n_entries) {
char opt_names[_MAX_FS_OPT+1][32+1]; char opt_names[_MAX_FS_OPT+1][32+1];
DirEntry* res_entry[_MAX_FS_OPT+1] = { NULL }; DirEntry* res_entry[MAX_DIR_ENTRIES+1] = { NULL };
u32 n_opt = 0; u32 n_opt = 0;
for (; pos < contents->n_entries; pos++) { for (; pos < contents->n_entries; pos++) {
DirEntry* entry = &(contents->entry[pos]); DirEntry* entry = &(contents->entry[pos]);
@ -821,11 +821,12 @@ bool FileSelectorWorker(char* result, const char* text, const char* path, const
((entry->type == T_FILE) && (no_files || (fvx_match_name(entry->name, pattern) != FR_OK))) || ((entry->type == T_FILE) && (no_files || (fvx_match_name(entry->name, pattern) != FR_OK))) ||
(entry->type == T_DOTDOT) || (strncmp(entry->name, "._", 2) == 0)) (entry->type == T_DOTDOT) || (strncmp(entry->name, "._", 2) == 0))
continue; continue;
if (n_opt == _MAX_FS_OPT) { if (!new_style && n_opt == _MAX_FS_OPT) {
snprintf(opt_names[n_opt++], 32, "[more...]"); snprintf(opt_names[n_opt++], 32, "[more...]");
break; break;
} }
if (!new_style) {
char temp_str[256]; char temp_str[256];
snprintf(temp_str, 256, "%s", entry->name); snprintf(temp_str, 256, "%s", entry->name);
if (hide_ext && (entry->type == T_FILE)) { if (hide_ext && (entry->type == T_FILE)) {
@ -833,23 +834,25 @@ bool FileSelectorWorker(char* result, const char* text, const char* path, const
if (dot) *dot = '\0'; if (dot) *dot = '\0';
} }
TruncateString(opt_names[n_opt], temp_str, 32, 8); TruncateString(opt_names[n_opt], temp_str, 32, 8);
}
res_entry[n_opt++] = entry; res_entry[n_opt++] = entry;
n_found++; n_found++;
} }
if ((pos >= contents->n_entries) && (n_opt < n_found)) if ((pos >= contents->n_entries) && (n_opt < n_found) && !new_style)
snprintf(opt_names[n_opt++], 32, "[more...]"); snprintf(opt_names[n_opt++], 32, "[more...]");
if (!n_opt) break; if (!n_opt) break;
const char* optionstr[_MAX_FS_OPT+1] = { NULL }; const char* optionstr[_MAX_FS_OPT+1] = { NULL };
for (u32 i = 0; i <= _MAX_FS_OPT; i++) optionstr[i] = opt_names[i]; for (u32 i = 0; i <= _MAX_FS_OPT; i++) optionstr[i] = opt_names[i];
u32 user_select = ShowSelectPrompt(n_opt, optionstr, "%s", text); u32 user_select = new_style ? ShowFileScrollPrompt(n_opt, (const DirEntry**)res_entry, hide_ext, "%s", text)
: ShowSelectPrompt(n_opt, optionstr, "%s", text);
if (!user_select) return false; if (!user_select) return false;
DirEntry* res_local = res_entry[user_select-1]; DirEntry* res_local = res_entry[user_select-1];
if (res_local && (res_local->type == T_DIR)) { // selected dir if (res_local && (res_local->type == T_DIR)) { // selected dir
if (select_dirs) { if (select_dirs) {
strncpy(result, res_local->path, 256); strncpy(result, res_local->path, 256);
return true; return true;
} else if (FileSelectorWorker(result, text, res_local->path, pattern, flags, buffer)) { } else if (FileSelectorWorker(result, text, res_local->path, pattern, flags, buffer, new_style)) {
return true; return true;
} }
break; break;
@ -867,11 +870,11 @@ bool FileSelectorWorker(char* result, const char* text, const char* path, const
} }
} }
bool FileSelector(char* result, const char* text, const char* path, const char* pattern, u32 flags) { bool FileSelector(char* result, const char* text, const char* path, const char* pattern, u32 flags, bool new_style) {
void* buffer = (void*) malloc(sizeof(DirStruct)); void* buffer = (void*) malloc(sizeof(DirStruct));
if (!buffer) return false; if (!buffer) return false;
bool ret = FileSelectorWorker(result, text, path, pattern, flags, buffer); bool ret = FileSelectorWorker(result, text, path, pattern, flags, buffer, new_style);
free(buffer); free(buffer);
return ret; return ret;
} }

View File

@ -85,4 +85,4 @@ bool PathRename(const char* path, const char* newname);
bool PathAttr(const char* path, u8 attr, u8 mask); bool PathAttr(const char* path, u8 attr, u8 mask);
/** Select a file **/ /** Select a file **/
bool FileSelector(char* result, const char* text, const char* path, const char* pattern, u32 flags); bool FileSelector(char* result, const char* text, const char* path, const char* pattern, u32 flags, bool new_style);

View File

@ -116,5 +116,5 @@ bool FileSelectorSupport(char* result, const char* text, const char* dname, cons
{ {
char path[256]; char path[256];
if (!GetSupportDir(path, dname)) return false; if (!GetSupportDir(path, dname)) return false;
return FileSelector(result, text, path, pattern, HIDE_EXT); return FileSelector(result, text, path, pattern, HIDE_EXT, false);
} }

View File

@ -26,7 +26,6 @@
#define COLOR_TOP_BAR (PERM_RED ? COLOR_RED : PERM_ORANGE ? COLOR_ORANGE : PERM_BLUE ? COLOR_BRIGHTBLUE : \ #define COLOR_TOP_BAR (PERM_RED ? COLOR_RED : PERM_ORANGE ? COLOR_ORANGE : PERM_BLUE ? COLOR_BRIGHTBLUE : \
PERM_YELLOW ? COLOR_BRIGHTYELLOW : PERM_GREEN ? COLOR_GREEN : COLOR_WHITE) PERM_YELLOW ? COLOR_BRIGHTYELLOW : PERM_GREEN ? COLOR_GREEN : COLOR_WHITE)
#define COLOR_ENTRY(e) (((e)->marked) ? COLOR_MARKED : ((e)->type == T_DIR) ? COLOR_DIR : ((e)->type == T_FILE) ? COLOR_FILE : ((e)->type == T_ROOT) ? COLOR_ROOT : COLOR_GREY)
#define BOOTPAUSE_KEY (BUTTON_R1|BUTTON_UP) #define BOOTPAUSE_KEY (BUTTON_R1|BUTTON_UP)
#define BOOTMENU_KEY (BUTTON_R1|BUTTON_LEFT) #define BOOTMENU_KEY (BUTTON_R1|BUTTON_LEFT)

View File

@ -153,8 +153,8 @@ Gm9ScriptCmd cmd_list[] = {
{ CMD_ID_QR , "qr" , 2, 0 }, { CMD_ID_QR , "qr" , 2, 0 },
{ CMD_ID_ASK , "ask" , 1, 0 }, { CMD_ID_ASK , "ask" , 1, 0 },
{ CMD_ID_INPUT , "input" , 2, 0 }, { CMD_ID_INPUT , "input" , 2, 0 },
{ CMD_ID_FILESEL , "filesel" , 3, _FLG('d') }, { CMD_ID_FILESEL , "filesel" , 3, _FLG('d') | _FLG('x') },
{ CMD_ID_DIRSEL , "dirsel" , 3, 0 }, { CMD_ID_DIRSEL , "dirsel" , 3, _FLG('x') },
{ CMD_ID_SET , "set" , 2, 0 }, { CMD_ID_SET , "set" , 2, 0 },
{ CMD_ID_STRSPLIT, "strsplit", 3, _FLG('b') | _FLG('f')}, { CMD_ID_STRSPLIT, "strsplit", 3, _FLG('b') | _FLG('f')},
{ CMD_ID_STRREP , "strrep" , 3, 0 }, { CMD_ID_STRREP , "strrep" , 3, 0 },
@ -562,6 +562,7 @@ u32 get_flag(char* str, u32 len, char* err_str) {
else if (strncmp(str, "--silent", len) == 0) flag_char = 's'; else if (strncmp(str, "--silent", len) == 0) flag_char = 's';
else if (strncmp(str, "--unequal", len) == 0) flag_char = 'u'; else if (strncmp(str, "--unequal", len) == 0) flag_char = 'u';
else if (strncmp(str, "--overwrite", len) == 0) flag_char = 'w'; else if (strncmp(str, "--overwrite", len) == 0) flag_char = 'w';
else if (strncmp(str, "--explorer", len) == 0) flag_char = 'x';
if ((flag_char < 'a') && (flag_char > 'z')) { if ((flag_char < 'a') && (flag_char > 'z')) {
if (err_str) snprintf(err_str, _ERR_STR_LEN, "illegal flag"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "illegal flag");
@ -1039,11 +1040,11 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
} else { } else {
u32 flags_ext = (flags & _FLG('d')) ? 0 : NO_DIRS; u32 flags_ext = (flags & _FLG('d')) ? 0 : NO_DIRS;
*(npattern++) = '\0'; *(npattern++) = '\0';
ret = FileSelector(choice, argv[0], path, npattern, flags_ext); ret = FileSelector(choice, argv[0], path, npattern, flags_ext, (flags & _FLG('x')));
if (err_str) snprintf(err_str, _ERR_STR_LEN, "fileselect abort"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "fileselect abort");
} }
} else { } else {
ret = FileSelector(choice, argv[0], path, NULL, NO_FILES | SELECT_DIRS); ret = FileSelector(choice, argv[0], path, NULL, NO_FILES | SELECT_DIRS, (flags & _FLG('x')));
if (err_str) snprintf(err_str, _ERR_STR_LEN, "dirselect abort"); if (err_str) snprintf(err_str, _ERR_STR_LEN, "dirselect abort");
} }

View File

@ -107,11 +107,13 @@ echo $[TESTREP]
# The 'filesel' command allows the user to choose a file inside a directory # The 'filesel' command allows the user to choose a file inside a directory
# The path is stored inside a variable, and the selection can be limited via wildcards # The path is stored inside a variable, and the selection can be limited via wildcards
# -d / --include_dirs allows to browse folders and select files inside # -d / --include_dirs allows to browse folders and select files inside
# -x / --explorer uses new style file selector like main file explorer
filesel "Please select a file" 0:/*.* SELFILE filesel "Please select a file" 0:/*.* SELFILE
# 'dirsel' COMMAND # 'dirsel' COMMAND
# The 'dirsel' command works identically to the 'filesel' command, but allows selecting a dir # The 'dirsel' command works identically to the 'filesel' command, but allows selecting a dir
# Note that a final slash ('/') is not expected here and there can be no wildcard pattern. # Note that a final slash ('/') is not expected here and there can be no wildcard pattern.
# -x / --explorer uses new style file selector like main file explorer
dirsel "Now, select a dir" 0: SELDIR dirsel "Now, select a dir" 0: SELDIR
echo "You selected $[SELFILE]\nand $[SELDIR]\nWe'll do nothing with either :)." echo "You selected $[SELFILE]\nand $[SELDIR]\nWe'll do nothing with either :)."