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.
This commit is contained in:
Michael Gratton 2020-08-14 16:02:42 +10:00 committed by Michael James Gratton
parent 30e5e5bedc
commit 44b62ed89c
2 changed files with 62 additions and 11 deletions

View file

@ -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);
}
get_action_area().add(gtk);
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);
}
button.show_all();
return button;
}
}

View file

@ -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;
}
}