summaryrefslogtreecommitdiff
path: root/src/gui/triggerSelectWindow.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/triggerSelectWindow.vala')
-rw-r--r--src/gui/triggerSelectWindow.vala257
1 files changed, 257 insertions, 0 deletions
diff --git a/src/gui/triggerSelectWindow.vala b/src/gui/triggerSelectWindow.vala
new file mode 100644
index 0000000..e003a84
--- /dev/null
+++ b/src/gui/triggerSelectWindow.vala
@@ -0,0 +1,257 @@
+/*
+Copyright (c) 2011 by Simon Schneegans
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+namespace GnomePie {
+
+/////////////////////////////////////////////////////////////////////////
+/// This window allows the selection of a hotkey. It is returned in form
+/// of a Trigger. Therefore it can be either a keyboard driven hotkey or
+/// a mouse based hotkey.
+/////////////////////////////////////////////////////////////////////////
+
+public class TriggerSelectWindow : Gtk.Dialog {
+
+ /////////////////////////////////////////////////////////////////////
+ /// This signal is emitted when the user selects a new hot key.
+ /////////////////////////////////////////////////////////////////////
+
+ public signal void on_select(Trigger trigger);
+
+ /////////////////////////////////////////////////////////////////////
+ /// Some private members which are needed by other methods.
+ /////////////////////////////////////////////////////////////////////
+
+ private Gtk.CheckButton turbo;
+ private Gtk.CheckButton delayed;
+ private Gtk.Label preview;
+
+ /////////////////////////////////////////////////////////////////////
+ /// The currently configured trigger.
+ /////////////////////////////////////////////////////////////////////
+
+ private Trigger trigger = null;
+
+ /////////////////////////////////////////////////////////////////////
+ /// The trigger which was active when this window was opened. It is
+ /// stored in order to check whether anything has changed when the
+ /// user clicks on OK.
+ /////////////////////////////////////////////////////////////////////
+
+ private Trigger original_trigger = null;
+
+ /////////////////////////////////////////////////////////////////////
+ /// These modifiers are ignored.
+ /////////////////////////////////////////////////////////////////////
+
+ private Gdk.ModifierType lock_modifiers = Gdk.ModifierType.MOD2_MASK
+ |Gdk.ModifierType.LOCK_MASK
+ |Gdk.ModifierType.MOD5_MASK;
+
+ /////////////////////////////////////////////////////////////////////
+ /// C'tor, constructs a new TriggerSelectWindow.
+ /////////////////////////////////////////////////////////////////////
+
+ public TriggerSelectWindow() {
+ this.title = _("Define an open-command");
+ this.resizable = false;
+ this.delete_event.connect(hide_on_delete);
+ this.key_press_event.connect(on_key_press);
+ this.button_press_event.connect(on_button_press);
+
+ this.show.connect_after(() => {
+ FocusGrabber.grab(this);
+ });
+
+ this.hide.connect(() => {
+ FocusGrabber.ungrab(this);
+ });
+
+ var container = new Gtk.VBox(false, 6);
+ container.set_border_width(6);
+
+ // click area
+ var click_frame = new Gtk.Frame(_("Click here if you want to bind a mouse button!"));
+
+ var click_box = new Gtk.EventBox();
+ click_box.height_request = 100;
+ click_box.button_press_event.connect(on_area_clicked);
+
+ this.preview = new Gtk.Label(null);
+
+ click_box.add(this.preview);
+
+ click_frame.add(click_box);
+
+ container.pack_start(click_frame, false);
+
+ // turbo checkbox
+ this.turbo = new Gtk.CheckButton.with_label (_("Turbo mode"));
+ this.turbo.tooltip_text = _("If checked, the Pie will close when you " +
+ "release the chosen hot key.");
+ this.turbo.active = false;
+ this.turbo.toggled.connect(() => {
+ if (this.trigger != null)
+ this.update_trigger(new Trigger.from_values(
+ this.trigger.key_sym, this.trigger.modifiers,
+ this.trigger.with_mouse, this.turbo.active,
+ this.delayed.active));
+ });
+
+ container.pack_start(turbo, false);
+
+ // delayed checkbox
+ this.delayed = new Gtk.CheckButton.with_label (_("Long press for activation"));
+ this.delayed.tooltip_text = _("If checked, the Pie will only open if you " +
+ "press this hot key a bit longer.");
+ this.delayed.active = false;
+ this.delayed.toggled.connect(() => {
+ if (this.trigger != null)
+ this.update_trigger(new Trigger.from_values(
+ this.trigger.key_sym, this.trigger.modifiers,
+ this.trigger.with_mouse, this.turbo.active,
+ this.delayed.active));
+ });
+
+ container.pack_start(delayed, false);
+
+ container.show_all();
+
+ this.vbox.pack_start(container, true, true);
+
+ this.add_button(Gtk.Stock.CANCEL, 1);
+ this.add_button(Gtk.Stock.OK, 0);
+
+ // select a new trigger on OK, hide on CANCEL
+ this.response.connect((id) => {
+ if (id == 1)
+ this.hide();
+ else if (id == 0) {
+ var assigned_id = PieManager.get_assigned_id(this.trigger);
+
+ if (this.trigger == this.original_trigger) {
+ // nothing did change
+ this.hide();
+ } else if (this.trigger.key_code == this.original_trigger.key_code
+ && this.trigger.modifiers == this.original_trigger.modifiers
+ && this.trigger.with_mouse == this.original_trigger.with_mouse) {
+ // only turbo and/or delayed mode changed, no need to check for double assignment
+ this.on_select(this.trigger);
+ this.hide();
+ } else if (assigned_id != "") {
+ // it's already assigned
+ var error = _("This hotkey is already assigned to the pie \"%s\"! \n\nPlease select " +
+ "another one or cancel your selection.").printf(PieManager.get_name_of(assigned_id));
+ var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(),
+ Gtk.DialogFlags.MODAL,
+ Gtk.MessageType.ERROR,
+ Gtk.ButtonsType.CANCEL,
+ error);
+ dialog.run();
+ dialog.destroy();
+ } else {
+ // a unused hot key has been chosen, great!
+ this.on_select(this.trigger);
+ this.hide();
+ }
+ }
+ });
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Used to set the currently selected trigger on opening.
+ /////////////////////////////////////////////////////////////////////
+
+ public void set_trigger(Trigger trigger) {
+ this.turbo.active = trigger.turbo;
+ this.delayed.active = trigger.delayed;
+ this.original_trigger = trigger;
+ this.update_trigger(trigger);
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Called when the user clicks in the click area.
+ /////////////////////////////////////////////////////////////////////
+
+ private bool on_area_clicked(Gdk.EventButton event) {
+ Gdk.ModifierType state = event.state & ~ this.lock_modifiers;
+
+ var new_trigger = new Trigger.from_values((int)event.button, state, true,
+ this.turbo.active, this.delayed.active);
+ if (new_trigger.key_code == 1) {
+ var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(), Gtk.DialogFlags.MODAL,
+ Gtk.MessageType.WARNING,
+ Gtk.ButtonsType.YES_NO,
+ _("It possible to make your system unusable if " +
+ "you bind a Pie to your left mouse button. Do " +
+ "you really want to do this?"));
+
+ dialog.response.connect((response) => {
+ if (response == Gtk.ResponseType.YES) {
+ this.update_trigger(new_trigger);
+ }
+ });
+
+ dialog.run();
+ dialog.destroy();
+ } else {
+ this.update_trigger(new_trigger);
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Called when the user presses a keyboard key.
+ /////////////////////////////////////////////////////////////////////
+
+ private bool on_key_press(Gdk.EventKey event) {
+ if (Gdk.keyval_name(event.keyval) == "Escape") {
+ this.hide();
+ } else if (Gdk.keyval_name(event.keyval) == "BackSpace") {
+ this.update_trigger(new Trigger());
+ } else if (event.is_modifier == 0) {
+ Gdk.ModifierType state = event.state & ~ this.lock_modifiers;
+ this.update_trigger(new Trigger.from_values((int)event.keyval, state, false,
+ this.turbo.active, this.delayed.active));
+ }
+
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Called when the user presses a mouse button.
+ /////////////////////////////////////////////////////////////////////
+
+ private bool on_button_press(Gdk.EventButton event) {
+ int width = 0, height = 0;
+ this.window.get_geometry(null, null, out width, out height, null);
+ if (event.x < 0 || event.x > width || event.y < 0 || event.y > height)
+ this.hide();
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ /// Helper method to update the content of the trigger preview label.
+ /////////////////////////////////////////////////////////////////////
+
+ private void update_trigger(Trigger new_trigger) {
+ this.trigger = new_trigger;
+ this.preview.set_markup("<big><b>" + this.trigger.label + "</b></big>");
+ }
+}
+
+}