[gnome-characters/bilelmoussaoui/gtk4] character dialog: redesign & cleanup



commit 42c0a0d46a8a90058b31fa8dc59f0aad33296d3a
Author: Bilal Elmoussaoui <bil elmoussaoui gmail com>
Date:   Mon Nov 22 14:06:12 2021 +0100

    character dialog: redesign & cleanup
    
    - Move from a GtkDialog to a AdwWindow, there's nothing we need from GtkDialog's api
    - Cleanup both UI file & the code
    - Rename the UI file according to the JS file

 data/character.ui                            | 150 -----------------------
 data/character_dialog.ui                     | 172 +++++++++++++++++++++++++++
 data/meson.build                             |   2 +-
 data/org.gnome.Characters.data.gresource.xml |   2 +-
 data/style.css                               |  18 ---
 src/characterDialog.js                       | 172 +++++++++++----------------
 6 files changed, 241 insertions(+), 275 deletions(-)
---
diff --git a/data/character_dialog.ui b/data/character_dialog.ui
new file mode 100644
index 0000000..c95431b
--- /dev/null
+++ b/data/character_dialog.ui
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="Gjs_CharacterDialog" parent="AdwWindow">
+    <property name="default-width">360</property>
+    <property name="default-height">500</property>
+    <child>
+      <object class="AdwToastOverlay" id="toastOverlay">
+        <property name="child">
+          <object class="GtkBox">
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkHeaderBar">
+                <child type="start">
+                  <object class="GtkRevealer" id="revealer">
+                    <property name="transition-type">crossfade</property>
+                    <child>
+                      <object class="GtkButton">
+                        <property name="icon-name">go-previous-symbolic</property>
+                        <property name="action-name">character.go-back</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <property name="title-widget">
+                  <object class="AdwWindowTitle" id="windowTitle" />
+                </property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkStack" id="mainStack">
+                <child>
+                  <object class="GtkStackPage">
+                    <property name="name">character</property>
+                    <property name="child">
+                      <object class="GtkBox">
+                        <property name="orientation">vertical</property>
+                        <property name="halign">fill</property>
+                        <property name="valign">center</property>
+                        <child>
+                          <object class="GtkStack" id="characterStack">
+                            <child>
+                              <object class="GtkStackPage">
+                                <property name="name">character</property>
+                                <property name="child">
+                                  <object class="GtkLabel" id="characterLabel">
+                                    <property name="ellipsize">end</property>
+                                    <property name="halign">center</property>
+                                    <property name="valign">center</property>
+                                    <style>
+                                      <class name="character-label" />
+                                    </style>
+                                  </object>
+                                </property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkStackPage">
+                                <property name="name">missing</property>
+                                <property name="child">
+                                  <object class="GtkLabel" id="missingLabel">
+                                    <property name="halign">center</property>
+                                    <property name="valign">center</property>
+                                    <property name="wrap">True</property>
+                                    <property name="wrap-mode">word</property>
+                                    <property name="width-chars">28</property>
+                                    <property name="max-width-chars">28</property>
+                                    <property name="justify">center</property>
+                                  </object>
+                                </property>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkButton">
+                            <property name="margin-top">18</property>
+                            <property name="margin-bottom">18</property>
+                            <property name="halign">center</property>
+                            <property name="label" translatable="yes">_Copy Character</property>
+                            <property name="use-underline">true</property>
+                            <property name="action-name">character.copy</property>
+                            <style>
+                              <class name="pill" />
+                            </style>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="AdwClamp">
+                            <property name="margin-top">18</property>
+                            <property name="margin-bottom">18</property>
+                            <property name="margin-start">18</property>
+                            <property name="margin-end">18</property>
+                            <property name="vexpand">True</property>
+                            <property name="valign">center</property>
+                            <child>
+                              <object class="GtkListBox">
+                                <property name="selection-mode">none</property>
+                                <child>
+                                  <object class="AdwActionRow">
+                                    <property name="title" translatable="yes">Unicode</property>
+                                    <child>
+                                      <object class="GtkLabel" id="detailLabel">
+                                        <property name="selectable">True</property>
+                                        <style>
+                                          <class name="dim-label" />
+                                        </style>
+                                      </object>
+                                    </child>
+                                  </object>
+                                </child>
+                                <child>
+                                  <object class="AdwActionRow" id="seeAlsoRow">
+                                    <property name="use-underline">true</property>
+                                    <property name="title" translatable="yes">_See Also</property>
+                                    <property name="action-name">character.see-also</property>
+                                    <property name="activatable">true</property>
+                                    <child>
+                                      <object class="GtkImage">
+                                        <property name="icon-name">go-next-symbolic</property>
+                                      </object>
+                                    </child>
+                                  </object>
+                                </child>
+                                <style>
+                                  <class name="boxed-list" />
+                                </style>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkStackPage">
+                    <property name="name">related</property>
+                    <property name="child">
+                      <object class="GtkScrolledWindow" id="related-scrolled">
+                        <property name="hscrollbar-policy">never</property>
+                        <property name="vexpand">True</property>
+                        <child>
+                          <object class="AdwClamp">
+                            <property name="margin-top">36</property>
+                            <property name="margin-bottom">36</property>
+                            <property name="margin-start">18</property>
+                            <property name="margin-end">18</property>
+                            <property name="vexpand">True</property>
+                            <property name="valign">center</property>
+                            <child>
+                              <object class="GtkListBox" id="relatedListbox">
+                                <style>
+                                  <class name="boxed-list" />
+                                </style>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </property>
+      </object>
+    </child>
+  </template>
+</interface>
+
+
diff --git a/data/meson.build b/data/meson.build
index 9855260..abd70fa 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -9,7 +9,7 @@ resource_data = files(
   'icons/hicolor/scalable/categories/characters-picture-symbolic.svg',
   'icons/hicolor/scalable/categories/characters-punctuation-symbolic.svg',
   'style.css',
-  'character.ui',
+  'character_dialog.ui',
   'characters_view.ui',
   'menu.ui',
   'shortcuts.ui',
diff --git a/data/org.gnome.Characters.data.gresource.xml b/data/org.gnome.Characters.data.gresource.xml
index e9d4b31..116d834 100644
--- a/data/org.gnome.Characters.data.gresource.xml
+++ b/data/org.gnome.Characters.data.gresource.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
   <gresource prefix="/org/gnome/Characters">
-    <file preprocess="xml-stripblanks">character.ui</file>
+    <file preprocess="xml-stripblanks">character_dialog.ui</file>
     <file preprocess="xml-stripblanks">characters_view.ui</file>
     <file preprocess="xml-stripblanks" alias="gtk/help-overlay.ui">shortcuts.ui</file>
     <file preprocess="xml-stripblanks">menu.ui</file>
diff --git a/data/style.css b/data/style.css
index 4d8f419..d9ceb22 100644
--- a/data/style.css
+++ b/data/style.css
@@ -19,26 +19,8 @@ Gjs_MenuPopover GtkScrolledWindow {
     font-size: x-large;
 }
 
-.character-list {
-    color: @theme_text_color;
-    background-color: @theme_base_color;
-}
-
 .character-label {
     font-size: 7em;
     font-weight: bold;
 }
 
-.detail-label {
-    font-size: small;
-}
-
-.related .character {
-    font-size: 3em;
-}
-
-.related .list-row {
-    border-style: groove;
-    border-width: 2pt;
-}
-
diff --git a/src/characterDialog.js b/src/characterDialog.js
index ff46f49..d45da7c 100644
--- a/src/characterDialog.js
+++ b/src/characterDialog.js
@@ -17,54 +17,49 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-const { Gc, GLib, Gio, GObject, Gtk, Pango } = imports.gi;
+const { Adw, Gc, Gdk, Gio, GObject, Gtk, Pango } = imports.gi;
 
 const Util = imports.util;
 
 var CharacterDialog = GObject.registerClass({
-
     Signals: {
         'character-copied': { param_types: [GObject.TYPE_STRING] },
     },
-    Template: 'resource:///org/gnome/Characters/character.ui',
-    InternalChildren: ['main-stack', 'character-stack',
-        'character-label', 'missing-label', 'detail-label',
-        'copy-button', 'copy-revealer', 'related-listbox'],
-}, class CharacterDialog extends Gtk.Dialog {
+    Template: 'resource:///org/gnome/Characters/character_dialog.ui',
+    InternalChildren: [
+        'mainStack', 'characterStack',
+        'characterLabel', 'missingLabel', 'detailLabel',
+        'seeAlsoRow', 'relatedListbox',
+        'windowTitle', 'revealer', 'toastOverlay',
+    ],
+}, class CharacterDialog extends Adw.Window {
     _init(character, fontDescription) {
-        super._init({
-            use_header_bar: true,
-            width_request: 400,
-            height_request: 400,
-        });
-
+        super._init();
         this._cancellable = new Gio.Cancellable();
+        this._fontDescription = fontDescription;
 
-        this._copy_button.connect('clicked', () => this._copyCharacter());
-
-        this._related_listbox.connect('row-selected', (listBox, row) => this._handleRowSelected(listBox, 
row));
-
-        this._relatedButton = new Gtk.ToggleButton({ label: _('See Also') });
-        this.add_action_widget(this._relatedButton, Gtk.ResponseType.HELP);
-        this._relatedButton.show();
+        const actions = new Gio.SimpleActionGroup();
+        Util.initActions(actions, [
+            { name: 'copy', activate: this._copyCharacter.bind(this) },
+            { name: 'see-also', activate: this._seeMore.bind(this) },
+            { name: 'go-back', activate: this._seeCharacter.bind(this) },
+        ]);
+        this.insert_action_group('character', actions);
 
-        this._relatedButton.connect('toggled', () => {
-            if (this._main_stack.visible_child_name === 'character')
-                this._main_stack.visible_child_name = 'related';
-            else
-                this._main_stack.visible_child_name = 'character';
-        });
-
-        this._fontDescription = fontDescription;
         this._setCharacter(character);
-
-        this._copyRevealerTimeoutId = 0;
     }
 
     _finishSearch(result) {
-        let children = this._related_listbox.get_children();
-        for (let index in children)
-            this._related_listbox.remove(children[index]);
+        let children = this._relatedListbox.get_first_child();
+        while (children !== null) {
+            let nextChild = children.get_next_sibling();
+            if (nextChild === null) {
+                this._relatedListbox.remove(children);
+                break;
+            }
+
+            this._relatedListbox.remove(nextChild);
+        }
 
         for (let index = 0; index < result.len; index++) {
             let uc = Gc.search_result_get(result, index);
@@ -72,30 +67,24 @@ var CharacterDialog = GObject.registerClass({
             if (name === null)
                 continue;
 
-            let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL });
-
-            let characterLabel = new Gtk.Label({ label: uc,
+            let row = new Adw.ActionRow();
+            row.set_title(Util.capitalize(name));
+            row.add_prefix(new Gtk.Label({
+                label: uc,
                 valign: Gtk.Align.CENTER,
                 halign: Gtk.Align.CENTER,
-                width_request: 45 });
-            characterLabel.add_css_class('character');
-            hbox.pack_start(characterLabel, false, false, 2);
-
-            let nameLabel = new Gtk.Label({ label: Util.capitalize(name),
-                halign: Gtk.Align.START,
-                ellipsize: Pango.EllipsizeMode.END });
-            hbox.pack_start(nameLabel, true, true, 0);
-
-            let row = new Gtk.ListBoxRow();
-            row._character = uc;
-            row.add(hbox);
-            row.show_all();
-
-            this._related_listbox.add(row);
+                width_request: 45,
+            }));
+            let gesture = new Gtk.GestureClick();
+            gesture.connect('pressed', () => {
+                this._setCharacter(uc);
+                this._seeCharacter();
+            });
+            row.add_controller(gesture);
+            row.set_activatable(true);
+            this._relatedListbox.append(row);
         }
-
-        this._relatedButton.visible =
-            this._related_listbox.get_children().length > 0;
+        this._seeAlsoRow.visible = result.len > 0;
     }
 
     _setCharacter(uc) {
@@ -108,30 +97,27 @@ var CharacterDialog = GObject.registerClass({
         if (name !== null)
             name = Util.capitalize(name);
         else
-            name = _('Unicode U+%04s').format(codePointHex);
-
+            name = 'U+%04s'.format(codePointHex);
 
-        let headerBar = this.get_header_bar();
-        headerBar.title = name;
+        this._windowTitle.title = name;
+        this._characterLabel.label = this._character;
+        this._detailLabel.label = 'U+%04s'.format(codePointHex);
 
-        this._character_label.override_font(this._fontDescription);
-        this._character_label.label = this._character;
+        let pangoContext = this._characterLabel.get_pango_context();
+        pangoContext.set_font_description(this._fontDescription);
 
-        var pangoContext = this._character_label.get_pango_context();
         var pangoLayout = Pango.Layout.new(pangoContext);
         pangoLayout.set_text(this._character, -1);
         if (pangoLayout.get_unknown_glyphs_count() === 0) {
-            this._character_stack.visible_child_name = 'character';
+            this._characterStack.visible_child_name = 'character';
         } else {
             var fontFamily = this._fontDescription.get_family();
-            this._missing_label.label =
+            this._missingLabel.label =
                 // TRANSLATORS: the first variable is a character, the second is a font
                 _('%s is not included in %s').format(name, fontFamily);
-            this._character_stack.visible_child_name = 'missing';
+            this._characterStack.visible_child_name = 'missing';
         }
 
-        this._detail_label.label = _('Unicode U+%04s').format(codePointHex);
-
         this._cancellable.cancel();
         this._cancellable.reset();
         let criteria = Gc.SearchCriteria.new_related(this._character);
@@ -148,54 +134,30 @@ var CharacterDialog = GObject.registerClass({
                 }
             });
 
-        this._relatedButton.active = false;
-        this._main_stack.visible_child_name = 'character';
-        this._main_stack.show_all();
+        this._seeAlsoRow.visible = false;
     }
 
-    _hideCopyRevealer() {
-        if (this._copyRevealerTimeoutId > 0) {
-            GLib.source_remove(this._copyRevealerTimeoutId);
-            this._copyRevealerTimeoutId = 0;
-            this._copy_revealer.set_reveal_child(false);
-        }
+    _seeMore() {
+        this._revealer.reveal_child = true;
+        this._mainStack.visible_child_name = 'related';
     }
 
-    _clipboardOwnerChanged(clipboard) {
-        let text = clipboard.wait_for_text();
-        if (text !== this._character)
-            this._hideCopyRevealer();
+    _seeCharacter() {
+        this._revealer.reveal_child = false;
+        this._mainStack.visible_child_name = 'character';
     }
 
     _copyCharacter() {
-        if (this._clipboard === null) {
-            this._clipboard = Gc.gtk_clipboard_get();
-            let clipboardOwnerChanged =
-                this._clipboard.connect('owner-change', clipboard => this._clipboardOwnerChanged(clipboard));
-            this.connect('destroy', () => this._clipboard.disconnect(clipboardOwnerChanged));
-        }
-        this._clipboard.set_text(this._character, -1);
+        let display = Gdk.Display.get_default();
+        let clipboard = display.get_clipboard();
+
+        clipboard.set(this._character);
         this.emit('character-copied', this._character);
 
-        // Show a feedback message with a revealer.  The message is
-        // hidden after 2 seconds, or when another client set a
-        // different text to clipboard.
-        this._hideCopyRevealer();
-        this._copy_revealer.set_reveal_child(true);
-        this._copyRevealerTimeoutId =
-            GLib.timeout_add(GLib.PRIORITY_DEFAULT, 2000, () => this._hideCopyRevealer());
-        this.connect('destroy', () => {
-            if (this._copyRevealerTimeoutId > 0)
-                GLib.source_remove(this._copyRevealerTimeoutId);
+        const toast = new Adw.Toast({
+            title: _('Character copied to clipboard'),
+            timeout: 2,
         });
-    }
-
-    _handleRowSelected(listBox, row) {
-        if (row !== null) {
-            this._setCharacter(row._character);
-            let toplevel = this.get_transient_for();
-            let action = toplevel.lookup_action('character');
-            action.activate(new GLib.Variant('s', row._character));
-        }
+        this._toastOverlay.add_toast(toast);
     }
 });


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