Commit 295fbc2
Customizable color theme
Changed files (53)
modifiedlibbirdfont/BackgroundImage.valamodifiedlibbirdfont/BackgroundSelectionTool.valamodifiedlibbirdfont/BirdFont.valamodifiedlibbirdfont/BirdFontFile.valamodifiedlibbirdfont/Button.valamodifiedlibbirdfont/CharDatabase.valamodifiedlibbirdfont/CharDatabaseParser.valamodifiedlibbirdfont/CheckBox.valamodifiedlibbirdfont/CutBackgroundTool.valamodifiedlibbirdfont/DescriptionDisplay.valamodifiedlibbirdfont/EmptyTab.valamodifiedlibbirdfont/Expander.valamodifiedlibbirdfont/ExportCallback.valamodifiedlibbirdfont/ExportTool.valamodifiedlibbirdfont/FileDialogTab.valamodifiedlibbirdfont/FileTab.valamodifiedlibbirdfont/Font.valamodifiedlibbirdfont/FontName.valamodifiedlibbirdfont/Glyph.valamodifiedlibbirdfont/GridTool.valamodifiedlibbirdfont/Headline.valamodifiedlibbirdfont/KerningDisplay.valamodifiedlibbirdfont/KerningList.valamodifiedlibbirdfont/KerningRange.valamodifiedlibbirdfont/KeyBindings.valamodifiedlibbirdfont/LabelTool.valamodifiedlibbirdfont/LanguageSelectionTab.valamodifiedlibbirdfont/Line.valamodifiedlibbirdfont/MainWindow.valamodifiedlibbirdfont/Menu.valamodifiedlibbirdfont/MenuAction.valamodifiedlibbirdfont/MessageDialog.valamodifiedlibbirdfont/MoveTool.valamodifiedlibbirdfont/OverView.valamodifiedlibbirdfont/OverViewItem.valamodifiedlibbirdfont/Path.valamodifiedlibbirdfont/PenTool.valamodifiedlibbirdfont/Renderer/TextArea.valamodifiedlibbirdfont/ResizeTool.valamodifiedlibbirdfont/SaveDialog.valamodifiedlibbirdfont/SettingsDisplay.valamodifiedlibbirdfont/SettingsItem.valamodifiedlibbirdfont/SpacingTab.valamodifiedlibbirdfont/SpinButton.valamodifiedlibbirdfont/TabBar.valamodifiedlibbirdfont/TabContent.valamodifiedlibbirdfont/Table.valaaddedlibbirdfont/Theme.valamodifiedlibbirdfont/Tool.valamodifiedlibbirdfont/Toolbox.valadeletedlibbirdfont/TooltipArea.valamodifiedlibbirdfont/ZoomBar.valamodifiedresources/key_bindings.xml
Diff
@@ -429,7 +429,7 @@ public class BackgroundImage { ct = new Context (st); ct.save (); - ct.set_source_rgba (1, 1, 1, 1);+ Theme.color (ct, "Background 1"); ct.rectangle (0, 0, allocation.width, allocation.height); ct.fill (); @@ -477,7 +477,7 @@ public class BackgroundImage { wc = get_margin_width (); hc = get_margin_height (); - cg.set_source_rgba (1, 1, 1, 1);+ Theme.color (cg, "Background 1"); cg.rectangle (0, 0, size_margin, size_margin); cg.fill (); @@ -502,7 +502,7 @@ public class BackgroundImage { c.save (); - c.set_source_rgba (1, 1, 1, 1);+ Theme.color (c, "Background 1"); c.rectangle (0, 0, size_margin, size_margin); c.fill (); @@ -589,7 +589,7 @@ public class BackgroundImage { double x, y; cr.save (); - cr.set_source_rgba (1, 0, 0.3, 1);+ Theme.color (cr, "Background 3"); x = img_middle_x - (img_scale_x * get_img ().get_width () / 2); y = img_middle_y - (img_scale_y * get_img ().get_height () / 2);@@ -611,9 +611,9 @@ public class BackgroundImage { cr.scale (g.view_zoom, g.view_zoom); - if (selected_handle == 2) cr.set_source_rgba (1, 0, 0.3, 1);- else if (active_handle == 2) cr.set_source_rgba (0, 0, 0.3, 1);- else cr.set_source_rgba (0.7, 0.7, 0.8, 1);+ if (selected_handle == 2) Theme.color (cr, "Highlighted 1");+ else if (active_handle == 2) Theme.color (cr, "Background 4");+ else Theme.color (cr, "Background 3"); x = img_offset_x - g.view_offset_x + (size_margin / 2) * img_scale_x; y = img_offset_y - g.view_offset_y + (size_margin / 2) * img_scale_y;@@ -647,9 +647,9 @@ public class BackgroundImage { cr.save (); cr.set_line_width (ivz); - if (selected_handle == 1) cr.set_source_rgba (1, 0, 0.3, 1);- else if (active_handle == 1) cr.set_source_rgba (0, 0, 0.3, 1);- else cr.set_source_rgba (0.7, 0.7, 0.8, 1); + if (selected_handle == 1) Theme.color (cr, "Highlighted 1");+ else if (active_handle == 1) Theme.color (cr, "Background 4");+ else Theme.color (cr, "Background 3"); size = (8) * s; @@ -712,7 +712,7 @@ public class BackgroundImage { c = new Context (s); c.save ();- c.set_source_rgba (1, 1, 1, 1);+ Theme.color (c, "Background 1"); c.rectangle (0, 0, scaled_width, scaled_width); c.fill (); @@ -68,7 +68,6 @@ public class BackgroundSelectionTool : CutBackgroundTool { if (bs.assigned_glyph != null) { if (label.has_character ((!) bs.assigned_glyph)) { font_height = 18;- cr.set_source_rgba (1, 1, 1, 1); label.set_text ((!) bs.assigned_glyph); label.set_font_size (font_height); tx = x + w - label.get_width () / 2.0;@@ -428,6 +428,12 @@ public class BirdFont { Preferences.load (); + // FIXME: DELETE+ Theme.load_theme ();+ save_default_colors ();++ Theme.load_theme ();+ current_font = new Font (); current_font.set_name (""); current_font.initialised = false;@@ -478,7 +484,7 @@ public class BirdFont { } Preferences.set_last_file (get_current_font ().get_path ());- + DefaultCharacterSet.create_default_character_sets (); DefaultCharacterSet.get_characters_for_prefered_language (); @@ -489,6 +495,51 @@ public class BirdFont { } } + void save_default_colors () {+ Theme.save_color ("Background 1", 1, 1, 1, 1);+ Theme.save_color ("Background 2", 101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.save_color ("Background 3", 38 / 255.0, 39 / 255.0, 43 / 255.0, 1);+ Theme.save_color ("Background 4", 51 / 255.0, 54 / 255.0, 59 / 255.0, 1);+ Theme.save_color ("Background 5", 0.3, 0.3, 0.3, 1);+ Theme.save_color ("Background 6", 224/255.0, 224/255.0, 224/255.0, 1);+ Theme.save_color ("Background 7", 56 / 255.0, 59 / 255.0, 65 / 255.0, 1);+ Theme.save_color ("Background 7", 55/255.0, 55/255.0, 55/255.0, 1);+ Theme.save_color ("Background 9", 72/255.0, 72/255.0, 72/255.0, 1);+ + Theme.save_color ("Foreground 1", 0, 0, 0, 1);+ Theme.save_color ("Foreground 2", 101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.save_color ("Foreground 3", 26 / 255.0, 30 / 255.0, 32 / 255.0, 1);+ Theme.save_color ("Foreground 4", 40 / 255.0, 57 / 255.0, 65 / 255.0, 1);+ Theme.save_color ("Foreground 5", 70 / 255.0, 77 / 255.0, 83 / 255.0, 1);+ + Theme.save_color ("Highlighted 1", 234 / 255.0, 77 / 255.0, 26 / 255.0, 1);+ + Theme.save_color ("Highlighted Guide", 0, 0, 0.3, 1);+ Theme.save_color ("Guide 1", 0.7, 0.7, 0.8, 1);+ Theme.save_color ("Guide 2", 0.7, 0, 0, 0.5);+ Theme.save_color ("Guide 3", 120 / 255.0, 68 / 255.0, 120 / 255.0, 120 / 255.0);+ + Theme.save_color ("Grid",0.2, 0.6, 0.2, 0.2);+ + Theme.save_color ("Background Glyph", 0.2, 0.2, 0.2, 0.5);+ + N_("Background 1");+ N_("Background 2");+ N_("Background 3");+ N_("Background 4");+ N_("Background 5");+ N_("Background 6");+ N_("Background 7");+ N_("Background 8");+ N_("Background 9");+ + N_("Foreground 1");+ N_("Foreground 2");+ N_("Foreground 3");+ + N_("Highlighted 1");+ }+ public static void set_bundle_path (string path) { bundle_path = path; }@@ -132,8 +132,6 @@ class BirdFontFile : GLib.Object { } catch (GLib.Error e) { warning (e.message); }- - TooltipArea.show_text (t_("Saving")); }); os.put_string ("\n");@@ -168,8 +166,6 @@ class BirdFontFile : GLib.Object { warning (@"Failed to save $path \n"); warning (@"$(ef.message) \n"); }- - TooltipArea.show_text (t_("Saving")); }); os.put_string ("\n");@@ -312,8 +308,6 @@ class BirdFontFile : GLib.Object { } catch (GLib.Error e) { warning (@"$(e.message) \n"); }- - TooltipArea.show_text (t_("Saving")); }); } @@ -726,8 +720,7 @@ class BirdFontFile : GLib.Object { parse_images (t); } }-- TooltipArea.show_text ("");+ return true; } @@ -27,19 +27,19 @@ public class Button : Widget { public Button (string label) { font_size = 17 * MainWindow.units; this.label = new Text (label, font_size);- this.label.set_source_rgba (1, 1, 1, 1);+ Theme.text_color (this.label, "Background 1"); padding = 15 * MainWindow.units; } public override void draw (Context cr) { cr.save ();- cr.set_source_rgba (51 / 255.0, 54 / 255.0, 59 / 255.0, 1);+ Theme.color (cr, "Background 4"); draw_rounded_rectangle (cr, widget_x, widget_y, get_width (), padding, padding); cr.fill (); cr.restore (); cr.save ();- cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); cr.set_line_width (1); draw_rounded_rectangle (cr, widget_x, widget_y, get_width (), padding, padding); cr.stroke ();@@ -36,10 +36,6 @@ public class CharDatabase { GlyphRange ucd_result = new GlyphRange (); unichar c; - if (!database_is_loaded) {- show_loading_message ();- }- return_val_if_fail (!is_null (index), result); return_val_if_fail (result.get_length () == 0, result); @@ -130,15 +126,7 @@ public class CharDatabase { return description; } - public static void show_loading_message () {- TooltipArea.show_text (t_("Loading the unicode character database") + " ...");- }- public static void get_full_unicode (GlyphRange glyph_range) {- if (!database_is_loaded) {- show_loading_message ();- }- try { if (!is_null (full_unicode_range)) { glyph_range.parse_ranges (full_unicode_range.get_all_ranges ());@@ -147,7 +147,6 @@ public class CharDatabaseParser : GLib.Object { IdleSource idle = new IdleSource (); idle.set_callback (() => { CharDatabase.full_unicode_range = utf8;- CharDatabase.show_loading_message (); CharDatabase.database_is_loaded = true; return false; });@@ -54,14 +54,14 @@ public class CheckBox : Widget { double center_y = (get_height () - (h + 2 * padding)) / 2.0 + padding; cr.save ();- cr.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1); + Theme.color (cr, "Background 2"); draw_rounded_rectangle (cr, widget_x, widget_y + center_y, w, h - padding, padding); cr.fill (); cr.restore (); cr.save (); cr.set_line_width (1);- cr.set_source_rgba (0, 0, 0, 1); + Theme.color (cr, "Foreground 1"); draw_rounded_rectangle (cr, widget_x, widget_y + center_y, w, h - padding, padding); cr.stroke (); cr.restore ();@@ -69,7 +69,7 @@ public class CheckBox : Widget { if (checked) { cr.save (); - cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); cr.set_line_width (1); cr.move_to (widget_x + d, widget_y + d + center_y);@@ -94,7 +94,7 @@ public class CutBackgroundTool : Tool { // draw a border around the selection cr.save (); cr.set_line_width (2.0);- cr.set_source_rgba (0, 0, 0, 0.3);+ Theme.color_opacity (cr, "Foreground 1", 0.3); cr.rectangle (fmin (x1, x2), fmin (y1, y2), fabs (x1 - x2), fabs (y1 - y2)); cr.stroke (); cr.restore ();@@ -102,7 +102,7 @@ public class CutBackgroundTool : Tool { // make the area outside of the selection grey cr.save (); cr.set_line_width (0);- cr.set_source_rgba (0, 0, 0, 0.075);+ Theme.color_opacity (cr, "Foreground 1", 0.075); cr.rectangle (0, 0, glyph.allocation.width, fmin (y1, y2)); cr.rectangle (0, fmin (y1, y2), fmin (x1, x2), fabs (y1 - y2)); cr.rectangle (0, fmin (y1, y2) + fabs (y1 - y2), glyph.allocation.width, glyph.allocation.height - fabs (y1 - y2));@@ -170,7 +170,7 @@ public class CutBackgroundTool : Tool { wc = bg.get_margin_width (); hc = bg.get_margin_height (); - cg.set_source_rgba (1, 1, 1, 1);+ Theme.color (cg, "Background 1"); cg.rectangle (0, 0, bg.size_margin, bg.size_margin); cg.fill (); @@ -203,7 +203,7 @@ public class CutBackgroundTool : Tool { sr = new Surface.similar (sg, img.get_content (), (int) (w / bg.img_scale_x), (int) (h / bg.img_scale_y)); cr = new Context (sr); - cr.set_source_rgba (1, 1, 1, 1);+ Theme.color (cr, "Background 1"); cr.rectangle (0, 0, w, h); cr.fill (); @@ -181,7 +181,9 @@ public class DescriptionDisplay : FontDisplay { cr.save (); cr.rectangle (0, 0, allocation.width, allocation.height); cr.set_line_width (0);- cr.set_source_rgba (51 / 255.0, 54 / 255.0, 59 / 255.0, 1);+ + Theme.color (cr, "Background 4");+ cr.fill (); cr.stroke (); cr.restore ();@@ -190,7 +192,7 @@ public class DescriptionDisplay : FontDisplay { if (w.is_on_screen ()) { if (w is Text) { cr.save ();- cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); w.draw (cr); cr.restore (); } else {@@ -36,7 +36,7 @@ public class EmptyTab : FontDisplay { public override void draw (WidgetAllocation allocation, Context cr) { cr.save ();- cr.set_source_rgba (242/255.0, 241/255.0, 240/255.0, 1);+ Theme.color (cr, "Background 9"); cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill (); cr.restore ();@@ -232,13 +232,13 @@ public class Expander : GLib.Object { if (headline != null) { title = new Text (); title.set_text ((!) headline);- title.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.text_color (title, "Foreground 2"); title.set_font_size (17 * Toolbox.get_scale ()); title.draw_at_baseline (cr, x, yt + HEADLINE_MARGIN + 13 * Toolbox.get_scale ());- } else if (draw_separator) { + } else if (draw_separator) { cr.save (); cr.set_line_width (0.5);- cr.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.color (cr, "Foreground 2"); cr.move_to (x, yt); cr.line_to (wd - w - x + 6, yt); cr.stroke ();@@ -248,7 +248,8 @@ public class Expander : GLib.Object { cr.save (); cr.new_path (); cr.set_line_width (1);- cr.set_source_rgba (0, 0, 0, opacity);+ + Theme.color_opacity (cr, "Foreground 2", opacity); cr.move_to (x - iw2 + 3, yt - ih2 - 0.7 + 1); cr.line_to (x + iw2 + 3, yt - ih2 - 0.7 + 1);@@ -43,7 +43,6 @@ public class ExportCallback : GLib.Object { public static void export_fonts () { ExportTool.export_ttf_font (); ExportTool.export_svg_font ();- TooltipArea.show_text (t_("Three font files have been created.")); } } @@ -401,9 +401,7 @@ os.put_string ( if (eot_file.query_exists ()) { eot_file.delete (); }- - TooltipArea.show_text (t_("Writing TTF and EOT files."));- + write_ttf ((!) ttf_file.get_path ()); write_eot ((!) ttf_file.get_path (), (!) eot_file.get_path ()); } catch (Error e) {@@ -416,7 +414,6 @@ os.put_string ( public static bool export_svg_font () { Font font = BirdFont.get_current_font ();- TooltipArea.show_text (t_("Writing SVG file.")); return export_svg_font_path (font.get_folder ()); } @@ -439,7 +436,6 @@ os.put_string ( fo.close (); } catch (Error e) { critical (@"$(e.message)");- TooltipArea.show_text (e.message); return false; } @@ -150,13 +150,13 @@ public class FileDialogTab : FontDisplay { visible_rows = (int) (allocation.height / 18.0); cr.save ();- cr.set_source_rgba (1, 1, 1, 1);+ Theme.color (cr, "Background 4"); cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill (); cr.restore (); cr.save ();- cr.set_source_rgba (0.3, 0.3, 0.3, 1);+ Theme.color (cr, "Background 5"); cr.set_font_size (12); foreach (string file in directories) {@@ -184,13 +184,13 @@ public class FileDialogTab : FontDisplay { if (color) { if (dark) { cr.save ();- cr.set_source_rgba (55/255.0, 55/255.0, 55/255.0, 1);+ Theme.color (cr, "Background 8"); cr.rectangle (0, y - 14 * MainWindow.units, allocation.width, 18 * MainWindow.units); cr.fill (); cr.restore (); } else { cr.save ();- cr.set_source_rgba (224/255.0, 224/255.0, 224/255.0, 1);+ Theme.color (cr, "Background 6"); cr.rectangle (0, y - 14 * MainWindow.units, allocation.width, 18 * MainWindow.units); cr.fill (); cr.restore ();@@ -198,7 +198,7 @@ public class FileDialogTab : FontDisplay { } else { if (dark) { cr.save ();- cr.set_source_rgba (72/255.0, 72/255.0, 72/255.0, 1);+ Theme.color (cr, "Background 9"); cr.rectangle (0, y - 14 * MainWindow.units, allocation.width, 18 * MainWindow.units); cr.fill (); cr.restore ();@@ -207,7 +207,7 @@ public class FileDialogTab : FontDisplay { cr.save (); if (dark) {- cr.set_source_rgba (255/255.0, 255/255.0, 255/255.0, 1);+ Theme.color (cr, "Background 1"); } cr.move_to (60, y); cr.set_font_size (12 * MainWindow.units);@@ -238,14 +238,14 @@ public class FileTab : FontDisplay { visible_rows = (int) (allocation.height / row_height); cr.save ();- cr.set_source_rgba (1, 1, 1, 1);+ Theme.color (cr, "Background 1"); cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill (); cr.restore (); if (recent_fonts.size == 0 && !has_backup ()) { cr.save ();- cr.set_source_rgba (0.3, 0.3, 0.3, 1);+ Theme.color (cr, "Background 5"); cr.set_font_size (18 * MainWindow.units); cr.move_to (50 * MainWindow.units, top - 9 * MainWindow.units); cr.show_text (t_("No fonts created yet."));@@ -256,7 +256,7 @@ public class FileTab : FontDisplay { if (scroll == 0 && recent_fonts.size > 0) { cr.save ();- cr.set_source_rgba (0.3, 0.3, 0.3, 1);+ Theme.color (cr, "Background 5"); cr.set_font_size (18 * MainWindow.units); cr.move_to (50 * MainWindow.units, top - 9 * MainWindow.units); cr.show_text (t_("Recent files"));@@ -264,7 +264,7 @@ public class FileTab : FontDisplay { } cr.save ();- cr.set_source_rgba (0.3, 0.3, 0.3, 1);+ Theme.color (cr, "Background 5"); cr.set_font_size (12 * MainWindow.units); foreach (Font font in recent_fonts) {@@ -280,7 +280,7 @@ public class FileTab : FontDisplay { if (s >= scroll) { cr.save ();- cr.set_source_rgba (0.3, 0.3, 0.3, 1);+ Theme.color (cr, "Background 5"); cr.set_font_size (18 * MainWindow.units); cr.move_to (50 * MainWindow.units, y + 2 * row_height - 9 * MainWindow.units); cr.show_text (t_("Backup"));@@ -648,7 +648,6 @@ public class Font : GLib.Object { if (read_only) { warning (@"$path is write protected.");- TooltipArea.show_text (t_("The file is write protected.")); return; } @@ -50,7 +50,7 @@ public class FontName : Tool { text_height *= max_width / extent; } - font_name.set_source_rgba (234 / 255.0, 77 / 255.0, 26 / 255.0, 1);+ Theme.text_color (font_name, "Highlighted 1"); font_name.set_font_size (text_height); font_name.draw_at_baseline (cr, x, y + 13 * Toolbox.get_scale ()); cr.restore ();@@ -404,7 +404,7 @@ public class Glyph : FontDisplay { double bgt = BirdFont.get_current_font ().top_limit; Line top_margin_line = new Line ("top margin", bgt, false);- top_margin_line.set_color (0.7, 0, 0, 0.5);+ top_margin_line.set_color_theme ("Guide 2"); top_margin_line.position_updated.connect ((pos) => { BirdFont.get_current_font ().top_limit = pos; });@@ -418,7 +418,7 @@ public class Glyph : FontDisplay { double xhp = BirdFont.get_current_font ().xheight_position; Line xheight_line = new Line ("x-height", xhp, false);- xheight_line.set_color (120 / 255.0, 68 / 255.0, 120 / 255.0, 120 / 255.0);+ xheight_line.set_color_theme ("Guide 3"); xheight_line.dashed = true; xheight_line.position_updated.connect ((pos) => { Font f = BirdFont.get_current_font ();@@ -434,14 +434,13 @@ public class Glyph : FontDisplay { double bp = BirdFont.get_current_font ().bottom_position; Line bottom_line = new Line ("bottom", bp, false);- bottom_line.set_color (33 / 255.0, 68 / 255.0, 120 / 255.0, 166 / 255.0); bottom_line.position_updated.connect ((pos) => { BirdFont.get_current_font ().bottom_position = pos; }); double bgb = BirdFont.get_current_font ().bottom_limit; Line bottom_margin_line = new Line ("bottom margin", bgb, false);- bottom_margin_line.set_color (0.7, 0, 0, 0.5);+ bottom_margin_line.set_color_theme ("Guide 2"); bottom_margin_line.position_updated.connect ((pos) => { BirdFont.get_current_font ().bottom_limit = pos; });@@ -1428,7 +1427,7 @@ public class Glyph : FontDisplay { } private void draw_coordinate (Context cr) {- cr.set_source_rgba (0.5, 0.5, 0.5, 1);+ Theme.color (cr, "Foreground 3"); cr.set_font_size (12); cr.move_to (0, 10); cr.show_text (@"($motion_x, $motion_y)");@@ -1533,20 +1532,20 @@ public class Glyph : FontDisplay { private void draw_zoom_area(Context cr) { cr.save (); cr.set_line_width (2.0);- cr.set_source_rgba (0, 0, 1, 0.3);+ Theme.color (cr, "Foreground 3"); cr.rectangle (Math.fmin (zoom_x1, zoom_x2), Math.fmin (zoom_y1, zoom_y2), Math.fabs (zoom_x1 - zoom_x2), Math.fabs (zoom_y1 - zoom_y2)); cr.stroke (); cr.restore (); } private void draw_background_color (Context cr, double opacity) {- cr.save ();- cr.rectangle (0, 0, allocation.width, allocation.height);- cr.set_line_width (0);- cr.set_source_rgba (1, 1, 1, opacity);- cr.fill ();- cr.stroke ();- cr.restore ();+ if (opacity > 0) {+ cr.save ();+ cr.rectangle (0, 0, allocation.width, allocation.height);+ Theme.color (cr, "Background 1");+ cr.fill ();+ cr.restore ();+ } } private void draw_help_lines (Context cr) {@@ -1776,34 +1775,6 @@ public class Glyph : FontDisplay { redraw_area (0, 0, allocation.width, allocation.height); }- - public ImageSurface get_thumbnail () {- ImageSurface img;- Context cr;- double gx, gy;- double x1, x2, y1, y2;- Font font = BirdFont.get_current_font ();-- remove_empty_paths ();- boundaries (out x1, out y1, out x2, out y2);-- if (x2 - x1 < 1 || y2 - y1 < 1) { // create an empty thumbnail - img = new ImageSurface (Format.ARGB32, 100, 100);- } else {- img = new ImageSurface (Format.ARGB32, (int) (x2 - x1), (int) (y2 - y1));- }- - gx = left_limit - x1;- gy = (y2 - y1) + font.base_line + y1;- - cr = new Context (img);- - cr.save ();- cr.set_source_rgba (0, 0, 0, 1);- Svg.draw_svg_path (cr, get_svg_data (), gx, gy); - cr.restore ();- return img;- } /** Split curve in two parts and add a new point in between. * @return the new point@@ -1903,7 +1874,7 @@ public class Glyph : FontDisplay { cr.save (); cr.scale (glyph.view_zoom, glyph.view_zoom);- cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); Svg.draw_svg_path (cr, juxtaposed.get_svg_data (), marker_x, marker_y); cr.restore ();@@ -1938,7 +1909,7 @@ public class Glyph : FontDisplay { cr.save (); cr.scale (glyph.view_zoom, glyph.view_zoom); cr.translate (-glyph.view_offset_x, -glyph.view_offset_y);- cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); Svg.draw_svg_path (cr, juxtaposed.get_svg_data (), marker_x, marker_y); cr.restore (); }@@ -1972,7 +1943,8 @@ public class Glyph : FontDisplay { cr.save (); cr.scale (view_zoom, view_zoom); cr.translate (-view_offset_x, -view_offset_y);- cr.set_source_rgba (0.2, 0.2, 0.2, 0.5);+ Theme.color (cr, "Background Glyph");+ Svg.draw_svg_path (cr, g.get_svg_data (), Glyph.xc () + left - (left - current_left) , Glyph.yc () - baseline);@@ -99,11 +99,13 @@ class GridTool : Tool { public static void update_lines () { Glyph g = MainWindow.get_current_glyph (); double step = size_y;+ Color color = Theme.get_color ("Grid"); double i; int max_lines = 600; int n; Line t, l, u; + Line baseline = g.get_line ("baseline"); Line bottom_margin = g.get_line ("bottom margin"); Line top_margin = g.get_line ("top margin");@@ -118,7 +120,7 @@ class GridTool : Tool { for (i = left.get_pos () - 7 * step; i <= right.get_pos () + 7 * step; i += step) { l = new Line ("grid", i, Line.VERTICAL); l.set_moveable (false);- l.set_color (0.2, 0.6, 0.2, 0.2);+ l.set_color (color.r, color.g, color.b, color.a); vertical.add (l); if (++n >= max_lines) {@@ -130,7 +132,7 @@ class GridTool : Tool { for (i = baseline.get_pos () - step; i >= bottom_margin.get_pos () - 7 * step; i -= step) { t = new Line ("grid", i, Line.HORIZONTAL); t.set_moveable (false);- t.set_color (0.2, 0.6, 0.2, 0.2);+ t.set_color (color.r, color.g, color.b, color.a); horizontal.insert (0, t); if (++n >= max_lines) {@@ -142,7 +144,7 @@ class GridTool : Tool { for (i = baseline.get_pos (); i <= top_margin.get_pos () + 7 * step; i += step) { u = new Line ("grid", i, Line.HORIZONTAL); u.set_moveable (false);- u.set_color (0.2, 0.6, 0.2, 0.2);+ u.set_color (color.r, color.g, color.b, color.a); horizontal.add (u); if (++n >= max_lines) {@@ -28,7 +28,7 @@ class Headline : Widget { public override void draw (Context cr) { cr.save ();- cr.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.color (cr, "Background 2"); cr.rectangle (0, widget_y, allocation.width, 40 * MainWindow.units); cr.fill (); cr.restore ();@@ -101,7 +101,7 @@ public class KerningDisplay : FontDisplay { // bg color cr.save ();- cr.set_source_rgba (1, 1, 1, 1);+ Theme.color (cr, "Background 1"); cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill (); cr.restore ();@@ -166,7 +166,7 @@ public class KerningDisplay : FontDisplay { cr.save (); if (selected_handle == i) {- cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); } else { cr.set_source_rgba (123/255.0, 123/255.0, 123/255.0, 1); }@@ -233,7 +233,7 @@ public class KerningDisplay : FontDisplay { caret_y = get_row_height () + font.base_line + 20; cr.save (); cr.set_line_width (1.0 / KerningTools.font_size);- cr.set_source_rgba (0, 0, 0, 0.5);+ Theme.color_opacity (cr, "Foreground 1", 0.5); cr.move_to (x2, caret_y + 20); cr.line_to (x2, 20); cr.stroke ();@@ -57,13 +57,13 @@ public class KerningList : FontDisplay { visible_rows = (int) (allocation.height / 18.0); cr.save ();- cr.set_source_rgba (1, 1, 1, 1);+ Theme.color (cr, "Background 1"); cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill (); cr.restore (); cr.save ();- cr.set_source_rgba (0.3, 0.3, 0.3, 1);+ Theme.color (cr, "Background 5"); cr.set_font_size (12); classes.get_classes ((left, right, kerning) => {@@ -97,7 +97,7 @@ public class KerningList : FontDisplay { if (color) { cr.save ();- cr.set_source_rgba (224/255.0, 224/255.0, 224/255.0, 1);+ Theme.color (cr, "Background 6"); cr.rectangle (0, y - 14, allocation.width, 18); cr.fill (); cr.restore ();@@ -44,12 +44,6 @@ public class KerningRange : Tool { }); panel_move_action.connect ((selected, button, tx, ty) => {- active = is_over (tx, ty);- - if (active) {- TooltipArea.show_text (t_("Right click to edit the class and left click to kern glyphs in the class."));- }- return false; }); @@ -136,13 +130,8 @@ public class KerningRange : Tool { cr.save (); - if (malformed) { - cr.set_source_rgba (0, 0, 0, 1);- } else if (!active) {- cr.set_source_rgba (99/255.0, 99/255.0, 99/255.0, 1);- } else {- cr.set_source_rgba (0, 0, 0, 1);- }+ // FIXME: use color to indicate error+ Theme.color (cr, "Foreground 1"); cr.set_font_size (10); cr.select_font_face ("Cantarell", FontSlant.NORMAL, FontWeight.NORMAL);@@ -14,8 +14,6 @@ namespace BirdFont { -// FIXME a lot of these things have been replaced and can safely be removed- public enum Key { NONE = 0, UP = 65362,@@ -55,7 +55,7 @@ public class LabelTool : Tool { // background if (is_selected ()) { cr.save ();- cr.set_source_rgba (38 / 255.0, 39 / 255.0, 43 / 255.0, 1);+ Theme.color (cr, "Background 3"); cr.rectangle (0, y - 2, w, h + 7); cr.fill (); cr.restore (); @@ -68,9 +68,9 @@ public class LabelTool : Tool { text_height = 18; if (is_selected ()) {- label_text.set_source_rgba (1, 1, 1, 1);+ Theme.text_color (label_text, "Background 1"); } else {- label_text.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.text_color (label_text, "Foreground 2"); } label_text.set_font_size (text_height);@@ -98,9 +98,9 @@ public class LabelTool : Tool { center_y = bgy + ((!) counter_background).get_height () / 2.0 + 4 / scale; if (is_selected ()) {- glyph_count.set_source_rgba (1, 1, 1, 1);+ Theme.text_color (glyph_count, "Background 1"); } else {- glyph_count.set_source_rgba (51 / 255.0, 54 / 255.0, 59 / 255.0, 1);+ Theme.text_color (glyph_count, "Background 4"); } glyph_count.set_font_size (text_height);@@ -55,13 +55,13 @@ public class LanguageSelectionTab : FontDisplay { visible_rows = (int) (allocation.height / 18.0); cr.save ();- cr.set_source_rgba (1, 1, 1, 1);+ Theme.color (cr, "Background 1"); cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill (); cr.restore (); cr.save ();- cr.set_source_rgba (0.3, 0.3, 0.3, 1);+ Theme.color (cr, "Background 5"); cr.set_font_size (12); foreach (string language in DefaultLanguages.names) {@@ -78,7 +78,7 @@ public class LanguageSelectionTab : FontDisplay { if (color) { cr.save ();- cr.set_source_rgba (224/255.0, 224/255.0, 224/255.0, 1);+ Theme.color (cr, "Background 6"); cr.rectangle (0, y - 14, allocation.width, 18); cr.fill (); cr.restore ();@@ -51,10 +51,7 @@ public class Line : GLib.Object { dashed = false; metrics = ""; - r = 0.7;- g = 0.7;- b = 0.8;- a = 1;+ set_color_theme ("Guide 1"); } public Line copy () {@@ -102,6 +99,15 @@ public class Line : GLib.Object { moveable = m; } + public void set_color_theme (string color) {+ Color c = Theme.get_color (color);+ + r = c.r;+ g = c.g;+ b = c.b;+ a = c.a;+ }+ public void set_color (double r, double g, double b, double a) { this.r = r; this.g = g;@@ -304,7 +310,7 @@ public class Line : GLib.Object { } if (active) {- cr.set_source_rgba (0, 0, 0.3, 1);+ Theme.color (cr, "Highlighted Guide"); } else { cr.set_source_rgba (r, this.g, b, a); }@@ -330,7 +336,7 @@ public class Line : GLib.Object { if (get_active ()) { glyph_metrics = new Text (metrics, 17);- glyph_metrics.set_source_rgba (72 / 255.0, 72 / 255.0, 72 / 255.0, 1);+ Theme.text_color (glyph_metrics, "Highlighted Guide"); glyph_metrics.widget_x = p + 10; glyph_metrics.widget_y = h - 25; glyph_metrics.draw (cr);@@ -371,7 +377,7 @@ public class Line : GLib.Object { } if (active) {- line_label.set_source_rgba (0, 0, 0.3, 1);+ Theme.text_color (line_label, "Highlighted Guide"); } else { line_label.set_source_rgba (r, this.g, b, a); }@@ -21,7 +21,6 @@ public class MainWindow : GLib.Object { public static MainWindow singleton; public static MenuTab menu_tab; public static FileTab file_tab; - public static TooltipArea tooltip; public static OverView over_view; public static TabBar tabs; public static NativeWindow native_window; @@ -44,7 +43,6 @@ public class MainWindow : GLib.Object { tools = new Toolbox (glyph_canvas, tabs); menu_tab = new MenuTab (); file_tab = new FileTab (); - tooltip = new TooltipArea (); over_view = new OverView(); kerning_display = new KerningDisplay (); character_database = new CharDatabase (); @@ -177,10 +175,6 @@ public class MainWindow : GLib.Object { return tabs.get_selected_tab (); } - public static TooltipArea get_tooltip () { - return tooltip; - } - public static bool select_tab (Tab t) { return tabs.selected_open_tab (t); } @@ -359,7 +359,7 @@ public class Menu : GLib.Object { }); kerning_menu.items.add (list_kernings); - MenuItem show_spacing = add_menu_item (t_("Spacing Classes"), "show spacing tab");+ MenuItem show_spacing = add_menu_item (t_("Spacing Classes"), "show spacing classes"); show_spacing.action.connect (() => { MenuTab.show_spacing_class_tab (); show_menu = false;@@ -660,7 +660,7 @@ public class Menu : GLib.Object { foreach (MenuItem item in current_menu.items) { cr.save ();- cr.set_source_rgba (38 / 255.0, 39 / 255.0, 43 / 255.0, 1);+ Theme.color (cr, "Background 3"); cr.rectangle (x, y, width, height); cr.fill (); cr.restore ();@@ -668,7 +668,7 @@ public class Menu : GLib.Object { cr.save (); label_x = allocation.width - width + 0.7 * height * MainWindow.units; label_y = y + font_size - 1 * MainWindow.units;- item.label.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.text_color (item.label, "Foreground 2"); item.label.draw_at_baseline (cr, label_x, label_y); key_binding.set_text (item.get_key_bindings ());@@ -676,7 +676,7 @@ public class Menu : GLib.Object { binding_extent = key_binding.get_extent (); label_x = x + width - binding_extent - 0.6 * height * MainWindow.units; key_binding.set_font_size (font_size);- key_binding.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.text_color (key_binding, "Foreground 2"); key_binding.draw_at_baseline (cr, label_x, label_y); y += height;@@ -699,11 +699,12 @@ public class Menu : GLib.Object { } try {- os = new DataOutputStream (file.create (FileCreateFlags.REPLACE_DESTINATION));- os.put_string ("""<?xml version="1.0" encoding="utf-8" standalone="yes"?>""");- os.put_string ("\n");- - os.put_string ("<bindings>\n");+ os = new DataOutputStream (file.create (FileCreateFlags.REPLACE_DESTINATION));+ os.put_string ("""<?xml version="1.0" encoding="utf-8" standalone="yes"?>""");+ os.put_string ("\n");+ + os.put_string ("<bindings>\n");+ foreach (MenuItem item in sorted_menu_items) { os.put_string ("\t<action "); @@ -43,7 +43,7 @@ public class MenuAction : GLib.Object { if (selected) { cr.save ();- cr.set_source_rgba (234/255.0, 234/255.0, 234/255.0, 1);+ Theme.color (cr, "Selected Menu Item"); cr.rectangle (x - 2, y - 12, 93, 15); cr.fill_preserve (); cr.stroke ();@@ -59,7 +59,8 @@ public class MenuAction : GLib.Object { } cr.save ();- cr.set_source_rgba (0, 0, 0, 1);+ + Theme.color (cr, "Foreground 1"); cr.set_font_size (12); cr.select_font_face ("Cantarell", FontSlant.NORMAL, FontWeight.NORMAL);@@ -51,19 +51,19 @@ public class MessageDialog : Dialog { cy = (allocation.height - height) / 2.0; cr.save ();- cr.set_source_rgba (0, 0, 0, 0.3);+ Theme.color_opacity (cr, "Foreground 1", 0.3); cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill (); cr.restore (); cr.save ();- cr.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.color (cr, "Background 2"); draw_rounded_rectangle (cr, cx, cy, width, height, 10 * MainWindow.units); cr.fill (); cr.restore (); cr.save ();- cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); cr.set_line_width (1); draw_rounded_rectangle (cr, cx, cy, width, height, 10 * MainWindow.units); cr.stroke ();@@ -228,7 +228,7 @@ public class MoveTool : Tool { cr.save (); - cr.set_source_rgba (0, 0, 0.3, 1);+ Theme.color (cr, "Background 4"); cr.set_line_width (2); cr.rectangle (x, y, w, h); cr.stroke ();@@ -439,7 +439,8 @@ public class OverView : FontDisplay { // clear canvas cr.save ();- cr.set_source_rgba (1, 1, 1, 1);+ Theme.color (cr, "Background 1");+ cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill (); cr.restore ();@@ -459,7 +460,7 @@ public class OverView : FontDisplay { void draw_empty_canvas (WidgetAllocation allocation, Context cr) { cr.save ();- cr.set_source_rgba (156/255.0, 156/255.0, 156/255.0, 1);+ Theme.color (cr, "Background 7"); cr.move_to (30, 40); cr.set_font_size (18); cr.show_text (t_("No glyphs in this view."));@@ -1114,13 +1115,13 @@ public class OverView : FontDisplay { // background cr.save ();- cr.set_source_rgba (1, 1, 1, 0.98);+ Theme.color_opacity (cr, "Background 1", 0.98); cr.rectangle (x, y, w, h); cr.fill (); cr.restore (); cr.save ();- cr.set_source_rgba (0, 0, 0, 0.98);+ Theme.color_opacity (cr, "Foreground 1", 0.98); cr.set_line_width (2); cr.rectangle (x, y, w, h); cr.stroke ();@@ -1172,7 +1173,7 @@ public class OverView : FontDisplay { void draw_info_line (string line, Context cr, double x, double y, int row) { cr.save (); cr.set_font_size (12);- cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); cr.move_to (x + 10, y + 28 + row * 18 * 1.2); cr.show_text (line); cr.restore (); @@ -97,13 +97,13 @@ public class OverViewItem : GLib.Object { public void draw (Context cr) { cr.save ();- cr.set_source_rgba (1, 1, 1, 1);+ Theme.color (cr, "Background 1"); cr.rectangle (x, y, width, height); cr.fill (); cr.restore (); cr.save ();- cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); cr.rectangle (x, y, width, height); cr.set_line_width (0.5); cr.stroke ();@@ -234,7 +234,7 @@ public class OverViewItem : GLib.Object { cr.save (); cr.set_font_size (14);- cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); cr.move_to (x + 0.08 * width, y + height - 6); if (glyphs == null) {@@ -211,7 +211,7 @@ public class Path { cr.save (); - cr.set_source_rgba (0, 0, 0.3, 1);+ Theme.color (cr, "Background 4"); cr.set_line_width (2); cr.rectangle (x, y, x2 - x, y2 - y); cr.stroke ();@@ -1617,7 +1617,7 @@ public class Path { cr.save (); all_of_path ((x, y) => {- //cr.set_source_rgba (0.3, 0.3, 0.3, 1);+ //Theme.color (cr, "Background 5"); cr.move_to (px + xc, -py + yc); cr.line_to (x + xc, -y + yc); @@ -1225,7 +1225,7 @@ public class PenTool : Tool { h = fmax (selection_box_y, selection_box_last_y) - y; cr.save ();- cr.set_source_rgba (0, 0, 0.3, 1);+ Theme.color (cr, "Background 4"); cr.set_line_width (2); cr.rectangle (x, y, w, h); cr.stroke ();@@ -743,7 +743,7 @@ public class TextArea : Widget { w = next_word.text; if (next_word.widget_y <= tt_click <= next_word.widget_y + font_size) {- next_word.set_source_rgba (0, 0, 0, 1);+ Theme.text_color (next_word, "Foreground 1"); p = next_word.get_sidebearing_extent (); @@ -986,7 +986,7 @@ public class TextArea : Widget { // background cr.save (); cr.set_line_width (1);- cr.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.color (cr, "Foreground 2"); draw_rounded_rectangle (cr, x, y, this.width, this.height, padding); cr.fill (); cr.restore ();@@ -994,7 +994,7 @@ public class TextArea : Widget { // border cr.save (); cr.set_line_width (1);- cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); draw_rounded_rectangle (cr, x, y, this.width, this.height, padding); cr.stroke (); cr.restore ();@@ -1018,7 +1018,7 @@ public class TextArea : Widget { selection_stop = get_selection_stop (); cr.save ();- cr.set_source_rgba (234 / 255.0, 77 / 255.0, 26 / 255.0, 1);+ Theme.color (cr, "Highlighted 1"); for (int i = selection_start.paragraph; i <= selection_stop.paragraph; i++) { return_if_fail (0 <= i < paragraphs.size);@@ -1129,7 +1129,7 @@ public class TextArea : Widget { if (cache_id == -1 && paragraphs.size > 0 && paragraphs.get (0).words.size > 0) { Text t = paragraphs.get (0).words.get (0);- t.set_source_rgba (0, 0, 0, 1);+ Theme.text_color (t, "Foreground 1"); cache_id = t.get_cache_id (); } @@ -1144,8 +1144,8 @@ public class TextArea : Widget { cc = new Context ((!) paragraph.cached_surface); foreach (Text next_word in paragraph.words) {- next_word.set_source_rgba (0, 0, 0, 1);-+ Theme.text_color (next_word, "Foreground 1");+ if (next_word.text != "\n") { next_word.draw_at_top (cc, next_word.widget_x, next_word.widget_y - ty, cache_id); }@@ -229,8 +229,7 @@ public class ResizeTool : Tool { cy = Glyph.reverse_path_coordinate_y (selection_box_center_y); cr.save ();- - cr.set_source_rgba (0, 0, 0.3, 1);+ Theme.color (cr, "Highlight 1"); cr.rectangle (cx - 2.5, cy - 2.5, 5, 5); cr.fill (); @@ -242,7 +241,7 @@ public class ResizeTool : Tool { cr.line_to (cx + hx, cy + hy); cr.stroke (); - cr.set_source_rgba (0, 0, 0.3, 1);+ Theme.color (cr, "Highlight 1"); cr.rectangle (cx + hx - 2.5, cy + hy - 2.5, 5, 5); cr.fill (); @@ -77,7 +77,7 @@ public class SaveDialog : Dialog { save_question.widget_x = save_button.widget_x + center; save_question.widget_y = cy + 15 * MainWindow.units;- save_question.set_source_rgba (1, 1, 1, 1);+ Theme.text_color (save_question, "Background 1"); qh = (question_font_size + 1) * MainWindow.units; @@ -100,19 +100,19 @@ public class SaveDialog : Dialog { cy = (allocation.height - height) / 2.0; cr.save ();- cr.set_source_rgba (0, 0, 0, 0.3);+ Theme.color_opacity (cr, "Foreground 1", 0.3); cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill (); cr.restore (); cr.save ();- cr.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.color (cr, "Background 2"); draw_rounded_rectangle (cr, cx, cy, width, height, 10 * MainWindow.units); cr.fill (); cr.restore (); cr.save ();- cr.set_source_rgba (0, 0, 0, 1);+ Theme.color (cr, "Foreground 1"); cr.set_line_width (1); draw_rounded_rectangle (cr, cx, cy, width, height, 10 * MainWindow.units); cr.stroke ();@@ -221,6 +221,12 @@ public class SettingsDisplay : FontDisplay { foreach (MenuItem menu_item in MainWindow.get_menu ().sorted_menu_items) { tools.add (new SettingsItem.key_binding (menu_item)); }+ + tools.add (new SettingsItem.head_line (t_("Colors")));++ foreach (string color in Theme.color_list) {+ tools.add (new SettingsItem.color (color));+ } } public override void draw (WidgetAllocation allocation, Context cr) { @@ -232,7 +238,7 @@ public class SettingsDisplay : FontDisplay { cr.save (); cr.rectangle (0, 0, allocation.width, allocation.height); cr.set_line_width (0);- cr.set_source_rgba (51 / 255.0, 54 / 255.0, 59 / 255.0, 1);+ Theme.color (cr, "Background 4"); cr.fill (); cr.stroke (); cr.restore ();@@ -53,6 +53,36 @@ class SettingsItem : GLib.Object { handle_events = false; headline = true; }++ public SettingsItem.color (string color) {+ ColorTool cb;+ Color c;+ + c = Theme.get_color (color);++ label = new Text ();+ label.set_text (color);+ handle_events = true;+ + cb = new ColorTool (color);+ cb.set_r (c.r);+ cb.set_g (c.g);+ cb.set_b (c.b);+ cb.set_a (c.a);+ + cb.color_updated.connect (() => {+ TabBar tab_bar;+ + Theme.save_color (color, cb.color_r, cb.color_g, cb.color_b, cb.color_a);+ + tab_bar = MainWindow.get_tab_bar ();+ tab_bar.redraw (0, 0, tab_bar.width, tab_bar.height);+ GlyphCanvas.redraw ();+ Toolbox.redraw_tool_box ();+ });+ + button = cb;+ } public void draw (WidgetAllocation allocation, Context cr) { Tool t;@@ -60,20 +90,20 @@ class SettingsItem : GLib.Object { if (headline) { cr.save ();- cr.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.color (cr, "Background 2"); cr.rectangle (0, y, allocation.width, 40 * MainWindow.units); cr.fill (); cr.restore (); cr.save ();- label.set_source_rgba (1, 1, 1, 1);+ Theme.text_color (label, "Background 1"); label.set_font_size (20 * MainWindow.units); label.draw_at_baseline (cr, 21 * MainWindow.units, y + 25 * MainWindow.units); cr.restore (); } else { if (active) { cr.save ();- cr.set_source_rgba (38 / 255.0, 39 / 255.0, 43 / 255.0, 1);+ Theme.color (cr, "Background 3"); cr.rectangle (0, y - 5 * MainWindow.units, allocation.width, 40 * MainWindow.units); cr.fill (); cr.restore ();@@ -88,7 +118,7 @@ class SettingsItem : GLib.Object { } cr.save ();- label.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.text_color (label, "Foreground 2"); label.set_font_size (17 * MainWindow.units); label.draw_at_baseline (cr, label_x, y + 20 * MainWindow.units); cr.restore ();@@ -99,9 +129,9 @@ class SettingsItem : GLib.Object { cr.save (); if (active) {- key_binding_text.set_source_rgba (1, 1, 1, 1);+ Theme.text_color (key_binding_text, "Background 1"); } else {- key_binding_text.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.text_color (key_binding_text, "Foreground 2"); } key_binding_text.set_font_size (17 * MainWindow.units);@@ -51,14 +51,14 @@ public class SpacingTab : KerningDisplay { // background cr.save ();- cr.set_source_rgba (1, 1, 1, 1);+ Theme.color (cr, "Background 1"); cr.rectangle (0, allocation.height - height, allocation.width, height); cr.fill (); cr.restore (); // character bar cr.save ();- cr.set_source_rgba (0.5, 0.5, 0.5, 1);+ Theme.color (cr, "Foreground 3"); cr.set_line_width (0.8); cr.move_to (0, allocation.height - height); cr.line_to (allocation.width, allocation.height - height);@@ -112,21 +112,21 @@ public class SpacingTab : KerningDisplay { c = g.get_unichar (); cap = new Text ((!) c.to_string (), 17);- cap.set_source_rgba (72 / 255.0, 72 / 255.0, 72 / 255.0, 1);+ Theme.text_color (cap, "Foreground 3"); cap.widget_x = middle - cap.get_extent () / 2.0; cap.widget_y = allocation.height - height + character_height - 4 * MainWindow.units; cap.draw_at_baseline (cr, cap.widget_x, cap.widget_y); l = g.get_left_side_bearing (); left = new Text (truncate (l, 5), 17);- left.set_source_rgba (72 / 255.0, 72 / 255.0, 72 / 255.0, 1);+ Theme.text_color (left, "Foreground 3"); left.widget_x = middle - box_size / 2.0 + (box_size / 2.0 - left.get_extent ()) / 2.0; left.widget_y = allocation.height - 7 * MainWindow.units; left.draw_at_baseline (cr, left.widget_x, left.widget_y); r = g.get_right_side_bearing (); right = new Text (truncate (r, 5), 17);- right.set_source_rgba (72 / 255.0, 72 / 255.0, 72 / 255.0, 1);+ Theme.text_color (right, "Foreground 3"); right.widget_x = end - (box_size / 2.0 - right.get_extent ()) / 2.0 - right.get_extent (); right.widget_y = allocation.height - 7 * MainWindow.units; right.draw_at_baseline (cr, right.widget_x, right.widget_y); @@ -447,9 +447,7 @@ public class SpinButton : Tool { if (!show_icon_tool_icon || waiting_for_icon_switch) { cr.save ();- - cr.set_source_rgba (101 / 255.0, 106 / 255.0, 115 / 255.0, 1);- + Theme.color (cr, "Background 2"); cr.set_font_size (10 * scale); cr.select_font_face ("Cantarell", FontSlant.NORMAL, FontWeight.NORMAL); @@ -18,8 +18,8 @@ namespace BirdFont { public class TabBar : GLib.Object { - int width = 0;- int height = 0;+ public int width = 0;+ public int height = 0; public Gee.ArrayList<Tab> tabs; @@ -677,7 +677,7 @@ public class TabBar : GLib.Object { if (menu_icon != null) { if (MainWindow.get_menu ().show_menu) {- cr.set_source_rgba (38 / 255.0, 39 / 255.0, 43 / 255.0, 1);+ Theme.color (cr, "Background 3"); cr.rectangle (w - 32 / scale, 0, 32 / scale, h); cr.fill (); }@@ -731,19 +731,19 @@ public class TabBar : GLib.Object { // background if (tab_index == selected) { cr.save ();- cr.set_source_rgba (234 / 255.0, 77 / 255.0, 26 / 255.0, 1);+ Theme.color (cr, "Highlighted 1"); cr.rectangle (0, 0, tab_width, h); cr.fill (); cr.restore (); } else if (tab_index == over) { cr.save ();- cr.set_source_rgba (56 / 255.0, 59 / 255.0, 65 / 255.0, 1);+ Theme.color (cr, "Backgrund 7"); cr.rectangle (0, 0, tab_width, h); cr.fill (); cr.restore (); } else { cr.save ();- cr.set_source_rgba (51 / 255.0, 54 / 255.0, 59 / 255.0, 1);+ Theme.color (cr, "Background 4"); cr.rectangle (0, 0, tab_width, h); cr.fill (); cr.restore ();@@ -758,9 +758,9 @@ public class TabBar : GLib.Object { close_opacity = (over_close_tab == tab_index) ? 1 : 0.2; if (tab_index == selected) {- cr.set_source_rgba (40 / 255.0, 57 / 255.0, 65 / 255.0, close_opacity);+ Theme.color_opacity (cr, "Foreground 4", close_opacity); } else {- cr.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, close_opacity);+ Theme.color_opacity (cr, "Foreground 2", close_opacity); } cr.move_to (tab_width - 7 / scale, h / 2.0 - 2.5 / scale);@@ -783,9 +783,9 @@ public class TabBar : GLib.Object { center_y = tab_height / 2.0 + 4 / scale; if (tab_index == selected) {- label.set_source_rgba (40 / 255.0, 57 / 255.0, 65 / 255.0, 1);+ Theme.text_color (label, "Foreground 4"); } else {- label.set_source_rgba (101 / 255.0, 108 / 255.0, 116 / 255.0, 1);+ Theme.text_color (label, "Foreground 2"); } label.set_font_size (text_height);@@ -795,7 +795,7 @@ public class TabBar : GLib.Object { if (tab_index != selected) { // don't draw edges for the selected tab if (tab_index + 1 != selected) { cr.save ();- cr.set_source_rgba (70 / 255.0, 77 / 255.0, 83 / 255.0, 1);+ Theme.color (cr, "Foreground 5"); cr.rectangle (tab_width - 1 / scale, 0, 1 / scale, h); cr.fill (); cr.restore ();@@ -803,7 +803,7 @@ public class TabBar : GLib.Object { if (tab_index == first_tab) { cr.save ();- cr.set_source_rgba (70 / 255.0, 77 / 255.0, 83 / 255.0, 1);+ Theme.color (cr, "Foreground 5"); cr.rectangle (0, 0, 1 / scale, h); cr.fill (); cr.restore ();@@ -64,7 +64,7 @@ public class TabContent : GLib.Object { if (unlikely (MenuTab.suppress_event)) { cr.save ();- cr.set_source_rgba (1, 1, 1, 1);+ Theme.color (cr, "Background 1"); cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill (); cr.restore ();@@ -43,13 +43,13 @@ public abstract class Table : FontDisplay { visible_rows = (int) (allocation.height / 18.0); cr.save ();- cr.set_source_rgba (1, 1, 1, 1);+ Theme.color (cr, "Background 1"); cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill (); cr.restore (); cr.save ();- cr.set_source_rgba (0.3, 0.3, 0.3, 1);+ Theme.color (cr, "Background 5"); cr.set_font_size (12); foreach (Row r in get_rows ()) {@@ -70,7 +70,7 @@ public abstract class Table : FontDisplay { if (color) { cr.save ();- cr.set_source_rgba (224/255.0, 224/255.0, 224/255.0, 1);+ Theme.color (cr, "Background 6"); cr.rectangle (0, y - 14 * MainWindow.units, allocation.width, 18 * MainWindow.units); cr.fill (); cr.restore ();new file mode 100644@@ -0,0 +1,202 @@+/*+ Copyright (C) 2015 Johan Mattsson++ This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version.++ This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details.+*/++using Bird;+using Cairo;++namespace BirdFont {++public class Theme : GLib.Object {++ static Gee.HashMap<string, Color> colors;+ public static Gee.ArrayList<string> color_list;++ public static void text_color (Text text, string name) {+ Color c;+ + if (unlikely (!colors.has_key (name))) {+ warning (@"Theme does not have a color for $name");+ return;+ }+ + c = colors.get (name);+ text.set_source_rgba (c.r, c.g, c.b, c.a);+ }++ public static void color (Context cr, string name) {+ Color c;+ + if (unlikely (!colors.has_key (name))) {+ warning (@"Theme does not have a color for $name");+ return;+ }+ + c = colors.get (name);+ cr.set_source_rgba (c.r, c.g, c.b, c.a);+ }++ public static void color_opacity (Context cr, string name, double opacity) {+ Color c;+ + if (unlikely (!colors.has_key (name))) {+ warning (@"Theme does not have a color for $name");+ return;+ }+ + c = colors.get (name);+ cr.set_source_rgba (c.r, c.g, c.b, opacity);+ }++ public static void text_color_opacity (Text text, string name, double opacity) {+ Color c;+ + if (unlikely (!colors.has_key (name))) {+ warning (@"Theme does not have a color for $name");+ return;+ }+ + c = colors.get (name);+ text.set_source_rgba (c.r, c.g, c.b, opacity);+ }+ public static Color get_color (string name) {+ Color c;+ + if (unlikely (!colors.has_key (name))) {+ warning (@"Theme does not have a color for $name");+ return new Color (0, 0, 0, 1);+ }+ + return colors.get (name);+ }+ + public static void save_color (string name, double r, double g, double b, double a) {+ colors.set (name, new Color (r, g, b, a));+ write_theme ();+ }++ public static void load_theme () {+ File default_theme = SearchPaths.find_file (null, "theme.xml");+ File user_theme = get_child (BirdFont.get_settings_directory (), "theme.xml");++ colors = new Gee.HashMap<string, Color> ();+ color_list = new Gee.ArrayList<string> ();+ + if (default_theme.query_exists ()) {+ parse_theme (default_theme);+ }++ if (user_theme.query_exists ()) {+ parse_theme (user_theme);+ }+ + color_list.sort ();+ }++ public static void write_theme () {+ DataOutputStream os;+ File file;++ file = get_child (BirdFont.get_settings_directory (), "theme.xml");+ + try {+ if (file.query_exists ()) {+ file.delete ();+ }+ } catch (GLib.Error e) {+ warning (e.message);+ }+ + try {+ os = new DataOutputStream (file.create (FileCreateFlags.REPLACE_DESTINATION));+ os.put_string ("""<?xml version="1.0" encoding="utf-8" standalone="yes"?>""");+ os.put_string ("\n");+ + os.put_string ("<theme>\n");+ foreach (string name in colors.keys) {+ Color color = colors.get (name);+ + os.put_string ("\t<color ");+ + os.put_string (@"name=\"$(Markup.escape_text (name))\" "); + os.put_string (@"red=\"$(color.r)\" ");+ os.put_string (@"green=\"$(color.g)\" ");+ os.put_string (@"blue=\"$(color.b)\" ");+ os.put_string (@"alpha=\"$(color.a)\"");+ + os.put_string ("/>\n");+ }+ os.put_string ("</theme>\n");+ + os.close ();+ } catch (GLib.Error e) {+ warning (e.message);+ }+ }++ static void parse_theme (File f) {+ string xml_data;+ XmlParser parser;+ + try {+ FileUtils.get_contents((!) f.get_path (), out xml_data);+ parser = new XmlParser (xml_data);+ parse_colors (parser.get_root_tag ());+ } catch (GLib.Error e) {+ warning (e.message);+ }+ }+ + static void parse_colors (Tag tag) {+ foreach (Tag t in tag) {+ if (t.get_name () == "color") {+ parse_color (t.get_attributes ());+ }+ }+ }+ + static void parse_color (Attributes attributes) {+ string name = "";+ double r = 0;+ double g = 0;+ double b = 0;+ double a = 1;+ + foreach (Attribute attr in attributes) {+ if (attr.get_name () == "name") {+ name = attr.get_content ();+ }+ + if (attr.get_name () == "red") {+ r = double.parse (attr.get_content ());+ }+ + if (attr.get_name () == "green") {+ g = double.parse (attr.get_content ());+ }+ + if (attr.get_name () == "blue") {+ b = double.parse (attr.get_content ());+ }++ if (attr.get_name () == "alpha") {+ a = double.parse (attr.get_content ());+ }+ }+ + color_list.add (name);+ colors.set (name, new Color (r, g, b, a));+ }+}++}@@ -105,7 +105,6 @@ public class Tool : GLib.Object { next_id++; panel_press_action.connect ((self, button, x, y) => {- MainWindow.get_tooltip ().set_text_from_tool (); }); move_out_action.connect ((self) => {@@ -214,10 +213,7 @@ public class Tool : GLib.Object { return (x <= xp <= x + w && y <= yp <= y + h); } - public bool set_selected (bool a) {- TooltipArea? tpa = null; - tpa = MainWindow.get_tooltip ();- + public bool set_selected (bool a) { new_selection = true; selected = a; set_active (a);@@ -233,7 +233,6 @@ public class Toolbox : GLib.Object { bool a; bool consumed = false; bool active;- TooltipArea? tpa = null; foreach (Expander exp in current_set.get_expanders ()) { a = exp.is_over (x, y);@@ -247,14 +246,12 @@ public class Toolbox : GLib.Object { foreach (Tool t in exp.tool) { if (t.tool_is_visible ()) { active = t.is_over (x, y);- tpa = null;- + if (!active && t.is_active ()) { t.move_out_action (t); } update = t.set_active (active);- tpa = MainWindow.get_tooltip (); if (update) { redraw (0, 0, allocation_width, allocation_height);@@ -453,7 +450,7 @@ public class Toolbox : GLib.Object { cr.rectangle (0, 0, w, h); cr.set_line_width (0);- cr.set_source_rgba (51/255.0, 54/255.0, 59/255.0, 1);+ Theme.color (cr, "Background 4"); cr.fill (); draw_expanders (w, h, cr);deleted file mode 100644@@ -1,123 +0,0 @@-/*- Copyright (C) 2012 2013 Johan Mattsson-- This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 3 of the - License, or (at your option) any later version.-- This library is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details.-*/--using Cairo;--namespace BirdFont {--public class TooltipArea : GLib.Object {- string tooltip;- - public signal void redraw ();-- public TooltipArea () {- set_text_from_tool ();- }-- public void update_text () {- set_text_from_current_tool ();- redraw ();- }- - public static void show_text (string text) {- IdleSource idle = new IdleSource ();- idle.set_callback (() => {- if (!is_null (MainWindow.get_tooltip ())) {- MainWindow.get_tooltip ().tooltip = text;- MainWindow.get_tooltip ().redraw ();- }- return false;- });- idle.attach (null);- }- - public void set_text_from_tool () {- set_text_from_current_tool ();- redraw ();- }- - private void set_text_from_current_tool () {- Toolbox? tb = MainWindow.get_toolbox ();- Tool? t;- Tool tool;- StringBuilder sb;- - if (tb == null) {- return;- }- - t = ((!)tb).get_active_tool ();- - if (t == null) {- return;- }- - tool = (!) t;- - if (tool.key != '\0') {- sb = new StringBuilder ();-- sb.append ("(");- - if (tool.modifier_flag == CTRL) {- sb.append ("Ctrl+");- } else if (tool.modifier_flag == SHIFT) {- sb.append ("Shift+");- } -- sb.append_unichar (tool.key);- sb.append (") ");- sb.append (tool.get_tip ());- - show_text (sb.str);- } else {- show_text (tool.get_tip ());- }- - }- - public void draw (Context cr, WidgetAllocation alloc) {- cr.save ();- cr.rectangle (0, 0, alloc.width, alloc.height);- cr.set_line_width (0);- cr.set_source_rgba (200/255.0, 200/255.0, 200/255.0, 1);- cr.fill_preserve ();- cr.stroke ();- cr.restore ();-- cr.save ();- cr.rectangle (0, 0, alloc.width, 1);- cr.set_line_width (0);- cr.set_source_rgba (127/255.0, 127/255.0, 127/255.0, 1);- cr.fill_preserve ();- cr.stroke ();- cr.restore ();- - cr.save ();- cr.rectangle (0, 1, alloc.width, 1);- cr.set_line_width (0);- cr.set_source_rgba (170/255.0, 170/255.0, 170/255.0, 1);- cr.fill_preserve ();- cr.stroke ();- cr.restore ();- - cr.save ();- cr.set_font_size (14);- cr.move_to (5, 15);- cr.show_text (tooltip);- cr.restore ();- }-}--}@@ -86,21 +86,21 @@ public class ZoomBar : Tool { // filled cr.save ();- cr.set_source_rgba (26 / 255.0, 30 / 255.0, 32 / 255.0, 1);+ Theme.color (cr, "Foreground 3"); draw_bar (cr); cr.fill (); cr.restore (); // remove non filled parts cr.save ();- cr.set_source_rgba (51 / 255.0, 54 / 255.0, 59 / 255.0, 1);+ Theme.color (cr, "Background 4"); cr.rectangle (x + bar_width * zoom_level, y, w, h); cr.fill (); cr.restore (); // border cr.save ();- cr.set_source_rgba (26 / 255.0, 30 / 255.0, 32 / 255.0, 1);+ Theme.color (cr, "Foreground 1"); cr.set_line_width (0.8); draw_bar (cr); cr.stroke ();@@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <bindings>- <action key="n" ctrl="false" alt="true" command="false" shift="false" action="new" />+ <action key="n" ctrl="true" alt="false" command="false" shift="false" action="new" /> <action key="o" ctrl="true" alt="false" command="false" shift="false" action="open" /> <action key="r" ctrl="true" alt="false" command="false" shift="false" action="recent files" /> <action key="s" ctrl="true" alt="false" command="false" shift="false" action="save" />@@ -25,6 +25,8 @@ <action key="" ctrl="false" alt="false" command="false" shift="false" action="glyph sequence" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="set background glyph" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="remove background glyph" />+ <action key="" ctrl="false" alt="false" command="false" shift="false" action="create guide" />+ <action key="" ctrl="false" alt="false" command="false" shift="false" action="show guide tab" /> <action key="r" ctrl="true" alt="false" command="false" shift="false" action="select point above" /> <action key="s" ctrl="true" alt="false" command="false" shift="false" action="select next point" /> <action key="q" ctrl="true" alt="false" command="false" shift="false" action="select previous point" />@@ -33,9 +35,10 @@ <action key="" ctrl="false" alt="false" command="false" shift="false" action="previous tab" /> <action key="w" ctrl="true" alt="false" command="false" shift="false" action="close tab" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="close all tabs" />+ <action key="l" ctrl="true" alt="false" command="false" shift="false" action="show spacing tab" /> <action key="k" ctrl="true" alt="false" command="false" shift="false" action="show kerning tab" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="list kerning pairs" />- <action key="" ctrl="false" alt="false" command="false" shift="false" action="show spacing tab" />+ <action key="" ctrl="false" alt="false" command="false" shift="false" action="show spacing classes" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="select next kerning pair" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="select previous kerning pair" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="show ligature tab" />@@ -92,13 +95,12 @@ <action key="" ctrl="false" alt="false" command="false" shift="false" action="next" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="circle" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="rectangle" />+ <action key="" ctrl="false" alt="false" command="false" shift="false" action="test_case" />+ <action key="" ctrl="false" alt="false" command="false" shift="false" action="slow_test" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="kerning_class" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="kerning_text_input" />- <action key="" ctrl="false" alt="false" command="false" shift="false" action="side_bearings" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="insert_last_glyph" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="insert_unichar" />- <action key="" ctrl="false" alt="false" command="false" shift="false" action="kerning_font_size_one" />- <action key="" ctrl="false" alt="false" command="false" shift="false" action="kerning_font_size_two" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="update_webview" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="export_fonts" /> <action key="" ctrl="false" alt="false" command="false" shift="false" action="generate_html_document" />