[geary/wip/765516-gtk-widget-conversation-viewer] Split up handling of emails and composers in conversation list box.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/765516-gtk-widget-conversation-viewer] Split up handling of emails and composers in conversation list box.
- Date: Sun, 25 Sep 2016 13:06:07 +0000 (UTC)
commit 55f981a9497b62fce33a307f068c7b22683d698e
Author: Michael James Gratton <mike vee net>
Date: Sun Sep 25 22:53:34 2016 +1000
Split up handling of emails and composers in conversation list box.
* src/client/conversation-viewer/conversation-listbox.vala: Add two
different listbox child row types, one for emails only and one for
composers only, with a common ConversationRow superclass. When a draft
composer is added, replace the draft email it is standing in for, and
replace it again when removed. Rename last_email_row to last_row and
make into a generic ConversationRow, only update it at the end of a
batch of changes.
.../conversation-viewer/conversation-listbox.vala | 245 +++++++++++--------
ui/geary.css | 4 +-
2 files changed, 144 insertions(+), 105 deletions(-)
---
diff --git a/src/client/conversation-viewer/conversation-listbox.vala
b/src/client/conversation-viewer/conversation-listbox.vala
index 37c802e..a077909 100644
--- a/src/client/conversation-viewer/conversation-listbox.vala
+++ b/src/client/conversation-viewer/conversation-listbox.vala
@@ -44,22 +44,59 @@ public class ConversationListBox : Gtk.ListBox {
private const int LOADING_TIMEOUT_MSEC = 150;
- // Custom class used to display ConversationEmail views in the
- // conversation listbox.
- private class EmailRow : Gtk.ListBoxRow {
+ // Base class for list rows it the list box
+ private abstract class ConversationRow : Gtk.ListBoxRow {
- private const string EXPANDED_CLASS = "geary-expanded";
+
+ protected const string EXPANDED_CLASS = "geary-expanded";
private const string LAST_CLASS = "geary-last";
- private const string MATCH_CLASS = "geary-match";
- // The email view for this row
- public ConversationEmail view { get; private set; }
- // The embedded composer for this row, if any
- public ComposerEmbed composer { get; private set; default = null; }
+ // The email being displayed by this row, if any
+ public Geary.Email? email { get; private set; default = null; }
// Is the row showing the email's message body or just headers?
- public bool is_expanded { get; private set; default = false; }
+ public bool is_expanded { get; protected set; default = false; }
+
+ // Designate this row as the last visible row in the
+ // conversation listbox, or not. See Bug 764710 and
+ // ::update_last_row() below.
+ internal bool is_last {
+ set { set_style_context_class(LAST_CLASS, value); }
+ }
+
+
+ public ConversationRow(Geary.Email? email) {
+ this.email = email;
+ }
+
+ // Request the row be expanded, if supported.
+ public virtual new void expand() {
+ // Not supported by default
+ }
+
+ // Request the row be collapsed, if supported.
+ public virtual void collapse() {
+ // Not supported by default
+ }
+
+ protected inline void set_style_context_class(string class_name, bool value) {
+ if (value) {
+ get_style_context().add_class(class_name);
+ } else {
+ get_style_context().remove_class(class_name);
+ }
+ }
+
+ }
+
+
+ // Displays a single ConversationEmail in the list box
+ private class EmailRow : ConversationRow {
+
+
+ private const string MATCH_CLASS = "geary-match";
+
// Has the row been temporarily expanded to show search matches?
public bool is_pinned { get; private set; default = false; }
@@ -74,14 +111,9 @@ public class ConversationListBox : Gtk.ListBox {
}
}
- // Designate this row as the last visible row in the
- // conversation listbox, or not. See Bug 764710 and
- // ::update_last_row() below.
- internal bool is_last {
- set { set_style_context_class(LAST_CLASS, value); }
- }
- private Gtk.Grid container = new Gtk.Grid();
+ // The email view for this row, if any
+ public ConversationEmail view { get; private set; }
// We can only scroll to a specific row once it has been
@@ -91,68 +123,26 @@ public class ConversationListBox : Gtk.ListBox {
public EmailRow(ConversationEmail view) {
+ base(view.email);
this.view = view;
-
- this.container.set_orientation(Gtk.Orientation.VERTICAL);
- this.container.show();
- this.container.add(view);
-
- add(this.container);
+ add(view);
}
- public new void expand() {
+ public override void expand() {
this.is_expanded = true;
update_row_expansion();
}
- public void collapse() {
+ public override void collapse() {
this.is_expanded = false;
this.is_pinned = false;
update_row_expansion();
}
- /**
- * Attach an embedded composer to this email view.
- */
- public void attach_composer(ComposerEmbed embed, bool is_draft) {
- this.composer = embed;
- this.container.add(embed);
- if (is_draft) {
- this.view.hide();
- }
- }
-
- /**
- * Detaches an embedded composer to this email view.
- */
- public void remove_composer(ComposerEmbed embed) {
- this.view.show();
- this.container.remove(embed);
- this.composer = null;
- }
-
public void enable_should_scroll() {
this.size_allocate.connect(on_size_allocate);
}
- private inline void update_row_expansion() {
- if (this.is_expanded || this.is_pinned) {
- get_style_context().add_class(EXPANDED_CLASS);
- this.view.expand_email();
- } else {
- get_style_context().remove_class(EXPANDED_CLASS);
- this.view.collapse_email();
- }
- }
-
- private inline void set_style_context_class(string class_name, bool value) {
- if (value) {
- get_style_context().add_class(class_name);
- } else {
- get_style_context().remove_class(class_name);
- }
- }
-
private void on_size_allocate() {
// We need to wait the web view to load first, so that the
// message has a non-trivial height, and then wait for it
@@ -164,18 +154,51 @@ public class ConversationListBox : Gtk.ListBox {
// like when the window has been resized.
this.size_allocate.disconnect(on_size_allocate);
}
-
should_scroll();
}
+ private inline void update_row_expansion() {
+ if (this.is_expanded || this.is_pinned) {
+ get_style_context().add_class(EXPANDED_CLASS);
+ this.view.expand_email();
+ } else {
+ get_style_context().remove_class(EXPANDED_CLASS);
+ this.view.collapse_email();
+ }
+ }
+
+ }
+
+
+ // Displays a single embedded composer in the list box
+ private class ComposerRow : ConversationRow {
+
+ // The embedded composer for this row
+ public ComposerEmbed view { get; private set; }
+
+
+ public ComposerRow(ComposerEmbed view) {
+ base(view.referred);
+ this.view = view;
+ this.is_expanded = true;
+ get_style_context().add_class(EXPANDED_CLASS);
+ add(this.view);
+ }
+
}
private static int on_sort(Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) {
- return Geary.Email.compare_sent_date_ascending(
- ((EmailRow) row1).view.email,
- ((EmailRow) row2).view.email
- );
+ Geary.Email? email1 = ((ConversationRow) row1).email;
+ Geary.Email? email2 = ((ConversationRow) row2).email;
+
+ if (email1 == null) {
+ return 1;
+ }
+ if (email2 == null) {
+ return -1;
+ }
+ return Geary.Email.compare_sent_date_ascending(email1, email2);
}
@@ -208,7 +231,7 @@ public class ConversationListBox : Gtk.ListBox {
Gee.HashMap<Geary.EmailIdentifier, EmailRow>();
// Last visible row in the list, if any
- private EmailRow? last_email_row = null;
+ private ConversationRow? last_row = null;
// Cached search terms to apply to new messages
private Gee.Set<string>? ordered_search_terms = null;
@@ -314,18 +337,21 @@ public class ConversationListBox : Gtk.ListBox {
}
}
- if (this.last_email_row != null && !this.cancellable.is_cancelled()) {
+ update_last_row();
+ EmailRow? last_email = this.last_row as EmailRow;
+
+ if (last_email != null && !this.cancellable.is_cancelled()) {
// The last row should always be expanded, so expand it
// and start loading if needed.
- this.last_email_row.expand();
- if (this.last_email_row != first_expanded_row) {
- yield this.last_email_row.view.start_loading(this.cancellable);
+ last_email.expand();
+ if (last_email != first_expanded_row) {
+ yield last_email.view.start_loading(this.cancellable);
}
// If no other row was expanded by default, use the last
// row.
if (first_expanded_row == null) {
- first_expanded_row = this.last_email_row;
+ first_expanded_row = last_email;
}
// Ensure we scroll to the first expanded roll when it
@@ -336,8 +362,8 @@ public class ConversationListBox : Gtk.ListBox {
// Start everything else loading
this.foreach((child) => {
if (!this.cancellable.is_cancelled()) {
- EmailRow row = (EmailRow) child;
- if (row != first_expanded_row) {
+ EmailRow? row = child as EmailRow;
+ if (row != null && row != first_expanded_row) {
row.view.start_loading.begin(this.cancellable);
}
}
@@ -359,8 +385,18 @@ public class ConversationListBox : Gtk.ListBox {
*/
public ConversationEmail? get_reply_target() {
ConversationEmail? view = get_selection_view();
- if (view == null && this.last_email_row != null) {
- view = this.last_email_row.view;
+ if (view == null) {
+ EmailRow? last = null;
+ this.foreach((child) => {
+ EmailRow? row = child as EmailRow;
+ if (row != null) {
+ last = row;
+ }
+ });
+
+ if (last != null) {
+ view = last.view;
+ }
}
return view;
}
@@ -387,19 +423,27 @@ public class ConversationListBox : Gtk.ListBox {
* Adds an an embedded composer to the view.
*/
public void add_embedded_composer(ComposerEmbed embed, bool is_draft) {
- EmailRow? row = this.id_to_row.get(embed.referred.id);
- if (row != null) {
- row.attach_composer(embed, is_draft);
- embed.loaded.connect((box) => {
- row.grab_focus();
- });
- embed.vanished.connect((box) => {
- row.remove_composer(embed);
- });
- } else {
- error("Could not find referred email for embedded composer: %s",
- embed.referred.id.to_string());
+ if (is_draft) {
+ EmailRow? draft = this.id_to_row.get(embed.referred.id);
+ if (draft != null) {
+ remove_email(draft.email);
+ }
}
+
+ ComposerRow row = new ComposerRow(embed);
+ row.show();
+ add(row);
+ update_last_row();
+
+ embed.loaded.connect(() => { row.grab_focus(); });
+ embed.vanished.connect(() => {
+ remove(row);
+ if (is_draft &&
+ row.email != null &&
+ !this.cancellable.is_cancelled()) {
+ load_full_email.begin(row.email.id);
+ }
+ });
}
/**
@@ -680,7 +724,6 @@ public class ConversationListBox : Gtk.ListBox {
this.id_to_row.set(email.id, row);
add(row);
- update_last_row();
email_added(view);
// Expand interesting messages by default
@@ -734,20 +777,16 @@ public class ConversationListBox : Gtk.ListBox {
// for GTK themes after 3.20.3, so for now manually maintain a
// class on the last box so we can emulate it
private void update_last_row() {
- EmailRow? last = null;
- this.foreach((child) => {
- if (child.get_visible()) {
- last = (EmailRow) child;
- }
- });
+ ConversationRow? last = null;
+ this.foreach((child) => { last = (ConversationRow) child; });
- if (this.last_email_row != last) {
- if (this.last_email_row != null) {
- this.last_email_row.is_last = false;
+ if (this.last_row != last) {
+ if (this.last_row != null) {
+ this.last_row.is_last = false;
}
- this.last_email_row = last;
- this.last_email_row.is_last = true;
+ this.last_row = last;
+ this.last_row.is_last = true;
}
}
@@ -889,7 +928,7 @@ public class ConversationListBox : Gtk.ListBox {
// be appended last. Finally, don't let rows with active
// composers be collapsed.
if (row.is_expanded) {
- if (this.last_email_row != row && row.composer == null) {
+ if (row != this.last_row) {
row.collapse();
}
} else {
diff --git a/ui/geary.css b/ui/geary.css
index 790055b..ff7899b 100644
--- a/ui/geary.css
+++ b/ui/geary.css
@@ -67,11 +67,11 @@ row.geary-folder-popover-list-row > label {
box-shadow: 0 4px 8px 1px rgba(0,0,0,0.4);
transition: margin 0.1s;
}
-.conversation-listbox > row > grid {
+.conversation-listbox > row > box {
background: @theme_base_color;
transition: background 0.25s;
}
-.conversation-listbox > row:hover > grid {
+.conversation-listbox > row:hover > box {
background: shade(@theme_base_color, 0.96);
}
.conversation-listbox > row.geary-expanded {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]