From 692d9c37171fb06c8e43150f1618cb8a07dcf109 Mon Sep 17 00:00:00 2001 From: Gijs de Rooy Date: Sat, 15 Jan 2011 22:48:43 +0100 Subject: [PATCH] Add screenshot dialog, to select directory --- Nasal/gui.nas | 74 +++++++++++ gui/dialogs/screenshot.xml | 261 +++++++++++++++++++++++++++++++++++++ gui/menubar.xml | 7 + 3 files changed, 342 insertions(+) create mode 100644 gui/dialogs/screenshot.xml diff --git a/Nasal/gui.nas b/Nasal/gui.nas index ee7cb8e4a..559e20102 100644 --- a/Nasal/gui.nas +++ b/Nasal/gui.nas @@ -532,6 +532,54 @@ var FileSelector = { }, }; +## +# ScreenshotSelector class (derived from Dialog class). +# +# SYNOPSIS: DirectorySelector.new(, , <button> [, <pattern> [, <dir>]]) +# +# callback ... callback function that gets return value as first argument +# title ... dialog title +# button ... button text (should say "Save", "Load", etc. and not just "OK") +# pattern ... array with shell pattern or nil (which is equivalent to "*") +# dir ... starting dir ($FG_ROOT if unset) + +var ScreenshotSelector = { + new: func(callback, title, button, pattern = nil, dir = "") { + var name = "screenshot"; + ## var data = props.globals.getNode("/sim/gui/dialogs/", 1); + # for (var i = 1; 1; i += 1) + # if (data.getNode(name ~ i, 0) == nil) + # break; + data = props.globals.getNode("sim/gui/dialogs/screenshot", 1); + + var m = Dialog.new(data.getNode("dialog", 1), "gui/dialogs/screenshot.xml", name); + m.parents = [ScreenshotSelector, Dialog]; + m.data = data; + m.set_title(title); + m.set_button(button); + m.set_directory(dir); + m.set_pattern(pattern); + m.cblistener = setlistener(data.getNode("path", 1), callback); + return m; + }, + # setters only take effect after the next call to open() + set_title: func(title) { me.data.getNode("title", 1).setValue(title) }, + set_button: func(button) { me.data.getNode("button", 1).setValue(button) }, + set_directory: func(dir) { me.data.getNode("directory", 1).setValue(dir) }, + set_pattern: func(pattern) { + me.data.removeChildren("pattern"); + if (pattern != nil) + forindex (var i; pattern) + me.data.getChild("pattern", i, 1).setValue(pattern[i]); + }, + del: func { + me.close(); + delete(me.instance, me.name); + removelistener(me.cblistener); + me.data.remove(); + }, +}; + ## # Save/load flight menu functions. @@ -561,6 +609,32 @@ var load_flight = func { } +## +# Save screenshot menu function. +# +var save_screenshot_sel = nil; +var save_screenshot = func { + foreach (var n; props.globals.getNode("/sim/presets").getChildren()) + n.setAttribute("archive", 1); + var save = func(n) { + save_screenshot_sel.close(); + setprop("/sim/paths/screenshot-dir", n.getValue()); + var hide_menubar = getprop("sim/gui/dialogs/screenshot/hide-menubar"); + if (hide_menubar == 1){ + menu_visibility = getprop("/sim/menubar/visibility"); + setprop("/sim/menubar/visibility",0); + } + settimer(func { fgcommand("screen-capture") },0); + if (hide_menubar == 1){ + settimer(func { setprop("/sim/menubar/visibility",menu_visibility) },0); + } + } + if (save_screenshot_sel == nil) + save_screenshot_sel = ScreenshotSelector.new(save, "Save Screenshot", "Take screenshot", + , getprop("/sim/paths/screenshot-dir"),); + save_screenshot_sel.open(); +} + ## # Open property browser with given target path. diff --git a/gui/dialogs/screenshot.xml b/gui/dialogs/screenshot.xml new file mode 100644 index 000000000..9e0671bd9 --- /dev/null +++ b/gui/dialogs/screenshot.xml @@ -0,0 +1,261 @@ +<?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 + Alt-click on ".." enters current working directory +--> + +<PropertyList> + <name>screenshot</name> + <dialog-name>screenshot</dialog-name> + <layout>vbox</layout> + <resizable>true</resizable> + <pref-width>450</pref-width> + + <group> + <layout>hbox</layout> + <empty><stretch>1</stretch></empty> + + <text> + <label>Select directory</label> + </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/> + + <input> + <name>dir-input</name> + <pref-width>442</pref-width> + <halign>fill</halign> + <property>/sim/gui/dialogs/screenshot/directory</property> + <live>1</live> + <binding> + <command>dialog-apply</command> + <object-name>dir-input</object-name> + </binding> + <binding> + <command>nasal</command> + <script>dir_input()</script> + </binding> + </input> + + <list> + <name>list</name> + <halign>fill</halign> + <valign>fill</valign> + <stretch>true</stretch> + <pref-height>300</pref-height> + <property>/sim/gui/dialogs/screenshot/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> + + <checkbox> + <halign>left</halign> + <label>Hide menubar from screenshot</label> + <name>hide-menubar</name> + <property>/sim/gui/dialogs/screenshot/hide-menubar</property> + <binding> + <command>dialog-apply</command> + <object-name>hide-menubar</object-name> + </binding> + </checkbox> + + <button> + <legend>OK</legend> + <live>1</live> + <pref-width>200</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"); + + # cloning + var dlgname = self.getNode("name").getValue(); + self.getNode("input/property").setValue("/sim/gui/dialogs/" ~ dlgname ~ "/directory"); + 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 title = dlg.getNode("title", 1); + var button = dlg.getNode("button", 1); + var dir = dlg.getNode("directory", 1); + var file = dlg.getNode("file", 1); + var path = dlg.getNode("path", 1); + var dotfiles = dlg.getNode("dotfiles", 1); + dotfiles.setBoolValue(dotfiles.getValue()); + + var kbdctrl = props.globals.getNode("/devices/status/keyboard/ctrl", 1); + var kbdshift = props.globals.getNode("/devices/status/keyboard/shift", 1); + var kbdalt = props.globals.getNode("/devices/status/keyboard/alt", 1); + var current = { dir : "", file : "" }; + var pattern = []; + foreach (var p; dlg.getChildren("pattern")) + append(pattern, p.getValue()); + + var matches = func(s) { + foreach (var p; pattern) + if (string.match(s, p)) + return 1; + return 0; + } + + var update = func(d) { + var entries = directory(d); + if (entries == nil) # dir doesn't exist or no permissions + return 0; + + var files = []; + var dirs = []; + var hide = !dotfiles.getValue(); + foreach (var e; entries) { + if (e == ".") { + append(dirs, e); + continue; + } + if (e == "..") { + if (d != "/") + append(dirs, e); + continue; + } + if (hide and e[0] == `.`) + continue; + + var stat = io.stat(d ~ "/" ~ e); + if (stat == nil) # dead link + continue; + + if (stat[11] == "dir") + append(dirs, e ~ "/"); + elsif (!size(pattern) or matches(e)) + append(files, e); + } + + list.removeChildren("value"); + var entries = sort(dirs, cmp) ~ sort(files, cmp); + forindex (var i; entries) + list.getChild("value", i, 1).setValue(entries[i]); + + dir.setValue(d); + gui.dialog_update(dlgname, "dir-input", "list"); + return 1; + } + + var select = func { + var e = selection.getValue(); + current.file = ""; + var new = nil; + if (e == ".") { + new = current.dir; + if (kbdctrl.getValue()) + dotfiles.setBoolValue(!dotfiles.getValue()); + } elsif (e == "..") { + if (kbdctrl.getValue()) + new = getprop("/sim/fg-root"); + elsif (kbdshift.getValue()) + new = getprop("/sim/fg-home"); + elsif (kbdalt.getValue()) + new = getprop("/sim/fg-current"); + else + new = current.dir ~ "/.."; + } elsif (e[size(e) - 1] == `/`) { + new = current.dir ~ "/" ~ e; + } else { + current.file = e; + gui.dialog_update(dlgname, "screenshot"); + } + if (new != nil) { + var p = string.normpath(new); + if (update(p)) + current.dir = p; + selection.setValue(""); + } + } + + var file_input = func { + current.file = selection.getValue(); + } + + var dir_input = func { + var p = string.normpath(dir.getValue()); + if (update(p)) + current.dir = p; + gui.dialog_update(dlgname, "list"); + } + + var close = func { + call(func { gui.Dialog.instance[dlgname].close() }, nil, var err = []); + } + + var ok = func { + dir_input(); + file_input(); + var p = string.normpath(current.dir ~ "/" ~ current.file); + var stat = io.stat(p); + path.setValue(stat != nil and stat[11] == "dir" ? p ~ "/" : p); + file.setValue(current.file); + close(); + } + + var op = button.getValue(); + if (op == nil or op == "") + op = "OK"; + self.getNode("group[1]/button/legend").setValue(op); + + var t = title.getValue(); + if (t == nil or t == "") + t = "Select File"; + self.getNode("group[0]/text/label").setValue(t); + + current.dir = (var d = dir.getValue()) != nil and d != "" ? d : getprop("/sim/fg-current"); + current.file = (var d = file.getValue()) != nil and d != "" ? d : ""; + gui.dialog_update(dlgname, "screenshot"); ## dir-input ? + update(string.normpath(current.dir)); + dir.setValue(current.dir); + </open> + </nasal> +</PropertyList> diff --git a/gui/menubar.xml b/gui/menubar.xml index 0d2cc528f..ca7cf38f8 100644 --- a/gui/menubar.xml +++ b/gui/menubar.xml @@ -67,6 +67,13 @@ </script> </binding> </item> + <item> + <label>Screesnhot (set directory)</label> + <binding> + <command>nasal</command> + <script>gui.save_screenshot()</script> + </binding> + </item> <!-- <item> <label>Last snapshot</label>