From 787e92e7316cd8e17abb989cef843b7ea5813059 Mon Sep 17 00:00:00 2001 From: Robert Schroll Date: Thu, 29 Jan 2015 03:19:14 -0500 Subject: [PATCH] Host new composers in ComposerBox, not in ComposerEmbed This allows us to avoid messing with the state of the conversation viewer when we're composing a new message. Instead, we hide it completely and show only the ComposerBox. The styling of paned composer is changed to resemble that of the inline composers. Because of restrictions on what styles are available for various widgets, the ComposerBox becomes a Gtk.Frame, and its border simulates the margin while some padding and an inset shadow simulate the border. I haven't figured out how to do an outset box-shadow. https://bugzilla.gnome.org/show_bug.cgi?id=743670 --- src/client/application/geary-controller.vala | 5 +- src/client/components/main-window.vala | 7 +- src/client/composer/composer-box.vala | 21 +++++- src/client/composer/composer-embed.vala | 75 ++++++------------- src/client/composer/composer-widget.vala | 4 +- .../conversation-viewer.vala | 11 +-- theming/message-viewer.css | 14 ---- 7 files changed, 60 insertions(+), 77 deletions(-) diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala index 3ed92e9d..2a647310 100644 --- a/src/client/application/geary-controller.vala +++ b/src/client/application/geary-controller.vala @@ -2139,7 +2139,8 @@ public class GearyController : Geary.BaseObject { widget.destroy.connect(on_composer_widget_destroy); if (inline) { - if (widget.state == ComposerWidget.ComposerState.PANED) + if (widget.state == ComposerWidget.ComposerState.NEW || + widget.state == ComposerWidget.ComposerState.PANED) main_window.conversation_viewer.set_paned_composer(widget); else new ComposerEmbed(widget, main_window.conversation_viewer, referred); // is_draft @@ -2181,7 +2182,7 @@ public class GearyController : Geary.BaseObject { // it if it hasn't been modified; otherwise open a new composer in a new window. if (compose_type == ComposerWidget.ComposeType.NEW_MESSAGE) { foreach (ComposerWidget cw in composer_widgets) { - if (cw.state == ComposerWidget.ComposerState.INLINE_NEW) { + if (cw.state == ComposerWidget.ComposerState.NEW) { if (!cw.blank) { inline = false; return true; diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala index 51d1c229..e907c8ea 100644 --- a/src/client/components/main-window.vala +++ b/src/client/components/main-window.vala @@ -145,9 +145,14 @@ public class MainWindow : Gtk.ApplicationWindow { border-top-width: 0px; border-bottom-width: 0px; } + ComposerBox { + border: 16px solid #ccc; + box-shadow: 0 0 0 1px rgba(0,0,0,0.4) inset; + padding: 1px; + } GtkBox GtkHeaderBar { border-radius: 0px; - } + } """; if(Gtk.MAJOR_VERSION >= 3 && Gtk.MINOR_VERSION >= 14) { diff --git a/src/client/composer/composer-box.vala b/src/client/composer/composer-box.vala index 36c3ffe6..afd7a7dd 100644 --- a/src/client/composer/composer-box.vala +++ b/src/client/composer/composer-box.vala @@ -4,9 +4,10 @@ * (version 2.1 or later). See the COPYING file in this distribution. */ -public class ComposerBox : Gtk.EventBox, ComposerContainer { +public class ComposerBox : Gtk.Frame, ComposerContainer { private ComposerWidget composer; + private Gee.Set? prev_selection = null; private bool has_accel_group = false; public Gtk.Window top_window { @@ -20,6 +21,13 @@ public class ComposerBox : Gtk.EventBox, ComposerContainer { composer.editor.focus_in_event.connect(on_focus_in); composer.editor.focus_out_event.connect(on_focus_out); show(); + + if (composer.state == ComposerWidget.ComposerState.NEW) { + ConversationListView conversation_list_view = ((MainWindow) GearyApplication. + instance.controller.main_window).conversation_list_view; + prev_selection = conversation_list_view.get_selected_conversations(); + conversation_list_view.get_selection().unselect_all(); + } } public Gtk.Widget? remove_composer() { @@ -63,6 +71,17 @@ public class ComposerBox : Gtk.EventBox, ComposerContainer { composer.state = ComposerWidget.ComposerState.DETACHED; composer.editor.focus_in_event.disconnect(on_focus_in); composer.editor.focus_out_event.disconnect(on_focus_out); + + if (prev_selection != null) { + ConversationListView conversation_list_view = ((MainWindow) GearyApplication. + instance.controller.main_window).conversation_list_view; + if (prev_selection.is_empty) + // Need to trigger "No messages selected" + conversation_list_view.conversations_selected(prev_selection); + else + conversation_list_view.select_conversations(prev_selection); + prev_selection = null; + } } public void close_container() { diff --git a/src/client/composer/composer-embed.vala b/src/client/composer/composer-embed.vala index 7bf5d07b..8ef4be4d 100644 --- a/src/client/composer/composer-embed.vala +++ b/src/client/composer/composer-embed.vala @@ -10,7 +10,6 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer { private ComposerWidget composer; private ConversationViewer conversation_viewer; - private Gee.Set? prev_selection = null; private string embed_id; private bool setting_inner_scroll; private bool scrolled_to_bottom = false; @@ -24,31 +23,23 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer { } public ComposerEmbed(ComposerWidget composer, ConversationViewer conversation_viewer, - Geary.Email? referred) { + Geary.Email referred) { this.composer = composer; this.conversation_viewer = conversation_viewer; halign = Gtk.Align.FILL; valign = Gtk.Align.FILL; WebKit.DOM.HTMLElement? email_element = null; - if (referred != null && composer.state != ComposerWidget.ComposerState.INLINE_NEW) { - email_element = conversation_viewer.web_view.get_dom_document().get_element_by_id( - conversation_viewer.get_div_id(referred.id)) as WebKit.DOM.HTMLElement; - embed_id = referred.id.to_string() + "_reply"; - } else { - embed_id = random_string(10); - } + email_element = conversation_viewer.web_view.get_dom_document().get_element_by_id( + conversation_viewer.get_div_id(referred.id)) as WebKit.DOM.HTMLElement; + embed_id = referred.id.to_string() + "_reply"; if (email_element == null) { - ConversationListView conversation_list_view = ((MainWindow) GearyApplication. - instance.controller.main_window).conversation_list_view; - prev_selection = conversation_list_view.get_selected_conversations(); - conversation_list_view.get_selection().unselect_all(); + warning("Embedded composer could not find email to follow."); email_element = conversation_viewer.web_view.get_dom_document().get_element_by_id( "placeholder") as WebKit.DOM.HTMLElement; } try { - conversation_viewer.show_conversation_div(); email_element.insert_adjacent_html("afterend", @"
"); } catch (Error error) { @@ -69,31 +60,27 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer { private void on_realize() { update_style(); - if (composer.state != ComposerWidget.ComposerState.INLINE_NEW) { - Gtk.ScrolledWindow win = (Gtk.ScrolledWindow) composer.editor.parent; - win.get_vscrollbar().hide(); - - composer.editor.vadjustment.value_changed.connect(on_inner_scroll); - composer.editor.vadjustment.changed.connect(on_adjust_changed); - composer.editor.user_changed_contents.connect(on_inner_size_changed); - - reroute_scroll_handling(this); - } + Gtk.ScrolledWindow win = (Gtk.ScrolledWindow) composer.editor.parent; + win.get_vscrollbar().hide(); + + composer.editor.vadjustment.value_changed.connect(on_inner_scroll); + composer.editor.vadjustment.changed.connect(on_adjust_changed); + composer.editor.user_changed_contents.connect(on_inner_size_changed); + + reroute_scroll_handling(this); } private void on_loaded() { - if (composer.state != ComposerWidget.ComposerState.INLINE_NEW) { - try { - composer.editor.get_dom_document().body.get_class_list().add("embedded"); - } catch (Error error) { - debug("Error setting class of editor: %s", error.message); - } - Idle.add(() => { - recalc_height(); - conversation_viewer.compose_overlay.queue_resize(); - return false; - }); + try { + composer.editor.get_dom_document().body.get_class_list().add("embedded"); + } catch (Error error) { + debug("Error setting class of editor: %s", error.message); } + Idle.add(() => { + recalc_height(); + conversation_viewer.compose_overlay.queue_resize(); + return false; + }); } private void reroute_scroll_handling(Gtk.Widget widget) { @@ -161,8 +148,7 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer { int y_top = (int) (embed.offset_top + embed.client_top) - (int) vscroll; int available_height = int.min(y_top + div_height, view_height) - int.max(y_top, 0); - if (available_height < 0 || available_height == div_height || - composer.state == ComposerWidget.ComposerState.INLINE_NEW) { + if (available_height < 0 || available_height == div_height) { // It fits in the available space, or it doesn't fit at all allocation.y = y_top; // When offscreen, make it very small to ensure scrolling during any edit @@ -179,10 +165,6 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer { allocation.x = (int) (embed.offset_left + embed.client_left) - (int) hscroll; allocation.width = (int) embed.client_width; - // INLINE_NEW handles its own scrolling. - if (composer.state == ComposerWidget.ComposerState.INLINE_NEW) - return true; - // Work out adjustment of composer web view setting_inner_scroll = true; composer.editor.vadjustment.set_value(allocation.y - y_top); @@ -290,17 +272,6 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer { } catch (Error error) { warning("Could not remove embed from WebView: %s", error.message); } - - if (prev_selection != null) { - ConversationListView conversation_list_view = ((MainWindow) GearyApplication. - instance.controller.main_window).conversation_list_view; - if (prev_selection.is_empty) - // Need to trigger "No messages selected" - conversation_list_view.conversations_selected(prev_selection); - else - conversation_list_view.select_conversations(prev_selection); - prev_selection = null; - } } public void close_container() { diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala index 78a6a3d4..459557eb 100644 --- a/src/client/composer/composer-widget.vala +++ b/src/client/composer/composer-widget.vala @@ -22,7 +22,7 @@ public class ComposerWidget : Gtk.EventBox { public enum ComposerState { DETACHED, PANED, - INLINE_NEW, + NEW, INLINE, INLINE_COMPACT } @@ -263,7 +263,7 @@ public class ComposerWidget : Gtk.EventBox { this.account = account; this.compose_type = compose_type; if (compose_type == ComposeType.NEW_MESSAGE) - state = ComposerState.INLINE_NEW; + state = ComposerState.NEW; else if (compose_type == ComposeType.FORWARD) state = ComposerState.INLINE; else diff --git a/src/client/conversation-viewer/conversation-viewer.vala b/src/client/conversation-viewer/conversation-viewer.vala index 27049869..d07c3df1 100644 --- a/src/client/conversation-viewer/conversation-viewer.vala +++ b/src/client/conversation-viewer/conversation-viewer.vala @@ -231,6 +231,10 @@ public class ConversationViewer : Gtk.Box { Configuration config = GearyApplication.instance.config; config.bind(Configuration.COMPOSER_PANE_POSITION_KEY, composer_paned, "position"); pack_start(composer_paned); + composer_boxes.notify["visible"].connect(() => { + if (!composer_boxes.visible && !message_overlay.visible) + message_overlay.show(); + }); conversation_find_bar = new ConversationFindBar(web_view); conversation_find_bar.no_show_all = true; @@ -243,6 +247,8 @@ public class ConversationViewer : Gtk.Box { ComposerBox container = new ComposerBox(composer); composer_boxes.pack_start(container); composer_boxes.show(); + if (composer.state == ComposerWidget.ComposerState.NEW) + message_overlay.hide(); } public Geary.Email? get_last_message() { @@ -2437,10 +2443,5 @@ public class ConversationViewer : Gtk.Box { return current_folder != null && current_folder.special_folder_type == Geary.SpecialFolderType.DRAFTS; } - - // The Composer may need to adjust the mode back to conversation - public void show_conversation_div() { - set_mode(DisplayMode.CONVERSATION); - } } diff --git a/theming/message-viewer.css b/theming/message-viewer.css index 1dc65abb..71ece10b 100644 --- a/theming/message-viewer.css +++ b/theming/message-viewer.css @@ -106,20 +106,6 @@ hr { } .composer_embed { - position: absolute; - top: 0px; /* margin-top has impact here, despite absolute positioning (!?) */ - bottom: 16px; - left: 16px; - right: 16px; - width: auto; -} -.email + .composer_embed { - position: relative; - top: auto; - bottom: auto; - left: auto; - right: auto; - width: 100%; height: 300px; }