compnents-info-bar: use custom infobar so that the buttons reflow
This commit is contained in:
parent
ed3a451434
commit
3530a804a1
9 changed files with 246 additions and 40 deletions
|
|
@ -460,6 +460,7 @@ ui/components-attachment-view.ui
|
|||
ui/components-conversation-actions.ui
|
||||
ui/components-conversation-action-bar.ui
|
||||
ui/components-in-app-notification.ui
|
||||
ui/components-info-bar.ui
|
||||
ui/components-inspector-error-view.ui
|
||||
ui/components-inspector-log-view.ui
|
||||
ui/components-inspector.ui
|
||||
|
|
|
|||
|
|
@ -889,7 +889,7 @@ public class Application.MainWindow :
|
|||
}
|
||||
|
||||
/** Displays an infobar in the window. */
|
||||
public void show_info_bar(Gtk.InfoBar info_bar) {
|
||||
public void show_info_bar(Components.InfoBar info_bar) {
|
||||
if (!this.info_bars.has_current) {
|
||||
this.info_bars.add(info_bar);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* A stack-like widget for displaying Gtk InfoBar widgets.
|
||||
* A stack-like widget for displaying Components.InfoBar widgets.
|
||||
*
|
||||
* The stack ensures only one info bar is shown at once, shows a frame
|
||||
* around the info bar, and manages revealing and hiding itself and
|
||||
|
|
@ -40,7 +40,7 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
|||
}
|
||||
|
||||
|
||||
private class SingletonQueue : Gee.AbstractQueue<Gtk.InfoBar> {
|
||||
private class SingletonQueue : Gee.AbstractQueue<Components.InfoBar> {
|
||||
|
||||
public override bool read_only {
|
||||
get { return false; }
|
||||
|
|
@ -62,10 +62,10 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
|||
get { return (this.element != null) ? 0 : 1; }
|
||||
}
|
||||
|
||||
private Gtk.InfoBar? element = null;
|
||||
private Components.InfoBar? element = null;
|
||||
|
||||
|
||||
public override bool add(Gtk.InfoBar to_add) {
|
||||
public override bool add(Components.InfoBar to_add) {
|
||||
var added = false;
|
||||
if (this.element != to_add) {
|
||||
this.element = to_add;
|
||||
|
|
@ -78,20 +78,20 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
|||
this.element = null;
|
||||
}
|
||||
|
||||
public override bool contains(Gtk.InfoBar other) {
|
||||
public override bool contains(Components.InfoBar other) {
|
||||
return (this.element == other);
|
||||
}
|
||||
|
||||
public override Gee.Iterator<Gtk.InfoBar> iterator() {
|
||||
public override Gee.Iterator<Components.InfoBar> iterator() {
|
||||
// This sucks but it won't ever be used so oh well
|
||||
return (
|
||||
this.element == null
|
||||
? Gee.Collection.empty<Gtk.InfoBar>().iterator()
|
||||
? Gee.Collection.empty<Components.InfoBar>().iterator()
|
||||
: Geary.Collection.single(this.element).iterator()
|
||||
);
|
||||
}
|
||||
|
||||
public override bool remove(Gtk.InfoBar to_remove) {
|
||||
public override bool remove(Components.InfoBar to_remove) {
|
||||
var removed = false;
|
||||
if (this.element == to_remove) {
|
||||
this.element = null;
|
||||
|
|
@ -100,11 +100,11 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
|||
return removed;
|
||||
}
|
||||
|
||||
public override Gtk.InfoBar peek() {
|
||||
public override Components.InfoBar peek() {
|
||||
return this.element;
|
||||
}
|
||||
|
||||
public override Gtk.InfoBar poll() {
|
||||
public override Components.InfoBar poll() {
|
||||
var element = this.element;
|
||||
this.element = null;
|
||||
return element;
|
||||
|
|
@ -126,7 +126,7 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
|||
* @see algorithm
|
||||
* @see StackType.PRIORITY_QUEUE
|
||||
*/
|
||||
public static int priority_queue_comparator(Gtk.InfoBar a, Gtk.InfoBar b) {
|
||||
public static int priority_queue_comparator(Components.InfoBar a, Components.InfoBar b) {
|
||||
return (
|
||||
b.get_data<int>(PRIORITY_QUEUE_KEY) -
|
||||
a.get_data<int>(PRIORITY_QUEUE_KEY)
|
||||
|
|
@ -150,11 +150,11 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
|||
}
|
||||
|
||||
/** Returns the currently displayed info bar, if any. */
|
||||
public Gtk.InfoBar? current_info_bar {
|
||||
get { return get_child() as Gtk.InfoBar; }
|
||||
public Components.InfoBar? current_info_bar {
|
||||
get { return get_child() as Components.InfoBar; }
|
||||
}
|
||||
|
||||
private Gee.Queue<Gtk.InfoBar> available;
|
||||
private Gee.Queue<Components.InfoBar> available;
|
||||
private int last_allocated_height = 0;
|
||||
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
|||
* stack constructed, the info bar may or may not be revealed
|
||||
* immediately.
|
||||
*/
|
||||
public new void add(Gtk.InfoBar to_add) {
|
||||
public new void add(Components.InfoBar to_add) {
|
||||
if (this.available.offer(to_add)) {
|
||||
update();
|
||||
}
|
||||
|
|
@ -188,7 +188,7 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
|||
* replaced with the next info bar added. If the only info bar
|
||||
* present is removed, the stack also hides itself.
|
||||
*/
|
||||
public new void remove(Gtk.InfoBar to_remove) {
|
||||
public new void remove(Components.InfoBar to_remove) {
|
||||
if (this.available.remove(to_remove)) {
|
||||
update();
|
||||
}
|
||||
|
|
@ -234,7 +234,7 @@ public class Components.InfoBarStack : Gtk.Frame, Geary.BaseInterface {
|
|||
this.available = new SingletonQueue();
|
||||
break;
|
||||
case PRIORITY_QUEUE:
|
||||
this.available = new Gee.PriorityQueue<Gtk.InfoBar>(
|
||||
this.available = new Gee.PriorityQueue<Components.InfoBar>(
|
||||
InfoBarStack.priority_queue_comparator
|
||||
);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
/**
|
||||
* A standard info bar widget with status message and description.
|
||||
*/
|
||||
public class Components.InfoBar : Gtk.InfoBar {
|
||||
|
||||
|
||||
[GtkTemplate (ui = "/org/gnome/Geary/components-info-bar.ui")]
|
||||
public class Components.InfoBar : Gtk.Box {
|
||||
public signal void response(int response_id);
|
||||
/**
|
||||
* A short, human-readable status message.
|
||||
*
|
||||
|
|
@ -26,11 +26,37 @@ public class Components.InfoBar : Gtk.InfoBar {
|
|||
*/
|
||||
public Gtk.Label? description { get; private set; default = null; }
|
||||
|
||||
public bool show_close_button { get; set; default = false;}
|
||||
public bool revealed { get; set; }
|
||||
private Gtk.MessageType _message_type = Gtk.MessageType.OTHER;
|
||||
public Gtk.MessageType message_type {
|
||||
get {
|
||||
return _message_type;
|
||||
}
|
||||
set {
|
||||
_set_message_type(value);
|
||||
}
|
||||
}
|
||||
|
||||
private Plugin.InfoBar? plugin = null;
|
||||
private string? plugin_action_group_name = null;
|
||||
private Gtk.Button? plugin_primary_button = null;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Revealer revealer;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Box action_area;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Box content_area;
|
||||
|
||||
[GtkChild]
|
||||
private Gtk.Button close_button;
|
||||
|
||||
static construct {
|
||||
set_css_name("infobar");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new info bar.
|
||||
|
|
@ -43,6 +69,19 @@ public class Components.InfoBar : Gtk.InfoBar {
|
|||
public InfoBar(string status, string? description = null) {
|
||||
this.status = new Gtk.Label(status);
|
||||
this.status.halign = START;
|
||||
this.status.xalign = 0;
|
||||
|
||||
_set_message_type(Gtk.MessageType.INFO);
|
||||
|
||||
this.bind_property("revealed",
|
||||
this.revealer,
|
||||
"reveal-child",
|
||||
BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
|
||||
|
||||
this.bind_property("show-close-button",
|
||||
this.close_button,
|
||||
"visible",
|
||||
BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
|
||||
|
||||
var attrs = new Pango.AttrList();
|
||||
attrs.change(Pango.attr_weight_new(BOLD));
|
||||
|
|
@ -57,11 +96,8 @@ public class Components.InfoBar : Gtk.InfoBar {
|
|||
this.description = new Gtk.Label(description);
|
||||
this.description.halign = START;
|
||||
this.description.valign = START;
|
||||
|
||||
// Set the description to be ellipsised and set and the
|
||||
// tool-tip to be the same, in case it is too long for the
|
||||
// info bar's width
|
||||
this.description.ellipsize = END;
|
||||
this.description.xalign = 0;
|
||||
this.description.wrap = true;
|
||||
this.description.tooltip_text = description;
|
||||
}
|
||||
|
||||
|
|
@ -85,15 +121,28 @@ public class Components.InfoBar : Gtk.InfoBar {
|
|||
this.plugin_action_group_name = action_group_name;
|
||||
this.show_close_button = plugin.show_close_button;
|
||||
|
||||
_message_type = Gtk.MessageType.OTHER;
|
||||
_set_message_type(Gtk.MessageType.INFO);
|
||||
|
||||
this.bind_property("revealed",
|
||||
this.revealer,
|
||||
"reveal-child",
|
||||
BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
|
||||
|
||||
this.bind_property("show-close-button",
|
||||
this.close_button,
|
||||
"visible",
|
||||
BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
|
||||
|
||||
plugin.notify["status"].connect(
|
||||
() => { this.status.label = plugin.status; }
|
||||
);
|
||||
);
|
||||
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();
|
||||
|
|
@ -108,11 +157,12 @@ public class Components.InfoBar : Gtk.InfoBar {
|
|||
show_all();
|
||||
}
|
||||
|
||||
/* {@inheritDoc} */
|
||||
public override void response(int response) {
|
||||
if (response == Gtk.ResponseType.CLOSE && this.plugin != null) {
|
||||
[GtkCallback]
|
||||
public void on_close_button_clicked() {
|
||||
if (this.plugin != null) {
|
||||
this.plugin.close_activated();
|
||||
}
|
||||
response(Gtk.ResponseType.CLOSE);
|
||||
}
|
||||
|
||||
/* {@inheritDoc} */
|
||||
|
|
@ -120,10 +170,22 @@ public class Components.InfoBar : Gtk.InfoBar {
|
|||
this.plugin = null;
|
||||
}
|
||||
|
||||
// GTK 3.24.16 fixed the binding for this, but that and the VAPI
|
||||
// change has yet to trickle down to common distros like F31
|
||||
public new Gtk.Box get_action_area() {
|
||||
return (Gtk.Box) base.get_action_area();
|
||||
public Gtk.Box get_action_area() {
|
||||
return this.action_area;
|
||||
}
|
||||
|
||||
public Gtk.Box get_content_area() {
|
||||
return this.content_area;
|
||||
}
|
||||
|
||||
public Gtk.Button add_button(string button_text, int response_id) {
|
||||
var button = new Gtk.Button.with_mnemonic(button_text);
|
||||
button.clicked.connect(() => {
|
||||
response(response_id);
|
||||
});
|
||||
get_action_area().add(button);
|
||||
button.visible = true;
|
||||
return button;
|
||||
}
|
||||
|
||||
private void update_plugin_primary_button() {
|
||||
|
|
@ -162,4 +224,59 @@ public class Components.InfoBar : Gtk.InfoBar {
|
|||
return button;
|
||||
}
|
||||
|
||||
private void _set_message_type(Gtk.MessageType message_type) {
|
||||
if (this._message_type != message_type) {
|
||||
Gtk.StyleContext context = this.get_style_context();
|
||||
const string[] type_class = {
|
||||
Gtk.STYLE_CLASS_INFO,
|
||||
Gtk.STYLE_CLASS_WARNING,
|
||||
Gtk.STYLE_CLASS_QUESTION,
|
||||
Gtk.STYLE_CLASS_ERROR,
|
||||
null
|
||||
};
|
||||
|
||||
if (type_class[this._message_type] != null)
|
||||
context.remove_class(type_class[this._message_type]);
|
||||
|
||||
this._message_type = message_type;
|
||||
|
||||
var atk_obj = this.get_accessible();
|
||||
if (atk_obj is Atk.Object) {
|
||||
string name = null;
|
||||
|
||||
atk_obj.set_role(Atk.Role.INFO_BAR);
|
||||
|
||||
switch (message_type) {
|
||||
case Gtk.MessageType.INFO:
|
||||
name = _("Information");
|
||||
break;
|
||||
|
||||
case Gtk.MessageType.QUESTION:
|
||||
name = _("Question");
|
||||
break;
|
||||
|
||||
case Gtk.MessageType.WARNING:
|
||||
name = _("Warning");
|
||||
break;
|
||||
|
||||
case Gtk.MessageType.ERROR:
|
||||
name = _("Error");
|
||||
break;
|
||||
|
||||
case Gtk.MessageType.OTHER:
|
||||
break;
|
||||
|
||||
default:
|
||||
warning("Unknown GtkMessageType %u", message_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (name != null)
|
||||
atk_obj.set_name(name);
|
||||
}
|
||||
|
||||
if (type_class[this._message_type] != null)
|
||||
context.add_class(type_class[this._message_type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -936,7 +936,7 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
|||
|
||||
/** Adds an info bar to the given email, if any. */
|
||||
public void add_email_info_bar(Geary.EmailIdentifier id,
|
||||
Gtk.InfoBar info_bar) {
|
||||
Components.InfoBar info_bar) {
|
||||
var row = this.email_rows.get(id);
|
||||
if (row != null) {
|
||||
row.view.primary_message.info_bars.add(info_bar);
|
||||
|
|
@ -945,7 +945,7 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
|||
|
||||
/** Adds an info bar to the given email, if any. */
|
||||
public void remove_email_info_bar(Geary.EmailIdentifier id,
|
||||
Gtk.InfoBar info_bar) {
|
||||
Components.InfoBar info_bar) {
|
||||
var row = this.email_rows.get(id);
|
||||
if (row != null) {
|
||||
row.view.primary_message.info_bars.remove(info_bar);
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
|||
[GtkChild]
|
||||
private Gtk.ProgressBar body_progress;
|
||||
|
||||
private Gtk.InfoBar? remote_images_info_bar = null;
|
||||
private Components.InfoBar? remote_images_info_bar = null;
|
||||
|
||||
private Gtk.Widget? body_placeholder = null;
|
||||
|
||||
|
|
@ -1460,7 +1460,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
|||
}
|
||||
}
|
||||
|
||||
private void on_remote_images_response(Gtk.InfoBar info_bar, int response_id) {
|
||||
private void on_remote_images_response(Components.InfoBar info_bar, int response_id) {
|
||||
switch (response_id) {
|
||||
case 1:
|
||||
// Show images for the message
|
||||
|
|
|
|||
83
ui/components-info-bar.ui
Normal file
83
ui/components-info-bar.ui
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<template class="ComponentsInfoBar" parent="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="revealer">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="transition_type">slide-down</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkFlowBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<property name="max_children_per_line">2</property>
|
||||
<property name="border-width">12</property>
|
||||
<child>
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="content_area">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">16</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child>
|
||||
<object class="GtkButtonBox" id="action_area">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<property name="spacing">6</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="close_button">
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin">6</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<signal name="clicked" handler="on_close_button_clicked" swapped="no"/>
|
||||
<style>
|
||||
<class name="titlebutton"/>
|
||||
<class name="close"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">window-close-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
|
|
@ -62,6 +62,10 @@ geary-conversation-viewer {
|
|||
border-right-width: 0;
|
||||
}
|
||||
|
||||
infobar flowboxchild {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* FolderPopover */
|
||||
|
||||
row.geary-folder-popover-list-row {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
<file compressed="true" preprocess="xml-stripblanks">components-conversation-action-bar.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-conversation-actions.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-in-app-notification.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-info-bar.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-inspector.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-inspector-error-view.ui</file>
|
||||
<file compressed="true" preprocess="xml-stripblanks">components-inspector-log-view.ui</file>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue