From 8e4209c5cb85600361302b7123116c37d64e9d65 Mon Sep 17 00:00:00 2001 From: mfranz Date: Wed, 13 Jun 2007 21:20:04 +0000 Subject: [PATCH] first stab at file-select dialog. Initial target dir can be set in /sim/gui/dialogs/file-select/directory, the selected file's full path is returned in /sim/gui/dialogs/file-select/directory. There will be a gui.file_selector class that allows to have more than one of these dialogs open, where each of them reports the result to a callback function. The dialog toggles dotfile display with ctrl-click on the "." entry, and switches to FG_ROOT and FG_HOME with ctrl-click and shift-click on the ".." entry. This dialog is ATM not used anywhere in fgfs, but might be needed by add-ons, much like the xml.nas code. Note that backslashes are converted to slashes, which should ensure that no characters can be sneaked in on UNIX systems. This breaks files containing escaped characters on MS Windows. Fix for that on request. :-) Special characters (like German umlauts) aren't displayed correctly, but properly returned. (Depending on the plib font.) --- gui/dialogs/file-select.xml | 219 ++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 gui/dialogs/file-select.xml diff --git a/gui/dialogs/file-select.xml b/gui/dialogs/file-select.xml new file mode 100644 index 000000000..b45ecd8f2 --- /dev/null +++ b/gui/dialogs/file-select.xml @@ -0,0 +1,219 @@ + + + + + + file-select + file-select + vbox + 450 + + + hbox + + + + /sim/gui/dialogs/file-select/title + 1 + + + 1 + + + + + + + + list + fill + 350 + /sim/gui/dialogs/file-select/selection + + dialog-apply + list + + + nasal + + + + + + hbox + + + input + 280 + /sim/gui/dialogs/file-select/selection + 1 + + dialog-apply + input + + + nasal + + + + + + + + + + var self = cmdarg(); + var list = self.getNode("list"); + + var dlgname = self.getNode("name").getValue(); + self.getNode("group/text/property").setValue("/sim/gui/dialogs/" ~ dlgname ~ "/title"); + self.getNode("list/property").setValue("/sim/gui/dialogs/" ~ dlgname ~ "/selection"); + self.getNode("group[1]/input/property").setValue("/sim/gui/dialogs/" ~ dlgname ~ "/selection"); + + var dlg = props.globals.getNode("/sim/gui/dialogs/" ~ dlgname, 1); + var selection = dlg.getNode("selection", 1); + var operation = dlg.getNode("operation", 1); + var title = dlg.getNode("title", 1); + var dir = dlg.getNode("directory", 1); + var file = dlg.getNode("file", 1); + var path = dlg.getNode("path", 1); + var show_hidden = dlg.getNode("show-hidden", 1); + show_hidden.setBoolValue(show_hidden.getValue()); + + var kbdctrl = props.globals.getNode("/devices/status/keyboard/ctrl", 1); + var kbdshift = props.globals.getNode("/devices/status/keyboard/shift", 1); + var root = getprop("/sim/fg-root"); + var current = { dir : "", file : "" }; + + var squeeze = func(s, n) { + return n >= size(s) ? s : "... " ~ substr(s, size(s) - n); + } + + var update = func(d) { + dir.setValue(d); + title.setValue(squeeze(d, 45)); + list.removeChildren("value"); + var dents = directory(current.dir); + if (dents == nil) + return; + var files = []; + var dirs = []; + var hide = !show_hidden.getValue(); + foreach (var e; dents) { + if (e == "." or e == "..") { + if (current.dir != "/") + append(dirs, e); + continue; + } + if (hide and e[0] == `.`) + continue; + + var stat = io.stat(current.dir ~ "/" ~ e); + if (stat == nil) # dead link + continue; + + if (io.isdir(stat[2])) + append(dirs, e ~ "/"); + else + append(files, e); + } + var entries = sort(dirs, cmp) ~ sort(files, cmp); + forindex (var i; entries) + list.getChild("value", i, 1).setValue(entries[i]); + } + + var select = func { + var e = selection.getValue(); + current.file = ""; + var new = nil; + if (e == ".") { + new = current.dir; + if (kbdctrl.getValue()) + show_hidden.setBoolValue(!show_hidden.getValue()); + } elsif (e == "..") { + if (kbdctrl.getValue()) + new = root; + elsif (kbdshift.getValue()) + new = getprop("/sim/fg-home"); + else + new = current.dir ~ "/.."; + } elsif (e[size(e) - 1] == `/`) { + new = current.dir ~ "/" ~ e; + } else { + current.file = e; + gui.dialog_update(dlgname, "input"); + } + if (new != nil) { + update(current.dir = io.fixpath(new)); + selection.setValue(""); + gui.dialog_update(dlgname, "list", "input"); + } + } + + var input = func { + current.file = selection.getValue(); + } + + var close = func { + if (contains(globals.gui, "file_selector") + and contains(gui.file_selector.instance, dlgname)) + gui.file_selector.instance[dlgname].close(); + } + + var ok = func { + input(); + file.setValue(current.file); + path.setValue(current.dir ~ "/" ~ current.file); + close(); + } + + var op = operation.getValue(); + if (op == nil or op == "") + op = "OK"; + self.getNode("group[1]/button/legend").setValue(op); + + current.dir = (var d = dir.getValue()) != nil and d != "" ? d : root; + current.file = (var d = file.getValue()) != nil and d != "" ? d : ""; + gui.dialog_update(dlgname, "input"); + update(io.fixpath(current.dir)); + + + + operation.setValue(""); + selection.setValue(""); + + +