1
0
Fork 0
fgdata/gui/dialogs/file-select.xml
mfranz 8e4209c5cb 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.)
2007-06-13 21:20:04 +00:00

219 lines
5.3 KiB
XML

<?xml version="1.0"?>
<!--
Ctrl-click on "." toggles display of hidden Unix filex (dotfiles)
Ctrl-click on ".." enters $FG_ROOT
Shift-click on ".." enters $FG_HOME
-->
<PropertyList>
<name>file-select</name>
<dialog-name>file-select</dialog-name>
<layout>vbox</layout>
<pref-width>450</pref-width>
<group>
<layout>hbox</layout>
<empty><whatever/></empty>
<text>
<property>/sim/gui/dialogs/file-select/title</property>
<live>1</live>
</text>
<empty><stretch>1</stretch></empty>
<button>
<pref-width>16</pref-width>
<pref-height>16</pref-height>
<legend></legend>
<default>1</default>
<keynum>27</keynum>
<border>2</border>
<binding>
<command>nasal</command>
<script>close()</script>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<hrule/>
<list>
<name>list</name>
<halign>fill</halign>
<pref-height>350</pref-height>
<property>/sim/gui/dialogs/file-select/selection</property>
<binding>
<command>dialog-apply</command>
<object-name>list</object-name>
</binding>
<binding>
<command>nasal</command>
<script>select()</script>
</binding>
</list>
<group>
<layout>hbox</layout>
<input>
<name>input</name>
<pref-width>280</pref-width>
<property>/sim/gui/dialogs/file-select/selection</property>
<live>1</live>
<binding>
<command>dialog-apply</command>
<object-name>input</object-name>
</binding>
<binding>
<command>nasal</command>
<script>input()</script>
</binding>
</input>
<button>
<legend>OK</legend>
<live>1</live>
<pref-width>150</pref-width>
<default>true</default>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>nasal</command>
<script>ok()</script>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<nasal>
<open>
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));
</open>
<close>
operation.setValue("");
selection.setValue("");
</close>
</nasal>
</PropertyList>