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