diff options
Diffstat (limited to 'source/gui.c')
-rw-r--r-- | source/gui.c | 428 |
1 files changed, 427 insertions, 1 deletions
diff --git a/source/gui.c b/source/gui.c index 713ad02..7e55b97 100644 --- a/source/gui.c +++ b/source/gui.c @@ -20,10 +20,160 @@ $Id$ */ -#include <nds.h> +#include <stdlib.h> +#include <stdio.h> #include <string.h> +#include <nds.h> + +#include <sys/dir.h> #include "framebuffer.h" +#include "config.h" + + +/* ---------------------------------------- PRIVATE INTERFACES - PATH HANDLING +*/ +#define FSEL_FILENAME_LEN 20 +#define FSEL_LINES 15 +#define FSEL_MAX_FILES 512 + +#define FSEL_LIST_Y 12 +#define FSEL_LIST_H FSEL_LINES*8 + +typedef struct +{ + char name[FSEL_FILENAME_LEN+1]; + int is_dir; + int size; +} FSEL_File; + +static FSEL_File fsel[FSEL_MAX_FILES]; + + +static void CheckPath(char *path) +{ + size_t l; + + l = strlen(path); + + if (l == 1) + { + path[0] = '/'; + } + else + { + if (path[l-1] != '/') + { + path[l] = '/'; + path[l+1] = 0; + } + } +} + + +static void AddPath(char *path, const char *dir) +{ + if (strcmp(dir,"..") == 0) + { + char *p; + + p = strrchr(path,'/'); + + if (p && p!=path) + { + *p = 0; + } + } + else + { + strcat(path,dir); + strcat(path,"/"); + } +} + + + + +static int SortFiles(const void *a, const void *b) +{ + const FSEL_File *f1; + const FSEL_File *f2; + + f1 = (const FSEL_File *)a; + f2 = (const FSEL_File *)b; + + if (f1->is_dir == f1->is_dir) + { + return strcmp(f1->name, f2->name); + } + else if (f1->is_dir) + { + return -1; + } + else + { + return 1; + } +} + + +static int ValidFilename(const char *name, int is_dir, const char *filter) +{ + size_t l; + size_t f; + + l = strlen(name); + + if (l > FSEL_FILENAME_LEN) + return 0; + + if (strcmp(name,".") == 0) + return 0; + + if (is_dir || !filter) + return 1; + + f = strlen(filter); + + if (l > f) + { + if (strcmp(name+l-f,filter) == 0) + { + return 1; + } + } + + return 0; +} + + +static int LoadDir(const char *path, const char *filter) +{ + DIR_ITER *dir; + struct stat st; + char name[FILENAME_MAX]; + int no = 0; + + if ((dir = diropen(path))) + { + while(no < FSEL_MAX_FILES && dirnext(dir,name,&st) == 0) + { + if (ValidFilename(name, (st.st_mode & S_IFDIR), filter)) + { + strcpy(fsel[no].name,name); + fsel[no].is_dir = (st.st_mode & S_IFDIR); + fsel[no].size = (int)st.st_size; + no++; + } + } + + dirclose(dir); + + qsort(fsel,no,sizeof fsel[0],SortFiles); + } + + return no; +} /* ---------------------------------------- PUBLIC INTERFACES @@ -189,3 +339,279 @@ void GUI_Alert(int fatal, const char *text) } } } + + +void GUI_Config(void) +{ + int sel; + DS81_ConfigItem f; + bool done; + bool save; + + sel = 0; + done = false; + save = false; + + FB_Clear(); + + FB_Centre("Up/Down to select",140,FB_RGB(31,31,0),-1); + FB_Centre("A to toggle",150,FB_RGB(31,31,0),-1); + FB_Centre("Or use touchscreen",160,FB_RGB(31,31,0),-1); + FB_Centre("START to finish",170,FB_RGB(31,31,0),-1); + +#ifndef DS81_DISABLE_FAT + FB_Centre("SELECT to save to \\DS81.CFG",180,FB_RGB(31,31,0),-1); +#endif + + for(f=0;f<DS81_NUM_CONFIG_ITEMS;f++) + { + FB_Print(ConfigDesc(f),14,20+f*14,FB_RGB(31,31,31),-1); + } + + while(!done) + { + uint32 key=0; + + for(f=0;f<DS81_NUM_CONFIG_ITEMS;f++) + { + FB_FillBox(2,20+f*14-1,10,10, + DS81_Config[f] ? FB_RGB(31,31,31):FB_RGB(0,0,0)); + + FB_Box(2,20+f*14-1,10,10,FB_RGB(18,18,18)); + } + + FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,FB_RGB(18,18,31)); + + do + { + swiWaitForVBlank(); + } while(!(key=keysDownRepeat())); + + FB_Box(0,20+sel*14-3,SCREEN_WIDTH-1,14,FB_RGB(0,0,0)); + + if (key & KEY_START) + { + done=true; + } +#ifndef DS81_DISABLE_FAT + else if (key & KEY_SELECT) + { + done=true; + save=true; + } +#endif + else if (key & KEY_A) + { + DS81_Config[sel] = !DS81_Config[sel]; + } + else if ((key & KEY_UP) && sel) + { + sel--; + } + else if ((key & KEY_DOWN) && sel<DS81_NUM_CONFIG_ITEMS-1) + { + sel++; + } + else if (key & KEY_TOUCH) + { + touchPosition tp = touchReadXY(); + int nsel; + + nsel = (tp.py-18)/14; + + if (nsel>=0 && nsel<DS81_NUM_CONFIG_ITEMS) + { + sel = nsel; + DS81_Config[sel] = !DS81_Config[sel]; + } + } + } + + if (save) + { + SaveConfig(); + } +} + + +bool GUI_FileSelect(char pwd[], char selected_file[], const char *filter) +{ + int no; + int sel; + int top; + int bar_size; + double bar_step; + bool done; + bool ret; + int pen; + int paper; + int off; + int f; + + CheckPath(pwd); + + FB_Clear(); + + FB_printf(0,0,FB_RGB(0,0,0),FB_RGB(22,22,22),"%-31.31s",pwd); + + no = LoadDir(pwd,filter); + + sel = 0; + top = 0; + done = false; + ret = false; + + if (no<=FSEL_LINES) + { + bar_step = 0; + bar_size = FSEL_LIST_H; + } + else + { + bar_step = FSEL_LIST_H/(double)no; + bar_size = bar_step*FSEL_LINES; + } + + while(!done) + { + uint32 key=0; + + for (f=0;f<FSEL_LINES;f++) + { + off = f + top; + + if (off<no) + { + if (off == sel) + { + pen = FB_RGB(0,0,0); + paper = FB_RGB(31,31,31); + } + else + { + pen = FB_RGB(31,31,31); + paper = FB_RGB(0,0,0); + } + + FB_printf(8,FSEL_LIST_Y+f*8,pen,paper, + "%-*s %s", + FSEL_FILENAME_LEN, + fsel[off].name, + fsel[off].is_dir ? "DIR" : " "); + } + else + { + FB_printf(8,FSEL_LIST_Y+f*8,FB_RGB(31,31,31),FB_RGB(0,0,0), + "%-*s %s", + FSEL_FILENAME_LEN, + off==0 ? "No Files!" : "", + ""); + } + } + + FB_FillBox(240,FSEL_LIST_Y,16,FSEL_LIST_H,FB_RGB(10,10,10)); + FB_FillBox(240,FSEL_LIST_Y+top*bar_step,16,bar_size,FB_RGB(31,31,31)); + + do + { + swiWaitForVBlank(); + } while(!(key=keysDownRepeat())); + + if (key & KEY_UP) + { + if (sel) + { + sel--; + + if (sel<top) + { + top--; + } + } + } + else if (key & KEY_DOWN) + { + if (sel < (no-1)) + { + sel++; + + if (sel >= (top+FSEL_LINES)) + { + top++; + } + } + } + else if (key & KEY_L) + { + if (sel) + { + sel-=FSEL_LINES; + + if (sel < 0) + { + sel = 0; + } + + top = sel; + } + } + else if (key & KEY_R) + { + if (sel < (no-1)) + { + sel+=FSEL_LINES; + + if (sel > (no-1)) + { + sel = no-1; + } + + top = sel - FSEL_LINES + 1; + + if (top < 0) + { + top = 0; + } + } + } + else if (key & KEY_A) + { + if (fsel[sel].is_dir) + { + AddPath(pwd,fsel[sel].name); + + no = LoadDir(pwd,filter); + + sel = 0; + top = 0; + + if (no<=FSEL_LINES) + { + bar_step = 0; + bar_size = FSEL_LIST_H; + } + else + { + bar_step = FSEL_LIST_H/(double)no; + bar_size = bar_step*FSEL_LINES; + } + } + else + { + done = true; + ret = true; + + strcpy(selected_file,pwd); + strcat(selected_file,fsel[sel].name); + } + } + else if (key & KEY_START) + { + done=true; + } + } + + while (keysHeld()); + + return ret; +} |