[geary/wip/765516-gtk-widget-conversation-viewer: 68/142] Update message header layout, use GtkFlowBox for addresses.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/765516-gtk-widget-conversation-viewer: 68/142] Update message header layout, use GtkFlowBox for addresses.
- Date: Fri, 2 Sep 2016 04:31:20 +0000 (UTC)
commit 686f91b0e4a65b3bd3818c2790fed5327e52e7f0
Author: Michael James Gratton <mike vee net>
Date: Fri Jun 10 10:56:18 2016 -0700
Update message header layout, use GtkFlowBox for addresses.
This takes some inspiration from the GNOME Mail mockups.
* src/client/components/main-window.vala (MainWindow::set_styling): Work
around GtkFlowBoxChild padding issue.
* src/client/conversation-viewer/conversation-message.vala
(ConversationMessage): Updated to populate new header labels, add
addresses to GtkFlowBoxes.
* ui/conversation-message.ui: Make date always visible and
right-aligned. Remove label for sender address. Use GtkFlowBoxes for
sender/to/cc/bcc.
.../conversation-viewer/conversation-message.vala | 124 ++++++---
src/client/util/util-gtk.vala | 13 +
ui/conversation-message.ui | 289 ++++++++-----------
ui/geary.css | 6 +-
4 files changed, 226 insertions(+), 206 deletions(-)
---
diff --git a/src/client/conversation-viewer/conversation-message.vala
b/src/client/conversation-viewer/conversation-message.vala
index 880ea46..da80c3c 100644
--- a/src/client/conversation-viewer/conversation-message.vala
+++ b/src/client/conversation-viewer/conversation-message.vala
@@ -79,26 +79,28 @@ public class ConversationMessage : Gtk.Box {
[GtkChild]
private Gtk.Image preview_avatar;
[GtkChild]
- private Gtk.Label from_preview;
+ private Gtk.Label preview_from;
[GtkChild]
- private Gtk.Label body_preview;
+ private Gtk.Label preview_date;
+ [GtkChild]
+ private Gtk.Label preview_body;
[GtkChild]
private Gtk.Revealer header_revealer;
[GtkChild]
private Gtk.Image header_avatar;
[GtkChild]
- private Gtk.Box from_header;
+ private Gtk.FlowBox from;
+ [GtkChild]
+ private Gtk.Label subject;
+ [GtkChild]
+ private Gtk.Label date;
[GtkChild]
private Gtk.Box to_header;
[GtkChild]
private Gtk.Box cc_header;
[GtkChild]
private Gtk.Box bcc_header;
- [GtkChild]
- private Gtk.Box subject_header;
- [GtkChild]
- private Gtk.Box date_header;
[GtkChild]
private Gtk.Revealer body_revealer;
@@ -201,35 +203,30 @@ public class ConversationMessage : Gtk.Box {
// Preview headers
- from_preview.set_text(format_addresses(message.from));
+ string? message_date = null;
+ if (message.date != null) {
+ Date.ClockFormat clock_format =
+ GearyApplication.instance.config.clock_format;
+ message_date = Date.pretty_print(message.date.value, clock_format);
+ }
+ preview_from.set_markup(format_sender_preview(message.from));
+ preview_date.set_text(message_date ?? "");
string preview_str = message.get_preview();
preview_str = Geary.String.reduce_whitespace(preview_str);
- body_preview.set_text(preview_str);
+ preview_body.set_text(preview_str);
// Full headers
- set_header_text(from_header, format_addresses(message.from));
- if (message.to != null) {
- set_header_text(to_header, format_addresses(message.to));
- }
- if (message.cc != null) {
- set_header_text(cc_header, format_addresses(message.cc));
- }
- if (message.bcc != null) {
- set_header_text(bcc_header, format_addresses(message.bcc));
- }
+ set_flowbox_addresses(from, message.from, "bold");
+ date.set_text(message_date ?? "");
if (message.subject != null) {
- set_header_text(subject_header, message.subject.value);
- }
- if (message.date != null) {
- Date.ClockFormat clock_format =
- GearyApplication.instance.config.clock_format;
- set_header_text(
- date_header,
- Date.pretty_print_verbose(message.date.value, clock_format)
- );
+ subject.set_text(message.subject.value);
+ subject.set_visible(true);
}
+ set_header_addresses(to_header, message.to);
+ set_header_addresses(cc_header, message.cc);
+ set_header_addresses(bcc_header, message.bcc);
// Web view
@@ -376,26 +373,77 @@ public class ConversationMessage : Gtk.Box {
}
}
- // Appends email address fields to the header.
- private string format_addresses(Geary.RFC822.MailboxAddresses? addresses) {
+ private void set_header_addresses(Gtk.Box header,
+ Geary.RFC822.MailboxAddresses? addresses) {
+ if (addresses != null && addresses.size > 0) {
+ Gtk.FlowBox box = header.get_children().nth(1).data as Gtk.FlowBox;
+ if (box != null) {
+ set_flowbox_addresses(box, addresses);
+ }
+ header.set_visible(true);
+ }
+ }
+
+ private void set_flowbox_addresses(Gtk.FlowBox address_box,
+ Geary.RFC822.MailboxAddresses? addresses,
+ string weight = "normal") {
+ string dim_color = GtkUtil.pango_color_from_theme(
+ address_box.get_style_context(), "insensitive_fg_color"
+ );
+ foreach (Geary.RFC822.MailboxAddress addr in addresses) {
+ Gtk.Label label = new Gtk.Label(null);
+ //label.set_halign(Gtk.Align.START);
+ //label.set_valign(Gtk.Align.BASELINE);
+ //label.set_ellipsize(Pango.EllipsizeMode.END);
+ //label.set_xalign(0.0f);
+
+ string name = Geary.HTML.escape_markup(addr.name);
+ string address = Geary.HTML.escape_markup(addr.address);
+ if (!Geary.String.is_empty(addr.name) && name != address) {
+ label.set_markup(
+ "<span weight=\"%s\">%s</span> <span color=\"%s\">%s</span>"
+ .printf(weight, name, dim_color, address)
+ );
+ } else {
+ label.set_markup(
+ "<span weight=\"%s\">%s</span>".printf(weight, address)
+ );
+ }
+
+ Gtk.FlowBoxChild child = new Gtk.FlowBoxChild();
+ child.add(label);
+ child.set_halign(Gtk.Align.START);
+ //child.set_valign(Gtk.Align.START);
+ child.show_all();
+
+ address_box.add(child);
+ }
+ }
+
+ private string format_sender_preview(Geary.RFC822.MailboxAddresses? addresses) {
+ string dim_color = GtkUtil.pango_color_from_theme(
+ get_style_context(), "insensitive_fg_color"
+ );
int i = 0;
string value = "";
Gee.List<Geary.RFC822.MailboxAddress> list = addresses.get_all();
- foreach (Geary.RFC822.MailboxAddress a in list) {
- value += a.to_string();
+ foreach (Geary.RFC822.MailboxAddress addr in list) {
+ string address = Geary.HTML.escape_markup(addr.address);
+ if (!Geary.String.is_empty(addr.name)) {
+ string name = Geary.HTML.escape_markup(addr.name);
+ value += "<span weight=\"bold\">%s</span> <span color=\"%s\">%s</span>".printf(
+ name, dim_color, address
+ );
+ } else {
+ value += "<span weight=\"bold\">%s</span>".printf(address);
+ }
if (++i < list.size)
value += ", ";
}
-
return value;
}
- private static void set_header_text(Gtk.Box header, string text) {
- ((Gtk.Label) header.get_children().nth(1).data).set_text(text);
- header.set_visible(true);
- }
-
private void set_avatar(uint8[] image_data) {
Gdk.Pixbuf avatar = null;
Gdk.PixbufLoader loader = new Gdk.PixbufLoader();
diff --git a/src/client/util/util-gtk.vala b/src/client/util/util-gtk.vala
index e60e7a9..6ef28c7 100644
--- a/src/client/util/util-gtk.vala
+++ b/src/client/util/util-gtk.vala
@@ -121,6 +121,19 @@ void apply_style(Gtk.Widget widget, string style) {
}
/**
+ * Returns a Pango markup-compatible string for a GTK+ CSS theme color name.
+ */
+string pango_color_from_theme(Gtk.StyleContext style, string name) {
+ Gdk.RGBA colour = new Gdk.RGBA();
+ style.lookup_color(name, out colour);
+ return "#%02x%02x%02x".printf(
+ (uint) (256.0 * colour.red),
+ (uint) (256.0 * colour.green),
+ (uint) (256.0 * colour.blue)
+ );
+}
+
+/**
* This is not bound in Vala < 0.26.
*/
[CCode(cname = "g_binding_unbind")]
diff --git a/ui/conversation-message.ui b/ui/conversation-message.ui
index 1028d0c..8ac9c14 100644
--- a/ui/conversation-message.ui
+++ b/ui/conversation-message.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
- <requires lib="gtk+" version="3.12"/>
+ <requires lib="gtk+" version="3.14"/>
<template class="ConversationMessage" parent="GtkBox">
<property name="name">ConversationMessage</property>
<property name="visible">True</property>
@@ -45,20 +45,50 @@
</packing>
</child>
<child>
- <object class="GtkBox">
+ <object class="GtkBox" id="preview_bod">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
- <object class="GtkLabel" id="from_preview">
+ <object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">From <email></property>
- <property name="ellipsize">end</property>
- <style>
- <class name="header-value"/>
- </style>
+ <child>
+ <object class="GtkLabel" id="preview_from">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">From <email></property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="header-value"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="preview_date">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">baseline</property>
+ <property name="margin_top">3</property>
+ <property name="label" translatable="yes">1/1/1970 </property>
+ <property name="selectable">True</property>
+ <property name="ellipsize">end</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">True</property>
@@ -67,12 +97,13 @@
</packing>
</child>
<child>
- <object class="GtkLabel" id="body_preview">
+ <object class="GtkLabel" id="preview_body">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Preview body text.</property>
<property name="ellipsize">end</property>
+ <property name="xalign">0</property>
<style>
<class name="preview-value"/>
</style>
@@ -85,7 +116,7 @@
</child>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
@@ -126,7 +157,7 @@
</packing>
</child>
<child>
- <object class="GtkBox" id="header_box">
+ <object class="GtkBox" id="headers">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
@@ -134,121 +165,101 @@
<object class="GtkBox" id="from_header">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="baseline_position">top</property>
<child>
- <object class="GtkLabel" id="from_label">
+ <object class="GtkFlowBox" id="from">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">From:</property>
- <property name="xalign">1</property>
- <style>
- <class name="header-label"/>
- <class name="dim-label"/>
- </style>
+ <property name="can_focus">True</property>
+ <property name="valign">baseline</property>
+ <property name="column_spacing">2</property>
+ <property name="min_children_per_line">1</property>
+ <property name="max_children_per_line">4</property>
+ <property name="selection_mode">none</property>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="from_text">
+ <object class="GtkLabel" id="date">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="label" translatable="yes">From <email></property>
+ <property name="valign">baseline</property>
+ <property name="label" translatable="yes">1/1/1970 </property>
<property name="selectable">True</property>
<property name="ellipsize">end</property>
+ <property name="xalign">1</property>
<style>
- <class name="header-value"/>
+ <class name="geary-header-label"/>
</style>
</object>
<packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkBox" id="to_header">
+ <object class="GtkLabel" id="subject">
+ <property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <object class="GtkLabel" id="to_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">To:</property>
- <property name="xalign">1</property>
- <style>
- <class name="header-label"/>
- <class name="dim-label"/>
- </style>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="to_text">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">To <email></property>
- <property name="selectable">True</property>
- <property name="ellipsize">end</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="halign">start</property>
+ <property name="valign">baseline</property>
+ <property name="label" translatable="yes">Subject</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ <property name="xalign">0</property>
<style>
- <class name="empty"/>
+ <class name="geary-header-label"/>
</style>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
- <object class="GtkBox" id="cc_header">
+ <object class="GtkBox" id="to_header">
<property name="can_focus">False</property>
+ <property name="baseline_position">top</property>
<child>
- <object class="GtkLabel" id="cc_label">
+ <object class="GtkLabel" id="to_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">Cc:</property>
- <property name="xalign">1</property>
+ <property name="label" translatable="yes">To:</property>
+ <property name="yalign">0</property>
<style>
- <class name="header-label"/>
<class name="dim-label"/>
+ <class name="geary-header-label"/>
</style>
</object>
<packing>
<property name="expand">False</property>
- <property name="fill">True</property>
+ <property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="cc_text">
+ <object class="GtkFlowBox" id="to">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">CC <email></property>
- <property name="selectable">True</property>
- <property name="ellipsize">end</property>
+ <property name="can_focus">True</property>
+ <property name="valign">start</property>
+ <property name="hexpand">False</property>
+ <property name="column_spacing">2</property>
+ <property name="min_children_per_line">1</property>
+ <property name="max_children_per_line">4</property>
+ <property name="selection_mode">none</property>
</object>
<packing>
<property name="expand">True</property>
@@ -256,44 +267,44 @@
<property name="position">1</property>
</packing>
</child>
- <style>
- <class name="empty"/>
- </style>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
- <object class="GtkBox" id="bcc_header">
+ <object class="GtkBox" id="cc_header">
<property name="can_focus">False</property>
+ <property name="baseline_position">top</property>
<child>
- <object class="GtkLabel" id="bcc_label">
+ <object class="GtkLabel" id="cc_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">Bcc:</property>
- <property name="xalign">1</property>
+ <property name="label" translatable="yes">Cc:</property>
+ <property name="yalign">0</property>
<style>
- <class name="header-label"/>
<class name="dim-label"/>
+ <class name="geary-header-label"/>
</style>
</object>
<packing>
<property name="expand">False</property>
- <property name="fill">True</property>
+ <property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="bcc_text">
+ <object class="GtkFlowBox" id="cc">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">BCC <email></property>
- <property name="selectable">True</property>
- <property name="ellipsize">end</property>
+ <property name="can_focus">True</property>
+ <property name="valign">start</property>
+ <property name="hexpand">False</property>
+ <property name="column_spacing">2</property>
+ <property name="min_children_per_line">1</property>
+ <property name="max_children_per_line">4</property>
+ <property name="selection_mode">none</property>
</object>
<packing>
<property name="expand">True</property>
@@ -301,44 +312,44 @@
<property name="position">1</property>
</packing>
</child>
- <style>
- <class name="empty"/>
- </style>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
- <object class="GtkBox" id="subject_header">
+ <object class="GtkBox" id="bcc_header">
<property name="can_focus">False</property>
+ <property name="baseline_position">top</property>
<child>
- <object class="GtkLabel" id="subject_label">
+ <object class="GtkLabel" id="bcc_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">Subject:</property>
- <property name="xalign">1</property>
+ <property name="label" translatable="yes">Bcc:</property>
+ <property name="yalign">0</property>
<style>
- <class name="header-label"/>
<class name="dim-label"/>
+ <class name="geary-header-label"/>
</style>
</object>
<packing>
<property name="expand">False</property>
- <property name="fill">True</property>
+ <property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="subject_text">
+ <object class="GtkFlowBox" id="bcc">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Subject</property>
- <property name="selectable">True</property>
- <property name="ellipsize">end</property>
+ <property name="can_focus">True</property>
+ <property name="valign">start</property>
+ <property name="hexpand">False</property>
+ <property name="column_spacing">2</property>
+ <property name="min_children_per_line">2</property>
+ <property name="max_children_per_line">4</property>
+ <property name="selection_mode">none</property>
</object>
<packing>
<property name="expand">True</property>
@@ -346,64 +357,19 @@
<property name="position">1</property>
</packing>
</child>
- <style>
- <class name="empty"/>
- </style>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
- <child>
- <object class="GtkBox" id="date_header">
- <property name="can_focus">False</property>
- <child>
- <object class="GtkLabel" id="date_label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Date:</property>
- <property name="xalign">1</property>
- <style>
- <class name="header-label"/>
- <class name="dim-label"/>
- </style>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="date_text">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">1/1/1970 </property>
- <property name="selectable">True</property>
- <property name="ellipsize">end</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <style>
- <class name="empty"/>
- </style>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">5</property>
- </packing>
- </child>
+ <style>
+ <class name="geary-headers"/>
+ </style>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
@@ -575,17 +541,6 @@
</packing>
</child>
</template>
- <object class="GtkSizeGroup" id="header_labels_sizegroup">
- <property name="ignore_hidden">True</property>
- <widgets>
- <widget name="from_label"/>
- <widget name="to_label"/>
- <widget name="cc_label"/>
- <widget name="bcc_label"/>
- <widget name="subject_label"/>
- <widget name="date_label"/>
- </widgets>
- </object>
<object class="GtkPopover" id="link_popover">
<property name="can_focus">False</property>
<property name="relative_to">body_box</property>
diff --git a/ui/geary.css b/ui/geary.css
index 2482509..5996f27 100644
--- a/ui/geary.css
+++ b/ui/geary.css
@@ -89,9 +89,13 @@ row.geary-folder-popover-list-row > label {
#ConversationMessage {
padding: 12px;
}
-#ConversationMessage .header-label {
+#ConversationMessage .geary-header-label {
margin-right: 6px;
}
+#ConversationMessage .geary-headers flowboxchild {
+ margin: 0;
+ padding: 0;
+}
#ConversationMessage separator {
margin: 12px 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]