Re-implement composer font family/size action state updating.
* src/client/composer/composer-web-view.vala (ComposerWebView): Add new ::cursor_style_changed signal, hook it up to the JS cursorStyleChanged message and interpret the raw results from the web view before passing it on. * src/client/composer/composer-widget.vala (ComposerWidget): Replace remainder of old ::update_actions method with a listener for ComposerWebView::cursor_style_changed. Reimplement in terms of that signal. * ui/composer-web-view.js: Keep track of font family and size changes, send a cursorStyleChanged message when they change.
This commit is contained in:
parent
2bd5306d30
commit
67d81c3e15
3 changed files with 106 additions and 70 deletions
|
|
@ -13,6 +13,17 @@ public class ComposerWebView : ClientWebView {
|
|||
|
||||
|
||||
private const string COMMAND_STACK_CHANGED = "commandStackChanged";
|
||||
private const string CURSOR_STYLE_CHANGED = "cursorStyleChanged";
|
||||
|
||||
private const string[] SANS_FAMILY_NAMES = {
|
||||
"sans", "arial", "trebuchet", "helvetica"
|
||||
};
|
||||
private const string[] SERIF_FAMILY_NAMES = {
|
||||
"serif", "georgia", "times"
|
||||
};
|
||||
private const string[] MONO_FAMILY_NAMES = {
|
||||
"monospace", "courier", "console"
|
||||
};
|
||||
|
||||
private const string HTML_BODY = """
|
||||
<html><head><title></title>
|
||||
|
|
@ -61,6 +72,21 @@ public class ComposerWebView : ClientWebView {
|
|||
</body></html>""";
|
||||
private const string CURSOR = "<span id=\"cursormarker\"></span>";
|
||||
|
||||
private static Gee.HashMap<string,string> font_family_map =
|
||||
new Gee.HashMap<string,string>();
|
||||
|
||||
static construct {
|
||||
foreach (string name in SANS_FAMILY_NAMES) {
|
||||
font_family_map["sans"] = name;
|
||||
}
|
||||
foreach (string name in SERIF_FAMILY_NAMES) {
|
||||
font_family_map["serif"] = name;
|
||||
}
|
||||
foreach (string name in MONO_FAMILY_NAMES) {
|
||||
font_family_map["monospace"] = name;
|
||||
}
|
||||
}
|
||||
|
||||
private static WebKit.UserScript? app_script = null;
|
||||
|
||||
public static void load_resources()
|
||||
|
|
@ -82,6 +108,10 @@ public class ComposerWebView : ClientWebView {
|
|||
/** Emitted when the web view's undo/redo stack has changed. */
|
||||
public signal void command_stack_changed(bool can_undo, bool can_redo);
|
||||
|
||||
/** Emitted when the style under the cursor has changed. */
|
||||
public signal void cursor_style_changed(string face, uint size);
|
||||
|
||||
|
||||
public ComposerWebView(Configuration config) {
|
||||
base(config);
|
||||
this.user_content_manager.add_script(ComposerWebView.app_script);
|
||||
|
|
@ -100,7 +130,12 @@ public class ComposerWebView : ClientWebView {
|
|||
}
|
||||
});
|
||||
result.unref();
|
||||
this.user_content_manager.script_message_received[CURSOR_STYLE_CHANGED].connect(
|
||||
on_cursor_style_changed_message
|
||||
);
|
||||
|
||||
register_message_handler(COMMAND_STACK_CHANGED);
|
||||
register_message_handler(CURSOR_STYLE_CHANGED);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -353,6 +388,29 @@ public class ComposerWebView : ClientWebView {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void on_cursor_style_changed_message(WebKit.JavascriptResult result) {
|
||||
try {
|
||||
string[] values = WebKitUtil.to_string(result).split(",");
|
||||
string view_name = values[0].down();
|
||||
string? font_family = "sans";
|
||||
foreach (string name in ComposerWebView.font_family_map.keys) {
|
||||
if (name in view_name) {
|
||||
font_family = ComposerWebView.font_family_map[name];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint font_size = 12;
|
||||
values[1].scanf("%dpx", out font_size);
|
||||
|
||||
cursor_style_changed(font_family, font_size);
|
||||
} catch (Geary.JS.Error err) {
|
||||
debug("Could not get cursor style: %s", err.message);
|
||||
} finally {
|
||||
result.unref();
|
||||
}
|
||||
}
|
||||
|
||||
// We really want to examine
|
||||
// Gdk.Keymap.get_default().get_modifier_state(), instead of
|
||||
// storing whether the shift key is down at each keypress, but it
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ private errordomain AttachmentError {
|
|||
// The actual widget for sending messages. Should be put in a ComposerContainer
|
||||
[GtkTemplate (ui = "/org/gnome/Geary/composer-widget.ui")]
|
||||
public class ComposerWidget : Gtk.EventBox {
|
||||
|
||||
|
||||
public enum ComposeType {
|
||||
NEW_MESSAGE,
|
||||
REPLY,
|
||||
|
|
@ -475,8 +477,8 @@ public class ComposerWidget : Gtk.EventBox {
|
|||
this.editor.load_changed.connect(on_load_changed);
|
||||
this.editor.mouse_target_changed.connect(on_mouse_target_changed);
|
||||
this.editor.get_editor_state().notify["typing-attributes"].connect(on_typing_attributes_changed);
|
||||
// this.editor.move_focus.connect(update_actions);
|
||||
this.editor.selection_changed.connect(on_selection_changed);
|
||||
this.editor.cursor_style_changed.connect(on_cursor_style_changed);
|
||||
this.editor.key_press_event.connect(on_editor_key_press);
|
||||
//this.editor.user_changed_contents.connect(reset_draft_timer);
|
||||
|
||||
|
|
@ -558,7 +560,6 @@ public class ComposerWidget : Gtk.EventBox {
|
|||
insert_action_group("cmp", this.actions);
|
||||
this.header.insert_action_group("cmh", this.actions);
|
||||
|
||||
update_actions();
|
||||
get_action(ACTION_UNDO).set_enabled(false);
|
||||
get_action(ACTION_REDO).set_enabled(false);
|
||||
}
|
||||
|
|
@ -799,11 +800,12 @@ public class ComposerWidget : Gtk.EventBox {
|
|||
// This is safe to call even when this connection hasn't been made.
|
||||
realize.disconnect(on_load_finished_and_realized);
|
||||
|
||||
update_actions();
|
||||
|
||||
this.actions.change_action_state(ACTION_SHOW_EXTENDED, false);
|
||||
this.actions.change_action_state(ACTION_COMPOSE_AS_HTML,
|
||||
GearyApplication.instance.config.compose_as_html);
|
||||
this.actions.change_action_state(
|
||||
ACTION_SHOW_EXTENDED, false
|
||||
);
|
||||
this.actions.change_action_state(
|
||||
ACTION_COMPOSE_AS_HTML, this.config.compose_as_html
|
||||
);
|
||||
|
||||
if (can_delete_quote)
|
||||
this.editor.selection_changed.connect(
|
||||
|
|
@ -1847,8 +1849,6 @@ public class ComposerWidget : Gtk.EventBox {
|
|||
// This overrides the keypress handling for the *widget*; the WebView editor's keypress overrides
|
||||
// are handled by on_editor_key_press
|
||||
public override bool key_press_event(Gdk.EventKey event) {
|
||||
update_actions();
|
||||
|
||||
switch (Gdk.keyval_name(event.keyval)) {
|
||||
case "Return":
|
||||
case "KP_Enter":
|
||||
|
|
@ -1860,7 +1860,7 @@ public class ComposerWidget : Gtk.EventBox {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return base.key_press_event(event);
|
||||
}
|
||||
|
||||
|
|
@ -2013,66 +2013,6 @@ public class ComposerWidget : Gtk.EventBox {
|
|||
return this.actions.lookup_action(action_name) as SimpleAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the states of the composer's actions and whether they should be enabled.
|
||||
*/
|
||||
private void update_actions() {
|
||||
// Basic editor commands
|
||||
get_action(ACTION_UNDO).set_enabled(this.editor.can_undo());
|
||||
get_action(ACTION_REDO).set_enabled(this.editor.can_redo());
|
||||
get_action(ACTION_CUT).set_enabled(this.editor.can_cut_clipboard());
|
||||
get_action(ACTION_COPY).set_enabled(this.editor.can_copy_clipboard());
|
||||
get_action(ACTION_PASTE).set_enabled(this.editor.can_paste_clipboard());
|
||||
get_action(ACTION_PASTE_WITH_FORMATTING).set_enabled(
|
||||
this.editor.can_paste_clipboard() &&
|
||||
this.editor.is_rich_text
|
||||
);
|
||||
|
||||
// // Style formatting actions.
|
||||
// WebKit.DOM.Document document = this.editor.get_dom_document();
|
||||
// WebKit.DOM.DOMWindow window = document.get_default_view();
|
||||
// WebKit.DOM.DOMSelection? selection = window.get_selection();
|
||||
// if (selection == null)
|
||||
// return;
|
||||
|
||||
// get_action(ACTION_REMOVE_FORMAT).set_enabled(!selection.is_collapsed
|
||||
// && this.editor.is_rich_text);
|
||||
|
||||
// WebKit.DOM.Element? active = selection.focus_node as WebKit.DOM.Element;
|
||||
// if (active == null && selection.focus_node != null)
|
||||
// active = selection.focus_node.get_parent_element();
|
||||
|
||||
// if (active != null) {
|
||||
// WebKit.DOM.CSSStyleDeclaration styles = window.get_computed_style(active, "");
|
||||
|
||||
// // Font family.
|
||||
// string font_name = styles.get_property_value("font-family").down();
|
||||
// if (font_name.contains("sans") ||
|
||||
// font_name.contains("arial") ||
|
||||
// font_name.contains("trebuchet") ||
|
||||
// font_name.contains("helvetica"))
|
||||
// this.actions.change_action_state(ACTION_FONT_FAMILY, "sans");
|
||||
// else if (font_name.contains("serif") ||
|
||||
// font_name.contains("georgia") ||
|
||||
// font_name.contains("times"))
|
||||
// this.actions.change_action_state(ACTION_FONT_FAMILY, "serif");
|
||||
// else if (font_name.contains("monospace") ||
|
||||
// font_name.contains("courier") ||
|
||||
// font_name.contains("console"))
|
||||
// this.actions.change_action_state(ACTION_FONT_FAMILY, "monospace");
|
||||
|
||||
// // Font size.
|
||||
// int font_size;
|
||||
// styles.get_property_value("font-size").scanf("%dpx", out font_size);
|
||||
// if (font_size < 11)
|
||||
// this.actions.change_action_state(ACTION_FONT_SIZE, "small");
|
||||
// else if (font_size > 20)
|
||||
// this.actions.change_action_state(ACTION_FONT_SIZE, "large");
|
||||
// else
|
||||
// this.actions.change_action_state(ACTION_FONT_SIZE, "medium");
|
||||
// }
|
||||
}
|
||||
|
||||
private bool add_account_emails_to_from_list(Geary.Account other_account, bool set_active = false) {
|
||||
Geary.RFC822.MailboxAddresses primary_address = new Geary.RFC822.MailboxAddresses.single(
|
||||
other_account.information.primary_mailbox);
|
||||
|
|
@ -2246,6 +2186,17 @@ public class ComposerWidget : Gtk.EventBox {
|
|||
);
|
||||
}
|
||||
|
||||
private void on_cursor_style_changed(string font_family, uint font_size) {
|
||||
this.actions.change_action_state(ACTION_FONT_FAMILY, font_family);
|
||||
|
||||
if (font_size < 11)
|
||||
this.actions.change_action_state(ACTION_FONT_SIZE, "small");
|
||||
else if (font_size > 20)
|
||||
this.actions.change_action_state(ACTION_FONT_SIZE, "large");
|
||||
else
|
||||
this.actions.change_action_state(ACTION_FONT_SIZE, "medium");
|
||||
}
|
||||
|
||||
private void on_typing_attributes_changed() {
|
||||
uint mask = this.editor.get_editor_state().get_typing_attributes();
|
||||
this.actions.change_action_state(
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ ComposerPageState.prototype = {
|
|||
this.undoEnabled = false;
|
||||
this.redoEnabled = false;
|
||||
|
||||
this.cursorFontFamily = null;
|
||||
this.cursorFontSize = null;
|
||||
|
||||
let state = this;
|
||||
|
||||
document.addEventListener("click", function(e) {
|
||||
|
|
@ -142,6 +145,30 @@ ComposerPageState.prototype = {
|
|||
},
|
||||
linkClicked: function(element) {
|
||||
window.getSelection().selectAllChildren(element);
|
||||
},
|
||||
selectionChanged: function() {
|
||||
PageState.prototype.selectionChanged.apply(this, []);
|
||||
|
||||
let selection = window.getSelection();
|
||||
let active = selection.focusNode;
|
||||
if (active != null && active.nodeType != Node.ELEMENT_TYPE) {
|
||||
active = active.parentNode;
|
||||
}
|
||||
|
||||
if (active != null) {
|
||||
let styles = window.getComputedStyle(active);
|
||||
let fontFamily = styles.getPropertyValue("font-family");
|
||||
let fontSize = styles.getPropertyValue("font-size");
|
||||
|
||||
if (fontFamily != this.cursorFontFamily ||
|
||||
fontSize != this.cursorFontSize) {
|
||||
this.cursorFontFamily = fontFamily;
|
||||
this.cursorFontSize = fontSize;
|
||||
window.webkit.messageHandlers.cursorStyleChanged.postMessage(
|
||||
fontFamily + "," + fontSize
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue