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