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