[gnome-shell] ui: Use MessageDialogContent where appropriate



commit 593b4318a3bf598a00af95c040d237c3d6644a74
Author: Florian Müllner <fmuellner gnome org>
Date:   Sat Jul 15 06:03:55 2017 +0200

    ui: Use MessageDialogContent where appropriate
    
    The gros of our ModalDialogs follow a UI pattern that matches the
    newly added widget, so port them over to cut down on duplication.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=784985

 data/theme/gnome-shell-high-contrast.css |   85 +++++----------------
 data/theme/gnome-shell-sass              |    2 +-
 data/theme/gnome-shell.css               |   85 +++++----------------
 js/ui/accessDialog.js                    |   36 ++-------
 js/ui/components/keyring.js              |   53 +++++--------
 js/ui/components/networkAgent.js         |   44 ++---------
 js/ui/components/polkitAgent.js          |   59 ++++-----------
 js/ui/shellMountOperation.js             |  121 +++++-------------------------
 js/ui/status/location.js                 |   37 ++-------
 js/ui/windowManager.js                   |   43 +++--------
 10 files changed, 132 insertions(+), 433 deletions(-)
---
diff --git a/data/theme/gnome-shell-high-contrast.css b/data/theme/gnome-shell-high-contrast.css
index 66aa66b..2de48db 100644
--- a/data/theme/gnome-shell-high-contrast.css
+++ b/data/theme/gnome-shell-high-contrast.css
@@ -315,24 +315,20 @@ StScrollBar {
 
 .mount-dialog {
   spacing: 24px; }
-
-.mount-dialog-subject {
-  padding-top: 10px;
-  padding-left: 17px;
-  padding-bottom: 6px;
-  max-width: 34em; }
-
-.mount-dialog-subject:rtl {
-  padding-left: 0px;
-  padding-right: 17px; }
-
-.mount-dialog-description {
-  padding-left: 17px;
-  width: 28em; }
-
-.mount-dialog-description:rtl {
-  padding-left: 0px;
-  padding-right: 17px; }
+  .mount-dialog .message-dialog-title {
+    padding-top: 10px;
+    padding-left: 17px;
+    padding-bottom: 6px;
+    max-width: 34em; }
+  .mount-dialog .message-dialog-title:rtl {
+    padding-left: 0px;
+    padding-right: 17px; }
+  .mount-dialog .message-dialog-body {
+    padding-left: 17px;
+    width: 28em; }
+  .mount-dialog .message-dialog-body:rtl {
+    padding-left: 0px;
+    padding-right: 17px; }
 
 .mount-dialog-app-list {
   max-height: 200px;
@@ -366,17 +362,13 @@ StScrollBar {
 .prompt-dialog {
   width: 34em;
   border: 3px solid rgba(238, 238, 236, 0.2); }
-
-.prompt-dialog-main-layout {
-  spacing: 24px;
-  padding: 10px; }
-
-.prompt-dialog-message-layout {
-  spacing: 16px; }
-
-.prompt-dialog-headline {
-  font-weight: bold;
-  color: #b2b2a9; }
+  .prompt-dialog .message-dialog-main-layout {
+    spacing: 24px;
+    padding: 10px; }
+  .prompt-dialog .message-dialog-content {
+    spacing: 16px; }
+  .prompt-dialog .message-dialog-title {
+    color: #b2b2a9; }
 
 .prompt-dialog-description:rtl {
   text-align: right; }
@@ -450,45 +442,10 @@ StScrollBar {
 .access-dialog {
   spacing: 30px; }
 
-.access-dialog-main-layout {
-  padding: 12px 20px 0;
-  spacing: 12px; }
-
-.access-dialog-content {
-  max-width: 28em;
-  spacing: 20px; }
-
-.access-dialog-icon {
-  min-width: 48px;
-  icon-size: 48px; }
-
-.access-dialog-title {
-  font-weight: bold; }
-
-.access-dialog-subtitle {
-  color: #999999;
-  font-weight: bold; }
-
 /* Geolocation Dialog */
 .geolocation-dialog {
   spacing: 30px; }
 
-.geolocation-dialog-main-layout {
-  spacing: 12px; }
-
-.geolocation-dialog-content {
-  spacing: 20px; }
-
-.geolocation-dialog-icon {
-  icon-size: 48px; }
-
-.geolocation-dialog-title {
-  font-weight: bold; }
-
-.geolocation-dialog-reason {
-  color: #999999;
-  font-weight: bold; }
-
 /* Extension Dialog */
 .extension-dialog .message-dialog-main-layout {
   spacing: 24px;
diff --git a/data/theme/gnome-shell-sass b/data/theme/gnome-shell-sass
index 68fff90..82941c9 160000
--- a/data/theme/gnome-shell-sass
+++ b/data/theme/gnome-shell-sass
@@ -1 +1 @@
-Subproject commit 68fff905b0927ff1594061d03418221c312b2f75
+Subproject commit 82941c9d93a879bab99545fdf57e4bb3299a9e7f
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 2d041cf..f835c6d 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -315,24 +315,20 @@ StScrollBar {
 
 .mount-dialog {
   spacing: 24px; }
-
-.mount-dialog-subject {
-  padding-top: 10px;
-  padding-left: 17px;
-  padding-bottom: 6px;
-  max-width: 34em; }
-
-.mount-dialog-subject:rtl {
-  padding-left: 0px;
-  padding-right: 17px; }
-
-.mount-dialog-description {
-  padding-left: 17px;
-  width: 28em; }
-
-.mount-dialog-description:rtl {
-  padding-left: 0px;
-  padding-right: 17px; }
+  .mount-dialog .message-dialog-title {
+    padding-top: 10px;
+    padding-left: 17px;
+    padding-bottom: 6px;
+    max-width: 34em; }
+  .mount-dialog .message-dialog-title:rtl {
+    padding-left: 0px;
+    padding-right: 17px; }
+  .mount-dialog .message-dialog-body {
+    padding-left: 17px;
+    width: 28em; }
+  .mount-dialog .message-dialog-body:rtl {
+    padding-left: 0px;
+    padding-right: 17px; }
 
 .mount-dialog-app-list {
   max-height: 200px;
@@ -366,17 +362,13 @@ StScrollBar {
 .prompt-dialog {
   width: 34em;
   border: 3px solid rgba(238, 238, 236, 0.2); }
-
-.prompt-dialog-main-layout {
-  spacing: 24px;
-  padding: 10px; }
-
-.prompt-dialog-message-layout {
-  spacing: 16px; }
-
-.prompt-dialog-headline {
-  font-weight: bold;
-  color: #b2b2a9; }
+  .prompt-dialog .message-dialog-main-layout {
+    spacing: 24px;
+    padding: 10px; }
+  .prompt-dialog .message-dialog-content {
+    spacing: 16px; }
+  .prompt-dialog .message-dialog-title {
+    color: #b2b2a9; }
 
 .prompt-dialog-description:rtl {
   text-align: right; }
@@ -450,45 +442,10 @@ StScrollBar {
 .access-dialog {
   spacing: 30px; }
 
-.access-dialog-main-layout {
-  padding: 12px 20px 0;
-  spacing: 12px; }
-
-.access-dialog-content {
-  max-width: 28em;
-  spacing: 20px; }
-
-.access-dialog-icon {
-  min-width: 48px;
-  icon-size: 48px; }
-
-.access-dialog-title {
-  font-weight: bold; }
-
-.access-dialog-subtitle {
-  color: #8e8e80;
-  font-weight: bold; }
-
 /* Geolocation Dialog */
 .geolocation-dialog {
   spacing: 30px; }
 
-.geolocation-dialog-main-layout {
-  spacing: 12px; }
-
-.geolocation-dialog-content {
-  spacing: 20px; }
-
-.geolocation-dialog-icon {
-  icon-size: 48px; }
-
-.geolocation-dialog-title {
-  font-weight: bold; }
-
-.geolocation-dialog-reason {
-  color: #8e8e80;
-  font-weight: bold; }
-
 /* Extension Dialog */
 .extension-dialog .message-dialog-main-layout {
   spacing: 24px;
diff --git a/js/ui/accessDialog.js b/js/ui/accessDialog.js
index 13b448c..4a5647d 100644
--- a/js/ui/accessDialog.js
+++ b/js/ui/accessDialog.js
@@ -7,6 +7,7 @@ const Shell = imports.gi.Shell;
 const St = imports.gi.St;
 
 const CheckBox = imports.ui.checkBox;
+const Dialog = imports.ui.dialog;
 const ModalDialog = imports.ui.modalDialog;
 
 const RequestIface = '<node> \
@@ -64,29 +65,11 @@ const AccessDialog = new Lang.Class({
         let iconName = options['icon'] || null;
         let choices = options['choices'] || [];
 
-        let mainContentBox = new St.BoxLayout();
-        mainContentBox.style_class = 'access-dialog-main-layout';
-        this.contentLayout.add_actor(mainContentBox);
-
-        let icon = new St.Icon({ style_class: 'access-dialog-icon',
-                                 icon_name: iconName,
-                                 y_align: Clutter.ActorAlign.START });
-        mainContentBox.add_actor(icon);
-
-        let messageBox = new St.BoxLayout({ vertical: true });
-        messageBox.style_class = 'access-dialog-content',
-        mainContentBox.add_actor(messageBox);
-
-        let label;
-        label = new St.Label({ style_class: 'access-dialog-title headline',
-                               text: title });
-        messageBox.add_actor(label);
-
-        label = new St.Label({ style_class: 'access-dialog-subtitle',
-                               text: subtitle });
-        label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
-        label.clutter_text.line_wrap = true;
-        messageBox.add_actor(label);
+        let contentParams = { title, subtitle, body };
+        if (iconName)
+            contentParams.icon = new Gio.ThemedIcon({ name: iconName });
+        let content = new Dialog.MessageDialogContent(contentParams);
+        this.contentLayout.add_actor(content);
 
         this._choices = new Map();
 
@@ -98,16 +81,11 @@ const AccessDialog = new Lang.Class({
             let check = new CheckBox.CheckBox();
             check.getLabelActor().text = name;
             check.actor.checked = selected == "true";
-            messageBox.add_actor(check.actor);
+            content.insertBeforeBody(check.actor);
 
             this._choices.set(id, check);
         }
 
-        label = new St.Label({ text: body });
-        label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
-        label.clutter_text.line_wrap = true;
-        messageBox.add_actor(label);
-
         this.addButton({ label: denyLabel,
                          action: () => {
                              this._sendResponse(DialogResponse.CANCEL);
diff --git a/js/ui/components/keyring.js b/js/ui/components/keyring.js
index 9446742..d51a0a4 100644
--- a/js/ui/components/keyring.js
+++ b/js/ui/components/keyring.js
@@ -10,6 +10,7 @@ const GObject = imports.gi.GObject;
 const Gcr = imports.gi.Gcr;
 
 const Animation = imports.ui.animation;
+const Dialog = imports.ui.dialog;
 const ModalDialog = imports.ui.modalDialog;
 const ShellEntry = imports.ui.shellEntry;
 const CheckBox = imports.ui.checkBox;
@@ -31,38 +32,24 @@ const KeyringDialog = new Lang.Class({
         this.prompt.connect('show-confirm', Lang.bind(this, this._onShowConfirm));
         this.prompt.connect('prompt-close', Lang.bind(this, this._onHidePrompt));
 
-        let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
-                                                vertical: false });
-        this.contentLayout.add(mainContentBox);
-
-        let icon = new St.Icon({ icon_name: 'dialog-password-symbolic' });
-        mainContentBox.add(icon,
-                           { x_fill:  true,
-                             y_fill:  false,
-                             x_align: St.Align.END,
-                             y_align: St.Align.START });
-
-        this._messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
-                                              vertical: true });
-        mainContentBox.add(this._messageBox,
-                           { y_align: St.Align.START, expand: true, x_fill: true, y_fill: true });
-
-        let subject = new St.Label({ style_class: 'prompt-dialog-headline headline' });
-        this.prompt.bind_property('message', subject, 'text', GObject.BindingFlags.SYNC_CREATE);
-
-        this._messageBox.add(subject,
-                             { x_fill: false,
-                               y_fill:  false,
-                               x_align: St.Align.START,
-                               y_align: St.Align.START });
-
-        let description = new St.Label({ style_class: 'prompt-dialog-description' });
-        description.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
-        description.clutter_text.line_wrap = true;
-        this.prompt.bind_property('description', description, 'text', GObject.BindingFlags.SYNC_CREATE);
-        this._messageBox.add(description,
-                            { y_fill:  true,
-                              y_align: St.Align.START });
+        let icon = new Gio.ThemedIcon({ name: 'dialog-password-symbolic' });
+        this._content = new Dialog.MessageDialogContent({ icon });
+        this.contentLayout.add(this._content);
+
+        // FIXME: Why does this break now?
+        /*
+        this.prompt.bind_property('message', this._content, 'title', GObject.BindingFlags.SYNC_CREATE);
+        this.prompt.bind_property('description', this._content, 'body', GObject.BindingFlags.SYNC_CREATE);
+        */
+        this.prompt.connect('notify::message', () => {
+            this._content.title = this.prompt.message;
+        });
+        this._content.title = this.prompt.message;
+
+        this.prompt.connect('notify::description', () => {
+            this._content.body = this.prompt.description;
+        });
+        this._content.body = this.prompt.description;
 
         this._workSpinner = null;
         this._controlTable = null;
@@ -195,7 +182,7 @@ const KeyringDialog = new Lang.Class({
         }
 
         this._controlTable = table;
-        this._messageBox.add(table, { x_fill: true, y_fill: true });
+        this._content.messageBox.add(table, { x_fill: true, y_fill: true });
     },
 
     _updateSensitivity: function(sensitive) {
diff --git a/js/ui/components/networkAgent.js b/js/ui/components/networkAgent.js
index 205d2f7..6ad787a 100644
--- a/js/ui/components/networkAgent.js
+++ b/js/ui/components/networkAgent.js
@@ -12,6 +12,7 @@ const Shell = imports.gi.Shell;
 const St = imports.gi.St;
 
 const Config = imports.misc.config;
+const Dialog = imports.ui.dialog;
 const Main = imports.ui.main;
 const MessageTray = imports.ui.messageTray;
 const ModalDialog = imports.ui.modalDialog;
@@ -38,41 +39,12 @@ const NetworkSecretDialog = new Lang.Class({
         else
             this._content = this._getContent();
 
-        let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
-                                                vertical: false });
-        this.contentLayout.add(mainContentBox,
-                               { x_fill: true,
-                                 y_fill: true });
-
-        let icon = new St.Icon({ icon_name: 'dialog-password-symbolic' });
-        mainContentBox.add(icon,
-                           { x_fill:  true,
-                             y_fill:  false,
-                             x_align: St.Align.END,
-                             y_align: St.Align.START });
-
-        let messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
-                                            vertical: true });
-        mainContentBox.add(messageBox,
-                           { y_align: St.Align.START });
-
-        let subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline headline',
-                                            text: this._content.title });
-        messageBox.add(subjectLabel,
-                       { y_fill:  false,
-                         y_align: St.Align.START });
-
-        if (this._content.message != null) {
-            let descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
-                                                  text: this._content.message });
-            descriptionLabel.clutter_text.line_wrap = true;
-            descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
-
-            messageBox.add(descriptionLabel,
-                           { y_fill:  true,
-                             y_align: St.Align.START,
-                             expand: true });
-        }
+        let icon = new Gio.ThemedIcon({ name: 'dialog-password-symbolic' });
+        let contentParams = { icon,
+                              title: this._content.title,
+                              body: this._content.message };
+        let contentBox = new Dialog.MessageDialogContent(contentParams);
+        this.contentLayout.add_actor(contentBox);
 
         let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
         let secretTable = new St.Widget({ style_class: 'network-dialog-secret-table',
@@ -135,7 +107,7 @@ const NetworkSecretDialog = new Lang.Class({
                 secret.entry.clutter_text.set_password_char('\u25cf');
         }
 
-        messageBox.add(secretTable);
+        contentBox.messageBox.add(secretTable);
 
         this._okButton = { label:  _("Connect"),
                            action: Lang.bind(this, this._onOk),
diff --git a/js/ui/components/polkitAgent.js b/js/ui/components/polkitAgent.js
index 6e49ced..9ab8433 100644
--- a/js/ui/components/polkitAgent.js
+++ b/js/ui/components/polkitAgent.js
@@ -15,6 +15,7 @@ const PolkitAgent = imports.gi.PolkitAgent;
 
 const Animation = imports.ui.animation;
 const Components = imports.ui.components;
+const Dialog = imports.ui.dialog;
 const ModalDialog = imports.ui.modalDialog;
 const ShellEntry = imports.ui.shellEntry;
 const UserWidget = imports.ui.userWidget;
@@ -34,47 +35,15 @@ const AuthenticationDialog = new Lang.Class({
         this.parent({ styleClass: 'prompt-dialog' });
 
         this.actionId = actionId;
-        this.message = message;
+        this.message = body;
         this.userNames = userNames;
         this._wasDismissed = false;
 
-        let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
-                                                vertical: false });
-        this.contentLayout.add(mainContentBox,
-                               { x_fill: true,
-                                 y_fill: true });
-
-        let icon = new St.Icon({ icon_name: 'dialog-password-symbolic' });
-        mainContentBox.add(icon,
-                           { x_fill:  true,
-                             y_fill:  false,
-                             x_align: St.Align.END,
-                             y_align: St.Align.START });
-
-        let messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
-                                            vertical: true });
-        mainContentBox.add(messageBox,
-                           { expand: true, y_align: St.Align.START });
-
-        this._subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline headline',
-                                            text: _("Authentication Required") });
-
-        messageBox.add(this._subjectLabel,
-                       { x_fill: false,
-                         y_fill:  false,
-                         x_align: St.Align.START,
-                         y_align: St.Align.START });
-
-        this._descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
-                                                text: message });
-        this._descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
-        this._descriptionLabel.clutter_text.line_wrap = true;
-
-        messageBox.add(this._descriptionLabel,
-                       { x_fill: false,
-                         y_fill:  true,
-                         x_align: St.Align.START,
-                         y_align: St.Align.START });
+        let icon = new Gio.ThemedIcon({ name: 'dialog-password-symbolic' });
+        let title = _("Authentication Required");
+
+        let content = new Dialog.MessageDialogContent({ icon, title, body });
+        this.contentLayout.add_actor(content);
 
         if (userNames.length > 1) {
             log('polkitAuthenticationAgent: Received ' + userNames.length +
@@ -105,12 +74,12 @@ const AuthenticationDialog = new Lang.Class({
         if (userIsRoot) {
             let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-root-label',
                                             text: userRealName }));
-            messageBox.add(userLabel, { x_fill: false,
-                                        x_align: St.Align.START });
+            content.messageBox.add(userLabel, { x_fill: false,
+                                                x_align: St.Align.START });
         } else {
             let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout',
                                              vertical: false });
-            messageBox.add(userBox);
+            content.messageBox.add(userBox);
             this._userAvatar = new UserWidget.Avatar(this._user,
                                                      { iconSize: DIALOG_ICON_SIZE,
                                                        styleClass: 'polkit-dialog-user-icon' });
@@ -132,7 +101,7 @@ const AuthenticationDialog = new Lang.Class({
         this._onUserChanged();
 
         this._passwordBox = new St.BoxLayout({ vertical: false, style_class: 'prompt-dialog-password-box' });
-        messageBox.add(this._passwordBox);
+        content.messageBox.add(this._passwordBox);
         this._passwordLabel = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
         this._passwordBox.add(this._passwordLabel, { y_fill: false, y_align: St.Align.MIDDLE });
         this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
@@ -155,13 +124,13 @@ const AuthenticationDialog = new Lang.Class({
         this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label' });
         this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
         this._errorMessageLabel.clutter_text.line_wrap = true;
-        messageBox.add(this._errorMessageLabel, { x_fill: false, x_align: St.Align.START });
+        content.messageBox.add(this._errorMessageLabel, { x_fill: false, x_align: St.Align.START });
         this._errorMessageLabel.hide();
 
         this._infoMessageLabel = new St.Label({ style_class: 'prompt-dialog-info-label' });
         this._infoMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
         this._infoMessageLabel.clutter_text.line_wrap = true;
-        messageBox.add(this._infoMessageLabel);
+        content.messageBox.add(this._infoMessageLabel);
         this._infoMessageLabel.hide();
 
         /* text is intentionally non-blank otherwise the height is not the same as for
@@ -173,7 +142,7 @@ const AuthenticationDialog = new Lang.Class({
         this._nullMessageLabel.add_style_class_name('hidden');
         this._nullMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
         this._nullMessageLabel.clutter_text.line_wrap = true;
-        messageBox.add(this._nullMessageLabel);
+        content.messageBox.add(this._nullMessageLabel);
         this._nullMessageLabel.show();
 
         this._cancelButton = this.addButton({ label: _("Cancel"),
diff --git a/js/ui/shellMountOperation.js b/js/ui/shellMountOperation.js
index 7327aa9..8f799e4 100644
--- a/js/ui/shellMountOperation.js
+++ b/js/ui/shellMountOperation.js
@@ -11,6 +11,7 @@ const St = imports.gi.St;
 const Shell = imports.gi.Shell;
 
 const CheckBox = imports.ui.checkBox;
+const Dialog = imports.ui.dialog;
 const Main = imports.ui.main;
 const MessageTray = imports.ui.messageTray;
 const ModalDialog = imports.ui.modalDialog;
@@ -46,12 +47,11 @@ function _setButtonsForChoices(dialog, choices) {
     dialog.setButtons(buttons);
 }
 
-function _setLabelsForMessage(dialog, message) {
+function _setLabelsForMessage(content, message) {
     let labels = message.split('\n');
 
-    _setLabelText(dialog.subjectLabel, labels.shift());
-    if (labels.length > 0)
-        _setLabelText(dialog.descriptionLabel, labels.join('\n'));
+    content.title = labels.shift();
+    content.body = labels.join('\n');
 }
 
 function _createIcon(gicon) {
@@ -281,43 +281,15 @@ const ShellMountQuestionDialog = new Lang.Class({
     Name: 'ShellMountQuestionDialog',
     Extends: ModalDialog.ModalDialog,
 
-    _init: function(gicon) {
+    _init: function(icon) {
         this.parent({ styleClass: 'mount-dialog' });
 
-        let mainContentLayout = new St.BoxLayout();
-        this.contentLayout.add(mainContentLayout, { x_fill: true,
-                                                    y_fill: false });
-
-        this._iconBin = new St.Bin({ child: _createIcon(gicon) });
-        mainContentLayout.add(this._iconBin,
-                              { x_fill:  true,
-                                y_fill:  false,
-                                x_align: St.Align.END,
-                                y_align: St.Align.MIDDLE });
-
-        let messageLayout = new St.BoxLayout({ vertical: true });
-        mainContentLayout.add(messageLayout,
-                              { y_align: St.Align.START });
-
-        this.subjectLabel = new St.Label({ style_class: 'mount-dialog-subject' });
-        this.subjectLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
-        this.subjectLabel.clutter_text.line_wrap = true;
-
-        messageLayout.add(this.subjectLabel,
-                          { y_fill:  false,
-                            y_align: St.Align.START });
-
-        this.descriptionLabel = new St.Label({ style_class: 'mount-dialog-description' });
-        this.descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
-        this.descriptionLabel.clutter_text.line_wrap = true;
-
-        messageLayout.add(this.descriptionLabel,
-                          { y_fill:  true,
-                            y_align: St.Align.START });
+        this._content = new Dialog.MessageDialogContent({ icon });
+        this.contentLayout.add(this._content, { x_fill: true, y_fill: false });
     },
 
     update: function(message, choices) {
-        _setLabelsForMessage(this, message);
+        _setLabelsForMessage(this._content, message);
         _setButtonsForChoices(this, choices);
     }
 });
@@ -327,44 +299,17 @@ const ShellMountPasswordDialog = new Lang.Class({
     Name: 'ShellMountPasswordDialog',
     Extends: ModalDialog.ModalDialog,
 
-    _init: function(message, gicon, flags) {
+    _init: function(message, icon, flags) {
         let strings = message.split('\n');
+        let title = strings.shift() || null;
+        let body = strings.shift() || null;
         this.parent({ styleClass: 'prompt-dialog' });
 
-        let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
-                                                vertical: false });
-        this.contentLayout.add(mainContentBox);
-
-        let icon = _createIcon(gicon);
-        mainContentBox.add(icon,
-                           { x_fill:  true,
-                             y_fill:  false,
-                             x_align: St.Align.END,
-                             y_align: St.Align.START });
-
-        this._messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
-                                              vertical: true });
-        mainContentBox.add(this._messageBox,
-                           { y_align: St.Align.START, expand: true, x_fill: true, y_fill: true });
-
-        let subject = new St.Label({ style_class: 'prompt-dialog-headline headline' });
-        this._messageBox.add(subject,
-                             { y_fill:  false,
-                               y_align: St.Align.START });
-        if (strings[0])
-            subject.set_text(strings[0]);
-
-        let description = new St.Label({ style_class: 'prompt-dialog-description' });
-        description.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
-        description.clutter_text.line_wrap = true;
-        this._messageBox.add(description,
-                            { y_fill:  true,
-                              y_align: St.Align.START });
-        if (strings[1])
-            description.set_text(strings[1]);
+        let content = new Dialog.MessageDialogContent({ icon, title, body });
+        this.contentLayout.add_actor(content);
 
         this._passwordBox = new St.BoxLayout({ vertical: false, style_class: 'prompt-dialog-password-box' });
-        this._messageBox.add(this._passwordBox);
+        content.messageBox.add(this._passwordBox);
 
         this._passwordLabel = new St.Label(({ style_class: 'prompt-dialog-password-label',
                                               text: _("Password") }));
@@ -384,14 +329,14 @@ const ShellMountPasswordDialog = new Lang.Class({
         this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
         this._errorMessageLabel.clutter_text.line_wrap = true;
         this._errorMessageLabel.hide();
-        this._messageBox.add(this._errorMessageLabel);
+        content.messageBox.add(this._errorMessageLabel);
 
         if (flags & Gio.AskPasswordFlags.SAVING_SUPPORTED) {
             this._rememberChoice = new CheckBox.CheckBox();
             this._rememberChoice.getLabelActor().text = _("Remember Password");
             this._rememberChoice.actor.checked =
                 global.settings.get_boolean(REMEMBER_MOUNT_PASSWORD_KEY);
-            this._messageBox.add(this._rememberChoice.actor);
+            content.messageBox.add(this._rememberChoice.actor);
         } else {
             this._rememberChoice = null;
         }
@@ -435,37 +380,11 @@ const ShellProcessesDialog = new Lang.Class({
     Name: 'ShellProcessesDialog',
     Extends: ModalDialog.ModalDialog,
 
-    _init: function(gicon) {
+    _init: function(icon) {
         this.parent({ styleClass: 'mount-dialog' });
 
-        let mainContentLayout = new St.BoxLayout();
-        this.contentLayout.add(mainContentLayout, { x_fill: true,
-                                                    y_fill: false });
-
-        this._iconBin = new St.Bin({ child: _createIcon(gicon) });
-        mainContentLayout.add(this._iconBin,
-                              { x_fill:  true,
-                                y_fill:  false,
-                                x_align: St.Align.END,
-                                y_align: St.Align.MIDDLE });
-
-        let messageLayout = new St.BoxLayout({ vertical: true });
-        mainContentLayout.add(messageLayout,
-                              { y_align: St.Align.START });
-
-        this.subjectLabel = new St.Label({ style_class: 'mount-dialog-subject' });
-
-        messageLayout.add(this.subjectLabel,
-                          { y_fill:  false,
-                            y_align: St.Align.START });
-
-        this.descriptionLabel = new St.Label({ style_class: 'mount-dialog-description' });
-        this.descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
-        this.descriptionLabel.clutter_text.line_wrap = true;
-
-        messageLayout.add(this.descriptionLabel,
-                          { y_fill:  true,
-                            y_align: St.Align.START });
+        this._content = new Dialog.MessageDialogContent({ icon });
+        this.contentLayout.add(this._content, { x_fill: true, y_fill: false });
 
         let scrollView = new St.ScrollView({ style_class: 'mount-dialog-app-list'});
         scrollView.set_policy(Gtk.PolicyType.NEVER,
@@ -515,7 +434,7 @@ const ShellProcessesDialog = new Lang.Class({
 
     update: function(message, processes, choices) {
         this._setAppsForPids(processes);
-        _setLabelsForMessage(this, message);
+        _setLabelsForMessage(this._content, message);
         _setButtonsForChoices(this, choices);
     }
 });
diff --git a/js/ui/status/location.js b/js/ui/status/location.js
index 7988dd4..8f4d2af 100644
--- a/js/ui/status/location.js
+++ b/js/ui/status/location.js
@@ -5,6 +5,7 @@ const GLib = imports.gi.GLib;
 const Gio = imports.gi.Gio;
 const Lang = imports.lang;
 
+const Dialog = imports.ui.dialog;
 const Main = imports.ui.main;
 const PanelMenu = imports.ui.panelMenu;
 const PopupMenu = imports.ui.popupMenu;
@@ -377,30 +378,19 @@ const GeolocationDialog = new Lang.Class({
     Name: 'GeolocationDialog',
     Extends: ModalDialog.ModalDialog,
 
-    _init: function(name, reason, reqAccuracyLevel) {
+    _init: function(name, subtitle, reqAccuracyLevel) {
         this.parent({ styleClass: 'geolocation-dialog' });
         this.reqAccuracyLevel = reqAccuracyLevel;
 
-        let mainContentBox = new St.BoxLayout({ style_class: 'geolocation-dialog-main-layout' });
-        this.contentLayout.add_actor(mainContentBox);
+        let icon = new Gio.ThemedIcon({ name: 'find-location-symbolic' });
 
-        let icon = new St.Icon({ style_class: 'geolocation-dialog-icon',
-                                 icon_name: 'find-location-symbolic',
-                                 y_align: Clutter.ActorAlign.START });
-        mainContentBox.add_actor(icon);
-
-        let messageBox = new St.BoxLayout({ style_class: 'geolocation-dialog-content',
-                                            vertical: true });
-        mainContentBox.add_actor(messageBox);
-
-        this._title = new St.Label({ style_class: 'geolocation-dialog-title headline' });
-        messageBox.add_actor(this._title);
-
-        this._reason = new St.Label({ style_class: 'geolocation-dialog-reason' });
-        messageBox.add_actor(this._reason);
+        /* Translators: %s is an application name */
+        let title = _("Give %s access to your location?").format(name);
+        let body = _("Location access can be changed at any time from the privacy settings.");
 
-        this._privacyNote = new St.Label();
-        messageBox.add_actor(this._privacyNote);
+        let contentParams = { icon, title, subtitle, body };
+        let content = new Dialog.MessageDialogContent(contentParams);
+        this.contentLayout.add_actor(content);
 
         let button = this.addButton({ label: _("Deny Access"),
                                       action: Lang.bind(this, this._onDenyClicked),
@@ -409,15 +399,6 @@ const GeolocationDialog = new Lang.Class({
                          action: Lang.bind(this, this._onGrantClicked) });
 
         this.setInitialKeyFocus(button);
-
-        /* Translators: %s is an application name */
-        this._title.text = _("Give %s access to your location?").format(name);
-
-        this._privacyNote.text = _("Location access can be changed at any time from the privacy settings.");
-
-        if (reason)
-            this._reason.text = reason;
-        this._reason.visible = (reason != null);
     },
 
     _onGrantClicked: function() {
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index f97ed76..4598120 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -12,6 +12,7 @@ const Shell = imports.gi.Shell;
 const Signals = imports.signals;
 
 const AltTab = imports.ui.altTab;
+const Dialog = imports.ui.dialog;
 const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
 const Main = imports.ui.main;
 const ModalDialog = imports.ui.modalDialog;
@@ -62,40 +63,18 @@ const DisplayChangeDialog = new Lang.Class({
 
         this._wm = wm;
 
-        let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
-                                                vertical: false });
-        this.contentLayout.add(mainContentBox,
-                               { x_fill: true,
-                                 y_fill: true });
-
-        let icon = new St.Icon({ icon_name: 'preferences-desktop-display-symbolic' });
-        mainContentBox.add(icon,
-                           { x_fill:  true,
-                             y_fill:  false,
-                             x_align: St.Align.END,
-                             y_align: St.Align.START });
-
-        let messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
-                                            vertical: true });
-        mainContentBox.add(messageBox,
-                           { expand: true, y_align: St.Align.START });
+        this._countDown = DISPLAY_REVERT_TIMEOUT;
 
-        let subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
-                                            text: _("Do you want to keep these display settings?") });
-        messageBox.add(subjectLabel,
-                       { y_fill:  false,
-                         y_align: St.Align.START });
+        let iconName = 'preferences-desktop-display-symbolic';
+        let icon = new Gio.ThemedIcon({ name: iconName });
+        let title = _("Do you want to keep these display settings?");
+        let body = this._formatCountDown();
 
-        this._countDown = DISPLAY_REVERT_TIMEOUT;
-        let message = this._formatCountDown();
-        this._descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
-                                                text: this._formatCountDown() });
-        this._descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
-        this._descriptionLabel.clutter_text.line_wrap = true;
+        this._content = new Dialog.MessageDialogContent({ icon, title, body });
 
-        messageBox.add(this._descriptionLabel,
-                       { y_fill:  true,
-                         y_align: St.Align.START });
+        this.contentLayout.add(this._content,
+                               { x_fill: true,
+                                 y_fill: true });
 
         /* Translators: this and the following message should be limited in lenght,
            to avoid ellipsizing the labels.
@@ -136,7 +115,7 @@ const DisplayChangeDialog = new Lang.Class({
             return GLib.SOURCE_REMOVE;
         }
 
-        this._descriptionLabel.text = this._formatCountDown();
+        this._content.body = this._formatCountDown();
         return GLib.SOURCE_CONTINUE;
     },
 


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