[gnome-shell] ui: Refactor modal dialog into separate Dialog class



commit 1c7a3ee61b1892b5614f8e2c58073d147cf9a042
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Jan 19 19:49:52 2017 +0100

    ui: Refactor modal dialog into separate Dialog class
    
    This is the basic dialog actor implementation, which will allow us to
    use the same implementation on the session-global modal dialogs. The
    ModalDialog class now uses it underneath, and so do all users of it.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=762083

 js/js-resources.gresource.xml |    1 +
 js/ui/dialog.js               |  131 +++++++++++++++++++++++++++++++++++++++++
 js/ui/modalDialog.js          |  107 ++-------------------------------
 3 files changed, 139 insertions(+), 100 deletions(-)
---
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index 591875f..71e713d 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -47,6 +47,7 @@
     <file>ui/ctrlAltTab.js</file>
     <file>ui/dash.js</file>
     <file>ui/dateMenu.js</file>
+    <file>ui/dialog.js</file>
     <file>ui/dnd.js</file>
     <file>ui/edgeDragAction.js</file>
     <file>ui/endSessionDialog.js</file>
diff --git a/js/ui/dialog.js b/js/ui/dialog.js
new file mode 100644
index 0000000..941ef75
--- /dev/null
+++ b/js/ui/dialog.js
@@ -0,0 +1,131 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Clutter = imports.gi.Clutter;
+const St = imports.gi.St;
+const Lang = imports.lang;
+
+const Dialog = new Lang.Class({
+    Name: 'Dialog',
+    Extends: St.Widget,
+
+    _init: function (parentActor, styleClass) {
+        this.parent({ layout_manager: new Clutter.BinLayout() });
+        this.connect('destroy', Lang.bind(this, this._onDestroy));
+
+        this._pressedKey = null;
+        this._buttonKeys = {};
+        this._createDialog();
+        this.add_child(this._dialog);
+
+        if (styleClass != null)
+            this._dialog.add_style_class_name(styleClass);
+
+        this._parentActor = parentActor;
+        this._eventId = this._parentActor.connect('event', Lang.bind(this, this._modalEventHandler));
+        this._parentActor.add_child(this);
+    },
+
+    _createDialog: function () {
+        this._dialog = new St.BoxLayout({ style_class: 'modal-dialog',
+                                          x_align:     Clutter.ActorAlign.CENTER,
+                                          y_align:     Clutter.ActorAlign.CENTER,
+                                          vertical:    true });
+
+        // modal dialogs are fixed width and grow vertically; set the request
+        // mode accordingly so wrapped labels are handled correctly during
+        // size requests.
+        this._dialog.request_mode = Clutter.RequestMode.HEIGHT_FOR_WIDTH;
+
+        this.contentLayout = new St.BoxLayout({ vertical: true,
+                                                style_class: "modal-dialog-content-box" });
+        this._dialog.add(this.contentLayout,
+                         { expand:  true,
+                           x_fill:  true,
+                           y_fill:  true,
+                           x_align: St.Align.MIDDLE,
+                           y_align: St.Align.START });
+
+        this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous:true }) });
+        this._dialog.add(this.buttonLayout,
+                         { x_align: St.Align.MIDDLE,
+                           y_align: St.Align.START });
+    },
+
+    _onDestroy: function () {
+        if (this._eventId != 0)
+            this._parentActor.disconnect(this._eventId);
+        this._eventId = 0;
+    },
+
+    _modalEventHandler: function (actor, event) {
+        if (event.type() == Clutter.EventType.KEY_PRESS) {
+            this._pressedKey = event.get_key_symbol();
+        } else if (event.type() == Clutter.EventType.KEY_RELEASE) {
+            let pressedKey = this._pressedKey;
+            this._pressedKey = null;
+
+            let symbol = event.get_key_symbol();
+            if (symbol != pressedKey)
+                return Clutter.EVENT_PROPAGATE;
+
+            let buttonInfo = this._buttonKeys[symbol];
+            if (!buttonInfo)
+                return Clutter.EVENT_PROPAGATE;
+
+            let { button, action } = buttonInfo;
+
+            if (action && button.reactive) {
+                action();
+                return Clutter.EVENT_STOP;
+            }
+        }
+
+        return Clutter.EVENT_PROPAGATE;
+    },
+
+    addContent: function (actor) {
+        this.contentLayout.add (actor, { expand: true });
+    },
+
+    addButton: function (buttonInfo) {
+        let { label, action, key } = buttonInfo;
+        let isDefault = buttonInfo['default'];
+        let keys;
+
+        if (key)
+            keys = [key];
+        else if (isDefault)
+            keys = [Clutter.KEY_Return, Clutter.KEY_KP_Enter, Clutter.KEY_ISO_Enter];
+        else
+            keys = [];
+
+        let button = new St.Button({ style_class: 'modal-dialog-linked-button',
+                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
+                                     reactive:    true,
+                                     can_focus:   true,
+                                     x_expand:    true,
+                                     y_expand:    true,
+                                     label:       label });
+        button.connect('clicked', action);
+
+        buttonInfo['button'] = button;
+
+        if (isDefault)
+            button.add_style_pseudo_class('default');
+
+        if (!this._initialKeyFocusDestroyId)
+            this._initialKeyFocus = button;
+
+        for (let i in keys)
+            this._buttonKeys[keys[i]] = buttonInfo;
+
+        this.buttonLayout.add_actor(button);
+
+        return button;
+    },
+
+    clearButtons: function () {
+        this.buttonLayout.destroy_all_children();
+        this._buttonKeys = {};
+    },
+});
diff --git a/js/ui/modalDialog.js b/js/ui/modalDialog.js
index ac77305..ed1b92f 100644
--- a/js/ui/modalDialog.js
+++ b/js/ui/modalDialog.js
@@ -14,6 +14,7 @@ const Atk = imports.gi.Atk;
 
 const Params = imports.misc.params;
 
+const Dialog = imports.ui.dialog;
 const Layout = imports.ui.layout;
 const Lightbox = imports.ui.lightbox;
 const Main = imports.ui.main;
@@ -61,11 +62,6 @@ const ModalDialog = new Lang.Class({
 
         this._group.connect('destroy', Lang.bind(this, this._onGroupDestroy));
 
-        this._pressedKey = null;
-        this._buttonKeys = {};
-        this._group.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
-        this._group.connect('key-release-event', Lang.bind(this, this._onKeyReleaseEvent));
-
         this.backgroundStack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
         this._backgroundBin = new St.Bin({ child: this.backgroundStack,
                                            x_fill: true, y_fill: true });
@@ -73,17 +69,9 @@ const ModalDialog = new Lang.Class({
         this._backgroundBin.add_constraint(this._monitorConstraint);
         this._group.add_actor(this._backgroundBin);
 
-        this.dialogLayout = new St.BoxLayout({ style_class: 'modal-dialog',
-                                               x_align:      Clutter.ActorAlign.CENTER,
-                                               y_align:      Clutter.ActorAlign.CENTER,
-                                               vertical:     true });
-        // modal dialogs are fixed width and grow vertically; set the request
-        // mode accordingly so wrapped labels are handled correctly during
-        // size requests.
-        this.dialogLayout.request_mode = Clutter.RequestMode.HEIGHT_FOR_WIDTH;
-
-        if (params.styleClass != null)
-            this.dialogLayout.add_style_class_name(params.styleClass);
+        this.dialogLayout = new Dialog.Dialog(this.backgroundStack, params.styleClass);
+        this.contentLayout = this.dialogLayout.contentLayout;
+        this.buttonLayout = this.dialogLayout.buttonLayout;
 
         if (!this._shellReactive) {
             this._lightbox = new Lightbox.Lightbox(this._group,
@@ -94,22 +82,6 @@ const ModalDialog = new Lang.Class({
             this._eventBlocker = new Clutter.Actor({ reactive: true });
             this.backgroundStack.add_actor(this._eventBlocker);
         }
-        this.backgroundStack.add_actor(this.dialogLayout);
-
-
-        this.contentLayout = new St.BoxLayout({ vertical: true,
-                                                style_class: "modal-dialog-content-box" });
-        this.dialogLayout.add(this.contentLayout,
-                              { expand:  true,
-                                x_fill:  true,
-                                y_fill:  true,
-                                x_align: St.Align.MIDDLE,
-                                y_align: St.Align.START });
-
-        this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout ({ homogeneous:true }) });
-        this.dialogLayout.add(this.buttonLayout,
-                              { x_align: St.Align.MIDDLE,
-                                y_align: St.Align.END });
 
         global.focus_manager.add_group(this.dialogLayout);
         this._initialKeyFocus = this.dialogLayout;
@@ -122,8 +94,7 @@ const ModalDialog = new Lang.Class({
     },
 
     clearButtons: function() {
-        this.buttonLayout.destroy_all_children();
-        this._buttonKeys = {};
+        this.dialogLayout.clearButtons();
     },
 
     setButtons: function(buttons) {
@@ -146,72 +117,8 @@ const ModalDialog = new Lang.Class({
         }
     },
 
-    addButton: function(buttonInfo) {
-        let label = buttonInfo['label']
-        let action = buttonInfo['action'];
-        let key = buttonInfo['key'];
-        let isDefault = buttonInfo['default'];
-
-        let keys;
-
-        if (key)
-            keys = [key];
-        else if (isDefault)
-            keys = [Clutter.KEY_Return, Clutter.KEY_KP_Enter, Clutter.KEY_ISO_Enter];
-        else
-            keys = [];
-
-        let button = new St.Button({ style_class: 'modal-dialog-linked-button',
-                                     button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
-                                     reactive:    true,
-                                     can_focus:   true,
-                                     x_expand:    true,
-                                     y_expand:    true,
-                                     label:       label });
-        button.connect('clicked', action);
-
-        buttonInfo['button'] = button;
-
-        if (isDefault)
-            button.add_style_pseudo_class('default');
-
-        if (!this._initialKeyFocusDestroyId)
-            this._initialKeyFocus = button;
-
-        for (let i in keys)
-            this._buttonKeys[keys[i]] = buttonInfo;
-
-        this.buttonLayout.add_actor(button);
-
-        return button;
-    },
-
-    _onKeyPressEvent: function(object, event) {
-        this._pressedKey = event.get_key_symbol();
-        return Clutter.EVENT_PROPAGATE;
-    },
-
-    _onKeyReleaseEvent: function(object, event) {
-        let pressedKey = this._pressedKey;
-        this._pressedKey = null;
-
-        let symbol = event.get_key_symbol();
-        if (symbol != pressedKey)
-            return Clutter.EVENT_PROPAGATE;
-
-        let buttonInfo = this._buttonKeys[symbol];
-        if (!buttonInfo)
-            return Clutter.EVENT_PROPAGATE;
-
-        let button = buttonInfo['button'];
-        let action = buttonInfo['action'];
-
-        if (action && button.reactive) {
-            action();
-            return Clutter.EVENT_STOP;
-        }
-
-        return Clutter.EVENT_PROPAGATE;
+    addButton: function (buttonInfo) {
+        return this.dialogLayout.addButton(buttonInfo);
     },
 
     _onGroupDestroy: function() {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]