[geary: 4/8] composer: Add font buttons to toolbar



commit 0eed1bb21aff8b66ada9316f00b8ad356dcbf3d3
Author: James Westman <flyingpimonster gmail com>
Date:   Tue Jan 14 22:35:18 2020 -0600

    composer: Add font buttons to toolbar
    
    This replaces the menu options in the overflow menu with nicer looking, more
    discoverable toolbar buttons. They work much the same way as before.

 icons/font-color-symbolic.svg                    |  19 ++
 icons/font-size-symbolic.svg                     |  19 ++
 icons/meson.build                                |   2 +
 src/client/composer/composer-web-view.vala       |  11 +-
 src/client/composer/composer-widget.vala         |  67 ++++---
 src/client/util/util-gtk.vala                    |   9 +
 test/client/composer/composer-web-view-test.vala |  19 +-
 test/js/composer-page-state-test.vala            |   6 +-
 ui/composer-menus.ui                             |  58 ------
 ui/composer-web-view.js                          |   9 +-
 ui/composer-widget.ui                            | 218 ++++++++++++++++++++---
 11 files changed, 316 insertions(+), 121 deletions(-)
---
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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/"; xmlns:cc="http://creativecommons.org/ns#"; 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"; xmlns:svg="http://www.w3.org/2000/svg"; 
xmlns="http://www.w3.org/2000/svg"; id="svg8" version="1.1" height="16" width="16">
+  <metadata id="metadata14">
+    <rdf:RDF>
+      <cc:Work rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+        <dc:title/>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs id="defs12"/>
+  <g transform="translate(-17.966098,-9.83008)" id="g851">
+    <g transform="translate(-123.0341,-347.16992)" id="g11782" style="display:inline;enable-background:new">
+      <path transform="translate(141.0002,357)" d="M 3 2 L 3 4 L 9 4 C 9.42816 4 10 4.61414 10 5 L 10 6 L 5 
6 C 4.08073 6 3.2644 6.3800638 2.75 6.9648438 C 2.2356 7.5496337 2.0072819 8.2891356 2.0136719 9.0097656 C 
2.0200619 9.7303856 2.2591644 10.458569 2.7714844 11.037109 C 3.2838144 11.615649 4.09172 12 5 12 L 7 12 L 7 
10 L 5 10 C 4.60213 10 4.4213712 9.8843506 4.2695312 9.7128906 C 4.1176913 9.5414306 4.0161519 9.2696144 
4.0136719 8.9902344 C 4.0111919 8.7108644 4.1066231 8.4503663 4.2519531 8.2851562 C 4.3972831 8.1199362 
4.57764 8 5 8 L 10 8 L 10 9 L 12 9 L 12 5 C 12 3.36566 10.6802 2 9 2 L 3 2 z " 
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-se
 ttings:n
 
ormal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;anonymous:0;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1"
 i
 d="path8
 57"/>
+    </g>
+    <rect class="success" 
style="opacity:1;vector-effect:none;fill:#ed333b;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
 id="rect11786" width="6.9998798" height="5.9999051" x="25.966673" y="19.831032" rx="2" ry="2"/>
+  </g>
+</svg>
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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/"; xmlns:cc="http://creativecommons.org/ns#"; 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"; xmlns:svg="http://www.w3.org/2000/svg"; 
xmlns="http://www.w3.org/2000/svg"; xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"; 
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"; inkscape:version="1.0beta2 (2b71d25d45, 
2019-12-03)" sodipodi:docname="font-size-symbolic.svg" id="svg4" version="1.1" height="16" width="16">
+  <metadata id="metadata10">
+    <rdf:RDF>
+      <cc:Work rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs id="defs8"/>
+  <sodipodi:namedview inkscape:current-layer="svg4" inkscape:window-maximized="1" inkscape:window-y="0" 
inkscape:window-x="0" inkscape:cy="6.3588258" inkscape:cx="-0.95496834" inkscape:zoom="14.009553" 
showgrid="false" id="namedview6" inkscape:window-height="1016" inkscape:window-width="1920" 
inkscape:pageshadow="2" inkscape:pageopacity="0" guidetolerance="10" gridtolerance="10" objecttolerance="10" 
borderopacity="1" inkscape:document-rotation="0" bordercolor="#666666" pagecolor="#ffffff"/>
+  <g id="g11812" style="fill:#2e3436;fill-opacity:1" transform="translate(-4596.792,-4140.9136)">
+    <rect y="4147.9146" x="4597.7925" height="2" width="5.9998794" id="rect11804" 
style="opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
+    <rect transform="rotate(90)" 
style="opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
 id="rect11806" width="7.9999051" height="2" x="4147.9146" y="-4601.7925"/>
+    <rect 
style="opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
 id="rect11808" width="11.000482" height="3.0000949" x="4601.792" y="4142.9146"/>
+    <rect y="-4608.7925" x="4143.9146" height="3.0001204" width="12" id="rect11810" 
style="opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
 transform="rotate(90)"/>
+  </g>
+</svg>
\ 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<Composer.WebView>
     }
 
     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<Composer.WebView> {
                 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<Composer.WebView> {
     }
 
     public void edit_context_font() throws Error {
-        string html = "<p id=\"test\" style=\"font-family: Comic Sans; font-size: 144\">para</p>";
+        string html = "<p id=\"test\" style=\"font-family: Comic Sans; font-size: 144; color: 
#FF7F01\">para</p>";
         load_body_fixture(html);
 
         try {
@@ -146,7 +146,7 @@ class Composer.PageStateTest : Components.WebViewTestCase<Composer.WebView> {
                 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 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <interface>
-  <menu id="html_menu_model">
-    <section>
-      <item>
-        <attribute name="label" translatable="yes">S_ans Serif</attribute>
-        <attribute name="action">edt.font-family</attribute>
-        <attribute name="target">sans</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">S_erif</attribute>
-        <attribute name="action">edt.font-family</attribute>
-        <attribute name="target">serif</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Fixed Width</attribute>
-        <attribute name="action">edt.font-family</attribute>
-        <attribute name="target">monospace</attribute>
-      </item>
-    </section>
-    <section>
-      <item>
-        <attribute name="label" translatable="yes">_Small</attribute>
-        <attribute name="action">edt.font-size</attribute>
-        <attribute name="target">small</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">_Medium</attribute>
-        <attribute name="action">edt.font-size</attribute>
-        <attribute name="target">medium</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">Lar_ge</attribute>
-        <attribute name="action">edt.font-size</attribute>
-        <attribute name="target">large</attribute>
-      </item>
-    </section>
-    <section>
-      <item>
-        <attribute name="label" translatable="yes">C_olor</attribute>
-        <attribute name="action">edt.color</attribute>
-      </item>
-    </section>
-    <section>
-      <item>
-        <attribute name="label" translatable="yes">_Rich Text</attribute>
-        <attribute name="action">win.compose-as-html</attribute>
-      </item>
-    </section>
-  </menu>
-
-  <menu id="plain_menu_model">
-    <section>
-      <item>
-        <attribute name="label" translatable="yes">_Rich Text</attribute>
-        <attribute name="action">win.compose-as-html</attribute>
-      </item>
-    </section>
-  </menu>
-
   <menu id="context_menu_model">
     <section id="context_menu_webkit_spelling"/>
     <section>
diff --git a/ui/composer-web-view.js b/ui/composer-web-view.js
index e3870190..fc5dbf91 100644
--- a/ui/composer-web-view.js
+++ b/ui/composer-web-view.js
@@ -684,21 +684,24 @@ EditContext.prototype = {
         }
         this.fontFamily = fontFamily;
         this.fontSize = styles.getPropertyValue("font-size").replace("px", "");
+        this.fontColor = styles.getPropertyValue("color");
     },
     equals: function(other) {
         return other != null
             && this.context == other.context
             && this.linkUrl == other.linkUrl
             && this.fontFamily == other.fontFamily
-            && this.fontSize == other.fontSize;
+            && this.fontSize == other.fontSize
+            && this.fontColor == other.fontColor;
     },
     encode: function() {
         return [
             this.context.toString(16),
             this.linkUrl,
             this.fontFamily,
-            this.fontSize
-        ].join(",");
+            this.fontSize,
+            this.fontColor
+        ].join(";");
     }
 };
 
diff --git a/ui/composer-widget.ui b/ui/composer-widget.ui
index 1288ac6e..94768a21 100644
--- a/ui/composer-widget.ui
+++ b/ui/composer-widget.ui
@@ -798,6 +798,137 @@
                                 </style>
                               </object>
                             </child>
+                            <child>
+                              <object class="GtkButton" id="remove_format_button">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="focus_on_click">False</property>
+                                <property name="receives_default">False</property>
+                                <property name="tooltip_text" translatable="yes">Remove text 
formatting</property>
+                                <property name="action_name">edt.remove-format</property>
+                                <property name="always_show_image">True</property>
+                                <child>
+                                  <object class="GtkImage" id="remove_format_image">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="pixel_size">16</property>
+                                    <property name="icon_name">format-text-remove-symbolic</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkBox" id="bottom_buttons">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="spacing">6</property>
+                            <property name="halign">start</property>
+                            <child>
+                              <object class="GtkMenuButton" id="font_button">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="menu_model">font_menu</property>
+                                <property name="tooltip_text" translatable="yes">Change font type</property>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="orientation">horizontal</property>
+                                    <child>
+                                      <object class="GtkStack" id="font_button_stack">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Sans Serif</property>
+                                            <property name="halign">start</property>
+                                          </object>
+                                          <packing>
+                                            <property name="name">sans</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Serif</property>
+                                            <property name="halign">start</property>
+                                          </object>
+                                          <packing>
+                                            <property name="name">serif</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="label" translatable="yes">Fixed Width</property>
+                                            <property name="halign">start</property>
+                                          </object>
+                                          <packing>
+                                            <property name="name">monospace</property>
+                                          </packing>
+                                        </child>
+                                      </object>
+                                    </child>
+                                    <child>
+                                      <object class="GtkImage">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="icon-name">pan-down</property>
+                                      </object>
+                                    </child>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkButton">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="action_name">edt.color</property>
+                                <property name="tooltip_text" translatable="yes">Change font color</property>
+                                <child>
+                                  <object class="GtkImage" id="font_color_icon">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkMenuButton" id="font_size_button">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="menu_model">font_size_menu</property>
+                                <property name="tooltip_text" translatable="yes">Change font size</property>
+                                <child>
+                                  <object class="GtkBox">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="orientation">horizontal</property>
+                                    <child>
+                                      <object class="GtkImage">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="icon-name">font-size-symbolic</property>
+                                      </object>
+                                    </child>
+                                    <child>
+                                      <object class="GtkImage">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="icon-name">pan-down</property>
+                                      </object>
+                                    </child>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
                             <child>
                               <object class="GtkBox" id="insert_buttons">
                                 <property name="visible">True</property>
@@ -857,33 +988,6 @@
                             </child>
                           </object>
                         </child>
-                        <child>
-                          <object class="GtkBox" id="bottom_buttons">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="spacing">6</property>
-                            <property name="halign">start</property>
-                            <child>
-                              <object class="GtkButton" id="remove_format_button">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="focus_on_click">False</property>
-                                <property name="receives_default">False</property>
-                                <property name="tooltip_text" translatable="yes">Remove text 
formatting</property>
-                                <property name="action_name">edt.remove-format</property>
-                                <property name="always_show_image">True</property>
-                                <child>
-                                  <object class="GtkImage" id="remove_format_image">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="pixel_size">16</property>
-                                    <property name="icon_name">format-text-remove-symbolic</property>
-                                  </object>
-                                </child>
-                              </object>
-                            </child>
-                          </object>
-                        </child>
                       </object>
                     </child>
                   </object>
@@ -963,15 +1067,16 @@
                   </object>
                 </child>
                 <child>
-                  <object class="GtkMenuButton" id="menu_button">
+                  <object class="GtkMenuButton" id="text_format_button">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="focus_on_click">False</property>
                     <property name="receives_default">False</property>
+                    <property name="menu_model">rich_text_menu</property>
                     <child>
                       <object class="GtkImage">
                         <property name="visible">True</property>
-                        <property name="icon_name">view-more-symbolic</property>
+                        <property name="icon_name">format-text-bold-symbolic</property>
                       </object>
                     </child>
                   </object>
@@ -1064,4 +1169,59 @@
       <widget name="subject_label"/>
     </widgets>
   </object>
+
+  <menu id="font_menu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">S_ans Serif</attribute>
+        <attribute name="action">edt.font-family</attribute>
+        <attribute name="target">sans</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">S_erif</attribute>
+        <attribute name="action">edt.font-family</attribute>
+        <attribute name="target">serif</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Fixed Width</attribute>
+        <attribute name="action">edt.font-family</attribute>
+        <attribute name="target">monospace</attribute>
+      </item>
+    </section>
+  </menu>
+
+  <menu id="font_size_menu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Small</attribute>
+        <attribute name="action">edt.font-size</attribute>
+        <attribute name="target">small</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Medium</attribute>
+        <attribute name="action">edt.font-size</attribute>
+        <attribute name="target">medium</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Lar_ge</attribute>
+        <attribute name="action">edt.font-size</attribute>
+        <attribute name="target">large</attribute>
+      </item>
+    </section>
+  </menu>
+
+  <menu id="rich_text_menu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Rich Text</attribute>
+        <attribute name="action">win.text-format</attribute>
+        <attribute name="target">html</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Plain Text</attribute>
+        <attribute name="action">win.text-format</attribute>
+        <attribute name="target">plain</attribute>
+      </item>
+    </section>
+  </menu>
 </interface>



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