src/util/gui/file-select.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "file-select.h"
7
8#include "util/gui/font.h"
9#include "util/vector.h"
10#include "util/vfs.h"
11
12DECLARE_VECTOR(FileList, char*);
13DEFINE_VECTOR(FileList, char*);
14
15void _cleanFiles(struct FileList* currentFiles) {
16 size_t size = FileListSize(currentFiles);
17 size_t i;
18 for (i = 0; i < size; ++i) {
19 free(*FileListGetPointer(currentFiles, i));
20 }
21 FileListClear(currentFiles);
22}
23
24void _upDirectory(char* currentPath) {
25 char* end = strrchr(currentPath, '/');
26 if (!end) {
27 return;
28 }
29 end[0] = '\0';
30 if (end[1]) {
31 return;
32 }
33 // TODO: What if there was a trailing slash?
34}
35
36bool _refreshDirectory(const char* currentPath, struct FileList* currentFiles) {
37 _cleanFiles(currentFiles);
38
39 struct VDir* dir = VDirOpen(currentPath);
40 if (!dir) {
41 return false;
42 }
43 struct VDirEntry* de;
44 while ((de = dir->listNext(dir))) {
45 if (de->name(de)[0] == '.') {
46 continue;
47 }
48 *FileListAppend(currentFiles) = strdup(de->name(de));
49 }
50 dir->close(dir);
51 return true;
52}
53
54bool selectFile(const struct GUIParams* params, const char* basePath, char* outPath, size_t outLen, const char* suffix) {
55 char currentPath[256];
56 strncpy(currentPath, basePath, sizeof(currentPath));
57 int oldInput = -1;
58 size_t fileIndex = 0;
59
60 struct FileList currentFiles;
61 FileListInit(¤tFiles, 0);
62 _refreshDirectory(currentPath, ¤tFiles);
63
64 while (true) {
65 int input = params->pollInput();
66 int newInput = input & (oldInput ^ input);
67 oldInput = input;
68
69 if (newInput & (1 << GUI_INPUT_UP) && fileIndex > 0) {
70 --fileIndex;
71 }
72 if (newInput & (1 << GUI_INPUT_DOWN) && fileIndex < FileListSize(¤tFiles) - 1) {
73 ++fileIndex;
74 }
75 if (newInput & (1 << GUI_INPUT_CANCEL)) {
76 _cleanFiles(¤tFiles);
77 FileListDeinit(¤tFiles);
78 return false;
79 }
80 if (newInput & (1 << GUI_INPUT_SELECT)) {
81 snprintf(currentPath, sizeof(currentPath), "%s%c%s", currentPath, '/', *FileListGetPointer(¤tFiles, fileIndex));
82 if (!_refreshDirectory(currentPath, ¤tFiles)) {
83 strncpy(outPath, currentPath, outLen);
84 return true;
85 }
86 fileIndex = 0;
87 }
88 if (newInput & (1 << GUI_INPUT_BACK)) {
89 if (strncmp(currentPath, basePath, sizeof(currentPath)) == 0) {
90 _cleanFiles(¤tFiles);
91 FileListDeinit(¤tFiles);
92 return false;
93 }
94 _upDirectory(currentPath);
95 _refreshDirectory(currentPath, ¤tFiles);
96 fileIndex = 0;
97 }
98
99 params->drawStart();
100 int y = GUIFontHeight(params->font);
101 GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, 0xFFFFFFFF, "Current directory: %s", currentPath);
102 y += 2 * GUIFontHeight(params->font);
103 size_t i;
104 for (i = 0; i < FileListSize(¤tFiles); ++i) {
105 int color = 0xE0A0A0A0;
106 char bullet = ' ';
107 if (i == fileIndex) {
108 color = 0xFFFFFFFF;
109 bullet = '>';
110 }
111 GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, color, "%c %s", bullet, *FileListGetPointer(¤tFiles, i));
112 y += GUIFontHeight(params->font);
113 if (y + GUIFontHeight(params->font) > params->height) {
114 break;
115 }
116 }
117 y += GUIFontHeight(params->font) * 2;
118
119 params->drawEnd();
120 }
121}