205 lines
5.7 KiB
Plaintext
205 lines
5.7 KiB
Plaintext
#include "audio_paths.nvgt"
|
|
#include "file_viewer.nvgt"
|
|
|
|
funcdef void docs_browser_speak_callback(const string &in message, bool interrupt);
|
|
funcdef void docs_browser_tick_callback();
|
|
|
|
docs_browser_speak_callback@ docsBrowserSpeakCallback = null;
|
|
docs_browser_tick_callback@ docsBrowserTickCallback = null;
|
|
|
|
string docsBrowserDirectory = "files";
|
|
string docsBrowserMenuSoundDir = "sounds/menu";
|
|
bool docsBrowserWrap = true;
|
|
|
|
string[] docsBrowserExtensions = {"md", "MD", "txt", "TXT"};
|
|
|
|
sound docsBrowserMoveSound;
|
|
sound docsBrowserSelectSound;
|
|
|
|
void docs_browser_set_speak_callback(docs_browser_speak_callback@ callback) {
|
|
@docsBrowserSpeakCallback = @callback;
|
|
}
|
|
|
|
void docs_browser_set_tick_callback(docs_browser_tick_callback@ callback) {
|
|
@docsBrowserTickCallback = @callback;
|
|
}
|
|
|
|
void docs_browser_set_docs_dir(const string docsDir) {
|
|
docsBrowserDirectory = docsDir;
|
|
}
|
|
|
|
void docs_browser_set_menu_sound_dir(const string menuSoundDir) {
|
|
docsBrowserMenuSoundDir = menuSoundDir;
|
|
}
|
|
|
|
void docs_browser_set_wrap(bool wrap) {
|
|
docsBrowserWrap = wrap;
|
|
}
|
|
|
|
void docs_browser_set_extensions(string[]@ extensions) {
|
|
docsBrowserExtensions.resize(0);
|
|
if (@extensions is null) return;
|
|
for (uint extIndex = 0; extIndex < extensions.length(); extIndex++) {
|
|
docsBrowserExtensions.insert_last(extensions[extIndex]);
|
|
}
|
|
}
|
|
|
|
void docs_browser_reset_default_extensions() {
|
|
string[] defaults = {"md", "MD", "txt", "TXT"};
|
|
docs_browser_set_extensions(defaults);
|
|
}
|
|
|
|
void docs_browser_speak(const string &in message, bool interrupt) {
|
|
if (@docsBrowserSpeakCallback !is null) {
|
|
docsBrowserSpeakCallback(message, interrupt);
|
|
return;
|
|
}
|
|
screen_reader_speak(message, interrupt);
|
|
}
|
|
|
|
void docs_browser_tick() {
|
|
if (@docsBrowserTickCallback !is null) {
|
|
docsBrowserTickCallback();
|
|
}
|
|
}
|
|
|
|
bool docs_browser_sort_case_insensitive(const string &in a, const string &in b) {
|
|
return a.lower() < b.lower();
|
|
}
|
|
|
|
void docs_browser_append_unique_case_insensitive(string[]@ items, const string&in value) {
|
|
string lowerValue = value.lower();
|
|
for (uint itemIndex = 0; itemIndex < items.length(); itemIndex++) {
|
|
if (items[itemIndex].lower() == lowerValue) return;
|
|
}
|
|
items.insert_last(value);
|
|
}
|
|
|
|
string docs_browser_collapse_spaces(const string&in text) {
|
|
string result = text;
|
|
while (result.find_first(" ") > -1) {
|
|
result = result.replace(" ", " ", true);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
string docs_browser_format_label(const string&in filename) {
|
|
string name = filename;
|
|
int dotPos = name.find_last_of(".");
|
|
if (dotPos > 0) {
|
|
name = name.substr(0, dotPos);
|
|
}
|
|
|
|
name = name.replace("_", " ", true);
|
|
name = name.replace("-", " ", true);
|
|
name = docs_browser_collapse_spaces(name);
|
|
name = name.lower();
|
|
name.trim_whitespace_this();
|
|
|
|
if (name.length() == 0) return "Document";
|
|
string first = name.substr(0, 1).upper();
|
|
if (name.length() == 1) return first;
|
|
return first + name.substr(1);
|
|
}
|
|
|
|
void docs_browser_collect_entries(string[]@ labels, string[]@ paths) {
|
|
labels.resize(0);
|
|
paths.resize(0);
|
|
|
|
if (!directory_exists(docsBrowserDirectory)) return;
|
|
|
|
string[] docFiles;
|
|
for (uint extIndex = 0; extIndex < docsBrowserExtensions.length(); extIndex++) {
|
|
string ext = docsBrowserExtensions[extIndex];
|
|
if (ext == "") continue;
|
|
if (ext.substr(0, 1) == ".") {
|
|
ext = ext.substr(1);
|
|
}
|
|
|
|
string[]@ found = find_files(docsBrowserDirectory + "/*." + ext);
|
|
if (@found is null) continue;
|
|
for (uint fileIndex = 0; fileIndex < found.length(); fileIndex++) {
|
|
docs_browser_append_unique_case_insensitive(docFiles, found[fileIndex]);
|
|
}
|
|
}
|
|
|
|
if (docFiles.length() > 1) {
|
|
docFiles.sort(docs_browser_sort_case_insensitive);
|
|
}
|
|
|
|
for (uint fileIndex = 0; fileIndex < docFiles.length(); fileIndex++) {
|
|
labels.insert_last(docs_browser_format_label(docFiles[fileIndex]));
|
|
paths.insert_last(docsBrowserDirectory + "/" + docFiles[fileIndex]);
|
|
}
|
|
}
|
|
|
|
void docs_browser_add_entries(string[]@ labels, string[]@ paths, int[]@ types, const int typeValue = 1) {
|
|
string[] docLabels;
|
|
string[] docPaths;
|
|
docs_browser_collect_entries(docLabels, docPaths);
|
|
|
|
for (uint entryIndex = 0; entryIndex < docLabels.length(); entryIndex++) {
|
|
labels.insert_last(docLabels[entryIndex]);
|
|
paths.insert_last(docPaths[entryIndex]);
|
|
types.insert_last(typeValue);
|
|
}
|
|
}
|
|
|
|
void docs_browser_play_ui_sound(sound &inout soundObj, const string basePath) {
|
|
string soundPath = resolve_audio_path(basePath);
|
|
if (soundPath == "") return;
|
|
|
|
soundObj.close();
|
|
if (!soundObj.load(soundPath)) return;
|
|
soundObj.play();
|
|
}
|
|
|
|
void docs_browser_run_menu(const string menuTitle = "Documents") {
|
|
string[] labels;
|
|
string[] paths;
|
|
docs_browser_collect_entries(labels, paths);
|
|
|
|
docs_browser_speak(menuTitle + ".", true);
|
|
if (labels.length() == 0) {
|
|
docs_browser_speak("No documents found.", true);
|
|
return;
|
|
}
|
|
|
|
int selection = 0;
|
|
docs_browser_speak(labels[selection], true);
|
|
|
|
while (true) {
|
|
wait(5);
|
|
docs_browser_tick();
|
|
|
|
if (key_pressed(KEY_ESCAPE)) {
|
|
docs_browser_speak("Closed.", true);
|
|
return;
|
|
}
|
|
|
|
if (key_pressed(KEY_DOWN)) {
|
|
docs_browser_play_ui_sound(docsBrowserMoveSound, docsBrowserMenuSoundDir + "/menu_move");
|
|
selection++;
|
|
if (selection >= int(labels.length())) {
|
|
selection = docsBrowserWrap ? 0 : int(labels.length()) - 1;
|
|
}
|
|
docs_browser_speak(labels[selection], true);
|
|
}
|
|
|
|
if (key_pressed(KEY_UP)) {
|
|
docs_browser_play_ui_sound(docsBrowserMoveSound, docsBrowserMenuSoundDir + "/menu_move");
|
|
selection--;
|
|
if (selection < 0) {
|
|
selection = docsBrowserWrap ? int(labels.length()) - 1 : 0;
|
|
}
|
|
docs_browser_speak(labels[selection], true);
|
|
}
|
|
|
|
if (key_pressed(KEY_RETURN)) {
|
|
docs_browser_play_ui_sound(docsBrowserSelectSound, docsBrowserMenuSoundDir + "/menu_select");
|
|
file_viewer_file(paths[selection], labels[selection], true);
|
|
docs_browser_speak(labels[selection], true);
|
|
}
|
|
}
|
|
}
|