The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

Menu.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/Menu.vala.
New color theme
1 /* 2 Copyright (C) 2014 2015 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 using Cairo; 16 using Bird; 17 18 namespace BirdFont { 19 20 /** Interface for events from native window to the current tab. */ 21 public class Menu : GLib.Object { 22 23 public bool show_menu { 24 get { 25 return menu_visibility; 26 } 27 28 set { 29 string tab_name; 30 31 menu_visibility = value; 32 current_menu = top_menu; 33 34 if (menu_visibility) { 35 tab_name = MainWindow.get_tab_bar ().get_selected_tab ().get_display ().get_name (); 36 if (tab_name == "Preview") { 37 MenuTab.select_overview (); 38 } 39 } 40 } 41 } 42 43 public bool menu_visibility = false; 44 public SubMenu top_menu; 45 46 SubMenu current_menu; 47 WidgetAllocation allocation; 48 49 double width = 250 * MainWindow.units; 50 double height = 25 * MainWindow.units; 51 52 public Gee.HashMap<string, MenuItem> menu_items = new Gee.HashMap<string, MenuItem> (); 53 public Gee.ArrayList<MenuItem> sorted_menu_items = new Gee.ArrayList<MenuItem> (); 54 55 public Menu () { 56 SubMenu menu = new SubMenu (); 57 SubMenu file_menu = new SubMenu (); 58 SubMenu edit_menu = new SubMenu (); 59 SubMenu tab_menu = new SubMenu (); 60 SubMenu kerning_menu = new SubMenu (); 61 SubMenu ligature_menu = new SubMenu (); 62 SubMenu git_menu = new SubMenu (); 63 64 // file menu 65 MenuItem file = add_menu_item (t_("File")); 66 file.action.connect (() => { 67 set_menu (file_menu); 68 }); 69 menu.items.add (file); 70 71 MenuItem new_file = add_menu_item (t_("New"), "new"); 72 new_file.action.connect (() => { 73 MenuTab.new_file (); 74 show_menu = false; 75 }); 76 file_menu.items.add (new_file); 77 78 MenuItem open = add_menu_item (t_("Open"), "open"); 79 open.action.connect (() => { 80 show_menu = false; 81 MenuTab.load (); 82 }); 83 file_menu.items.add (open); 84 85 MenuItem recent_files = add_menu_item (t_("Recent Files"), "recent files"); 86 recent_files.action.connect (() => { 87 show_menu = false; 88 MainWindow.open_recent_files_tab (); 89 }); 90 file_menu.items.add (recent_files); 91 92 MenuItem save = add_menu_item (t_("Save"), "save"); 93 save.action.connect (() => { 94 MenuTab.save (); 95 show_menu = false; 96 }); 97 file_menu.items.add (save); 98 99 MenuItem save_as = add_menu_item (t_("Save As"), "save as"); 100 save_as.action.connect (() => { 101 MenuTab.save_as (); 102 show_menu = false; 103 }); 104 file_menu.items.add (save_as); 105 106 MenuItem export = add_menu_item (t_("Export"), "export"); 107 export.action.connect (() => { 108 MenuTab.export_fonts_in_background (); 109 show_menu = false; 110 }); 111 file_menu.items.add (export); 112 113 MenuItem export_settings = add_menu_item (t_("Export Settings"), "export settings"); 114 export_settings.action.connect (() => { 115 MenuTab.show_export_settings_tab (); 116 show_menu = false; 117 }); 118 file_menu.items.add (export_settings); 119 120 MenuItem preview = add_menu_item (t_("Preview"), "preview"); 121 preview.action.connect (() => { 122 MenuTab.preview (); 123 show_menu = false; 124 }); 125 file_menu.items.add (preview); 126 127 MenuItem select_character_set = add_menu_item (t_("Select Character Set"), "select character set"); 128 select_character_set.action.connect (() => { 129 MenuTab.select_language (); 130 show_menu = false; 131 }); 132 file_menu.items.add (select_character_set); 133 134 MenuItem quit = add_menu_item (t_("Quit"), "quit"); 135 quit.action.connect (() => { 136 MenuTab.quit (); 137 show_menu = false; 138 }); 139 file_menu.items.add (quit); 140 141 // edit menu 142 MenuItem edit = add_menu_item (t_("Edit")); 143 edit.action.connect (() => { 144 set_menu (edit_menu); 145 }); 146 menu.items.add (edit); 147 148 MenuItem undo = add_menu_item (t_("Undo"), "undo"); 149 undo.action.connect (() => { 150 TabContent.undo (); 151 show_menu = false; 152 }); 153 edit_menu.items.add (undo); 154 155 MenuItem redo = add_menu_item (t_("Redo"), "redo"); 156 redo.action.connect (() => { 157 TabContent.redo (); 158 show_menu = false; 159 }); 160 edit_menu.items.add (redo); 161 162 MenuItem copy = add_menu_item (t_("Copy"), "copy"); 163 copy.action.connect (() => { 164 ClipTool.copy (); 165 show_menu = false; 166 }); 167 edit_menu.items.add (copy); 168 169 MenuItem paste = add_menu_item (t_("Paste"), "paste"); 170 paste.action.connect (() => { 171 ClipTool.paste (); 172 show_menu = false; 173 }); 174 edit_menu.items.add (paste); 175 176 MenuItem paste_in_place = add_menu_item (t_("Paste In Place"), "paste in place", "Glyph"); 177 paste_in_place.action.connect (() => { 178 ClipTool.paste_in_place (); 179 show_menu = false; 180 }); 181 edit_menu.items.add (paste_in_place); 182 183 MenuItem select_all_paths = add_menu_item (t_("Select All Paths"), "select all paths", "Glyph"); 184 select_all_paths.action.connect (() => { 185 MainWindow.select_all_paths (); 186 show_menu = false; 187 }); 188 edit_menu.items.add (select_all_paths); 189 190 MenuItem move_to_baseline = add_menu_item (t_("Move To Baseline"), "move to baseline", "Glyph"); 191 move_to_baseline.action.connect (() => { 192 MenuTab.move_to_baseline (); 193 show_menu = false; 194 }); 195 edit_menu.items.add (move_to_baseline); 196 197 MenuItem search = add_menu_item (t_("Search"), "search"); 198 search.action.connect (() => { 199 OverView.search (); 200 show_menu = false; 201 }); 202 edit_menu.items.add (search); 203 204 MenuItem export_glyph = add_menu_item (t_("Export Glyph as SVG"), "export glyph as svg", "Glyph"); 205 export_glyph.action.connect (() => { 206 ExportTool.export_current_glyph (); 207 show_menu = false; 208 }); 209 edit_menu.items.add (export_glyph); 210 211 MenuItem import_svg = add_menu_item (t_("Import SVG file"), "import svg file", "Glyph"); 212 import_svg.action.connect (() => { 213 SvgParser.import (); 214 show_menu = false; 215 }); 216 edit_menu.items.add (import_svg); 217 218 MenuItem import_background_image = add_menu_item (t_("Import Background Image"), "import background image"); 219 import_background_image.action.connect (() => { 220 MenuTab.show_background_tab (); 221 show_menu = false; 222 }); 223 edit_menu.items.add (import_background_image); 224 225 MenuItem simplify_path = add_menu_item (t_("Simplify Path"), "simplify path", "Glyph"); 226 simplify_path.action.connect (() => { 227 MenuTab.simplify_path (); 228 show_menu = false; 229 }); 230 edit_menu.items.add (simplify_path); 231 232 MenuItem close_path = add_menu_item (t_("Close Path"), "close path", "Glyph"); 233 close_path.action.connect (() => { 234 PenTool.close_all_paths (); 235 show_menu = false; 236 }); 237 edit_menu.items.add (close_path); 238 239 MenuItem glyph_sequence = add_menu_item (t_("Glyph Sequence"), "glyph sequence"); 240 glyph_sequence.action.connect (() => { 241 MainWindow.update_glyph_sequence (); 242 show_menu = false; 243 }); 244 edit_menu.items.add (glyph_sequence); 245 246 MenuItem set_background_glyph = add_menu_item (t_("Set Background Glyph"), "set background glyph", "Glyph"); 247 set_background_glyph.action.connect (() => { 248 MenuTab.use_current_glyph_as_background (); 249 show_menu = false; 250 }); 251 edit_menu.items.add (set_background_glyph); 252 253 MenuItem remove_background_glyph = add_menu_item (t_("Remove Background Glyph"), "remove background glyph", "Glyph"); 254 remove_background_glyph.action.connect (() => { 255 MenuTab.reset_glyph_background (); 256 show_menu = false; 257 }); 258 edit_menu.items.add (remove_background_glyph); 259 260 MenuItem create_guide = add_menu_item (t_("Create Guide"), "create guide"); 261 create_guide.action.connect (() => { 262 MainWindow.get_current_glyph ().add_custom_guide (); 263 show_menu = false; 264 }); 265 edit_menu.items.add (create_guide); 266 267 MenuItem show_guide_guide = add_menu_item (t_("List Guides"), "show guide tab"); 268 show_guide_guide.action.connect (() => { 269 MenuTab.show_guide_tab (); 270 show_menu = false; 271 }); 272 edit_menu.items.add (show_guide_guide); 273 274 MenuItem select_point_above = add_menu_item (t_("Select Point Above"), "select point above", "Glyph"); 275 select_point_above.action.connect (() => { 276 PenTool.select_point_up (); 277 show_menu = false; 278 }); 279 edit_menu.items.add (select_point_above); 280 281 MenuItem select_next_point = add_menu_item (t_("Select Next Point"), "select next point", "Glyph"); 282 select_next_point.action.connect (() => { 283 PenTool.select_point_right (); 284 show_menu = false; 285 }); 286 edit_menu.items.add (select_next_point); 287 288 MenuItem select_previous_point = add_menu_item (t_("Select Previous Point"), "select previous point", "Glyph"); 289 select_previous_point.action.connect (() => { 290 PenTool.select_point_left (); 291 show_menu = false; 292 }); 293 edit_menu.items.add (select_previous_point); 294 295 MenuItem select_point_below = add_menu_item (t_("Select Point Below"), "select point below", "Glyph"); 296 select_point_below.action.connect (() => { 297 PenTool.select_point_down (); 298 show_menu = false; 299 }); 300 edit_menu.items.add (select_point_below); 301 302 // tab menu 303 MenuItem tab = add_menu_item (t_("Tab")); 304 tab.action.connect (() => { 305 set_menu (tab_menu); 306 }); 307 menu.items.add (tab); 308 309 MenuItem next_tab = add_menu_item (t_("Next Tab"), "next tab"); 310 next_tab.action.connect (() => { 311 MainWindow.next_tab (); 312 show_menu = false; 313 }); 314 tab_menu.items.add (next_tab); 315 316 MenuItem previous_tab = add_menu_item (t_("Previous Tab"), "previous tab"); 317 previous_tab.action.connect (() => { 318 MainWindow.previous_tab (); 319 show_menu = false; 320 }); 321 tab_menu.items.add (previous_tab); 322 323 MenuItem close_tab = add_menu_item (t_("Close Tab"), "close tab"); 324 close_tab.action.connect (() => { 325 MainWindow.close_tab (); 326 show_menu = false; 327 }); 328 tab_menu.items.add (close_tab); 329 330 MenuItem close_all_tabs = add_menu_item (t_("Close All Tabs"), "close all tabs"); 331 close_all_tabs.action.connect (() => { 332 MainWindow.close_all_tabs (); 333 show_menu = false; 334 }); 335 tab_menu.items.add (close_all_tabs); 336 337 // tab menu 338 MenuItem kerning = add_menu_item (t_("Spacing and Kerning")); 339 kerning.action.connect (() => { 340 set_menu (kerning_menu); 341 }); 342 menu.items.add (kerning); 343 344 MenuItem spacing_tab = add_menu_item (t_("Show Spacing Tab"), "show spacing tab"); 345 spacing_tab.action.connect (() => { 346 MenuTab.show_spacing_tab (); 347 show_menu = false; 348 }); 349 kerning_menu.items.add (spacing_tab); 350 351 MenuItem kerning_tab = add_menu_item (t_("Show Kerning Tab"), "show kerning tab"); 352 kerning_tab.action.connect (() => { 353 MenuTab.show_kerning_context (); 354 show_menu = false; 355 }); 356 kerning_menu.items.add (kerning_tab); 357 358 MenuItem list_kernings = add_menu_item (t_("List Kerning Pairs"), "list kerning pairs"); 359 list_kernings.action.connect (() => { 360 MenuTab.list_all_kerning_pairs (); 361 show_menu = false; 362 }); 363 kerning_menu.items.add (list_kernings); 364 365 MenuItem show_spacing = add_menu_item (t_("Spacing Classes"), "show spacing classes"); 366 show_spacing.action.connect (() => { 367 MenuTab.show_spacing_class_tab (); 368 show_menu = false; 369 }); 370 kerning_menu.items.add (show_spacing); 371 372 MenuItem next_kerning_pair = add_menu_item (t_("Select Next Kerning Pair"), "select next kerning pair"); 373 next_kerning_pair.action.connect (() => { 374 KerningDisplay.next_pair (); 375 show_menu = false; 376 }); 377 next_kerning_pair.add_display("Kerning"); 378 next_kerning_pair.add_display("Spacing"); 379 kerning_menu.items.add (next_kerning_pair); 380 381 MenuItem previous_kerning_pair = add_menu_item (t_("Select Previous Kerning Pair"), "select previous kerning pair"); 382 previous_kerning_pair.action.connect (() => { 383 KerningDisplay.previous_pair (); 384 show_menu = false; 385 }); 386 previous_kerning_pair.add_display("Kerning"); 387 previous_kerning_pair.add_display("Spacing"); 388 kerning_menu.items.add (previous_kerning_pair); 389 390 MenuItem load_kerning_strings = add_menu_item (t_("Load Kerning Strings"), "load kerning strings"); 391 load_kerning_strings.action.connect (() => { 392 BirdFont.get_current_font ().kerning_strings.load_file (); 393 show_menu = false; 394 }); 395 kerning_menu.items.add (load_kerning_strings); 396 397 MenuItem reload_kerning_strings = add_menu_item (t_("Reload Kerning Strings"), "reloadload kerning strings"); 398 reload_kerning_strings.action.connect (() => { 399 Font f = BirdFont.get_current_font (); 400 f.kerning_strings.load (f); 401 show_menu = false; 402 }); 403 kerning_menu.items.add (reload_kerning_strings); 404 405 // ligature menu 406 MenuItem ligature = add_menu_item (t_("Ligatures")); 407 ligature.action.connect (() => { 408 set_menu (ligature_menu); 409 }); 410 menu.items.add (ligature); 411 412 MenuItem ligature_tab = add_menu_item (t_("Show Ligatures"), "show ligature tab"); 413 ligature_tab.action.connect (() => { 414 MenuTab.show_ligature_tab (); 415 show_menu = false; 416 }); 417 ligature_menu.items.add (ligature_tab); 418 419 MenuItem add_ligature = add_menu_item (t_("Add Ligature"), "add ligature"); 420 add_ligature.action.connect (() => { 421 MenuTab.add_ligature (); 422 show_menu = false; 423 }); 424 ligature_menu.items.add (add_ligature); 425 426 // git menu 427 if (BirdFont.has_argument ("--test")) { 428 MenuItem git = add_menu_item (t_("Git")); 429 git.action.connect (() => { 430 set_menu (git_menu); 431 }); 432 menu.items.add (git); 433 434 MenuItem save_bfp = add_menu_item (t_("Save As .bfp"), "save as .bfp"); 435 save_bfp.action.connect (() => { 436 MenuTab.save_as_bfp (); 437 show_menu = false; 438 }); 439 git_menu.items.add (save_bfp); 440 } 441 442 // show overview 443 MenuItem overview = add_menu_item (t_("Overview")); 444 overview.action.connect (() => { 445 MenuTab.select_overview (); 446 show_menu = false; 447 }); 448 menu.items.add (overview); 449 450 // settings 451 MenuItem settings = add_menu_item (t_("Settings"), "settings"); 452 settings.action.connect (() => { 453 MenuTab.show_settings_tab (); 454 show_menu = false; 455 }); 456 menu.items.add (settings); 457 458 MenuItem description = add_menu_item (t_("Name and Description"), "name and description"); 459 description.action.connect (() => { 460 MenuTab.show_description (); 461 show_menu = false; 462 }); 463 menu.items.add (description); 464 465 current_menu = menu; 466 top_menu = menu; 467 allocation = new WidgetAllocation (); 468 469 add_tool_key_bindings (); 470 load_key_bindings (); 471 } 472 473 public void process_key_binding_events (uint keyval) { 474 string display; 475 FontDisplay current_display = MainWindow.get_current_display (); 476 ToolItem tm; 477 478 foreach (MenuItem item in sorted_menu_items) { 479 if (item.key == (unichar) keyval && item.modifiers == KeyBindings.modifier) { 480 481 display = current_display.get_name (); 482 483 if (current_display is Glyph) { 484 display = "Glyph"; 485 } 486 487 if (!current_display.needs_modifier () || item.modifiers != NONE) { 488 if (!SettingsDisplay.update_key_bindings 489 && item.in_display (display) 490 && !(item is ToolItem)) { 491 item.action (); 492 return; 493 } 494 495 if (item is ToolItem) { 496 tm = (ToolItem) item; 497 498 if (tm.in_display (display)) { 499 if (tm.tool.editor_events) { 500 MainWindow.get_toolbox ().set_current_tool (tm.tool); 501 tm.tool.select_action (tm.tool); 502 return; 503 } else { 504 tm.tool.select_action (tm.tool); 505 return; 506 } 507 } 508 } 509 } 510 } 511 } 512 } 513 514 void load_key_bindings () { 515 File default_key_bindings = SearchPaths.find_file (null, "key_bindings.xml"); 516 File user_key_bindings = get_child (BirdFont.get_settings_directory (), "key_bindings.xml"); 517 518 if (default_key_bindings.query_exists ()) { 519 parse_key_bindings (default_key_bindings); 520 } 521 522 if (user_key_bindings.query_exists ()) { 523 parse_key_bindings (user_key_bindings); 524 } 525 } 526 527 void parse_key_bindings (File f) { 528 string xml_data; 529 XmlParser parser; 530 531 try { 532 FileUtils.get_contents((!) f.get_path (), out xml_data); 533 parser = new XmlParser (xml_data); 534 parse_bindings (parser.get_root_tag ()); 535 } catch (GLib.Error e) { 536 warning (e.message); 537 } 538 } 539 540 void parse_bindings (Tag tag) { 541 foreach (Tag t in tag) { 542 if (t.get_name () == "action") { 543 parse_binding (t.get_attributes ()); 544 } 545 } 546 } 547 548 void parse_binding (Attributes attr) { 549 uint modifier = NONE; 550 unichar key = '\0'; 551 string action = ""; 552 MenuItem menu_action; 553 MenuItem? ma; 554 555 foreach (Attribute a in attr) { 556 if (a.get_name () == "key") { 557 key = a.get_content ().get_char (0); 558 } 559 560 if (a.get_name () == "ctrl" && a.get_content () == "true") { 561 modifier |= CTRL; 562 } 563 564 if (a.get_name () == "alt" && a.get_content () == "true") { 565 modifier |= ALT; 566 } 567 568 if (a.get_name () == "command" && a.get_content () == "true") { 569 modifier |= LOGO; 570 } 571 572 if (a.get_name () == "shift" && a.get_content () == "true") { 573 modifier |= SHIFT; 574 } 575 576 if (a.get_name () == "action") { 577 action = a.get_content (); 578 } 579 } 580 581 ma = menu_items.get (action); 582 if (ma != null) { 583 menu_action = (!) ma; 584 menu_action.modifiers = modifier; 585 menu_action.key = key; 586 } 587 } 588 589 MenuItem add_menu_item (string label, string description = "", string display = "") { 590 MenuItem i = new MenuItem (label, description); 591 592 if (description != "") { 593 menu_items.set (description, i); 594 sorted_menu_items.add (i); 595 } 596 597 if (display != "") { 598 i.add_display (display); 599 } 600 601 return i; 602 } 603 604 public void button_release (int button, double ex, double ey) { 605 double y = 0; 606 double x = allocation.width - width; 607 608 if (button == 1) { 609 foreach (MenuItem item in current_menu.items) { 610 if (x <= ex < allocation.width && y <= ey <= y + height) { 611 item.action (); 612 GlyphCanvas.redraw (); 613 return; 614 } 615 616 y += height; 617 } 618 619 menu_visibility = false; 620 current_menu = (!) top_menu; 621 GlyphCanvas.redraw (); 622 } 623 } 624 625 void add_tool_key_bindings () { 626 ToolItem tool_item; 627 foreach (ToolCollection tool_set in MainWindow.get_toolbox ().tool_sets) { 628 foreach (Expander e in tool_set.get_expanders ()) { 629 foreach (Tool t in e.tool) { 630 tool_item = new ToolItem (t); 631 if (tool_item.identifier != "" && !has_menu_item (tool_item.identifier)) { 632 menu_items.set (tool_item.identifier, tool_item); 633 sorted_menu_items.add (tool_item); 634 } 635 636 foreach (string d in tool_set.get_displays ()) { 637 tool_item.add_display (d); 638 } 639 } 640 } 641 } 642 } 643 644 public bool has_menu_item (string identifier) { 645 foreach (MenuItem mi in sorted_menu_items) { 646 if (mi.identifier == identifier) { 647 return true; 648 } 649 } 650 651 return false; 652 } 653 654 public void set_menu (SubMenu m) { 655 current_menu = m; 656 GlyphCanvas.redraw (); 657 } 658 659 public double layout_width () { 660 Text key_binding = new Text (); 661 double font_size = 17 * MainWindow.units;; 662 double w; 663 664 width = 0; 665 foreach (MenuItem item in current_menu.items) { 666 key_binding.set_text (item.get_key_bindings ()); 667 668 item.label.set_font_size (font_size); 669 key_binding.set_font_size (font_size); 670 671 w = item.label.get_extent (); 672 w += key_binding.get_extent (); 673 w += 3 * height * MainWindow.units; 674 675 if (w > width) { 676 width = w; 677 } 678 } 679 680 return width; 681 } 682 683 public void draw (WidgetAllocation allocation, Context cr) { 684 double y; 685 double x; 686 double label_x; 687 double label_y; 688 double font_size; 689 Text key_binding; 690 double binding_extent; 691 692 width = layout_width (); 693 694 key_binding = new Text (); 695 696 x = allocation.width - width; 697 y = 0; 698 font_size = 17 * MainWindow.units; 699 this.allocation = allocation; 700 701 foreach (MenuItem item in current_menu.items) { 702 cr.save (); 703 Theme.color (cr, "Background 3"); 704 cr.rectangle (x, y, width, height); 705 cr.fill (); 706 cr.restore (); 707 708 cr.save (); 709 label_x = allocation.width - width + 0.7 * height * MainWindow.units; 710 label_y = y + font_size - 1 * MainWindow.units; 711 Theme.text_color (item.label, "Menu Foreground"); 712 item.label.draw_at_baseline (cr, label_x, label_y); 713 714 key_binding.set_text (item.get_key_bindings ()); 715 key_binding.set_font_size (font_size); 716 binding_extent = key_binding.get_extent (); 717 label_x = x + width - binding_extent - 0.6 * height * MainWindow.units; 718 key_binding.set_font_size (font_size); 719 Theme.text_color (key_binding, "Menu Foreground"); 720 key_binding.draw_at_baseline (cr, label_x, label_y); 721 722 y += height; 723 } 724 } 725 726 public void write_key_bindings () { 727 DataOutputStream os; 728 File file; 729 bool has_ctrl, has_alt, has_command, has_shift; 730 731 file = get_child (BirdFont.get_settings_directory (), "key_bindings.xml"); 732 733 try { 734 if (file.query_exists ()) { 735 file.delete (); 736 } 737 } catch (GLib.Error e) { 738 warning (e.message); 739 } 740 741 try { 742 os = new DataOutputStream (file.create (FileCreateFlags.REPLACE_DESTINATION)); 743 os.put_string ("""<?xml version="1.0" encoding="utf-8" standalone="yes"?>"""); 744 os.put_string ("\n"); 745 746 os.put_string ("<bindings>\n"); 747 748 foreach (MenuItem item in sorted_menu_items) { 749 os.put_string ("\t<action "); 750 751 os.put_string (@"key=\"$((!)item.key.to_string ())\" "); 752 753 has_ctrl = (item.modifiers & CTRL) > 0; 754 os.put_string (@"ctrl=\"$(has_ctrl.to_string ())\" "); 755 756 has_alt = (item.modifiers & ALT) > 0; 757 os.put_string (@"alt=\"$(has_alt.to_string ())\" "); 758 759 has_command = (item.modifiers & LOGO) > 0; 760 os.put_string (@"command=\"$(has_command.to_string ())\" "); 761 762 has_shift = (item.modifiers & SHIFT) > 0; 763 os.put_string (@"shift=\"$(has_shift.to_string ())\" "); 764 765 os.put_string (@"action=\"$(item.identifier)\" "); 766 767 os.put_string ("/>\n"); 768 } 769 os.put_string ("</bindings>\n"); 770 771 os.close (); 772 } catch (GLib.Error e) { 773 warning (e.message); 774 } 775 } 776 777 public class SubMenu : GLib.Object { 778 public Gee.ArrayList<MenuItem> items; 779 780 public SubMenu () { 781 items = new Gee.ArrayList<MenuItem> (); 782 } 783 } 784 } 785 786 } 787