The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

SettingsDisplay.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/SettingsDisplay.vala.
New color theme
1 /* 2 Copyright (C) 2014 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 Cairo; 16 using Math; 17 18 namespace BirdFont { 19 20 public class SettingsDisplay : FontDisplay { 21 22 double scroll = 0; 23 double content_height = 1; 24 WidgetAllocation allocation; 25 Gee.ArrayList<SettingsItem> tools; 26 27 public static SpinButton precision; 28 29 SettingsItem new_key_bindings = new SettingsItem.head_line (""); 30 public static bool update_key_bindings = false; 31 32 public SettingsDisplay () { 33 allocation = new WidgetAllocation (); 34 tools = new Gee.ArrayList<SettingsItem> (); 35 content_height = 200; 36 precision = new SpinButton ("precision"); 37 create_setting_items (); 38 } 39 40 public void create_setting_items () { 41 tools.clear (); 42 // setting items 43 tools.add (new SettingsItem.head_line (t_("Settings"))); 44 45 SpinButton stroke_width = new SpinButton ("stroke_width"); 46 tools.add (new SettingsItem (stroke_width, t_("Stroke width"))); 47 48 stroke_width.set_max (4); 49 stroke_width.set_min (0.002); 50 stroke_width.set_value_round (1); 51 52 if (Preferences.get ("stroke_width_for_open_paths") != "") { 53 stroke_width.set_value (Preferences.get ("stroke_width_for_open_paths")); 54 } 55 56 stroke_width.new_value_action.connect ((self) => { 57 Glyph g = MainWindow.get_current_glyph (); 58 Path.stroke_width = stroke_width.get_value (); 59 g.redraw_area (0, 0, g.allocation.width, g.allocation.height); 60 Preferences.set ("stroke_width_for_open_paths", stroke_width.get_display_value ()); 61 MainWindow.get_toolbox ().redraw ((int) stroke_width.x, (int) stroke_width.y, 70, 70); 62 }); 63 64 Path.stroke_width = stroke_width.get_value (); 65 66 // adjust precision 67 string precision_value = Preferences.get ("precision"); 68 69 if (precision_value != "") { 70 precision.set_value (precision_value); 71 } else { 72 #if ANDROID 73 precision.set_value_round (0.5); 74 #else 75 precision.set_value_round (1); 76 #endif 77 } 78 79 precision.new_value_action.connect ((self) => { 80 MainWindow.get_toolbox ().select_tool (precision); 81 Preferences.set ("precision", self.get_display_value ()); 82 MainWindow.get_toolbox ().redraw ((int) precision.x, (int) precision.y, 70, 70); 83 }); 84 85 precision.select_action.connect((self) => { 86 DrawingTools.pen_tool.set_precision (((SpinButton)self).get_value ()); 87 }); 88 89 precision.set_min (0.001); 90 precision.set_max (1); 91 92 tools.add (new SettingsItem (precision, t_("Precision for pen tool"))); 93 94 Tool show_all_line_handles = new Tool ("show_all_line_handles"); 95 show_all_line_handles.select_action.connect((self) => { 96 Path.show_all_line_handles = !Path.show_all_line_handles; 97 Glyph g = MainWindow.get_current_glyph (); 98 g.redraw_area (0, 0, g.allocation.width, g.allocation.height); 99 }); 100 tools.add (new SettingsItem (show_all_line_handles, t_("Show or hide control point handles"))); 101 102 Tool fill_open_path = new Tool ("fill_open_path"); 103 fill_open_path.select_action.connect((self) => { 104 Path.fill_open_path = !Path.fill_open_path; 105 Glyph g = MainWindow.get_current_glyph (); 106 g.redraw_area (0, 0, g.allocation.width, g.allocation.height); 107 }); 108 tools.add (new SettingsItem (fill_open_path, t_("Fill open paths."))); 109 110 Tool ttf_units = new Tool ("ttf_units"); 111 ttf_units.select_action.connect((self) => { 112 GridTool.ttf_units = !GridTool.ttf_units; 113 Preferences.set ("ttf_units", @"$(GridTool.ttf_units)"); 114 }); 115 tools.add (new SettingsItem (ttf_units, t_("Use TTF units."))); 116 117 SpinButton freehand_samples = new SpinButton ("freehand_samples_per_point"); 118 tools.add (new SettingsItem (freehand_samples, t_("Number of points added by the freehand tool"))); 119 120 freehand_samples.set_max (9); 121 freehand_samples.set_min (0.002); 122 123 if (BirdFont.android) { 124 freehand_samples.set_value_round (2.5); 125 } else { 126 freehand_samples.set_value_round (1); 127 } 128 129 if (Preferences.get ("freehand_samples") != "") { 130 freehand_samples.set_value (Preferences.get ("freehand_samples")); 131 DrawingTools.track_tool.set_samples_per_point (freehand_samples.get_value ()); 132 } 133 134 freehand_samples.new_value_action.connect ((self) => { 135 DrawingTools.track_tool.set_samples_per_point (freehand_samples.get_value ()); 136 }); 137 138 SpinButton simplification_threshold = new SpinButton ("simplification_threshold"); 139 simplification_threshold.set_value_round (0.5); 140 tools.add (new SettingsItem (simplification_threshold, t_("Path simplification threshold"))); 141 142 simplification_threshold.set_max (5); 143 freehand_samples.set_min (0.002); 144 145 if (Preferences.get ("simplification_threshold") != "") { 146 freehand_samples.set_value (Preferences.get ("simplification_threshold")); 147 DrawingTools.pen_tool.set_simplification_threshold (simplification_threshold.get_value ()); 148 } 149 150 freehand_samples.new_value_action.connect ((self) => { 151 DrawingTools.pen_tool.set_simplification_threshold (simplification_threshold.get_value ()); 152 }); 153 154 tools.add (new SettingsItem.head_line (t_("Key Bindings"))); 155 156 foreach (MenuItem menu_item in MainWindow.get_menu ().sorted_menu_items) { 157 tools.add (new SettingsItem.key_binding (menu_item)); 158 } 159 160 tools.add (new SettingsItem.head_line (t_("Themes"))); 161 162 Gee.ArrayList<Tool> theme_buttons = new Gee.ArrayList<Tool> (); 163 164 foreach (string theme in Theme.themes) { 165 string label; 166 Tool select_theme = new Tool (theme); 167 168 select_theme.deselect_action.connect((self) => { 169 self.set_active (false); 170 }); 171 172 select_theme.select_action.connect((self) => { 173 string theme_file = self.get_name (); 174 TabBar tb; 175 176 Preferences.set ("theme", theme_file); 177 Theme.load_theme (theme_file); 178 179 foreach (Tool t in theme_buttons) { 180 t.set_selected (false); 181 t.set_active (false); 182 } 183 184 self.set_selected (true); 185 create_setting_items (); 186 187 Toolbox.redraw_tool_box (); 188 GlyphCanvas.redraw (); 189 190 tb = MainWindow.get_tab_bar (); 191 tb.redraw (0, 0, tb.width, tb.height); 192 }); 193 194 select_theme.set_icon ("theme"); 195 196 if (theme == "default.theme") { 197 label = t_("Default theme"); 198 } else if (theme == "high_contrast.theme") { 199 label = t_("High contrast theme"); 200 } else if (theme == "custom.theme") { 201 label = t_("Custom theme"); 202 } else { 203 label = theme.replace (".theme", ""); 204 } 205 206 tools.add (new SettingsItem (select_theme, label)); 207 theme_buttons.add (select_theme); 208 209 if (select_theme.get_name () == Theme.current_theme) { 210 select_theme.set_selected (true); 211 } 212 } 213 214 foreach (Tool t in theme_buttons) { 215 t.set_selected (t.name == Theme.current_theme); 216 } 217 218 Tool add_theme = new Tool ("add_new_theme"); 219 add_theme.select_action.connect((self) => { 220 foreach (Tool t in theme_buttons) { 221 t.set_selected (false); 222 } 223 224 self.set_selected (false); 225 Theme.add_new_theme (this); 226 GlyphCanvas.redraw (); 227 }); 228 tools.add (new SettingsItem (add_theme, t_("Add new theme"))); 229 230 tools.add (new SettingsItem.head_line (t_("Colors"))); 231 232 foreach (string color in Theme.color_list) { 233 SettingsItem s = new SettingsItem.color (color); 234 ColorTool c = (ColorTool) ((!) s.button); 235 236 tools.add (s); 237 238 c.color_updated.connect (() => { 239 create_setting_items (); 240 GlyphCanvas.redraw (); 241 }); 242 } 243 } 244 245 public override void draw (WidgetAllocation allocation, Context cr) { 246 this.allocation = allocation; 247 248 layout (); 249 250 // background 251 cr.save (); 252 cr.rectangle (0, 0, allocation.width, allocation.height); 253 cr.set_line_width (0); 254 Theme.color (cr, "Default Background"); 255 cr.fill (); 256 cr.stroke (); 257 cr.restore (); 258 259 foreach (SettingsItem s in tools) { 260 if (-20 * MainWindow.units <= s.y <= allocation.height + 20 * MainWindow.units) { 261 s.draw (allocation, cr); 262 } 263 } 264 } 265 266 public void layout () { 267 double y = -scroll; 268 bool first = true; 269 foreach (SettingsItem s in tools) { 270 271 if (!first && s.headline) { 272 y += 30 * MainWindow.units; 273 } 274 275 s.y = y; 276 277 if (s.button != null) { 278 ((!) s.button).y = y; 279 ((!) s.button).x = 20 * MainWindow.units; 280 } 281 282 if (s.headline) { 283 y += 50 * MainWindow.units; 284 } else { 285 y += 40 * MainWindow.units; 286 } 287 288 first = false; 289 } 290 291 content_height = y + scroll; 292 } 293 294 void set_key_bindings (SettingsItem item) { 295 if (new_key_bindings.active) { 296 new_key_bindings.active = false; 297 update_key_bindings = false; 298 } else { 299 new_key_bindings.active = false; 300 new_key_bindings = item; 301 update_key_bindings = true; 302 new_key_bindings.active = true; 303 } 304 } 305 306 public override void key_release (uint keyval) { 307 SettingsItem old_key_binding; 308 309 if (update_key_bindings) { 310 if (keyval == Key.BACK_SPACE) { 311 update_key_bindings = false; 312 new_key_bindings.active = false; 313 new_key_bindings.menu_item.modifiers = NONE; 314 new_key_bindings.menu_item.key = '\0'; 315 } else if (KeyBindings.get_mod_from_key (keyval) == NONE) { 316 317 if (has_key_binding (KeyBindings.modifier, (unichar) keyval)) { 318 old_key_binding = (!) get_key_binding (KeyBindings.modifier, (unichar) keyval); 319 old_key_binding.menu_item.modifiers = NONE; 320 old_key_binding.menu_item.key = '\0'; 321 } 322 323 new_key_bindings.menu_item.modifiers = KeyBindings.modifier; 324 new_key_bindings.menu_item.key = (unichar) keyval; 325 update_key_bindings = false; 326 new_key_bindings.active = false; 327 } 328 329 MainWindow.get_menu ().write_key_bindings (); 330 GlyphCanvas.redraw (); 331 } 332 } 333 334 bool has_key_binding (uint modifier, unichar key) { 335 return get_key_binding (modifier, key) != null; 336 } 337 338 SettingsItem? get_key_binding (uint modifier, unichar key) { 339 foreach (SettingsItem i in tools) { 340 if (i.menu_item.modifiers == modifier && i.menu_item.key == key) { 341 return i; 342 } 343 } 344 345 return null; 346 } 347 348 public override void button_press (uint button, double x, double y) { 349 foreach (SettingsItem s in tools) { 350 if (s.handle_events && s.button != null) { 351 if (((!) s.button).is_over (x, y)) { 352 353 ((!) s.button).set_selected (! ((!) s.button).selected); 354 355 if (((!) s.button).selected) { 356 ((!) s.button).select_action ((!) s.button); 357 } 358 359 ((!) s.button).panel_press_action ((!) s.button, button, x, y); 360 } 361 } 362 } 363 GlyphCanvas.redraw (); 364 } 365 366 public override void button_release (int button, double x, double y) { 367 foreach (SettingsItem s in tools) { 368 if (s.handle_events && s.button != null) { 369 ((!) s.button).panel_release_action (((!) s.button), button, x, y); 370 } 371 372 if (s.key_bindings && s.y <= y < s.y + 40 * MainWindow.units && button == 1) { 373 set_key_bindings (s); 374 } 375 } 376 GlyphCanvas.redraw (); 377 } 378 379 public override void motion_notify (double x, double y) { 380 bool consumed = false; 381 bool active; 382 bool update = false; 383 384 foreach (SettingsItem si in tools) { 385 386 if (si.handle_events && si.button != null) { 387 active = ((!) si.button).is_over (x, y); 388 389 if (!active && ((!) si.button).is_active ()) { 390 ((!) si.button).move_out_action ((!) si.button); 391 } 392 393 if (((!) si.button).set_active (active)) { 394 update = true; 395 } 396 } 397 } 398 399 foreach (SettingsItem s in tools) { 400 if (s.handle_events && s.button != null) { 401 if (((!) s.button).panel_move_action ((!) s.button, x, y)) { 402 consumed = true; 403 } 404 } 405 } 406 407 if (consumed || update) { 408 GlyphCanvas.redraw (); 409 } 410 } 411 412 public override string get_label () { 413 return t_("Settings"); 414 } 415 416 public override string get_name () { 417 return "Settings"; 418 } 419 420 public override bool has_scrollbar () { 421 return true; 422 } 423 424 public override void scroll_wheel_down (double x, double y) { 425 foreach (SettingsItem s in tools) { 426 if (s.handle_events && s.button != null) { 427 if (((!) s.button).is_over (x, y)) { 428 ((!) s.button).scroll_wheel_down_action ((!) s.button); 429 return; 430 } 431 } 432 } 433 434 scroll += 25 * MainWindow.units; 435 436 if (scroll + allocation.height >= content_height) { 437 scroll = content_height - allocation.height; 438 } 439 440 update_scrollbar (); 441 GlyphCanvas.redraw (); 442 } 443 444 public override void scroll_wheel_up (double x, double y) { 445 foreach (SettingsItem s in tools) { 446 if (s.handle_events && s.button != null) { 447 if (((!) s.button).is_over (x, y)) { 448 ((!) s.button).scroll_wheel_up_action ((!) s.button); 449 return; 450 } 451 } 452 } 453 454 scroll -= 25 * MainWindow.units; 455 456 if (scroll < 0) { 457 scroll = 0; 458 } 459 460 update_scrollbar (); 461 GlyphCanvas.redraw (); 462 } 463 464 public override void selected_canvas () { 465 MainWindow.get_toolbox ().set_default_tool_size (); 466 update_scrollbar (); 467 GlyphCanvas.redraw (); 468 } 469 470 public override void update_scrollbar () { 471 double h = content_height - allocation.height; 472 MainWindow.set_scrollbar_size (allocation.height / content_height); 473 MainWindow.set_scrollbar_position (scroll / h); 474 } 475 476 public override void scroll_to (double percent) { 477 double h = content_height - allocation.height; 478 scroll = percent * h; 479 GlyphCanvas.redraw (); 480 } 481 } 482 483 } 484