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