mirror of https://github.com/mgba-emu/mgba.git
GUI: File select usability improvements
This commit is contained in:
parent
7e74cba49a
commit
7023103163
|
@ -136,13 +136,15 @@ int main() {
|
||||||
|
|
||||||
struct GUIParams params = {
|
struct GUIParams params = {
|
||||||
320, 240,
|
320, 240,
|
||||||
font, _drawStart, _drawEnd, _pollInput
|
font, "/", _drawStart, _drawEnd, _pollInput,
|
||||||
};
|
|
||||||
|
GUI_PARAMS_TRAIL
|
||||||
|
};
|
||||||
|
GUIInit(¶ms);
|
||||||
|
|
||||||
char currentPath[256] = "";
|
|
||||||
while (aptMainLoop()) {
|
while (aptMainLoop()) {
|
||||||
char path[256];
|
char path[256];
|
||||||
if (!selectFile(¶ms, "/", path, currentPath, sizeof(path), GBAIsROM)) {
|
if (!GUISelectFile(¶ms, path, sizeof(path), GBAIsROM)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_drawStart();
|
_drawStart();
|
||||||
|
|
|
@ -65,13 +65,13 @@ int main() {
|
||||||
GBAPSP2Setup();
|
GBAPSP2Setup();
|
||||||
struct GUIParams params = {
|
struct GUIParams params = {
|
||||||
PSP2_HORIZONTAL_PIXELS, PSP2_VERTICAL_PIXELS,
|
PSP2_HORIZONTAL_PIXELS, PSP2_VERTICAL_PIXELS,
|
||||||
font, _drawStart, _drawEnd, _pollInput
|
font, "cache0:", _drawStart, _drawEnd, _pollInput
|
||||||
};
|
};
|
||||||
|
GUIInit(¶ms);
|
||||||
|
|
||||||
char currentPath[256] = "";
|
|
||||||
while (true) {
|
while (true) {
|
||||||
char path[256];
|
char path[256];
|
||||||
if (!selectFile(¶ms, "cache0:", path, currentPath, sizeof(path), GBAIsROM)) {
|
if (!GUISelectFile(¶ms, path, sizeof(path), GBAIsROM)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!GBAPSP2LoadROM(path)) {
|
if (!GBAPSP2LoadROM(path)) {
|
||||||
|
|
|
@ -165,18 +165,21 @@ int main() {
|
||||||
blip_set_rates(context.gba->audio.right, GBA_ARM7TDMI_FREQUENCY, 48000);
|
blip_set_rates(context.gba->audio.right, GBA_ARM7TDMI_FREQUENCY, 48000);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char currentPath[256] = "";
|
struct GUIParams params = {
|
||||||
|
352, 230,
|
||||||
|
font, "/", _drawStart, _drawEnd, _pollInput,
|
||||||
|
|
||||||
|
GUI_PARAMS_TRAIL
|
||||||
|
};
|
||||||
|
GUIInit(¶ms);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
char path[256];
|
char path[256];
|
||||||
guOrtho(proj, -20, 240, 0, 352, 0, 300);
|
guOrtho(proj, -20, 240, 0, 352, 0, 300);
|
||||||
GX_LoadProjectionMtx(proj, GX_ORTHOGRAPHIC);
|
GX_LoadProjectionMtx(proj, GX_ORTHOGRAPHIC);
|
||||||
GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
|
GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
|
||||||
|
|
||||||
struct GUIParams params = {
|
if (!GUISelectFile(¶ms, path, sizeof(path), GBAIsROM) || !GBAWiiLoadGame(path)) {
|
||||||
352, 230,
|
|
||||||
font, _drawStart, _drawEnd, _pollInput
|
|
||||||
};
|
|
||||||
if (!selectFile(¶ms, "/", path, currentPath, sizeof(path), GBAIsROM) || !GBAWiiLoadGame(path)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GBAContextStart(&context);
|
GBAContextStart(&context);
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
|
||||||
|
void GUIInit(struct GUIParams* params) {
|
||||||
|
memset(params->inputHistory, 0, sizeof(params->inputHistory));
|
||||||
|
strncpy(params->currentPath, params->basePath, PATH_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
void GUIPollInput(struct GUIParams* params, int* newInputOut, int* heldInput) {
|
void GUIPollInput(struct GUIParams* params, int* newInputOut, int* heldInput) {
|
||||||
int input = params->pollInput();
|
int input = params->pollInput();
|
||||||
int newInput = 0;
|
int newInput = 0;
|
||||||
|
@ -25,3 +30,9 @@ void GUIPollInput(struct GUIParams* params, int* newInputOut, int* heldInput) {
|
||||||
*heldInput = input;
|
*heldInput = input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GUIInvalidateKeys(struct GUIParams* params) {
|
||||||
|
for (int i = 0; i < GUI_INPUT_MAX; ++i) {
|
||||||
|
params->inputHistory[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,10 @@
|
||||||
|
|
||||||
#include "util/common.h"
|
#include "util/common.h"
|
||||||
|
|
||||||
|
#include "util/vector.h"
|
||||||
|
|
||||||
struct GUIFont;
|
struct GUIFont;
|
||||||
|
DECLARE_VECTOR(FileList, char*);
|
||||||
|
|
||||||
enum GUIInput {
|
enum GUIInput {
|
||||||
GUI_INPUT_NONE = -1,
|
GUI_INPUT_NONE = -1,
|
||||||
|
@ -28,6 +31,7 @@ struct GUIParams {
|
||||||
unsigned width;
|
unsigned width;
|
||||||
unsigned height;
|
unsigned height;
|
||||||
const struct GUIFont* font;
|
const struct GUIFont* font;
|
||||||
|
const char* basePath;
|
||||||
|
|
||||||
void (*drawStart)(void);
|
void (*drawStart)(void);
|
||||||
void (*drawEnd)(void);
|
void (*drawEnd)(void);
|
||||||
|
@ -35,8 +39,16 @@ struct GUIParams {
|
||||||
|
|
||||||
// State
|
// State
|
||||||
int inputHistory[GUI_INPUT_MAX];
|
int inputHistory[GUI_INPUT_MAX];
|
||||||
|
|
||||||
|
// Directories
|
||||||
|
char currentPath[PATH_MAX];
|
||||||
|
size_t fileIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GUI_PARAMS_TRAIL {}, ""
|
||||||
|
|
||||||
|
void GUIInit(struct GUIParams* params);
|
||||||
void GUIPollInput(struct GUIParams* params, int* newInput, int* heldInput);
|
void GUIPollInput(struct GUIParams* params, int* newInput, int* heldInput);
|
||||||
|
void GUIInvalidateKeys(struct GUIParams* params);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,12 +6,10 @@
|
||||||
#include "file-select.h"
|
#include "file-select.h"
|
||||||
|
|
||||||
#include "util/gui/font.h"
|
#include "util/gui/font.h"
|
||||||
#include "util/vector.h"
|
|
||||||
#include "util/vfs.h"
|
#include "util/vfs.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
DECLARE_VECTOR(FileList, char*);
|
|
||||||
DEFINE_VECTOR(FileList, char*);
|
DEFINE_VECTOR(FileList, char*);
|
||||||
|
|
||||||
#define ITERATION_SIZE 5
|
#define ITERATION_SIZE 5
|
||||||
|
@ -91,11 +89,7 @@ static bool _refreshDirectory(struct GUIParams* params, const char* currentPath,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool selectFile(struct GUIParams* params, const char* basePath, char* outPath, char* currentPath, size_t outLen, bool (*filter)(struct VFile*)) {
|
bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool (*filter)(struct VFile*)) {
|
||||||
if (!currentPath[0]) {
|
|
||||||
strncpy(currentPath, basePath, outLen);
|
|
||||||
}
|
|
||||||
size_t fileIndex = 0;
|
|
||||||
size_t start = 0;
|
size_t start = 0;
|
||||||
size_t pageSize = params->height / GUIFontHeight(params->font);
|
size_t pageSize = params->height / GUIFontHeight(params->font);
|
||||||
if (pageSize > 4) {
|
if (pageSize > 4) {
|
||||||
|
@ -104,63 +98,66 @@ bool selectFile(struct GUIParams* params, const char* basePath, char* outPath, c
|
||||||
pageSize = 1;
|
pageSize = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GUIInvalidateKeys(params);
|
||||||
struct FileList currentFiles;
|
struct FileList currentFiles;
|
||||||
FileListInit(¤tFiles, 0);
|
FileListInit(¤tFiles, 0);
|
||||||
_refreshDirectory(params, currentPath, ¤tFiles, filter);
|
_refreshDirectory(params, params->currentPath, ¤tFiles, filter);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int newInput = 0;
|
int newInput = 0;
|
||||||
GUIPollInput(params, &newInput, 0);
|
GUIPollInput(params, &newInput, 0);
|
||||||
|
|
||||||
if (newInput & (1 << GUI_INPUT_UP) && fileIndex > 0) {
|
if (newInput & (1 << GUI_INPUT_UP) && params->fileIndex > 0) {
|
||||||
--fileIndex;
|
--params->fileIndex;
|
||||||
}
|
}
|
||||||
if (newInput & (1 << GUI_INPUT_DOWN) && fileIndex < FileListSize(¤tFiles) - 1) {
|
if (newInput & (1 << GUI_INPUT_DOWN) && params->fileIndex < FileListSize(¤tFiles) - 1) {
|
||||||
++fileIndex;
|
++params->fileIndex;
|
||||||
}
|
}
|
||||||
if (newInput & (1 << GUI_INPUT_LEFT)) {
|
if (newInput & (1 << GUI_INPUT_LEFT)) {
|
||||||
if (fileIndex >= pageSize) {
|
if (params->fileIndex >= pageSize) {
|
||||||
fileIndex -= pageSize;
|
params->fileIndex -= pageSize;
|
||||||
} else {
|
} else {
|
||||||
fileIndex = 0;
|
params->fileIndex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newInput & (1 << GUI_INPUT_RIGHT)) {
|
if (newInput & (1 << GUI_INPUT_RIGHT)) {
|
||||||
if (fileIndex + pageSize < FileListSize(¤tFiles)) {
|
if (params->fileIndex + pageSize < FileListSize(¤tFiles)) {
|
||||||
fileIndex += pageSize;
|
params->fileIndex += pageSize;
|
||||||
} else {
|
} else {
|
||||||
fileIndex = FileListSize(¤tFiles) - 1;
|
params->fileIndex = FileListSize(¤tFiles) - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileIndex < start) {
|
if (params->fileIndex < start) {
|
||||||
start = fileIndex;
|
start = params->fileIndex;
|
||||||
}
|
}
|
||||||
while ((fileIndex - start + 4) * GUIFontHeight(params->font) > params->height) {
|
while ((params->fileIndex - start + 4) * GUIFontHeight(params->font) > params->height) {
|
||||||
++start;
|
++start;
|
||||||
}
|
}
|
||||||
if (newInput & (1 << GUI_INPUT_CANCEL)) {
|
if (newInput & (1 << GUI_INPUT_CANCEL)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (newInput & (1 << GUI_INPUT_SELECT)) {
|
if (newInput & (1 << GUI_INPUT_SELECT)) {
|
||||||
if (fileIndex == 0) {
|
if (params->fileIndex == 0) {
|
||||||
_upDirectory(currentPath);
|
_upDirectory(params->currentPath);
|
||||||
if (!_refreshDirectory(params, currentPath, ¤tFiles, filter)) {
|
if (!_refreshDirectory(params, params->currentPath, ¤tFiles, filter)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
size_t len = strlen(currentPath);
|
size_t len = strlen(params->currentPath);
|
||||||
const char* sep = PATH_SEP;
|
const char* sep = PATH_SEP;
|
||||||
if (currentPath[len - 1] == *sep) {
|
if (params->currentPath[len - 1] == *sep) {
|
||||||
sep = "";
|
sep = "";
|
||||||
}
|
}
|
||||||
snprintf(outPath, outLen, "%s%s%s", currentPath, sep, *FileListGetPointer(¤tFiles, fileIndex));
|
snprintf(outPath, outLen, "%s%s%s", params->currentPath, sep, *FileListGetPointer(¤tFiles, params->fileIndex));
|
||||||
if (!_refreshDirectory(params, outPath, ¤tFiles, filter)) {
|
|
||||||
|
struct FileList newFiles;
|
||||||
|
FileListInit(&newFiles, 0);
|
||||||
|
if (!_refreshDirectory(params, outPath, &newFiles, filter)) {
|
||||||
|
_cleanFiles(&newFiles);
|
||||||
|
FileListDeinit(&newFiles);
|
||||||
struct VFile* vf = VFileOpen(outPath, O_RDONLY);
|
struct VFile* vf = VFileOpen(outPath, O_RDONLY);
|
||||||
if (!vf) {
|
if (!vf) {
|
||||||
if (!_refreshDirectory(params, currentPath, ¤tFiles, filter)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!filter || filter(vf)) {
|
if (!filter || filter(vf)) {
|
||||||
|
@ -172,31 +169,34 @@ bool selectFile(struct GUIParams* params, const char* basePath, char* outPath, c
|
||||||
vf->close(vf);
|
vf->close(vf);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
strncpy(currentPath, outPath, outLen);
|
_cleanFiles(¤tFiles);
|
||||||
|
FileListDeinit(¤tFiles);
|
||||||
|
currentFiles = newFiles;
|
||||||
|
strncpy(params->currentPath, outPath, PATH_MAX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fileIndex = 0;
|
params->fileIndex = 0;
|
||||||
}
|
}
|
||||||
if (newInput & (1 << GUI_INPUT_BACK)) {
|
if (newInput & (1 << GUI_INPUT_BACK)) {
|
||||||
if (strncmp(currentPath, basePath, outLen) == 0) {
|
if (strncmp(params->currentPath, params->basePath, PATH_MAX) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_upDirectory(currentPath);
|
_upDirectory(params->currentPath);
|
||||||
if (!_refreshDirectory(params, currentPath, ¤tFiles, filter)) {
|
if (!_refreshDirectory(params, params->currentPath, ¤tFiles, filter)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fileIndex = 0;
|
params->fileIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
params->drawStart();
|
params->drawStart();
|
||||||
unsigned y = GUIFontHeight(params->font);
|
unsigned y = GUIFontHeight(params->font);
|
||||||
GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, 0xFFFFFFFF, "%s", currentPath);
|
GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, 0xFFFFFFFF, "%s", params->currentPath);
|
||||||
y += 2 * GUIFontHeight(params->font);
|
y += 2 * GUIFontHeight(params->font);
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = start; i < FileListSize(¤tFiles); ++i) {
|
for (i = start; i < FileListSize(¤tFiles); ++i) {
|
||||||
int color = 0xE0A0A0A0;
|
int color = 0xE0A0A0A0;
|
||||||
char bullet = ' ';
|
char bullet = ' ';
|
||||||
if (i == fileIndex) {
|
if (i == params->fileIndex) {
|
||||||
color = 0xFFFFFFFF;
|
color = 0xFFFFFFFF;
|
||||||
bullet = '>';
|
bullet = '>';
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@
|
||||||
|
|
||||||
struct VFile;
|
struct VFile;
|
||||||
|
|
||||||
bool selectFile(struct GUIParams*, const char* basePath, char* outPath, char* currentPath, size_t outLen, bool (*filter)(struct VFile*));
|
bool GUISelectFile(struct GUIParams*, char* outPath, size_t outLen, bool (*filter)(struct VFile*));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue