The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

MenuTab.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/MenuTab.vala.
Update font name in toolbox
1 /* 2 Copyright (C) 2012, 2014 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 namespace BirdFont { 16 17 public class MenuTab : FontDisplay { 18 19 /** Ignore input events when the background thread is running. 20 * 21 * Do always check the return value of set_suppress_event when this 22 * variable is updated. 23 * 24 * This variable is used only in the gui thread. 25 */ 26 public static bool suppress_event; 27 28 /** True if the background thread is running. */ 29 public static bool background_thread; 30 31 /** A notification sent when the file has been saved. */ 32 public static SaveCallback save_callback; 33 34 /** A notification sent when the file has been loaded. */ 35 public static LoadCallback load_callback; 36 37 /** A notification sent when the file has been loaded. */ 38 public static ExportCallback export_callback; 39 40 public MenuTab () { 41 save_callback = new SaveCallback (); 42 save_callback.is_done = true; 43 44 load_callback = new LoadCallback (); 45 export_callback = new ExportCallback (); 46 47 suppress_event = false; 48 background_thread = false; 49 } 50 51 public static void set_save_callback (SaveCallback c) { 52 if (!save_callback.is_done) { 53 warning ("Prevoius save command has not finished"); 54 } 55 56 save_callback = c; 57 } 58 59 public static void start_background_thread () { 60 if (!set_suppress_event (true)) { 61 warning ("suppressed event"); 62 return; 63 } 64 65 TabBar.start_wheel (); 66 } 67 68 public static void stop_background_thread () { 69 IdleSource idle = new IdleSource (); 70 idle.set_callback (() => { 71 set_suppress_event (false); 72 TabBar.stop_wheel (); 73 GlyphCanvas.redraw (); 74 return false; 75 }); 76 idle.attach (null); 77 } 78 79 public static bool validate_metadata () { 80 Font font = BirdFont.get_current_font (); 81 string m = t_("Missing metadata in font:") + "\n"; 82 83 if (font.postscript_name == "") { 84 MainWindow.show_message (m + t_("PostScript Name")); 85 return false; 86 } 87 88 if (font.name == "") { 89 MainWindow.show_message (m + t_("Name")); 90 return false; 91 } 92 93 if (font.subfamily == "") { 94 MainWindow.show_message (m + t_("Style")); 95 return false; 96 } 97 98 if (font.full_name == "") { 99 MainWindow.show_message (m + t_("Full Name (Name and Style)")); 100 return false; 101 } 102 103 if (font.unique_identifier == "") { 104 MainWindow.show_message (m + t_("Unique Identifier")); 105 return false; 106 } 107 108 Font current_font = BirdFont.get_current_font (); 109 string ttf_name = ExportSettings.get_file_name (current_font) + ".ttf"; 110 string ttf_name_mac = ExportSettings.get_file_name_mac (current_font) + ".ttf"; 111 112 print (@"$ttf_name == $ttf_name_mac"); 113 if (ttf_name == ttf_name_mac) { 114 MainWindow.show_message (t_("You need to choose a different name for the TTF file with Mac adjustmets.")); 115 ttf_name_mac = ExportSettings.get_file_name_mac (current_font) + " Mac.ttf"; 116 return false; 117 } 118 119 return true; 120 } 121 122 public static void export_fonts_in_background () { 123 Font f; 124 125 if (suppress_event || !MainWindow.native_window.can_export ()) { 126 return; 127 } 128 129 f = BirdFont.get_current_font (); 130 131 if (f.font_file == null) { 132 MainWindow.show_message (t_("You need to save your font before exporting it.")); 133 return; 134 } 135 136 if (!validate_metadata ()) { 137 return; 138 } 139 140 if (!ExportSettings.has_export_settings (f)) { 141 show_export_settings_tab (); 142 } else { 143 MenuTab.export_callback = new ExportCallback (); 144 MenuTab.export_callback.export_fonts_in_background (); 145 } 146 } 147 148 public static bool set_suppress_event (bool e) { 149 if (suppress_event && e) { 150 warning ("suppress_event is already set"); 151 return false; 152 } 153 background_thread = e; 154 suppress_event = e; 155 return true; 156 } 157 158 public override string get_label () { 159 return t_("Menu"); 160 } 161 162 public override string get_name () { 163 return "Menu"; 164 } 165 166 public static void select_overview () { 167 if (suppress_event) { 168 warn_if_test ("Event suppressed"); 169 return; 170 } 171 172 if (BirdFont.get_current_font ().is_empty ()) { 173 show_default_characters (); 174 } else { 175 MainWindow.get_tab_bar ().add_unique_tab (new OverView ()); 176 MainWindow.get_tab_bar ().select_tab_name ("Overview"); 177 } 178 } 179 180 public static void signal_file_exported () { 181 IdleSource idle = new IdleSource (); 182 idle.set_callback (() => { 183 export_callback.file_exported (); 184 return false; 185 }); 186 idle.attach (null); 187 } 188 189 public static void signal_file_saved () { 190 IdleSource idle = new IdleSource (); 191 idle.set_callback (() => { 192 save_callback.file_saved (); 193 return false; 194 }); 195 idle.attach (null); 196 } 197 198 public static void signal_file_loaded () { 199 IdleSource idle = new IdleSource (); 200 idle.set_callback (() => { 201 load_callback.file_loaded (); 202 MainWindow.native_window.font_loaded (); 203 return false; 204 }); 205 idle.attach (null); 206 } 207 208 public static void apply_font_setting (Font f) { 209 DrawingTools.background_scale.set_value (f.background_scale); 210 211 DrawingTools.grid_expander.tool.clear (); 212 213 if (f.grid_width.size == 0) { 214 f.grid_width.add ("1"); 215 f.grid_width.add ("2"); 216 f.grid_width.add ("4"); 217 } 218 219 foreach (string grid in f.grid_width) { 220 DrawingTools.add_new_grid (double.parse (grid), false); 221 } 222 223 string sw = f.settings.get_setting ("stroke_width"); 224 if (sw != ""){ 225 StrokeTool.stroke_width = double.parse (sw); 226 DrawingTools.object_stroke.set_value_round (StrokeTool.stroke_width); 227 } 228 229 string pt = f.settings.get_setting ("point_type"); 230 DrawingTools.set_default_point_type (pt); 231 232 string stroke = f.settings.get_setting ("apply_stroke"); 233 bool s = bool.parse (stroke); 234 DrawingTools.add_stroke.set_selected (s); 235 StrokeTool.add_stroke = s; 236 237 string lc = f.settings.get_setting ("line_cap"); 238 239 if (lc == "butt") { 240 StrokeTool.line_cap = LineCap.BUTT; 241 } else if (lc == "square") { 242 StrokeTool.line_cap = LineCap.SQUARE; 243 } else if (lc == "round") { 244 StrokeTool.line_cap = LineCap.ROUND; 245 } 246 247 DrawingTools.set_stroke_tool_visibility (); 248 249 string lock_grid = f.settings.get_setting ("lock_grid"); 250 bool lg = bool.parse (lock_grid); 251 GridTool.lock_grid = lg; 252 DrawingTools.lock_grid.selected = GridTool.lock_grid; 253 254 string skew_overview = f.settings.get_setting ("skew_overview"); 255 if (skew_overview != "") { 256 double so = double.parse (skew_overview); 257 OverviewTools.skew.set_value_round (so); 258 } 259 260 string autotrace_resolution = f.settings.get_setting ("autotrace_resolution"); 261 if (autotrace_resolution != "") { 262 double ar = double.parse (autotrace_resolution); 263 DrawingTools.background_threshold.set_value_round (ar); 264 } 265 266 string autotrace_threshold = f.settings.get_setting ("autotrace_threshold"); 267 if (autotrace_threshold != "") { 268 double at = double.parse (autotrace_threshold); 269 DrawingTools.auto_trace_resolution.set_value_round (at); 270 } 271 272 string autotrace_simplification = f.settings.get_setting ("autotrace_simplification"); 273 if (autotrace_simplification != "") { 274 double asi = double.parse (autotrace_simplification); 275 DrawingTools.auto_trace_simplify.set_value_round (asi); 276 } 277 278 MainWindow.get_toolbox ().update_expanders (); 279 MainWindow.get_toolbox ().update_all_expanders (); 280 Toolbox.redraw_tool_box (); 281 } 282 283 // FIXME: background thread 284 public static void save_as_bfp () { 285 FileChooser fc = new FileChooser (); 286 287 if (suppress_event) { 288 warn_if_test ("Event suppressed"); 289 return; 290 } 291 292 if (!set_suppress_event (true)) { 293 return; 294 } 295 296 fc.file_selected.connect((fn) => { 297 Font f = BirdFont.get_current_font (); 298 299 if (fn != null) { 300 f.init_bfp ((!) fn); 301 } 302 303 set_suppress_event (false); 304 }); 305 306 MainWindow.file_chooser (t_("Save"), fc, FileChooser.SAVE); 307 } 308 309 public static void new_file () { 310 Font font; 311 SaveDialogListener dialog = new SaveDialogListener (); 312 313 if (suppress_event) { 314 warn_if_test ("Event suppressed"); 315 return; 316 } 317 318 font = BirdFont.get_current_font (); 319 320 dialog.signal_discard.connect (() => { 321 MainWindow.close_all_tabs (); 322 323 BirdFont.new_font (); 324 MainWindow.native_window.font_loaded (); 325 326 show_default_characters (); 327 328 GlyphCanvas.redraw (); 329 }); 330 331 dialog.signal_save.connect (() => { 332 MenuTab.save_callback = new SaveCallback (); 333 MenuTab.save_callback.file_saved.connect (() => { 334 dialog.signal_discard (); 335 }); 336 save_callback.save (); 337 }); 338 339 dialog.signal_cancel.connect (() => { 340 MainWindow.hide_dialog (); 341 }); 342 343 if (!font.is_modified ()) { 344 dialog.signal_discard (); 345 } else { 346 MainWindow.show_dialog (new SaveDialog (dialog)); 347 } 348 349 return; 350 } 351 352 public static void quit () { 353 if (suppress_event) { 354 warn_if_test ("Event suppressed"); 355 return; 356 } 357 358 TabContent.hide_text_input (); 359 360 SaveDialogListener dialog = new SaveDialogListener (); 361 Font font = BirdFont.get_current_font (); 362 363 Preferences.save (); 364 365 dialog.signal_discard.connect (() => { 366 ensure_main_loop_is_empty (); 367 MainWindow.native_window.quit (); 368 }); 369 370 dialog.signal_save.connect (() => { 371 MenuTab.set_save_callback (new SaveCallback ()); 372 MenuTab.save_callback.file_saved.connect (() => { 373 ensure_main_loop_is_empty (); 374 MainWindow.native_window.quit (); 375 }); 376 save_callback.save (); 377 }); 378 379 dialog.signal_cancel.connect (() => { 380 MainWindow.hide_dialog (); 381 }); 382 383 if (!font.is_modified ()) { 384 dialog.signal_discard (); 385 } else { 386 MainWindow.show_dialog (new SaveDialog (dialog)); 387 } 388 } 389 390 public static void show_export_settings_tab () { 391 MainWindow.get_tab_bar ().add_unique_tab (new ExportSettings ()); 392 } 393 394 public static void show_description () { 395 MainWindow.get_tab_bar ().add_unique_tab (new DescriptionDisplay ()); 396 } 397 398 public static void show_kerning_context () { 399 if (suppress_event) { 400 warn_if_test ("Event suppressed"); 401 return; 402 } 403 404 KerningDisplay kd = MainWindow.get_kerning_display (); 405 MainWindow.get_tab_bar ().add_unique_tab (kd); 406 } 407 408 public static void show_spacing_tab () { 409 if (suppress_event) { 410 warn_if_test ("Event suppressed"); 411 return; 412 } 413 414 SpacingTab s = MainWindow.get_spacing_tab (); 415 MainWindow.get_tab_bar ().add_unique_tab (s); 416 } 417 418 public static void show_ligature_tab () { 419 if (suppress_event) { 420 warn_if_test ("Event suppressed"); 421 return; 422 } 423 424 LigatureList d = MainWindow.get_ligature_display (); 425 MainWindow.get_tab_bar ().add_unique_tab (d); 426 } 427 428 public static void preview () { 429 Font font = BirdFont.get_current_font (); 430 431 if (suppress_event) { 432 warn_if_test ("Event suppressed"); 433 return; 434 } 435 436 if (font.font_file == null) { 437 save_callback = new SaveCallback (); 438 save_callback.file_saved.connect (() => { 439 show_preview_tab (); 440 }); 441 save_callback.save (); 442 } else { 443 show_preview_tab (); 444 } 445 } 446 447 public static void show_preview_tab () { 448 OverWriteDialogListener dialog = new OverWriteDialogListener (); 449 TabBar tab_bar = MainWindow.get_tab_bar (); 450 FontFormat format = BirdFont.get_current_font ().format; 451 452 if (suppress_event) { 453 warn_if_test ("Event suppressed"); 454 return; 455 } 456 457 dialog.overwrite_signal.connect (() => { 458 KeyBindings.set_modifier (NONE); 459 tab_bar.add_unique_tab (new Preview (), true); 460 PreviewTools.update_preview (); 461 }); 462 463 if ((format == FontFormat.SVG || format == FontFormat.FREETYPE) && !OverWriteDialogListener.dont_ask_again) { 464 MainWindow.native_window.set_overwrite_dialog (dialog); 465 } else { 466 dialog.overwrite (); 467 } 468 } 469 470 /** Display the language selection tab. */ 471 public static void select_language () { 472 if (suppress_event) { 473 warn_if_test ("Event suppressed"); 474 return; 475 } 476 477 MainWindow.get_tab_bar ().add_unique_tab (new LanguageSelectionTab ()); 478 } 479 480 public static void use_current_glyph_as_background () { 481 if (suppress_event) { 482 warn_if_test ("Event suppressed"); 483 return; 484 } 485 486 Glyph.background_glyph = MainWindow.get_current_glyph (); 487 488 if (MainWindow.get_current_display () is OverView) { 489 Glyph.background_glyph = MainWindow.get_overview ().get_current_glyph (); 490 } 491 } 492 493 public static void reset_glyph_background () { 494 Glyph.background_glyph = null; 495 } 496 497 public static void remove_all_kerning_pairs () { 498 if (suppress_event) { 499 warn_if_test ("Event suppressed"); 500 return; 501 } 502 503 KerningClasses classes = BirdFont.get_current_font ().get_kerning_classes (); 504 classes.remove_all_pairs (); 505 KerningTools.update_kerning_classes (); 506 } 507 508 public static void list_all_kerning_pairs () { 509 if (suppress_event) { 510 warn_if_test ("Event suppressed"); 511 return; 512 } 513 514 MainWindow.get_tab_bar ().add_unique_tab (new KerningList ()); 515 } 516 517 public static void ensure_main_loop_is_empty () { 518 unowned MainContext context; 519 bool acquired; 520 521 context = MainContext.default (); 522 acquired = context.acquire (); 523 524 if (unlikely (!acquired)) { 525 warning ("Failed to acquire main loop.\n"); 526 return; 527 } 528 529 while (context.pending ()) { 530 context.iteration (true); 531 } 532 context.release (); 533 } 534 535 public static void save_as () { 536 if (MenuTab.suppress_event || !save_callback.is_done) { 537 warn_if_test ("Event suppressed"); 538 return; 539 } 540 541 MenuTab.set_save_callback (new SaveCallback ()); 542 MenuTab.save_callback.save_as(); 543 } 544 545 public static void save () { 546 if (MenuTab.suppress_event && !save_callback.is_done) { 547 warn_if_test ("Event suppressed"); 548 return; 549 } 550 551 MenuTab.set_save_callback (new SaveCallback ()); 552 MenuTab.save_callback.save (); 553 } 554 555 public static void load () { 556 if (MenuTab.suppress_event) { 557 warn_if_test ("Event suppressed"); 558 return; 559 } 560 561 MenuTab.load_callback = new LoadCallback (); 562 MenuTab.load_callback.load (); 563 564 MenuTab.load_callback.file_loaded.connect (() => { 565 Font f = BirdFont.get_current_font (); 566 MenuTab.apply_font_setting (f); 567 }); 568 } 569 570 public static void move_to_baseline () { 571 if (suppress_event) { 572 warn_if_test ("Event suppressed"); 573 return; 574 } 575 576 DrawingTools.move_tool.move_to_baseline (); 577 } 578 579 public static void show_file_dialog_tab (string title, FileChooser action, bool folder) { 580 FileDialogTab ft = new FileDialogTab (title, action, folder); 581 MainWindow.get_tab_bar ().add_tab (ft); 582 } 583 584 public static void simplify_path () { 585 if (suppress_event) { 586 warn_if_test ("Event suppressed"); 587 return; 588 } 589 590 Task t = new Task (); 591 t.task.connect (simplify); 592 MainWindow.native_window.run_background_thread (t); 593 } 594 595 private static void simplify () { 596 Glyph g = MainWindow.get_current_glyph (); 597 Gee.ArrayList<Path> paths = new Gee.ArrayList<Path> (); 598 599 // selected objects 600 foreach (Path p in g.active_paths) { 601 paths.add (PenTool.simplify (p, false, PenTool.simplification_threshold)); 602 } 603 604 // selected segments 605 if (paths.size == 0) { 606 foreach (Path p in g.get_all_paths ()) { 607 g.add_active_path (null, p); 608 } 609 610 foreach (Path p in g.active_paths) { 611 paths.add (PenTool.simplify (p, true, PenTool.simplification_threshold)); 612 } 613 } 614 615 g.store_undo_state (); 616 617 foreach (Path p in g.active_paths) { 618 g.layers.remove_path (p); 619 } 620 621 foreach (Path p in g.active_paths) { 622 g.layers.remove_path (p); 623 } 624 625 foreach (Path p in paths) { 626 g.add_path (p); 627 g.add_active_path (null, p); 628 } 629 630 g.active_paths.clear (); 631 g.update_view (); 632 } 633 634 public static void show_spacing_class_tab () { 635 SpacingClassTab t = MainWindow.get_spacing_class_tab (); 636 MainWindow.get_tab_bar ().add_unique_tab (t); 637 } 638 639 public static void add_ligature () { 640 TextListener listener; 641 string ligature_name = ""; 642 643 if (suppress_event) { 644 warn_if_test ("Event suppressed"); 645 return; 646 } 647 648 listener = new TextListener (t_("Name"), "", t_("Add ligature")); 649 650 listener.signal_text_input.connect ((text) => { 651 ligature_name = text; 652 }); 653 654 listener.signal_submit.connect (() => { 655 Font font = BirdFont.get_current_font (); 656 GlyphCollection? fg; 657 Glyph glyph; 658 GlyphCollection glyph_collection; 659 OverView o = MainWindow.get_overview (); 660 661 fg = font.get_glyph_collection_by_name (ligature_name); 662 663 if (fg == null) { 664 glyph_collection = new GlyphCollection ('\0', ligature_name); 665 666 glyph = new Glyph (ligature_name, '\0'); 667 glyph_collection.set_unassigned (true); 668 glyph_collection.insert_glyph (glyph, true); 669 670 font.add_glyph_collection (glyph_collection); 671 } 672 673 o.display_all_available_glyphs (); 674 o.scroll_to_glyph (ligature_name); 675 676 TabContent.hide_text_input (); 677 show_all_available_characters (); 678 }); 679 680 TabContent.show_text_input (listener); 681 } 682 683 public static void show_default_characters () { 684 MainWindow.get_tab_bar ().add_unique_tab (new OverView ()); 685 OverView o = MainWindow.get_overview (); 686 GlyphRange gr = new GlyphRange (); 687 688 if (!BirdFont.get_current_font ().initialised) { 689 MenuTab.new_file (); 690 } 691 692 DefaultCharacterSet.use_default_range (gr); 693 o.set_current_glyph_range (gr); 694 695 MainWindow.get_tab_bar ().select_tab_name ("Overview"); 696 } 697 698 public static void show_all_available_characters () { 699 MainWindow.get_tab_bar ().add_unique_tab (new OverView ()); 700 701 if (!BirdFont.get_current_font ().initialised) { 702 MenuTab.new_file (); 703 } 704 705 MainWindow.get_tab_bar ().select_tab_name ("Overview"); 706 OverviewTools.show_all_available_characters (); 707 } 708 709 public static void show_background_tab () { 710 BackgroundTab bt; 711 712 if (suppress_event) { 713 warn_if_test ("Event suppressed"); 714 return; 715 } 716 717 bt = BackgroundTab.get_instance (); 718 MainWindow.get_tab_bar ().add_unique_tab (bt); 719 } 720 721 public static void show_settings_tab () { 722 MainWindow.get_tab_bar ().add_unique_tab (new SettingsTab ()); 723 } 724 725 public static void show_theme_tab () { 726 MainWindow.get_tab_bar ().add_unique_tab (new ThemeTab ()); 727 } 728 729 public static void show_guide_tab () { 730 MainWindow.get_tab_bar ().add_unique_tab (new GuideTab ()); 731 } 732 } 733 734 } 735