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 self intersecting stroke
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 set_font_setting_from_tools (Font f) { 198 string stroke_width; 199 200 f.background_scale = DrawingTools.background_scale.get_display_value (); 201 202 f.grid_width.clear (); 203 204 foreach (SpinButton s in GridTool.sizes) { 205 f.grid_width.add (s.get_display_value ()); 206 } 207 208 stroke_width = f.settings.get_setting ("stroke_width"); 209 210 if (stroke_width != "") { 211 DrawingTools.object_stroke.set_value (stroke_width); 212 StrokeTool.stroke_width = DrawingTools.object_stroke.get_value (); 213 } 214 } 215 216 // FIXME: background thread 217 public static void save_as_bfp () { 218 FileChooser fc = new FileChooser (); 219 220 if (suppress_event) { 221 warn_if_test ("Event suppressed"); 222 return; 223 } 224 225 if (!set_suppress_event (true)) { 226 return; 227 } 228 229 fc.file_selected.connect((fn) => { 230 Font f = BirdFont.get_current_font (); 231 232 if (fn != null) { 233 f.init_bfp ((!) fn); 234 } 235 236 set_suppress_event (false); 237 }); 238 239 MainWindow.file_chooser (t_("Save"), fc, FileChooser.SAVE); 240 } 241 242 public static void new_file () { 243 Font font; 244 SaveDialogListener dialog = new SaveDialogListener (); 245 246 if (suppress_event) { 247 warn_if_test ("Event suppressed"); 248 return; 249 } 250 251 font = BirdFont.get_current_font (); 252 253 dialog.signal_discard.connect (() => { 254 MainWindow.close_all_tabs (); 255 256 BirdFont.new_font (); 257 MainWindow.native_window.font_loaded (); 258 259 show_default_characters (); 260 261 GlyphCanvas.redraw (); 262 }); 263 264 dialog.signal_save.connect (() => { 265 MenuTab.save_callback = new SaveCallback (); 266 MenuTab.save_callback.file_saved.connect (() => { 267 dialog.signal_discard (); 268 }); 269 save_callback.save (); 270 }); 271 272 dialog.signal_cancel.connect (() => { 273 MainWindow.hide_dialog (); 274 }); 275 276 if (!font.is_modified ()) { 277 dialog.signal_discard (); 278 } else { 279 MainWindow.show_dialog (new SaveDialog (dialog)); 280 } 281 282 return; 283 } 284 285 public static void quit () { 286 if (suppress_event) { 287 warn_if_test ("Event suppressed"); 288 return; 289 } 290 291 TabContent.hide_text_input (); 292 293 SaveDialogListener dialog = new SaveDialogListener (); 294 Font font = BirdFont.get_current_font (); 295 296 Preferences.save (); 297 298 dialog.signal_discard.connect (() => { 299 ensure_main_loop_is_empty (); 300 MainWindow.native_window.quit (); 301 }); 302 303 dialog.signal_save.connect (() => { 304 MenuTab.set_save_callback (new SaveCallback ()); 305 MenuTab.save_callback.file_saved.connect (() => { 306 ensure_main_loop_is_empty (); 307 MainWindow.native_window.quit (); 308 }); 309 save_callback.save (); 310 }); 311 312 dialog.signal_cancel.connect (() => { 313 MainWindow.hide_dialog (); 314 }); 315 316 if (!font.is_modified ()) { 317 dialog.signal_discard (); 318 } else { 319 MainWindow.show_dialog (new SaveDialog (dialog)); 320 } 321 } 322 323 public static void show_export_settings_tab () { 324 MainWindow.get_tab_bar ().add_unique_tab (new ExportSettings ()); 325 } 326 327 public static void show_description () { 328 MainWindow.get_tab_bar ().add_unique_tab (new DescriptionDisplay ()); 329 } 330 331 public static void show_kerning_context () { 332 if (suppress_event) { 333 warn_if_test ("Event suppressed"); 334 return; 335 } 336 337 KerningDisplay kd = MainWindow.get_kerning_display (); 338 MainWindow.get_tab_bar ().add_unique_tab (kd); 339 } 340 341 public static void show_spacing_tab () { 342 if (suppress_event) { 343 warn_if_test ("Event suppressed"); 344 return; 345 } 346 347 SpacingTab s = MainWindow.get_spacing_tab (); 348 MainWindow.get_tab_bar ().add_unique_tab (s); 349 } 350 351 public static void show_ligature_tab () { 352 if (suppress_event) { 353 warn_if_test ("Event suppressed"); 354 return; 355 } 356 357 LigatureList d = MainWindow.get_ligature_display (); 358 MainWindow.get_tab_bar ().add_unique_tab (d); 359 } 360 361 public static void preview () { 362 Font font = BirdFont.get_current_font (); 363 364 if (suppress_event) { 365 warn_if_test ("Event suppressed"); 366 return; 367 } 368 369 if (font.font_file == null) { 370 save_callback = new SaveCallback (); 371 save_callback.file_saved.connect (() => { 372 show_preview_tab (); 373 }); 374 save_callback.save (); 375 } else { 376 show_preview_tab (); 377 } 378 } 379 380 public static void show_preview_tab () { 381 OverWriteDialogListener dialog = new OverWriteDialogListener (); 382 TabBar tab_bar = MainWindow.get_tab_bar (); 383 FontFormat format = BirdFont.get_current_font ().format; 384 385 if (suppress_event) { 386 warn_if_test ("Event suppressed"); 387 return; 388 } 389 390 dialog.overwrite_signal.connect (() => { 391 KeyBindings.set_modifier (NONE); 392 tab_bar.add_unique_tab (new Preview (), true); 393 PreviewTools.update_preview (); 394 }); 395 396 if ((format == FontFormat.SVG || format == FontFormat.FREETYPE) && !OverWriteDialogListener.dont_ask_again) { 397 MainWindow.native_window.set_overwrite_dialog (dialog); 398 } else { 399 dialog.overwrite (); 400 } 401 } 402 403 /** Display the language selection tab. */ 404 public static void select_language () { 405 if (suppress_event) { 406 warn_if_test ("Event suppressed"); 407 return; 408 } 409 410 MainWindow.get_tab_bar ().add_unique_tab (new LanguageSelectionTab ()); 411 } 412 413 public static void use_current_glyph_as_background () { 414 if (suppress_event) { 415 warn_if_test ("Event suppressed"); 416 return; 417 } 418 419 Glyph.background_glyph = MainWindow.get_current_glyph (); 420 421 if (MainWindow.get_current_display () is OverView) { 422 Glyph.background_glyph = MainWindow.get_overview ().get_current_glyph (); 423 } 424 } 425 426 public static void reset_glyph_background () { 427 Glyph.background_glyph = null; 428 } 429 430 public static void remove_all_kerning_pairs () { 431 if (suppress_event) { 432 warn_if_test ("Event suppressed"); 433 return; 434 } 435 436 KerningClasses classes = BirdFont.get_current_font ().get_kerning_classes (); 437 classes.remove_all_pairs (); 438 KerningTools.update_kerning_classes (); 439 } 440 441 public static void list_all_kerning_pairs () { 442 if (suppress_event) { 443 warn_if_test ("Event suppressed"); 444 return; 445 } 446 447 MainWindow.get_tab_bar ().add_unique_tab (new KerningList ()); 448 } 449 450 public static void ensure_main_loop_is_empty () { 451 unowned MainContext context; 452 bool acquired; 453 454 context = MainContext.default (); 455 acquired = context.acquire (); 456 457 if (unlikely (!acquired)) { 458 warning ("Failed to acquire main loop.\n"); 459 return; 460 } 461 462 while (context.pending ()) { 463 context.iteration (true); 464 } 465 context.release (); 466 } 467 468 public static void save_as () { 469 if (MenuTab.suppress_event || !save_callback.is_done) { 470 warn_if_test ("Event suppressed"); 471 return; 472 } 473 474 MenuTab.set_save_callback (new SaveCallback ()); 475 MenuTab.save_callback.save_as(); 476 } 477 478 public static void save () { 479 if (MenuTab.suppress_event && !save_callback.is_done) { 480 warn_if_test ("Event suppressed"); 481 return; 482 } 483 484 MenuTab.set_save_callback (new SaveCallback ()); 485 MenuTab.save_callback.save (); 486 } 487 488 public static void load () { 489 if (MenuTab.suppress_event) { 490 warn_if_test ("Event suppressed"); 491 return; 492 } 493 494 MenuTab.load_callback = new LoadCallback (); 495 MenuTab.load_callback.load (); 496 497 MenuTab.load_callback.file_loaded.connect (() => { 498 Font f = BirdFont.get_current_font (); 499 MenuTab.set_font_setting_from_tools (f); 500 }); 501 } 502 503 public static void move_to_baseline () { 504 if (suppress_event) { 505 warn_if_test ("Event suppressed"); 506 return; 507 } 508 509 DrawingTools.move_tool.move_to_baseline (); 510 } 511 512 public static void show_file_dialog_tab (string title, FileChooser action) { 513 MainWindow.get_tab_bar ().add_tab (new FileDialogTab (title, action)); 514 } 515 516 public static void simplify_path () { 517 if (suppress_event) { 518 warn_if_test ("Event suppressed"); 519 return; 520 } 521 522 Task t = new Task (); 523 t.task.connect (simplify); 524 MainWindow.native_window.run_background_thread (t); 525 } 526 527 private static void simplify () { 528 Glyph g = MainWindow.get_current_glyph (); 529 Gee.ArrayList<Path> paths = new Gee.ArrayList<Path> (); 530 531 // selected objects 532 foreach (Path p in g.active_paths) { 533 paths.add (PenTool.simplify (p, false, PenTool.simplification_threshold)); 534 } 535 536 // selected segments 537 if (paths.size == 0) { 538 foreach (Path p in g.path_list) { 539 g.add_active_path (p); 540 } 541 542 foreach (Path p in g.active_paths) { 543 paths.add (PenTool.simplify (p, true, PenTool.simplification_threshold)); 544 } 545 } 546 547 g.store_undo_state (); 548 549 foreach (Path p in g.active_paths) { 550 g.path_list.remove (p); 551 } 552 553 foreach (Path p in g.active_paths) { 554 g.path_list.remove (p); 555 } 556 557 foreach (Path p in paths) { 558 g.add_path (p); 559 g.add_active_path (p); 560 } 561 562 g.active_paths.clear (); 563 g.update_view (); 564 } 565 566 public static void show_spacing_class_tab () { 567 SpacingClassTab t = MainWindow.get_spacing_class_tab (); 568 MainWindow.get_tab_bar ().add_unique_tab (t); 569 } 570 571 public static void add_ligature () { 572 TextListener listener; 573 string ligature_name = ""; 574 575 if (suppress_event) { 576 warn_if_test ("Event suppressed"); 577 return; 578 } 579 580 listener = new TextListener (t_("Name"), "", t_("Add ligature")); 581 582 listener.signal_text_input.connect ((text) => { 583 ligature_name = text; 584 }); 585 586 listener.signal_submit.connect (() => { 587 Font font = BirdFont.get_current_font (); 588 GlyphCollection? fg; 589 Glyph glyph; 590 GlyphCollection glyph_collection; 591 OverView o = MainWindow.get_overview (); 592 593 fg = font.get_glyph_collection_by_name (ligature_name); 594 595 if (fg == null) { 596 glyph_collection = new GlyphCollection ('\0', ligature_name); 597 598 glyph = new Glyph (ligature_name, '\0'); 599 glyph_collection.set_unassigned (true); 600 glyph_collection.insert_glyph (glyph, true); 601 602 font.add_glyph_collection (glyph_collection); 603 } 604 605 o.display_all_available_glyphs (); 606 o.scroll_to_glyph (ligature_name); 607 608 TabContent.hide_text_input (); 609 show_all_available_characters (); 610 }); 611 612 TabContent.show_text_input (listener); 613 } 614 615 public static void show_default_characters () { 616 MainWindow.get_tab_bar ().add_unique_tab (new OverView ()); 617 OverView o = MainWindow.get_overview (); 618 GlyphRange gr = new GlyphRange (); 619 620 if (!BirdFont.get_current_font ().initialised) { 621 MenuTab.new_file (); 622 } 623 624 DefaultCharacterSet.use_default_range (gr); 625 o.set_glyph_range (gr); 626 627 MainWindow.get_tab_bar ().select_tab_name ("Overview"); 628 } 629 630 public static void show_all_available_characters () { 631 MainWindow.get_tab_bar ().add_unique_tab (new OverView ()); 632 633 if (!BirdFont.get_current_font ().initialised) { 634 MenuTab.new_file (); 635 } 636 637 MainWindow.get_tab_bar ().select_tab_name ("Overview"); 638 OverviewTools.show_all_available_characters (); 639 } 640 641 public static void show_background_tab () { 642 BackgroundTab bt; 643 644 if (suppress_event) { 645 warn_if_test ("Event suppressed"); 646 return; 647 } 648 649 bt = BackgroundTab.get_instance (); 650 MainWindow.get_tab_bar ().add_unique_tab (bt); 651 } 652 653 public static void show_settings_tab () { 654 MainWindow.get_tab_bar ().add_unique_tab (new SettingsTab ()); 655 } 656 657 public static void show_theme_tab () { 658 MainWindow.get_tab_bar ().add_unique_tab (new ThemeTab ()); 659 } 660 661 public static void show_guide_tab () { 662 MainWindow.get_tab_bar ().add_unique_tab (new GuideTab ()); 663 } 664 } 665 666 } 667