1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gtk.MenuShell; 26 27 private import gio.MenuModel; 28 private import glib.Str; 29 private import gobject.ObjectG; 30 private import gobject.Signals; 31 private import gtk.Container; 32 private import gtk.MenuItem; 33 private import gtk.Widget; 34 private import gtk.c.functions; 35 public import gtk.c.types; 36 public import gtkc.gtktypes; 37 private import std.algorithm; 38 39 40 /** 41 * A #GtkMenuShell is the abstract base class used to derive the 42 * #GtkMenu and #GtkMenuBar subclasses. 43 * 44 * A #GtkMenuShell is a container of #GtkMenuItem objects arranged 45 * in a list which can be navigated, selected, and activated by the 46 * user to perform application functions. A #GtkMenuItem can have a 47 * submenu associated with it, allowing for nested hierarchical menus. 48 * 49 * # Terminology 50 * 51 * A menu item can be “selected”, this means that it is displayed 52 * in the prelight state, and if it has a submenu, that submenu 53 * will be popped up. 54 * 55 * A menu is “active” when it is visible onscreen and the user 56 * is selecting from it. A menubar is not active until the user 57 * clicks on one of its menuitems. When a menu is active, 58 * passing the mouse over a submenu will pop it up. 59 * 60 * There is also is a concept of the current menu and a current 61 * menu item. The current menu item is the selected menu item 62 * that is furthest down in the hierarchy. (Every active menu shell 63 * does not necessarily contain a selected menu item, but if 64 * it does, then the parent menu shell must also contain 65 * a selected menu item.) The current menu is the menu that 66 * contains the current menu item. It will always have a GTK 67 * grab and receive all key presses. 68 */ 69 public class MenuShell : Container 70 { 71 /** the main Gtk struct */ 72 protected GtkMenuShell* gtkMenuShell; 73 74 /** Get the main Gtk struct */ 75 public GtkMenuShell* getMenuShellStruct(bool transferOwnership = false) 76 { 77 if (transferOwnership) 78 ownedRef = false; 79 return gtkMenuShell; 80 } 81 82 /** the main Gtk struct as a void* */ 83 protected override void* getStruct() 84 { 85 return cast(void*)gtkMenuShell; 86 } 87 88 protected override void setStruct(GObject* obj) 89 { 90 gtkMenuShell = cast(GtkMenuShell*)obj; 91 super.setStruct(obj); 92 } 93 94 /** 95 * Sets our main struct and passes it to the parent class. 96 */ 97 public this (GtkMenuShell* gtkMenuShell, bool ownedRef = false) 98 { 99 this.gtkMenuShell = gtkMenuShell; 100 super(cast(GtkContainer*)gtkMenuShell, ownedRef); 101 } 102 103 104 /** */ 105 public static GType getType() 106 { 107 return gtk_menu_shell_get_type(); 108 } 109 110 /** 111 * Activates the menu item within the menu shell. 112 * 113 * Params: 114 * menuItem = the #GtkMenuItem to activate 115 * forceDeactivate = if %TRUE, force the deactivation of the 116 * menu shell after the menu item is activated 117 */ 118 public void activateItem(Widget menuItem, bool forceDeactivate) 119 { 120 gtk_menu_shell_activate_item(gtkMenuShell, (menuItem is null) ? null : menuItem.getWidgetStruct(), forceDeactivate); 121 } 122 123 /** 124 * Adds a new #GtkMenuItem to the end of the menu shell's 125 * item list. 126 * 127 * Params: 128 * child = The #GtkMenuItem to add 129 */ 130 public void append(MenuItem child) 131 { 132 gtk_menu_shell_append(gtkMenuShell, (child is null) ? null : cast(GtkWidget*)child.getMenuItemStruct()); 133 } 134 135 /** 136 * Establishes a binding between a #GtkMenuShell and a #GMenuModel. 137 * 138 * The contents of @shell are removed and then refilled with menu items 139 * according to @model. When @model changes, @shell is updated. 140 * Calling this function twice on @shell with different @model will 141 * cause the first binding to be replaced with a binding to the new 142 * model. If @model is %NULL then any previous binding is undone and 143 * all children are removed. 144 * 145 * @with_separators determines if toplevel items (eg: sections) have 146 * separators inserted between them. This is typically desired for 147 * menus but doesn’t make sense for menubars. 148 * 149 * If @action_namespace is non-%NULL then the effect is as if all 150 * actions mentioned in the @model have their names prefixed with the 151 * namespace, plus a dot. For example, if the action “quit” is 152 * mentioned and @action_namespace is “app” then the effective action 153 * name is “app.quit”. 154 * 155 * This function uses #GtkActionable to define the action name and 156 * target values on the created menu items. If you want to use an 157 * action group other than “app” and “win”, or if you want to use a 158 * #GtkMenuShell outside of a #GtkApplicationWindow, then you will need 159 * to attach your own action group to the widget hierarchy using 160 * gtk_widget_insert_action_group(). As an example, if you created a 161 * group with a “quit” action and inserted it with the name “mygroup” 162 * then you would use the action name “mygroup.quit” in your 163 * #GMenuModel. 164 * 165 * For most cases you are probably better off using 166 * gtk_menu_new_from_model() or gtk_menu_bar_new_from_model() or just 167 * directly passing the #GMenuModel to gtk_application_set_app_menu() or 168 * gtk_application_set_menubar(). 169 * 170 * Params: 171 * model = the #GMenuModel to bind to or %NULL to remove 172 * binding 173 * actionNamespace = the namespace for actions in @model 174 * withSeparators = %TRUE if toplevel items in @shell should have 175 * separators between them 176 * 177 * Since: 3.6 178 */ 179 public void bindModel(MenuModel model, string actionNamespace, bool withSeparators) 180 { 181 gtk_menu_shell_bind_model(gtkMenuShell, (model is null) ? null : model.getMenuModelStruct(), Str.toStringz(actionNamespace), withSeparators); 182 } 183 184 /** 185 * Cancels the selection within the menu shell. 186 * 187 * Since: 2.4 188 */ 189 public void cancel() 190 { 191 gtk_menu_shell_cancel(gtkMenuShell); 192 } 193 194 /** 195 * Deactivates the menu shell. 196 * 197 * Typically this results in the menu shell being erased 198 * from the screen. 199 */ 200 public void deactivate() 201 { 202 gtk_menu_shell_deactivate(gtkMenuShell); 203 } 204 205 /** 206 * Deselects the currently selected item from the menu shell, 207 * if any. 208 */ 209 public void deselect() 210 { 211 gtk_menu_shell_deselect(gtkMenuShell); 212 } 213 214 /** 215 * Gets the parent menu shell. 216 * 217 * The parent menu shell of a submenu is the #GtkMenu or #GtkMenuBar 218 * from which it was opened up. 219 * 220 * Returns: the parent #GtkMenuShell 221 * 222 * Since: 3.0 223 */ 224 public Widget getParentShell() 225 { 226 auto p = gtk_menu_shell_get_parent_shell(gtkMenuShell); 227 228 if(p is null) 229 { 230 return null; 231 } 232 233 return ObjectG.getDObject!(Widget)(cast(GtkWidget*) p); 234 } 235 236 /** 237 * Gets the currently selected item. 238 * 239 * Returns: the currently selected item 240 * 241 * Since: 3.0 242 */ 243 public Widget getSelectedItem() 244 { 245 auto p = gtk_menu_shell_get_selected_item(gtkMenuShell); 246 247 if(p is null) 248 { 249 return null; 250 } 251 252 return ObjectG.getDObject!(Widget)(cast(GtkWidget*) p); 253 } 254 255 /** 256 * Returns %TRUE if the menu shell will take the keyboard focus on popup. 257 * 258 * Returns: %TRUE if the menu shell will take the keyboard focus on popup. 259 * 260 * Since: 2.8 261 */ 262 public bool getTakeFocus() 263 { 264 return gtk_menu_shell_get_take_focus(gtkMenuShell) != 0; 265 } 266 267 /** 268 * Adds a new #GtkMenuItem to the menu shell’s item list 269 * at the position indicated by @position. 270 * 271 * Params: 272 * child = The #GtkMenuItem to add 273 * position = The position in the item list where @child 274 * is added. Positions are numbered from 0 to n-1 275 */ 276 public void insert(Widget child, int position) 277 { 278 gtk_menu_shell_insert(gtkMenuShell, (child is null) ? null : child.getWidgetStruct(), position); 279 } 280 281 /** 282 * Adds a new #GtkMenuItem to the beginning of the menu shell's 283 * item list. 284 * 285 * Params: 286 * child = The #GtkMenuItem to add 287 */ 288 public void prepend(Widget child) 289 { 290 gtk_menu_shell_prepend(gtkMenuShell, (child is null) ? null : child.getWidgetStruct()); 291 } 292 293 /** 294 * Select the first visible or selectable child of the menu shell; 295 * don’t select tearoff items unless the only item is a tearoff 296 * item. 297 * 298 * Params: 299 * searchSensitive = if %TRUE, search for the first selectable 300 * menu item, otherwise select nothing if 301 * the first item isn’t sensitive. This 302 * should be %FALSE if the menu is being 303 * popped up initially. 304 * 305 * Since: 2.2 306 */ 307 public void selectFirst(bool searchSensitive) 308 { 309 gtk_menu_shell_select_first(gtkMenuShell, searchSensitive); 310 } 311 312 /** 313 * Selects the menu item from the menu shell. 314 * 315 * Params: 316 * menuItem = The #GtkMenuItem to select 317 */ 318 public void selectItem(Widget menuItem) 319 { 320 gtk_menu_shell_select_item(gtkMenuShell, (menuItem is null) ? null : menuItem.getWidgetStruct()); 321 } 322 323 /** 324 * If @take_focus is %TRUE (the default) the menu shell will take 325 * the keyboard focus so that it will receive all keyboard events 326 * which is needed to enable keyboard navigation in menus. 327 * 328 * Setting @take_focus to %FALSE is useful only for special applications 329 * like virtual keyboard implementations which should not take keyboard 330 * focus. 331 * 332 * The @take_focus state of a menu or menu bar is automatically 333 * propagated to submenus whenever a submenu is popped up, so you 334 * don’t have to worry about recursively setting it for your entire 335 * menu hierarchy. Only when programmatically picking a submenu and 336 * popping it up manually, the @take_focus property of the submenu 337 * needs to be set explicitly. 338 * 339 * Note that setting it to %FALSE has side-effects: 340 * 341 * If the focus is in some other app, it keeps the focus and keynav in 342 * the menu doesn’t work. Consequently, keynav on the menu will only 343 * work if the focus is on some toplevel owned by the onscreen keyboard. 344 * 345 * To avoid confusing the user, menus with @take_focus set to %FALSE 346 * should not display mnemonics or accelerators, since it cannot be 347 * guaranteed that they will work. 348 * 349 * See also gdk_keyboard_grab() 350 * 351 * Params: 352 * takeFocus = %TRUE if the menu shell should take the keyboard 353 * focus on popup 354 * 355 * Since: 2.8 356 */ 357 public void setTakeFocus(bool takeFocus) 358 { 359 gtk_menu_shell_set_take_focus(gtkMenuShell, takeFocus); 360 } 361 362 protected class OnActivateCurrentDelegateWrapper 363 { 364 void delegate(bool, MenuShell) dlg; 365 gulong handlerId; 366 367 this(void delegate(bool, MenuShell) dlg) 368 { 369 this.dlg = dlg; 370 onActivateCurrentListeners ~= this; 371 } 372 373 void remove(OnActivateCurrentDelegateWrapper source) 374 { 375 foreach(index, wrapper; onActivateCurrentListeners) 376 { 377 if (wrapper.handlerId == source.handlerId) 378 { 379 onActivateCurrentListeners[index] = null; 380 onActivateCurrentListeners = std.algorithm.remove(onActivateCurrentListeners, index); 381 break; 382 } 383 } 384 } 385 } 386 OnActivateCurrentDelegateWrapper[] onActivateCurrentListeners; 387 388 /** 389 * An action signal that activates the current menu item within 390 * the menu shell. 391 * 392 * Params: 393 * forceHide = if %TRUE, hide the menu after activating the menu item 394 */ 395 gulong addOnActivateCurrent(void delegate(bool, MenuShell) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 396 { 397 auto wrapper = new OnActivateCurrentDelegateWrapper(dlg); 398 wrapper.handlerId = Signals.connectData( 399 this, 400 "activate-current", 401 cast(GCallback)&callBackActivateCurrent, 402 cast(void*)wrapper, 403 cast(GClosureNotify)&callBackActivateCurrentDestroy, 404 connectFlags); 405 return wrapper.handlerId; 406 } 407 408 extern(C) static void callBackActivateCurrent(GtkMenuShell* menushellStruct, bool forceHide, OnActivateCurrentDelegateWrapper wrapper) 409 { 410 wrapper.dlg(forceHide, wrapper.outer); 411 } 412 413 extern(C) static void callBackActivateCurrentDestroy(OnActivateCurrentDelegateWrapper wrapper, GClosure* closure) 414 { 415 wrapper.remove(wrapper); 416 } 417 418 protected class OnCancelDelegateWrapper 419 { 420 void delegate(MenuShell) dlg; 421 gulong handlerId; 422 423 this(void delegate(MenuShell) dlg) 424 { 425 this.dlg = dlg; 426 onCancelListeners ~= this; 427 } 428 429 void remove(OnCancelDelegateWrapper source) 430 { 431 foreach(index, wrapper; onCancelListeners) 432 { 433 if (wrapper.handlerId == source.handlerId) 434 { 435 onCancelListeners[index] = null; 436 onCancelListeners = std.algorithm.remove(onCancelListeners, index); 437 break; 438 } 439 } 440 } 441 } 442 OnCancelDelegateWrapper[] onCancelListeners; 443 444 /** 445 * An action signal which cancels the selection within the menu shell. 446 * Causes the #GtkMenuShell::selection-done signal to be emitted. 447 */ 448 gulong addOnCancel(void delegate(MenuShell) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 449 { 450 auto wrapper = new OnCancelDelegateWrapper(dlg); 451 wrapper.handlerId = Signals.connectData( 452 this, 453 "cancel", 454 cast(GCallback)&callBackCancel, 455 cast(void*)wrapper, 456 cast(GClosureNotify)&callBackCancelDestroy, 457 connectFlags); 458 return wrapper.handlerId; 459 } 460 461 extern(C) static void callBackCancel(GtkMenuShell* menushellStruct, OnCancelDelegateWrapper wrapper) 462 { 463 wrapper.dlg(wrapper.outer); 464 } 465 466 extern(C) static void callBackCancelDestroy(OnCancelDelegateWrapper wrapper, GClosure* closure) 467 { 468 wrapper.remove(wrapper); 469 } 470 471 protected class OnCycleFocusDelegateWrapper 472 { 473 void delegate(GtkDirectionType, MenuShell) dlg; 474 gulong handlerId; 475 476 this(void delegate(GtkDirectionType, MenuShell) dlg) 477 { 478 this.dlg = dlg; 479 onCycleFocusListeners ~= this; 480 } 481 482 void remove(OnCycleFocusDelegateWrapper source) 483 { 484 foreach(index, wrapper; onCycleFocusListeners) 485 { 486 if (wrapper.handlerId == source.handlerId) 487 { 488 onCycleFocusListeners[index] = null; 489 onCycleFocusListeners = std.algorithm.remove(onCycleFocusListeners, index); 490 break; 491 } 492 } 493 } 494 } 495 OnCycleFocusDelegateWrapper[] onCycleFocusListeners; 496 497 /** 498 * A keybinding signal which moves the focus in the 499 * given @direction. 500 * 501 * Params: 502 * direction = the direction to cycle in 503 */ 504 gulong addOnCycleFocus(void delegate(GtkDirectionType, MenuShell) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 505 { 506 auto wrapper = new OnCycleFocusDelegateWrapper(dlg); 507 wrapper.handlerId = Signals.connectData( 508 this, 509 "cycle-focus", 510 cast(GCallback)&callBackCycleFocus, 511 cast(void*)wrapper, 512 cast(GClosureNotify)&callBackCycleFocusDestroy, 513 connectFlags); 514 return wrapper.handlerId; 515 } 516 517 extern(C) static void callBackCycleFocus(GtkMenuShell* menushellStruct, GtkDirectionType direction, OnCycleFocusDelegateWrapper wrapper) 518 { 519 wrapper.dlg(direction, wrapper.outer); 520 } 521 522 extern(C) static void callBackCycleFocusDestroy(OnCycleFocusDelegateWrapper wrapper, GClosure* closure) 523 { 524 wrapper.remove(wrapper); 525 } 526 527 protected class OnDeactivateDelegateWrapper 528 { 529 void delegate(MenuShell) dlg; 530 gulong handlerId; 531 532 this(void delegate(MenuShell) dlg) 533 { 534 this.dlg = dlg; 535 onDeactivateListeners ~= this; 536 } 537 538 void remove(OnDeactivateDelegateWrapper source) 539 { 540 foreach(index, wrapper; onDeactivateListeners) 541 { 542 if (wrapper.handlerId == source.handlerId) 543 { 544 onDeactivateListeners[index] = null; 545 onDeactivateListeners = std.algorithm.remove(onDeactivateListeners, index); 546 break; 547 } 548 } 549 } 550 } 551 OnDeactivateDelegateWrapper[] onDeactivateListeners; 552 553 /** 554 * This signal is emitted when a menu shell is deactivated. 555 */ 556 gulong addOnDeactivate(void delegate(MenuShell) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 557 { 558 auto wrapper = new OnDeactivateDelegateWrapper(dlg); 559 wrapper.handlerId = Signals.connectData( 560 this, 561 "deactivate", 562 cast(GCallback)&callBackDeactivate, 563 cast(void*)wrapper, 564 cast(GClosureNotify)&callBackDeactivateDestroy, 565 connectFlags); 566 return wrapper.handlerId; 567 } 568 569 extern(C) static void callBackDeactivate(GtkMenuShell* menushellStruct, OnDeactivateDelegateWrapper wrapper) 570 { 571 wrapper.dlg(wrapper.outer); 572 } 573 574 extern(C) static void callBackDeactivateDestroy(OnDeactivateDelegateWrapper wrapper, GClosure* closure) 575 { 576 wrapper.remove(wrapper); 577 } 578 579 protected class OnInsertDelegateWrapper 580 { 581 void delegate(Widget, int, MenuShell) dlg; 582 gulong handlerId; 583 584 this(void delegate(Widget, int, MenuShell) dlg) 585 { 586 this.dlg = dlg; 587 onInsertListeners ~= this; 588 } 589 590 void remove(OnInsertDelegateWrapper source) 591 { 592 foreach(index, wrapper; onInsertListeners) 593 { 594 if (wrapper.handlerId == source.handlerId) 595 { 596 onInsertListeners[index] = null; 597 onInsertListeners = std.algorithm.remove(onInsertListeners, index); 598 break; 599 } 600 } 601 } 602 } 603 OnInsertDelegateWrapper[] onInsertListeners; 604 605 /** 606 * The ::insert signal is emitted when a new #GtkMenuItem is added to 607 * a #GtkMenuShell. A separate signal is used instead of 608 * GtkContainer::add because of the need for an additional position 609 * parameter. 610 * 611 * The inverse of this signal is the GtkContainer::removed signal. 612 * 613 * Params: 614 * child = the #GtkMenuItem that is being inserted 615 * position = the position at which the insert occurs 616 * 617 * Since: 3.2 618 */ 619 gulong addOnInsert(void delegate(Widget, int, MenuShell) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 620 { 621 auto wrapper = new OnInsertDelegateWrapper(dlg); 622 wrapper.handlerId = Signals.connectData( 623 this, 624 "insert", 625 cast(GCallback)&callBackInsert, 626 cast(void*)wrapper, 627 cast(GClosureNotify)&callBackInsertDestroy, 628 connectFlags); 629 return wrapper.handlerId; 630 } 631 632 extern(C) static void callBackInsert(GtkMenuShell* menushellStruct, GtkWidget* child, int position, OnInsertDelegateWrapper wrapper) 633 { 634 wrapper.dlg(ObjectG.getDObject!(Widget)(child), position, wrapper.outer); 635 } 636 637 extern(C) static void callBackInsertDestroy(OnInsertDelegateWrapper wrapper, GClosure* closure) 638 { 639 wrapper.remove(wrapper); 640 } 641 642 protected class OnMoveCurrentDelegateWrapper 643 { 644 void delegate(GtkMenuDirectionType, MenuShell) dlg; 645 gulong handlerId; 646 647 this(void delegate(GtkMenuDirectionType, MenuShell) dlg) 648 { 649 this.dlg = dlg; 650 onMoveCurrentListeners ~= this; 651 } 652 653 void remove(OnMoveCurrentDelegateWrapper source) 654 { 655 foreach(index, wrapper; onMoveCurrentListeners) 656 { 657 if (wrapper.handlerId == source.handlerId) 658 { 659 onMoveCurrentListeners[index] = null; 660 onMoveCurrentListeners = std.algorithm.remove(onMoveCurrentListeners, index); 661 break; 662 } 663 } 664 } 665 } 666 OnMoveCurrentDelegateWrapper[] onMoveCurrentListeners; 667 668 /** 669 * An keybinding signal which moves the current menu item 670 * in the direction specified by @direction. 671 * 672 * Params: 673 * direction = the direction to move 674 */ 675 gulong addOnMoveCurrent(void delegate(GtkMenuDirectionType, MenuShell) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 676 { 677 auto wrapper = new OnMoveCurrentDelegateWrapper(dlg); 678 wrapper.handlerId = Signals.connectData( 679 this, 680 "move-current", 681 cast(GCallback)&callBackMoveCurrent, 682 cast(void*)wrapper, 683 cast(GClosureNotify)&callBackMoveCurrentDestroy, 684 connectFlags); 685 return wrapper.handlerId; 686 } 687 688 extern(C) static void callBackMoveCurrent(GtkMenuShell* menushellStruct, GtkMenuDirectionType direction, OnMoveCurrentDelegateWrapper wrapper) 689 { 690 wrapper.dlg(direction, wrapper.outer); 691 } 692 693 extern(C) static void callBackMoveCurrentDestroy(OnMoveCurrentDelegateWrapper wrapper, GClosure* closure) 694 { 695 wrapper.remove(wrapper); 696 } 697 698 protected class OnMoveSelectedDelegateWrapper 699 { 700 bool delegate(int, MenuShell) dlg; 701 gulong handlerId; 702 703 this(bool delegate(int, MenuShell) dlg) 704 { 705 this.dlg = dlg; 706 onMoveSelectedListeners ~= this; 707 } 708 709 void remove(OnMoveSelectedDelegateWrapper source) 710 { 711 foreach(index, wrapper; onMoveSelectedListeners) 712 { 713 if (wrapper.handlerId == source.handlerId) 714 { 715 onMoveSelectedListeners[index] = null; 716 onMoveSelectedListeners = std.algorithm.remove(onMoveSelectedListeners, index); 717 break; 718 } 719 } 720 } 721 } 722 OnMoveSelectedDelegateWrapper[] onMoveSelectedListeners; 723 724 /** 725 * The ::move-selected signal is emitted to move the selection to 726 * another item. 727 * 728 * Params: 729 * distance = +1 to move to the next item, -1 to move to the previous 730 * 731 * Returns: %TRUE to stop the signal emission, %FALSE to continue 732 * 733 * Since: 2.12 734 */ 735 gulong addOnMoveSelected(bool delegate(int, MenuShell) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 736 { 737 auto wrapper = new OnMoveSelectedDelegateWrapper(dlg); 738 wrapper.handlerId = Signals.connectData( 739 this, 740 "move-selected", 741 cast(GCallback)&callBackMoveSelected, 742 cast(void*)wrapper, 743 cast(GClosureNotify)&callBackMoveSelectedDestroy, 744 connectFlags); 745 return wrapper.handlerId; 746 } 747 748 extern(C) static int callBackMoveSelected(GtkMenuShell* menushellStruct, int distance, OnMoveSelectedDelegateWrapper wrapper) 749 { 750 return wrapper.dlg(distance, wrapper.outer); 751 } 752 753 extern(C) static void callBackMoveSelectedDestroy(OnMoveSelectedDelegateWrapper wrapper, GClosure* closure) 754 { 755 wrapper.remove(wrapper); 756 } 757 758 protected class OnSelectionDoneDelegateWrapper 759 { 760 void delegate(MenuShell) dlg; 761 gulong handlerId; 762 763 this(void delegate(MenuShell) dlg) 764 { 765 this.dlg = dlg; 766 onSelectionDoneListeners ~= this; 767 } 768 769 void remove(OnSelectionDoneDelegateWrapper source) 770 { 771 foreach(index, wrapper; onSelectionDoneListeners) 772 { 773 if (wrapper.handlerId == source.handlerId) 774 { 775 onSelectionDoneListeners[index] = null; 776 onSelectionDoneListeners = std.algorithm.remove(onSelectionDoneListeners, index); 777 break; 778 } 779 } 780 } 781 } 782 OnSelectionDoneDelegateWrapper[] onSelectionDoneListeners; 783 784 /** 785 * This signal is emitted when a selection has been 786 * completed within a menu shell. 787 */ 788 gulong addOnSelectionDone(void delegate(MenuShell) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 789 { 790 auto wrapper = new OnSelectionDoneDelegateWrapper(dlg); 791 wrapper.handlerId = Signals.connectData( 792 this, 793 "selection-done", 794 cast(GCallback)&callBackSelectionDone, 795 cast(void*)wrapper, 796 cast(GClosureNotify)&callBackSelectionDoneDestroy, 797 connectFlags); 798 return wrapper.handlerId; 799 } 800 801 extern(C) static void callBackSelectionDone(GtkMenuShell* menushellStruct, OnSelectionDoneDelegateWrapper wrapper) 802 { 803 wrapper.dlg(wrapper.outer); 804 } 805 806 extern(C) static void callBackSelectionDoneDestroy(OnSelectionDoneDelegateWrapper wrapper, GClosure* closure) 807 { 808 wrapper.remove(wrapper); 809 } 810 }