[gnome-shell] modalDialog: Add modal dialog base class
- From: Ray Strode <halfline src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] modalDialog: Add modal dialog base class
- Date: Fri, 14 Jan 2011 05:13:00 +0000 (UTC)
commit 47b8d16067180cb5c7ad86efb99819ad466312a4
Author: Ray Strode <rstrode redhat com>
Date: Wed Oct 20 20:46:38 2010 -0400
modalDialog: Add modal dialog base class
This is a base class to make it easier to
gain a consistent look for system modal dialogs.
It handles creating a darkened backdrop behind the dialog, setting
up buttons in the dialog, keynav, etc.
https://bugzilla.gnome.org/show_bug.cgi?id=637187
data/theme/gnome-shell.css | 48 +++++++++
js/Makefile.am | 1 +
js/ui/modalDialog.js | 233 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 282 insertions(+), 0 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 344692a..1240c12 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -1080,6 +1080,54 @@ StTooltip StLabel {
border-radius: 8px;
}
+/* Modal Dialogs */
+.modal-dialog {
+ font: 12pt sans-serif;
+ border-radius: 24px;
+ background-color: rgba(0.0, 0.0, 0.0, 0.9);
+ border: 2px solid #868686;
+ color: #ffffff;
+
+ padding-right: 42px;
+ padding-left: 42px;
+ padding-bottom: 30px;
+ padding-top: 30px;
+}
+
+.modal-dialog-button {
+ border: 1px solid #8b8b8b;
+ border-radius: 18px;
+ font: 14px sans-serif;
+
+ margin-left: 10px;
+ margin-right: 10px;
+
+ padding-left: 32px;
+ padding-right: 32px;
+ padding-top: 8px;
+ padding-bottom: 8px;
+
+ background-gradient-direction: vertical;
+ background-gradient-start: #29323b;
+ background-gradient-end: #121a24;
+}
+
+.modal-dialog-button:active,
+.modal-dialog-button:pressed {
+ border-color: #a5a5a5;
+ background-gradient-start: #121a24;
+ background-gradient-end: #29323b;
+}
+
+.modal-dialog-button:focus {
+ border: 2px solid #a5a5a5;
+
+ padding-left: 31px;
+ padding-right: 31px;
+ padding-top: 7px;
+ padding-bottom: 7px;
+}
+
/* Run Dialog */
.run-dialog-label {
font: 12px sans-serif;
diff --git a/js/Makefile.am b/js/Makefile.am
index 3d87dec..3dce4f2 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -32,6 +32,7 @@ nobase_dist_js_DATA = \
ui/magnifierDBus.js \
ui/main.js \
ui/messageTray.js \
+ ui/modalDialog.js \
ui/notificationDaemon.js \
ui/overview.js \
ui/panel.js \
diff --git a/js/ui/modalDialog.js b/js/ui/modalDialog.js
new file mode 100644
index 0000000..7b3f0d3
--- /dev/null
+++ b/js/ui/modalDialog.js
@@ -0,0 +1,233 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+const Clutter = imports.gi.Clutter;
+const Gdk = imports.gi.Gdk;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Lang = imports.lang;
+const Meta = imports.gi.Meta;
+const Pango = imports.gi.Pango;
+const St = imports.gi.St;
+const Shell = imports.gi.Shell;
+const Signals = imports.signals;
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
+
+const Params = imports.misc.params;
+
+const Lightbox = imports.ui.lightbox;
+const Main = imports.ui.main;
+const Tweener = imports.ui.tweener;
+
+const OPEN_AND_CLOSE_TIME = 0.1;
+const FADE_OUT_DIALOG_TIME = 1.0;
+
+const State = {
+ OPENED: 0,
+ CLOSED: 1,
+ OPENING: 2,
+ CLOSING: 3,
+ FADED_OUT: 4
+};
+
+function ModalDialog() {
+ this._init();
+}
+
+ModalDialog.prototype = {
+ _init: function(params) {
+ params = Params.parse(params, { styleClass: null });
+
+ this.state = State.CLOSED;
+
+ this._group = new St.Group({ visible: false,
+ x: 0,
+ y: 0 });
+ Main.uiGroup.add_actor(this._group);
+ global.focus_manager.add_group(this._group);
+ this._initialKeyFocus = this._group;
+
+ this._group.connect('destroy', Lang.bind(this, this._onGroupDestroy));
+
+ this._actionKeys = {};
+ this._group.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
+
+ this._lightbox = new Lightbox.Lightbox(this._group,
+ { inhibitEvents: true });
+
+ this._backgroundBin = new St.Bin();
+
+ this._group.add_actor(this._backgroundBin);
+ this._lightbox.highlight(this._backgroundBin);
+
+ this._dialogLayout = new St.BoxLayout({ style_class: 'modal-dialog',
+ vertical: true });
+ if (params.styleClass != null) {
+ this._dialogLayout.add_style_class_name(params.styleClass);
+ }
+ this._backgroundBin.child = this._dialogLayout;
+
+ this.contentLayout = new St.BoxLayout({ vertical: true });
+ this._dialogLayout.add(this.contentLayout,
+ { x_fill: true,
+ y_fill: true,
+ x_align: St.Align.MIDDLE,
+ y_align: St.Align.START });
+
+ this._buttonLayout = new St.BoxLayout({ opacity: 220,
+ vertical: false });
+ this._dialogLayout.add(this._buttonLayout,
+ { expand: true,
+ x_align: St.Align.MIDDLE,
+ y_align: St.Align.END });
+ },
+
+ setButtons: function(buttons) {
+ this._buttonLayout.remove_all();
+ let i = 0;
+ for (let index in buttons) {
+ let buttonInfo = buttons[index];
+ let label = buttonInfo['label'];
+ let action = buttonInfo['action'];
+ let key = buttonInfo['key'];
+
+ let button = new St.Button({ style_class: 'modal-dialog-button',
+ reactive: true,
+ can_focus: true,
+ label: label });
+
+ let x_alignment;
+ if (buttons.length == 1)
+ x_alignment = St.Align.END;
+ else if (i == 0)
+ x_alignment = St.Align.START;
+ else if (i == buttons.length - 1)
+ x_alignment = St.Align.END;
+ else
+ x_alignment = St.Align.MIDDLE;
+
+ this._initialKeyFocus = button;
+ this._buttonLayout.add(button,
+ { expand: true,
+ x_fill: false,
+ y_fill: false,
+ x_align: x_alignment,
+ y_align: St.Align.MIDDLE });
+
+ button.connect('clicked', action);
+
+ if (key)
+ this._actionKeys[key] = action;
+ i++;
+ }
+ },
+
+ _onKeyPressEvent: function(object, keyPressEvent) {
+ let symbol = keyPressEvent.get_key_symbol();
+ let action = this._actionKeys[symbol];
+
+ if (action)
+ action();
+ },
+
+ _onGroupDestroy: function() {
+ this.emit('destroy');
+ },
+
+ _fadeOpen: function() {
+ let monitor = global.get_focus_monitor();
+
+ this._backgroundBin.set_position(monitor.x, monitor.y);
+ this._backgroundBin.set_size(monitor.width, monitor.height);
+
+ this.state = State.OPENING;
+
+ this._dialogLayout.opacity = 255;
+ this._lightbox.show();
+ this._group.opacity = 0;
+ this._group.show();
+ Tweener.addTween(this._group,
+ { opacity: 255,
+ time: OPEN_AND_CLOSE_TIME,
+ transition: 'easeOutQuad',
+ onComplete: Lang.bind(this,
+ function() {
+ this._initialKeyFocus.grab_key_focus();
+ this.state = State.OPENED;
+ this.emit('opened');
+ }),
+ });
+ },
+
+ open: function(timestamp) {
+ if (this.state == State.OPENED || this.state == State.OPENING)
+ return true;
+
+ if (!Main.pushModal(this._group, timestamp))
+ return false;
+
+ global.stage.set_key_focus(this._group);
+
+ this._fadeOpen();
+ return true;
+ },
+
+ close: function(timestamp) {
+ if (this.state == State.CLOSED || this.state == State.CLOSING)
+ return;
+
+ let needsPopModal;
+
+ if (this.state == State.OPENED || this.state == State.OPENING)
+ needsPopModal = true;
+ else
+ needsPopModal = false;
+
+ this.state = State.CLOSING;
+
+ Tweener.addTween(this._group,
+ { opacity: 0,
+ time: OPEN_AND_CLOSE_TIME,
+ transition: 'easeOutQuad',
+ onComplete: Lang.bind(this,
+ function() {
+ this.state = State.CLOSED;
+ this._group.hide();
+
+ if (needsPopModal)
+ Main.popModal(this._group, timestamp);
+ })
+ });
+ },
+
+ // This method is like close, but fades the dialog out much slower,
+ // and leaves the lightbox in place. Once in the faded out state,
+ // the dialog can be brought back by an open call, or the lightbox
+ // can be dismissed by a close call.
+ //
+ // The main point of this method is to give some indication to the user
+ // that the dialog reponse has been acknowledged but will take a few
+ // moments before being processed.
+ // e.g., if a user clicked "Log Out" then the dialog should go away
+ // imediately, but the lightbox should remain until the logout is
+ // complete.
+ _fadeOutDialog: function(timestamp) {
+ if (this.state == State.CLOSED || this.state == State.CLOSING)
+ return;
+
+ if (this.state == State.FADED_OUT)
+ return;
+
+ Tweener.addTween(this._dialogLayout,
+ { opacity: 0,
+ time: FADE_OUT_DIALOG_TIME,
+ transition: 'easeOutQuad',
+ onComplete: Lang.bind(this,
+ function() {
+ this.state = State.FADED_OUT;
+ Main.popModal(this._group, timestamp);
+ })
+ });
+ }
+};
+Signals.addSignalMethods(ModalDialog.prototype);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]