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
This commit is contained in:
parent
ec41d86fd1
commit
787e92e731
7 changed files with 60 additions and 77 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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<Geary.App.Conversation>? 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() {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer {
|
|||
|
||||
private ComposerWidget composer;
|
||||
private ConversationViewer conversation_viewer;
|
||||
private Gee.Set<Geary.App.Conversation>? 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",
|
||||
@"<div id='$embed_id' class='composer_embed'></div>");
|
||||
} 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() {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue