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