diff --git a/icons/font-color-symbolic.svg b/icons/font-color-symbolic.svg
new file mode 100644
index 00000000..c51bc931
--- /dev/null
+++ b/icons/font-color-symbolic.svg
@@ -0,0 +1,19 @@
+
+
diff --git a/icons/font-size-symbolic.svg b/icons/font-size-symbolic.svg
new file mode 100644
index 00000000..07ecc544
--- /dev/null
+++ b/icons/font-size-symbolic.svg
@@ -0,0 +1,19 @@
+
+
\ No newline at end of file
diff --git a/icons/meson.build b/icons/meson.build
index 2234d3b0..138ed558 100644
--- a/icons/meson.build
+++ b/icons/meson.build
@@ -6,6 +6,8 @@ icon_files = files(
'detach-symbolic.svg',
'text-x-generic-symbolic.svg',
'edit-symbolic.svg',
+ 'font-size-symbolic.svg',
+ 'font-color-symbolic.svg',
'format-ordered-list-symbolic.svg',
'format-ordered-list-symbolic-rtl.svg',
'format-text-remove-symbolic.svg',
diff --git a/src/client/composer/composer-web-view.vala b/src/client/composer/composer-web-view.vala
index 7f73becd..3dabf7fe 100644
--- a/src/client/composer/composer-web-view.vala
+++ b/src/client/composer/composer-web-view.vala
@@ -55,11 +55,16 @@ public class Composer.WebView : Components.WebView {
public string link_url { get; private set; default = ""; }
public string font_family { get; private set; default = "sans"; }
public uint font_size { get; private set; default = 12; }
+ public Gdk.RGBA font_color {
+ get;
+ private set;
+ default = Util.Gtk.rgba(0, 0, 0, 1);
+ }
private uint context = 0;
public EditContext(string message) {
- string[] values = message.split(",");
+ string[] values = message.split(";");
this.context = (uint) uint64.parse(values[0]);
this.link_url = values[1];
@@ -73,6 +78,10 @@ public class Composer.WebView : Components.WebView {
}
this.font_size = (uint) uint64.parse(values[3]);
+
+ Gdk.RGBA font_color = {0, 0, 0, 0};
+ font_color.parse(values[4]);
+ this.font_color = font_color;
}
}
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
index b4668980..e09a8806 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -129,7 +129,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
private const string ACTION_COLOR = "color";
private const string ACTION_INSERT_IMAGE = "insert-image";
private const string ACTION_INSERT_LINK = "insert-link";
- private const string ACTION_COMPOSE_AS_HTML = "compose-as-html";
+ private const string ACTION_TEXT_FORMAT = "text-format";
private const string ACTION_SHOW_EXTENDED_HEADERS = "show-extended-headers";
private const string ACTION_SHOW_FORMATTING = "show-formatting";
private const string ACTION_DISCARD = "discard";
@@ -181,7 +181,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
{ ACTION_ADD_ORIGINAL_ATTACHMENTS, on_pending_attachments },
{ ACTION_CLOSE, on_close },
{ ACTION_DISCARD, on_discard },
- { ACTION_COMPOSE_AS_HTML, on_toggle_action, null, "true", on_compose_as_html_toggled },
+ { ACTION_TEXT_FORMAT, null, "s", "'html'", on_text_format },
{ ACTION_DETACH, on_detach },
{ ACTION_OPEN_INSPECTOR, on_open_inspector },
{ ACTION_SELECT_DICTIONARY, on_select_dictionary },
@@ -377,13 +377,17 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
[GtkChild] private Gtk.Box toolbar_box;
[GtkChild] private Gtk.Box top_buttons;
[GtkChild] private Gtk.Box bottom_buttons;
+ [GtkChild] private Gtk.MenuButton font_button;
+ [GtkChild] private Gtk.Stack font_button_stack;
+ [GtkChild] private Gtk.MenuButton font_size_button;
+ [GtkChild] private Gtk.Image font_color_icon;
+ [GtkChild] private Gtk.MenuButton text_format_button;
+
[GtkChild]
private Gtk.Button insert_link_button;
[GtkChild]
private Gtk.Button select_dictionary_button;
[GtkChild]
- private Gtk.MenuButton menu_button;
- [GtkChild]
private Gtk.Label info_label;
[GtkChild]
@@ -392,9 +396,6 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
private GLib.SimpleActionGroup composer_actions = new GLib.SimpleActionGroup();
private GLib.SimpleActionGroup editor_actions = new GLib.SimpleActionGroup();
- private Menu html_menu;
- private Menu plain_menu;
-
private Menu context_menu_model;
private Menu context_menu_rich_text;
private Menu context_menu_plain_text;
@@ -549,8 +550,6 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
Gtk.Builder builder = new Gtk.Builder.from_resource(
"/org/gnome/Geary/composer-menus.ui"
);
- this.html_menu = (Menu) builder.get_object("html_menu_model");
- this.plain_menu = (Menu) builder.get_object("plain_menu_model");
this.context_menu_model = (Menu) builder.get_object("context_menu_model");
this.context_menu_rich_text = (Menu) builder.get_object("context_menu_rich_text");
this.context_menu_plain_text = (Menu) builder.get_object("context_menu_plain_text");
@@ -614,6 +613,8 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
((Gtk.CellRendererText) cells.data).ellipsize = END;
load_entry_completions();
+
+ update_color_icon.begin(Util.Gtk.rgba(0, 0, 0, 0));
}
public Widget.from_mailbox(Application.Client application,
@@ -757,8 +758,8 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
// model and hence the menu_button constructs a new
// popover.
this.composer_actions.change_action_state(
- ACTION_COMPOSE_AS_HTML,
- this.application.config.compose_as_html
+ ACTION_TEXT_FORMAT,
+ this.application.config.compose_as_html ? "html" : "plain"
);
set_mode(DETACHED);
@@ -1149,7 +1150,8 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
ACTION_SHOW_EXTENDED_HEADERS, false
);
entries_users.change_action_state(
- ACTION_COMPOSE_AS_HTML, this.application.config.compose_as_html
+ ACTION_TEXT_FORMAT,
+ this.application.config.compose_as_html ? "html" : "plain"
);
}
@@ -2119,9 +2121,9 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
action.change_state(!action.state.get_boolean());
}
- private void on_compose_as_html_toggled(SimpleAction? action, Variant? new_state) {
- bool compose_as_html = new_state.get_boolean();
- action.set_state(compose_as_html);
+ private void on_text_format(SimpleAction? action, Variant? new_state) {
+ bool compose_as_html = new_state.get_string() == "html";
+ action.set_state(new_state.get_string());
foreach (string html_action in HTML_ACTIONS)
get_action(html_action).set_enabled(compose_as_html);
@@ -2132,11 +2134,10 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
show_formatting.set_enabled(compose_as_html);
update_formatting_toolbar();
- this.menu_button.menu_model = (compose_as_html) ? this.html_menu : this.plain_menu;
-
this.editor.set_rich_text(compose_as_html);
this.application.config.compose_as_html = compose_as_html;
+ this.text_format_button.popover.popdown();
}
private void on_show_extended_headers_toggled(GLib.SimpleAction? action,
@@ -2165,10 +2166,14 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
}
private void on_font_family(SimpleAction action, Variant? param) {
+ string font = param.get_string();
this.editor.execute_editing_command_with_argument(
- "fontname", param.get_string()
+ "fontname", font
);
- action.set_state(param.get_string());
+ action.set_state(font);
+
+ this.font_button_stack.visible_child_name = font;
+ this.font_button.popover.popdown();
}
private void on_font_size(SimpleAction action, Variant? param) {
@@ -2182,15 +2187,35 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
this.editor.execute_editing_command_with_argument("fontsize", size);
action.set_state(param.get_string());
+
+ this.font_size_button.popover.popdown();
+ }
+
+ private async void update_color_icon(Gdk.RGBA color) {
+ var theme = Gtk.IconTheme.get_default();
+ var icon = theme.lookup_icon("font-color-symbolic", 16, 0);
+ Gdk.RGBA fg_color = Util.Gtk.rgba(0, 0, 0, 1);
+ this.get_style_context().lookup_color("theme_fg_color", out fg_color);
+
+ try {
+ var pixbuf = yield icon.load_symbolic_async(fg_color, color, null, null, null);
+ this.font_color_icon.pixbuf = pixbuf;
+ } catch(Error e) {
+ warning("Could not load icon `font-color-symbolic`!");
+ this.font_color_icon.icon_name = "font-color-symbolic";
+ }
}
private void on_select_color() {
Gtk.ColorChooserDialog dialog = new Gtk.ColorChooserDialog(_("Select Color"),
this.container.top_window);
if (dialog.run() == Gtk.ResponseType.OK) {
+ var rgba = dialog.get_rgba();
this.editor.execute_editing_command_with_argument(
- "forecolor", dialog.get_rgba().to_string()
+ "forecolor", rgba.to_string()
);
+
+ this.update_color_icon.begin(rgba);
}
dialog.destroy();
}
@@ -2675,6 +2700,8 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
ACTION_FONT_FAMILY, context.font_family
);
+ this.update_color_icon.begin(context.font_color);
+
if (context.font_size < 11)
this.editor_actions.change_action_state(ACTION_FONT_SIZE, "small");
else if (context.font_size > 20)
diff --git a/src/client/util/util-gtk.vala b/src/client/util/util-gtk.vala
index 70864ac9..1d41f2e5 100644
--- a/src/client/util/util-gtk.vala
+++ b/src/client/util/util-gtk.vala
@@ -218,4 +218,13 @@ namespace Util.Gtk {
return new_url;
}
+ public Gdk.RGBA rgba(double red, double green, double blue, double alpha) {
+ return Gdk.RGBA() {
+ red = red,
+ green = green,
+ blue = blue,
+ alpha = alpha
+ };
+ }
+
}
diff --git a/test/client/composer/composer-web-view-test.vala b/test/client/composer/composer-web-view-test.vala
index 64828f04..97c2af29 100644
--- a/test/client/composer/composer-web-view-test.vala
+++ b/test/client/composer/composer-web-view-test.vala
@@ -35,15 +35,20 @@ public class Composer.WebViewTest : Components.WebViewTestCase
}
public void edit_context() throws Error {
- assert(!(new WebView.EditContext("0,,,").is_link));
- assert(new WebView.EditContext("1,,,").is_link);
- assert(new WebView.EditContext("1,url,,").link_url == "url");
+ assert(!(new WebView.EditContext("0;;;;").is_link));
+ assert(new WebView.EditContext("1;;;;").is_link);
+ assert(new WebView.EditContext("1;url;;;").link_url == "url");
- assert(new WebView.EditContext("0,,Helvetica,").font_family == "sans");
- assert(new WebView.EditContext("0,,Times New Roman,").font_family == "serif");
- assert(new WebView.EditContext("0,,Courier,").font_family == "monospace");
+ assert(new WebView.EditContext("0;;Helvetica;;").font_family == "sans");
+ assert(new WebView.EditContext("0;;Times New Roman;;").font_family == "serif");
+ assert(new WebView.EditContext("0;;Courier;;").font_family == "monospace");
- assert(new WebView.EditContext("0,,,12").font_size == 12);
+ assert(new WebView.EditContext("0;;;12;").font_size == 12);
+
+ assert(new WebView.EditContext("0;;;;rgb(0, 0, 0)").font_color == Util.Gtk.rgba(0, 0, 0, 1));
+ assert(new WebView.EditContext("0;;;;rgb(255, 0, 0)").font_color == Util.Gtk.rgba(1, 0, 0, 1));
+ assert(new WebView.EditContext("0;;;;rgb(0, 255, 0)").font_color == Util.Gtk.rgba(0, 1, 0, 1));
+ assert(new WebView.EditContext("0;;;;rgb(0, 0, 255)").font_color == Util.Gtk.rgba(0, 0, 1, 1));
}
public void get_html() throws GLib.Error {
diff --git a/test/js/composer-page-state-test.vala b/test/js/composer-page-state-test.vala
index dfb8566c..6228cc68 100644
--- a/test/js/composer-page-state-test.vala
+++ b/test/js/composer-page-state-test.vala
@@ -127,7 +127,7 @@ class Composer.PageStateTest : Components.WebViewTestCase {
Util.JS.to_string(
run_javascript(@"new EditContext(document.getElementById('test')).encode()")
.get_js_value()
- ).has_prefix("1,url,"));
+ ).has_prefix("1;url;"));
} catch (Util.JS.Error err) {
print("Util.JS.Error: %s\n", err.message);
assert_not_reached();
@@ -138,7 +138,7 @@ class Composer.PageStateTest : Components.WebViewTestCase {
}
public void edit_context_font() throws Error {
- string html = "para
";
+ string html = "para
";
load_body_fixture(html);
try {
@@ -146,7 +146,7 @@ class Composer.PageStateTest : Components.WebViewTestCase {
Util.JS.to_string(
run_javascript(@"new EditContext(document.getElementById('test')).encode()")
.get_js_value()
- ) == "0,,Comic Sans,144");
+ ) == "0;;Comic Sans;144;rgb(255, 127, 1)");
} catch (Util.JS.Error err) {
print("Util.JS.Error: %s\n", err.message);
assert_not_reached();
diff --git a/ui/composer-menus.ui b/ui/composer-menus.ui
index 2f4c342f..7acf20ab 100644
--- a/ui/composer-menus.ui
+++ b/ui/composer-menus.ui
@@ -1,64 +1,6 @@
-
-
-
-