[geary/wip/765516-gtk-widget-conversation-viewer: 41/169] Tidy up ConversationMessage styling and state management.



commit 4d452a796f29320145b0f649838e29d0fc4bfb53
Author: Michael James Gratton <mike vee net>
Date:   Sat Apr 16 23:59:19 2016 +1000

    Tidy up ConversationMessage styling and state management.
    
    * src/client/components/main-window.vala: Adjust theme CSS style to
      account for new widget classes. Fix style for last row in the convo
      listbox.
    
    * src/client/conversation-viewer/conversation-message.vala: Decouple
      updating message state and updating message flags. Prefix CSS classes
      with "geary_" to prevent class name clashes.
    
    * src/client/conversation-viewer/conversation-viewer.vala: Manually
      maintain a CSS class on the last row of the convo listbox to work
      around Bug 764710. Prefix CSS classes with "geary_" to prevent class
      name clashes.
      (ConversationViewer::on_update_flags): Renamed from update_flags since
      it is only ever called as a signal handler. Remove most of the work -
      it is now done by ConversationMessage.

 .../conversation-viewer/conversation-message.vala  |   35 +++++----
 .../conversation-viewer/conversation-viewer.vala   |   88 ++++++++++---------
 ui/geary.css                                       |   19 +++--
 3 files changed, 78 insertions(+), 64 deletions(-)
---
diff --git a/src/client/conversation-viewer/conversation-message.vala 
b/src/client/conversation-viewer/conversation-message.vala
index c15ab9e..036595a 100644
--- a/src/client/conversation-viewer/conversation-message.vala
+++ b/src/client/conversation-viewer/conversation-message.vala
@@ -57,6 +57,9 @@ public class ConversationMessage : Gtk.Box {
     // The allocation for the web view
     public Gdk.Rectangle web_view_allocation { get; private set; }
 
+    // Is the message body shown or not?
+    public bool is_message_body_visible = false;
+
     // Has the message body been been fully loaded?
     public bool is_loading_complete = false;
 
@@ -235,15 +238,12 @@ public class ConversationMessage : Gtk.Box {
         //     }
         // }
 
-        update_flags(email);
-    }
-
-    public bool is_message_visible() {
-        return get_style_context().has_class("show-message");
+        update_message_state(false);
     }
 
-    public void show_message(bool include_transitions=true) {
-        get_style_context().add_class("show-message");
+    public void show_message_body(bool include_transitions=true) {
+        is_message_body_visible = true;
+        get_style_context().add_class("geary_show_body");
         avatar_image.set_pixel_size(32); // XXX constant
 
         Gtk.RevealerTransitionType revealer = preview_revealer.get_transition_type();
@@ -264,7 +264,6 @@ public class ConversationMessage : Gtk.Box {
         unstar_button.set_sensitive(true);
         message_menubutton.set_sensitive(true);
 
-        // XXX this is pretty gross
         revealer = body_revealer.get_transition_type();
         if (!include_transitions) {
             body_revealer.set_transition_type(Gtk.RevealerTransitionType.NONE);
@@ -273,8 +272,9 @@ public class ConversationMessage : Gtk.Box {
         body_revealer.set_transition_type(revealer);
     }
 
-    public void hide_message() {
-        get_style_context().remove_class("show-message");
+    public void hide_message_body() {
+        is_message_body_visible = false;
+        get_style_context().remove_class("geary_show_body");
         avatar_image.set_pixel_size(24); // XXX constant
         preview_revealer.set_reveal_child(true);
         header_revealer.set_reveal_child(false);
@@ -379,11 +379,20 @@ public class ConversationMessage : Gtk.Box {
         return menu;
     }
 
+    public void update_flags(Geary.Email email) {
+        this.email.set_flags(email.email_flags);
+        update_message_state();
+    }
+
     public bool is_manual_read() {
         return get_style_context().has_class("geary_manual_read");
     }
 
-    public void update_flags(Geary.Email email) {
+    public void mark_manual_read() {
+        get_style_context().add_class("geary_manual_read");
+    }
+
+    private void update_message_state(bool include_transitions=true) {
         Geary.EmailFlags flags = email.email_flags;
         Gtk.StyleContext style = get_style_context();
         
@@ -409,10 +418,6 @@ public class ConversationMessage : Gtk.Box {
         //            Geary.SpecialFolderType.SENT.get_display_name()));
     }
 
-    public void mark_manual_read() {
-        get_style_context().add_class("manual_read");
-    }
-
     private void load_message_body() {
         bool load_images = false;
         string? body_text = null;
diff --git a/src/client/conversation-viewer/conversation-viewer.vala 
b/src/client/conversation-viewer/conversation-viewer.vala
index 965fb38..d9948ae 100644
--- a/src/client/conversation-viewer/conversation-viewer.vala
+++ b/src/client/conversation-viewer/conversation-viewer.vala
@@ -101,6 +101,7 @@ public class ConversationViewer : Gtk.Stack {
     // Conversation messages list
     [GtkChild]
     private Gtk.ListBox conversation_listbox;
+    private Gtk.Widget? last_list_row;
 
     // Label for displaying messages in the main pane.
     [GtkChild]
@@ -148,7 +149,11 @@ public class ConversationViewer : Gtk.Stack {
                 // embedded composer and should not be activated.
                 ConversationMessage? msg = row.get_child() as ConversationMessage;
                 if (email_to_row.size > 1 && msg != null) {
-                    toggle_show_message(row);
+                    if (msg.is_message_body_visible) {
+                        hide_message(row);
+                    } else {
+                        show_message(row);
+                    }
                 }
             });
         conversation_listbox.realize.connect(() => {
@@ -156,6 +161,24 @@ public class ConversationViewer : Gtk.Stack {
                     .value_changed.connect(check_mark_read);
             });
         conversation_listbox.size_allocate.connect(check_mark_read);
+        conversation_listbox.add.connect((widget) => {
+                // Due to Bug 764710, we can only use the CSS
+                // :last-child selector for GTK themes after 3.20.3,
+                // so for now manually maintain a class on the last
+                // box in the convo listbox so we can emulate it.
+
+                Gtk.Widget current_last_row =
+                    conversation_listbox.get_children().last().data;;
+                if (last_list_row != current_last_row) {
+                    if (last_list_row != null) {
+                        last_list_row.get_style_context().remove_class("geary_last");
+                    }
+
+                    last_list_row = current_last_row;
+                    last_list_row.get_style_context().add_class("geary_last");
+                }
+            });
+
 
         // Setup state machine for search/find states.
         Geary.State.Mapping[] mappings = {
@@ -308,7 +331,7 @@ public class ConversationViewer : Gtk.Stack {
         embed.set_property("name", "composer_embed"); // Bug 764622
 
         Gtk.ListBoxRow row = new Gtk.ListBoxRow();
-        row.get_style_context().add_class("composer");
+        row.get_style_context().add_class("geary_composer");
         row.show();
         row.add(embed);
         conversation_listbox.add(row);
@@ -377,7 +400,7 @@ public class ConversationViewer : Gtk.Stack {
         if (current_conversation != null) {
             current_conversation.appended.disconnect(on_conversation_appended);
             current_conversation.trimmed.disconnect(on_conversation_trimmed);
-            current_conversation.email_flags_changed.disconnect(update_flags);
+            current_conversation.email_flags_changed.disconnect(on_update_flags);
             current_conversation = null;
         }
 
@@ -430,7 +453,7 @@ public class ConversationViewer : Gtk.Stack {
             
             current_conversation.appended.connect(on_conversation_appended);
             current_conversation.trimmed.connect(on_conversation_trimmed);
-            current_conversation.email_flags_changed.connect(update_flags);
+            current_conversation.email_flags_changed.connect(on_update_flags);
             
             GearyApplication.instance.controller.enable_message_buttons(true);
         }
@@ -616,7 +639,7 @@ public class ConversationViewer : Gtk.Stack {
 
         ConversationMessage message = new ConversationMessage(email, current_folder);
         message.link_selected.connect((link) => { link_selected(link); });
-        message.web_view.button_release_event.connect_after((event) => {
+        message.body_box.button_release_event.connect_after((event) => {
                 // Consume all non-consumed clicks so the row is not
                 // inadvertently activated after clicking on the
                 // message body.
@@ -626,11 +649,10 @@ public class ConversationViewer : Gtk.Stack {
         Gtk.ListBoxRow row = new Gtk.ListBoxRow();
         row.show();
         row.add(message);
+        email_to_row.set(email.id, row);
 
         conversation_listbox.add(row);
 
-        email_to_row.set(email.id, row);
-
         if (email.is_unread() == Geary.Trillian.TRUE) {
             show_message(row, false);
         }
@@ -647,52 +669,23 @@ public class ConversationViewer : Gtk.Stack {
     }
 
     private void show_message(Gtk.ListBoxRow row, bool include_transitions=true) {
-        row.get_style_context().add_class("show-message");
-        ((ConversationMessage) row.get_child()).show_message(include_transitions);
+        row.get_style_context().add_class("geary_expand");
+        ((ConversationMessage) row.get_child()).show_message_body(include_transitions);
     }
 
     private void hide_message(Gtk.ListBoxRow row) {
-        row.get_style_context().remove_class("show-message");
-        ((ConversationMessage) row.get_child()).hide_message();
-    }
-
-    private void toggle_show_message(Gtk.ListBoxRow row) {
-        if (row.get_style_context().has_class("show-message")) {
-            hide_message(row);
-        } else {
-            show_message(row);
-        }
+        row.get_style_context().remove_class("geary_expand");
+        ((ConversationMessage) row.get_child()).hide_message_body();
     }
 
     private void compress_emails() {
-        conversation_listbox.get_style_context().add_class("compressed");
+        conversation_listbox.get_style_context().add_class("geary_compressed");
     }
     
     //private void decompress_emails() {
-    //  conversation_listbox.get_style_context().remove_class("compressed");
+    //  conversation_listbox.get_style_context().remove_class("geary_compressed");
     //}
     
-    private void update_flags(Geary.Email email) {
-        // Nothing to do if we aren't displaying this email.
-        if (!email_to_row.has_key(email.id)) {
-            return;
-        }
-
-        Geary.EmailFlags flags = email.email_flags;
-        
-        // Update the flags in our message set.
-        foreach (Geary.Email message in messages) {
-            if (message.id.equal_to(email.id)) {
-                message.set_flags(flags);
-                break;
-            }
-        }
-
-        // Get the convo message and update its state.
-        Gtk.ListBoxRow row = email_to_row.get(email.id);
-        ((ConversationMessage) row.get_child()).update_flags(email);
-    }
-    
     public void show_find_bar() {
         fsm.issue(SearchEvent.OPEN_FIND_BAR);
         conversation_find_bar.focus_entry();
@@ -705,6 +698,17 @@ public class ConversationViewer : Gtk.Stack {
         conversation_find_bar.find(forward);
     }
     
+    private void on_update_flags(Geary.Email email) {
+        // Nothing to do if we aren't displaying this email.
+        if (!email_to_row.has_key(email.id)) {
+            return;
+        }
+
+        // Get the convo message and update its state.
+        Gtk.ListBoxRow row = email_to_row.get(email.id);
+        ((ConversationMessage) row.get_child()).update_flags(email);
+    }
+
     // State reset.
     private uint on_reset(uint state, uint event, void *user, Object? object) {
         //web_view.set_highlight_text_matches(false);
diff --git a/ui/geary.css b/ui/geary.css
index 3835513..fa79d12 100644
--- a/ui/geary.css
+++ b/ui/geary.css
@@ -58,27 +58,32 @@ row.geary-folder-popover-list-row > label {
 }
 
 #conversation_listbox {
-  padding: 18px 18px calc(18px/2);
+  padding: 18px;
 }
 #conversation_listbox > row {
   margin: 0;
   border: 1px solid @borders;
   border-bottom-width: 0;
   padding: 0;
-  background: shade(@theme_base_color, 0.96);
   box-shadow: 0 4px 8px 1px rgba(0,0,0,0.4);
   transition: margin 0.1s, background 0.15s;
 }
+#conversation_listbox > row > box {
+  background: shade(@theme_base_color, 0.96);
+}
 #conversation_listbox > row:hover,
-#conversation_listbox > row.show-message,
-#conversation_listbox > row.show-message:hover {
+#conversation_listbox > row > box.geary_show_body,
+#conversation_listbox > row:hover > box.geary_show_body {
   background: @theme_base_color;
 }
-#conversation_listbox > row.show-message,
-#conversation_listbox > row.composer {
-  margin-bottom: calc(18px/2);
+#conversation_listbox > row.geary_expand,
+#conversation_listbox > row.geary_composer {
+  margin-bottom: 18px;
   border-bottom-width: 1px;
 }
+#conversation_listbox > row.geary_last {
+  margin-bottom: 0;
+}
 
 #ConversationMessage {
   padding: 12px;


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