The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

Theme.vala in libbirdfont

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of libbirdfont/Theme.vala.
Fix selection in overview
1 /* 2 Copyright (C) 2015 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 15 using Bird; 16 using Cairo; 17 18 namespace BirdFont { 19 20 public class Theme : GLib.Object { 21 22 static Gee.HashMap<string, Color> colors; 23 public static Gee.ArrayList<string> color_list; 24 public static Gee.ArrayList<string> themes; 25 public static string current_theme; 26 27 public static void text_color (Text text, string name) { 28 Color c; 29 30 if (unlikely (!colors.has_key (name))) { 31 warning (@"Theme does not have a color for $name"); 32 return; 33 } 34 35 c = colors.get (name); 36 text.set_source_rgba (c.r, c.g, c.b, c.a); 37 } 38 39 public static void color (Context cr, string name) { 40 Color c; 41 42 if (unlikely (!colors.has_key (name))) { 43 warning (@"Theme does not have a color for $name"); 44 return; 45 } 46 47 c = colors.get (name); 48 cr.set_source_rgba (c.r, c.g, c.b, c.a); 49 } 50 51 public static void color_opacity (Context cr, string name, double opacity) { 52 Color c; 53 54 if (unlikely (!colors.has_key (name))) { 55 warning (@"Theme does not have a color for $name"); 56 return; 57 } 58 59 c = colors.get (name); 60 cr.set_source_rgba (c.r, c.g, c.b, opacity); 61 } 62 63 public static void gradient (Cairo.Pattern p, string name1, string name2) { 64 Color c1 = get_color (name1); 65 Color c2 = get_color (name2); 66 67 p.add_color_stop_rgba (1, c1.r, c1.g, c1.b, c1.a); 68 p.add_color_stop_rgba (0, c2.r, c2.g, c2.b, c2.a); 69 } 70 71 public static void text_color_opacity (Text text, string name, double opacity) { 72 Color c; 73 74 if (unlikely (!colors.has_key (name))) { 75 warning (@"Theme does not have a color for $name"); 76 return; 77 } 78 79 c = colors.get (name); 80 text.set_source_rgba (c.r, c.g, c.b, opacity); 81 } 82 83 public static Color get_color (string name) { 84 if (unlikely (!colors.has_key (name))) { 85 warning (@"Theme does not have a color for $name"); 86 return new Color (0, 0, 0, 1); 87 } 88 89 return colors.get (name); 90 } 91 92 public static void set_default_colors () { 93 current_theme = "default.theme"; 94 color_list = new Gee.ArrayList<string> (); 95 colors = new Gee.HashMap<string, Color> (); 96 themes = new Gee.ArrayList<string> (); 97 98 add_theme_files (); 99 100 Theme.set_default_color ("Stroke Color", 0, 0, 0, 1); 101 Theme.set_default_color ("Handle Color", 0, 0, 0, 1); 102 Theme.set_default_color ("Fill Color", 0.5, 0.5, 0.5, 1); 103 Theme.set_default_color ("Selected Objects", 35 / 255.0, 131 / 255.0, 194 / 255.0, 1); 104 105 Theme.set_default_color ("Background 1", 1, 1, 1, 1); 106 Theme.set_default_color ("Dialog Background", 238 / 255.0, 239 / 255.0, 243 / 255.0, 1); 107 Theme.set_default_color ("Menu Background", 222 / 255.0, 221 / 255.0, 226 / 255.0, 1); 108 Theme.set_default_color ("Default Background", 238 / 255.0, 239 / 255.0, 243 / 255.0, 1); 109 Theme.set_default_color ("Headline Background", 110 / 255.0, 113 / 255.0, 130 / 255.0, 1); 110 Theme.set_default_color ("Empty Tool Box", 110 / 255.0, 113 / 255.0, 130 / 255.0, 1); 111 112 Theme.set_default_color ("Background 6", 224/255.0, 224/255.0, 224/255.0, 1); 113 Theme.set_default_color ("Background 7", 56 / 255.0, 59 / 255.0, 65 / 255.0, 1); 114 Theme.set_default_color ("Background 8", 55/255.0, 55/255.0, 55/255.0, 1); 115 Theme.set_default_color ("Background 9", 72/255.0, 72/255.0, 72/255.0, 1); 116 Theme.set_default_color ("Background 10", 223/255.0, 223/255.0, 223/255.0, 1); 117 118 Theme.set_default_color ("Checkbox Background", 255 / 255.0, 255 / 255.0, 255 / 255.0, 1); 119 120 Theme.set_default_color ("Foreground 1", 0, 0, 0, 1); 121 Theme.set_default_color ("Text Foreground", 3 / 255.0, 16 / 255.0, 24 / 255.0, 1); 122 Theme.set_default_color ("Foreground 3", 26 / 255.0, 30 / 255.0, 32 / 255.0, 1); 123 Theme.set_default_color ("Foreground 4", 40 / 255.0, 57 / 255.0, 65 / 255.0, 1); 124 Theme.set_default_color ("Foreground 5", 70 / 255.0, 77 / 255.0, 83 / 255.0, 1); 125 Theme.set_default_color ("Foreground 6", 45 / 255.0, 45 / 255.0, 45 / 255.0, 1); 126 Theme.set_default_color ("Foreground 7", 219 / 255.0, 221 / 255.0, 233 / 255.0, 1); 127 128 Theme.set_default_color ("Table Background 1", 238 / 255.0, 239 / 255.0, 243 / 255.0, 1); 129 Theme.set_default_color ("Table Background 2", 210 / 255.0, 212 / 255.0, 223 / 255.0, 1); 130 131 Theme.set_default_color ("Selected Tab Foreground", 0, 0, 0, 1); 132 Theme.set_default_color ("Tab Separator", 207 / 255.0, 210 / 255.0, 215 / 255.0, 1); 133 134 Theme.set_default_color ("Foreground Inverted", 1, 1, 1, 1); 135 Theme.set_default_color ("Menu Foreground", 3 / 255.0, 16 / 255.0, 24 / 255.0, 1); 136 137 // FIXME: DELETE Theme.set_default_color ("Highlighted 1", 234 / 255.0, 77 / 255.0, 26 / 255.0, 1); 138 Theme.set_default_color ("Highlighted 1", 159 / 255.0, 165 / 255.0, 192 / 255.0, 1); 139 140 141 Theme.set_default_color ("Highlighted Guide", 0, 0, 0.3, 1); 142 Theme.set_default_color ("Guide 1", 0.7, 0.7, 0.8, 1); 143 Theme.set_default_color ("Guide 2", 0.7, 0, 0, 0.5); 144 Theme.set_default_color ("Guide 3", 120 / 255.0, 68 / 255.0, 120 / 255.0, 120 / 255.0); 145 146 Theme.set_default_color ("Grid",0.2, 0.6, 0.2, 0.2); 147 148 Theme.set_default_color ("Background Glyph", 0.2, 0.2, 0.2, 0.5); 149 150 Theme.set_default_color ("Button Border 1", 173 / 255.0, 176 / 255.0, 188 / 255.0, 1); 151 Theme.set_default_color ("Button Background 1", 211 / 255.0, 212 / 255.0, 216 / 255.0, 1); 152 153 Theme.set_default_color ("Button Border 2", 173 / 255.0, 176 / 255.0, 188 / 255.0, 1); 154 Theme.set_default_color ("Button Background 2", 211 / 255.0, 212 / 255.0, 216 / 255.0, 1); 155 156 Theme.set_default_color ("Button Border 3", 173 / 255.0, 176 / 255.0, 188 / 255.0, 1); 157 Theme.set_default_color ("Button Background 3", 242 / 255.0, 246 / 255.0, 246 / 255.0, 1); 158 159 Theme.set_default_color ("Button Border 4", 173 / 255.0, 176 / 255.0, 188 / 255.0, 1); 160 Theme.set_default_color ("Button Background 4", 242 / 255.0, 246 / 255.0, 246 / 255.0, 1); 161 162 Theme.set_default_color ("Button Foreground", 3 / 255.0, 16 / 255.0, 24 / 255.0, 1); 163 Theme.set_default_color ("Selected Button Foreground", 3 / 255.0, 16 / 255.0, 24 / 255.0, 1); 164 165 Theme.set_default_color ("Tool Foreground", 3 / 255.0, 16 / 255.0, 24 / 255.0, 1); 166 Theme.set_default_color ("Selected Tool Foreground", 3 / 255.0, 16 / 255.0, 24 / 255.0, 1); 167 168 Theme.set_default_color ("Text Area Background", 255 / 255.0, 255 / 255.0, 255 / 255.0, 1); 169 170 Theme.set_default_color ("Overview Item Border", 207 / 255.0, 210 / 255.0, 215 / 255.0, 1); 171 172 Theme.set_default_color ("Selected Overview Item", 211 / 255.0, 212 / 255.0, 216 / 255.0, 1); 173 Theme.set_default_color ("Overview Item 1", 236 / 255.0, 236 / 255.0, 236 / 255.0, 1); 174 Theme.set_default_color ("Overview Item 2", 246 / 255.0, 246 / 255.0, 246 / 255.0, 1); 175 176 Theme.set_default_color ("Overview Selected Foreground", 45 / 255.0, 45 / 255.0, 45 / 255.0, 1); 177 Theme.set_default_color ("Overview Foreground", 45 / 255.0, 45 / 255.0, 45 / 255.0, 1); 178 179 Theme.set_default_color ("Glyph Count Background 1", 255 / 255.0, 255 / 255.0, 255 / 255.0, 1); 180 Theme.set_default_color ("Glyph Count Background 2", 255 / 255.0, 255 / 255.0, 255 / 255.0, 1); 181 182 Theme.set_default_color ("Dialog Shadow", 0, 0, 0, 0.3); 183 184 Theme.set_default_color ("Selected Active Cubic Control Point", 0, 0, 0, 1); 185 Theme.set_default_color ("Selected Cubic Control Point", 0, 0, 0, 1); 186 Theme.set_default_color ("Active Cubic Control Point", 70 / 255.0, 70 / 255.0, 70 / 255.0, 1); 187 Theme.set_default_color ("Cubic Control Point", 116 / 255.0, 116 / 255.0, 116 / 255.0, 1); 188 189 Theme.set_default_color ("Selected Active Quadratic Control Point", 0, 0, 0, 1); 190 Theme.set_default_color ("Selected Quadratic Control Point", 0, 0, 0, 1); 191 Theme.set_default_color ("Active Quadratic Control Point", 85 / 255.0, 115 / 255.0, 149 / 255.0, 1); 192 Theme.set_default_color ("Quadratic Control Point", 123 / 255.0, 151 / 255.0, 184 / 255.0, 1); 193 194 Theme.set_default_color ("Selected Control Point Handle", 0, 0, 0, 1); 195 Theme.set_default_color ("Active Control Point Handle", 81 / 255.0, 147 / 255.0, 90 / 255.0, 1); 196 Theme.set_default_color ("Control Point Handle", 81 / 255.0, 147 / 255.0, 90 / 255.0, 1); 197 198 Theme.set_default_color ("Merge", 167 / 255.0, 170 / 255.0, 178 / 255.0, 0.3); 199 200 Theme.set_default_color ("Spin Button", 164 / 255.0, 167 / 255.0, 175 / 255.0, 1); 201 Theme.set_default_color ("Active Spin Button", 104 / 255.0, 108 / 255.0, 119 / 255.0, 1); 202 Theme.set_default_color ("Zoom Bar Border", 122 / 255.0, 131 / 255.0, 145 / 255.0, 1); 203 Theme.set_default_color ("Font Name", 0 / 255.0, 0 / 255.0, 0 / 255.0, 1); 204 205 if (BirdFont.has_argument ("--test")) { 206 current_theme = "generated_theme.theme"; 207 write_theme (); 208 209 t_("Stroke Color"); 210 t_("Handle Color"); 211 t_("Fill Color"); 212 t_("Selected Objects"); 213 214 t_("Background 1"); 215 t_("Dialog Background"); 216 t_("Menu Background"); 217 t_("Default Background"); 218 t_("Background 6"); 219 t_("Background 7"); 220 t_("Background 8"); 221 t_("Background 9"); 222 223 t_("Checkbox Background"); 224 225 t_("Foreground 1"); 226 t_("Text Foreground"); 227 t_("Foreground 3"); 228 t_("Foreground 4"); 229 t_("Foreground 5"); 230 t_("Foreground 6"); 231 t_("Foreground 7"); 232 t_("Foreground Inverted"); 233 t_("Menu Foreground"); 234 t_("Selected Tab Foreground"); 235 t_("Tab Separator"); 236 237 t_("Highlighted 1"); 238 t_("Highlighted Guide"); 239 240 t_("Grid"); 241 242 t_("Guide 1"); 243 t_("Guide 2"); 244 t_("Guide 3"); 245 246 t_("Button Border 1"); 247 t_("Button Background 1"); 248 t_("Button Border 2"); 249 t_("Button Background 2"); 250 t_("Button Border 3"); 251 t_("Button Background 3"); 252 t_("Button Border 4"); 253 t_("Button Background 4"); 254 255 t_("Button Foreground"); 256 t_("Selected Button Foreground"); 257 258 t_("Tool Foreground"); 259 t_("Selected Tool Foreground"); 260 261 t_("Text Area Background"); 262 263 t_("Overview Item Border"); 264 265 t_("Selected Overview Item"); 266 t_("Overview Item 1"); 267 t_("Overview Item 2"); 268 269 t_("Overview Selected Foreground"); 270 t_("Overview Foreground"); 271 272 t_("Glyph Count Background 1"); 273 t_("Glyph Count Background 2"); 274 275 t_("Dialog Shadow"); 276 277 t_("Selected Active Cubic Control Point"); 278 t_("Selected Cubic Control Point"); 279 t_("Active Cubic Control Point"); 280 t_("Cubic Control Point"); 281 282 t_("Selected Active Quadratic Control Point"); 283 t_("Selected Quadratic Control Point"); 284 t_("Active Quadratic Control Point"); 285 t_("Cubic Quadratic Point"); 286 287 t_("Selected Control Point Handle"); 288 t_("Active Control Point Handle"); 289 t_("Control Point Handle"); 290 291 t_("Merge"); 292 t_("Spin Button"); 293 t_("Active Spin Button"); 294 t_("Zoom Bar Border"); 295 t_("Font Name"); 296 } 297 } 298 299 static void add_theme_files () { 300 FileEnumerator enumerator; 301 FileInfo? file_info; 302 string file_name; 303 File dir; 304 305 dir = BirdFont.get_settings_directory (); 306 307 themes.clear (); 308 themes.add ("default.theme"); 309 themes.add ("high_contrast.theme"); 310 311 try { 312 enumerator = dir.enumerate_children (FileAttribute.STANDARD_NAME, 0); 313 while ((file_info = enumerator.next_file ()) != null) { 314 file_name = ((!) file_info).get_name (); 315 316 if (file_name.has_suffix (".theme")) { 317 themes.add (file_name); 318 } 319 } 320 } catch (Error e) { 321 warning (e.message); 322 } 323 } 324 325 public static void set_default_color (string name, double r, double g, double b, double a) { 326 color_list.add (name); 327 colors.set (name, new Color (r, g, b, a)); 328 } 329 330 public static void save_color (string name, double r, double g, double b, double a) { 331 colors.set (name, new Color (r, g, b, a)); 332 write_theme (); 333 } 334 335 public static void load_theme (string theme_file) { 336 File default_theme; 337 File user_theme; 338 339 user_theme = get_child (BirdFont.get_settings_directory (), theme_file); 340 if (user_theme.query_exists ()) { 341 current_theme = theme_file; 342 parse_theme (user_theme); 343 return; 344 } 345 346 default_theme = SearchPaths.find_file (null, theme_file); 347 if (default_theme.query_exists ()) { 348 current_theme = theme_file; 349 parse_theme (default_theme); 350 return; 351 } 352 353 warning (@"Theme not found: $theme_file"); 354 } 355 356 public static void write_theme () { 357 DataOutputStream os; 358 File file; 359 int i; 360 string base_name; 361 362 if (current_theme == "") { 363 warning ("No name for theme."); 364 return; 365 } 366 367 if (current_theme == "default.theme" || current_theme == "high_contrast.theme") { 368 current_theme = "custom.theme"; 369 370 file = get_child (BirdFont.get_settings_directory (), current_theme); 371 i = 2; 372 base_name = "custom"; 373 while (file.query_exists ()) { 374 current_theme = @"$(base_name)_theme_$(i).theme"; 375 file = get_child (BirdFont.get_settings_directory (), current_theme); 376 i++; 377 } 378 } 379 380 file = get_child (BirdFont.get_settings_directory (), current_theme); 381 382 try { 383 if (file.query_exists ()) { 384 file.delete (); 385 } 386 } catch (GLib.Error e) { 387 warning (e.message); 388 } 389 390 try { 391 os = new DataOutputStream (file.create (FileCreateFlags.REPLACE_DESTINATION)); 392 os.put_string ("""<?xml version="1.0" encoding="utf-8" standalone="yes"?>"""); 393 os.put_string ("\n"); 394 395 os.put_string ("<theme>\n"); 396 foreach (string name in colors.keys) { 397 Color color = colors.get (name); 398 399 os.put_string ("\t<color "); 400 401 os.put_string (@"name=\"$(Markup.escape_text (name))\" "); 402 os.put_string (@"red=\"$(color.r)\" "); 403 os.put_string (@"green=\"$(color.g)\" "); 404 os.put_string (@"blue=\"$(color.b)\" "); 405 os.put_string (@"alpha=\"$(color.a)\""); 406 407 os.put_string ("/>\n"); 408 } 409 os.put_string ("</theme>\n"); 410 411 os.close (); 412 } catch (GLib.Error e) { 413 warning (e.message); 414 } 415 416 add_theme_files (); 417 } 418 419 static void parse_theme (File f) { 420 string xml_data; 421 XmlParser parser; 422 423 try { 424 FileUtils.get_contents((!) f.get_path (), out xml_data); 425 parser = new XmlParser (xml_data); 426 parse_colors (parser.get_root_tag ()); 427 } catch (GLib.Error e) { 428 warning (e.message); 429 } 430 } 431 432 static void parse_colors (Tag tag) { 433 foreach (Tag t in tag) { 434 if (t.get_name () == "color") { 435 parse_color (t.get_attributes ()); 436 } 437 } 438 } 439 440 static void parse_color (Attributes attributes) { 441 string name = ""; 442 double r = 0; 443 double g = 0; 444 double b = 0; 445 double a = 1; 446 447 foreach (Attribute attr in attributes) { 448 if (attr.get_name () == "name") { 449 name = attr.get_content (); 450 } 451 452 if (attr.get_name () == "red") { 453 r = double.parse (attr.get_content ()); 454 } 455 456 if (attr.get_name () == "green") { 457 g = double.parse (attr.get_content ()); 458 } 459 460 if (attr.get_name () == "blue") { 461 b = double.parse (attr.get_content ()); 462 } 463 464 if (attr.get_name () == "alpha") { 465 a = double.parse (attr.get_content ()); 466 } 467 } 468 469 colors.set (name, new Color (r, g, b, a)); 470 } 471 472 public static void add_new_theme (SettingsDisplay d) { 473 TextListener listener; 474 475 listener = new TextListener (t_("New theme"), "", t_("Set")); 476 477 listener.signal_text_input.connect ((text) => { 478 if (text != "") { 479 current_theme = text + ".theme"; 480 themes.add (current_theme); 481 } 482 }); 483 484 listener.signal_submit.connect (() => { 485 TabContent.hide_text_input (); 486 write_theme (); 487 d.create_setting_items (); 488 }); 489 490 TabContent.show_text_input (listener); 491 } 492 493 public static string get_icon_file () { 494 string icons; 495 File f; 496 497 return_val_if_fail (!is_null (current_theme), "icons.bf".dup ()); 498 return_val_if_fail (current_theme != "", "icons.bf".dup ()); 499 500 if (current_theme == "default.theme" || current_theme == "high_contrast.theme") { 501 return "icons.bf".dup (); 502 } 503 504 icons = current_theme.replace (".theme", ".bf"); 505 f = SearchPaths.search_file (null, icons); 506 507 if (f.query_exists ()) { 508 return icons; 509 } 510 511 return "icons.bf".dup (); 512 } 513 } 514 515 } 516