[geary/mjog/mail-merge-plugin: 66/72] Plugin.Actionable: Support specifying icons




commit 44b62ed89c7d333bf232bae024c2d570fd856e72
Author: Michael Gratton <mike vee net>
Date:   Fri Aug 14 16:02:42 2020 +1000

    Plugin.Actionable: Support specifying icons
    
    Add new ctor to `Actionable` to allow specifying an icon name but
    keeping the class immutable. Add support for displaying icon in
    `Plugin.InfoBar` buttons by implementing support for it
    `Components.InfoBar`. Also support updating the primary button when
    the plugin's primary button changes.

 src/client/components/components-info-bar.vala | 52 ++++++++++++++++++++------
 src/client/plugin/plugin-actionable.vala       | 21 +++++++++++
 2 files changed, 62 insertions(+), 11 deletions(-)
---
diff --git a/src/client/components/components-info-bar.vala b/src/client/components/components-info-bar.vala
index a6e1d4b6b..05124c009 100644
--- a/src/client/components/components-info-bar.vala
+++ b/src/client/components/components-info-bar.vala
@@ -28,6 +28,8 @@ public class Components.InfoBar : Gtk.InfoBar {
 
 
     private Plugin.InfoBar? plugin = null;
+    private string? plugin_action_group_name = null;
+    private Gtk.Button? plugin_primary_button = null;
 
 
     /**
@@ -80,6 +82,7 @@ public class Components.InfoBar : Gtk.InfoBar {
                               int priority) {
         this(plugin.status, plugin.description);
         this.plugin = plugin;
+        this.plugin_action_group_name = action_group_name;
         this.show_close_button = plugin.show_close_button;
 
         plugin.notify["status"].connect(
@@ -88,16 +91,17 @@ public class Components.InfoBar : Gtk.InfoBar {
         plugin.notify["description"].connect(
             () => { this.description.label = plugin.description; }
         );
+        plugin.notify["primary-button"].connect(
+            () => { this.update_plugin_primary_button(); }
+        );
 
         var secondaries = plugin.secondary_buttons.bidir_list_iterator();
         bool has_prev = secondaries.last();
         while (has_prev) {
-            add_plugin_button(secondaries.get(), action_group_name);
+            get_action_area().add(new_plugin_button(secondaries.get()));
             has_prev = secondaries.previous();
         }
-        if (plugin.primary_button != null) {
-            add_plugin_button(plugin.primary_button, action_group_name);
-        }
+        update_plugin_primary_button();
 
         set_data<int>(InfoBarStack.PRIORITY_QUEUE_KEY, priority);
 
@@ -122,14 +126,40 @@ public class Components.InfoBar : Gtk.InfoBar {
         return (Gtk.Box) base.get_action_area();
     }
 
-    private void add_plugin_button(Plugin.Actionable plugin,
-                                   string action_group_name) {
-        var gtk = new Gtk.Button.with_label(plugin.label);
-        gtk.set_action_name(action_group_name + "." + plugin.action.name);
-        if (plugin.action_target != null) {
-            gtk.set_action_target_value(plugin.action_target);
+    private void update_plugin_primary_button() {
+        Gtk.Button? new_button = null;
+        if (this.plugin != null && this.plugin.primary_button != null) {
+            new_button = new_plugin_button(this.plugin.primary_button);
+        }
+        if (this.plugin_primary_button != null) {
+            get_action_area().remove(plugin_primary_button);
+        }
+        if (new_button != null) {
+            get_action_area().add(new_button);
+        }
+        this.plugin_primary_button = new_button;
+    }
+
+    private Gtk.Button new_plugin_button(Plugin.Actionable ui) {
+        Gtk.Button? button = null;
+        if (ui.icon_name == null) {
+            button = new Gtk.Button.with_label(ui.label);
+        } else {
+            var icon = new Gtk.Image.from_icon_name(
+                ui.icon_name, Gtk.IconSize.BUTTON
+            );
+            button = new Gtk.Button();
+            button.add(icon);
+            button.tooltip_text = ui.label;
+        }
+        button.set_action_name(
+            this.plugin_action_group_name + "." + ui.action.name
+        );
+        if (ui.action_target != null) {
+            button.set_action_target_value(ui.action_target);
         }
-        get_action_area().add(gtk);
+        button.show_all();
+        return button;
     }
 
 }
diff --git a/src/client/plugin/plugin-actionable.vala b/src/client/plugin/plugin-actionable.vala
index 2d6f48b30..850ea9253 100644
--- a/src/client/plugin/plugin-actionable.vala
+++ b/src/client/plugin/plugin-actionable.vala
@@ -25,6 +25,16 @@ public class Plugin.Actionable : Geary.BaseObject {
      */
     public string label { get; private set; }
 
+    /**
+     * The name of an icon from the current icon theme to display.
+     *
+     * How and if the image displayed depends on the context and
+     * implementation. When used for a button, this may be displayed
+     * instead of {@link label}, for menu items it may not be
+     * displayed at all.
+     */
+    public string? icon_name { get; private set; default = null; }
+
     /** The action to be invoked when the actionable is activated. */
     public GLib.Action action { get; private set; }
 
@@ -40,4 +50,15 @@ public class Plugin.Actionable : Geary.BaseObject {
         this.action_target = action_target;
     }
 
+    /** Constructs a new actionable with a text label and icon name. */
+    public Actionable.with_icon(string label,
+                                string icon_name,
+                                GLib.Action action,
+                                GLib.Variant? action_target = null) {
+        this.label = label;
+        this.icon_name = icon_name;
+        this.action = action;
+        this.action_target = action_target;
+    }
+
 }


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