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.UIManager; 26 27 private import glib.ConstructionException; 28 private import glib.ErrorG; 29 private import glib.GException; 30 private import glib.ListG; 31 private import glib.ListSG; 32 private import glib.Str; 33 private import gobject.ObjectG; 34 private import gobject.Signals; 35 private import gtk.AccelGroup; 36 private import gtk.Action; 37 private import gtk.ActionGroup; 38 private import gtk.BuildableIF; 39 private import gtk.BuildableT; 40 private import gtk.Widget; 41 private import gtk.c.functions; 42 public import gtk.c.types; 43 public import gtkc.gtktypes; 44 private import std.algorithm; 45 46 47 /** 48 * A #GtkUIManager constructs a user interface (menus and toolbars) from 49 * one or more UI definitions, which reference actions from one or more 50 * action groups. 51 * 52 * # UI Definitions # {#XML-UI} 53 * 54 * The UI definitions are specified in an XML format which can be 55 * roughly described by the following DTD. 56 * 57 * > Do not confuse the GtkUIManager UI Definitions described here with 58 * > the similarly named [GtkBuilder UI Definitions][BUILDER-UI]. 59 * 60 * |[ 61 * <!ELEMENT ui (menubar|toolbar|popup|accelerator)* > 62 * <!ELEMENT menubar (menuitem|separator|placeholder|menu)* > 63 * <!ELEMENT menu (menuitem|separator|placeholder|menu)* > 64 * <!ELEMENT popup (menuitem|separator|placeholder|menu)* > 65 * <!ELEMENT toolbar (toolitem|separator|placeholder)* > 66 * <!ELEMENT placeholder (menuitem|toolitem|separator|placeholder|menu)* > 67 * <!ELEMENT menuitem EMPTY > 68 * <!ELEMENT toolitem (menu?) > 69 * <!ELEMENT separator EMPTY > 70 * <!ELEMENT accelerator EMPTY > 71 * <!ATTLIST menubar name #IMPLIED 72 * action #IMPLIED > 73 * <!ATTLIST toolbar name #IMPLIED 74 * action #IMPLIED > 75 * <!ATTLIST popup name #IMPLIED 76 * action #IMPLIED 77 * accelerators (true|false) #IMPLIED > 78 * <!ATTLIST placeholder name #IMPLIED 79 * action #IMPLIED > 80 * <!ATTLIST separator name #IMPLIED 81 * action #IMPLIED 82 * expand (true|false) #IMPLIED > 83 * <!ATTLIST menu name #IMPLIED 84 * action #REQUIRED 85 * position (top|bot) #IMPLIED > 86 * <!ATTLIST menuitem name #IMPLIED 87 * action #REQUIRED 88 * position (top|bot) #IMPLIED 89 * always-show-image (true|false) #IMPLIED > 90 * <!ATTLIST toolitem name #IMPLIED 91 * action #REQUIRED 92 * position (top|bot) #IMPLIED > 93 * <!ATTLIST accelerator name #IMPLIED 94 * action #REQUIRED > 95 * ]| 96 * 97 * There are some additional restrictions beyond those specified in the 98 * DTD, e.g. every toolitem must have a toolbar in its anchestry and 99 * every menuitem must have a menubar or popup in its anchestry. Since 100 * a #GMarkupParser is used to parse the UI description, it must not only 101 * be valid XML, but valid markup. 102 * 103 * If a name is not specified, it defaults to the action. If an action is 104 * not specified either, the element name is used. The name and action 105 * attributes must not contain “/” characters after parsing (since that 106 * would mess up path lookup) and must be usable as XML attributes when 107 * enclosed in doublequotes, thus they must not “"” characters or references 108 * to the " entity. 109 * 110 * # A UI definition # 111 * 112 * |[ 113 * <ui> 114 * <menubar> 115 * <menu name="FileMenu" action="FileMenuAction"> 116 * <menuitem name="New" action="New2Action" /> 117 * <placeholder name="FileMenuAdditions" /> 118 * </menu> 119 * <menu name="JustifyMenu" action="JustifyMenuAction"> 120 * <menuitem name="Left" action="justify-left"/> 121 * <menuitem name="Centre" action="justify-center"/> 122 * <menuitem name="Right" action="justify-right"/> 123 * <menuitem name="Fill" action="justify-fill"/> 124 * </menu> 125 * </menubar> 126 * <toolbar action="toolbar1"> 127 * <placeholder name="JustifyToolItems"> 128 * <separator/> 129 * <toolitem name="Left" action="justify-left"/> 130 * <toolitem name="Centre" action="justify-center"/> 131 * <toolitem name="Right" action="justify-right"/> 132 * <toolitem name="Fill" action="justify-fill"/> 133 * <separator/> 134 * </placeholder> 135 * </toolbar> 136 * </ui> 137 * ]| 138 * 139 * The constructed widget hierarchy is very similar to the element tree 140 * of the XML, with the exception that placeholders are merged into their 141 * parents. The correspondence of XML elements to widgets should be 142 * almost obvious: 143 * 144 * - menubar 145 * 146 * a #GtkMenuBar 147 * 148 * - toolbar 149 * 150 * a #GtkToolbar 151 * 152 * - popup 153 * 154 * a toplevel #GtkMenu 155 * 156 * - menu 157 * 158 * a #GtkMenu attached to a menuitem 159 * 160 * - menuitem 161 * 162 * a #GtkMenuItem subclass, the exact type depends on the action 163 * 164 * - toolitem 165 * 166 * a #GtkToolItem subclass, the exact type depends on the 167 * action. Note that toolitem elements may contain a menu element, 168 * but only if their associated action specifies a 169 * #GtkMenuToolButton as proxy. 170 * 171 * - separator 172 * 173 * a #GtkSeparatorMenuItem or #GtkSeparatorToolItem 174 * 175 * - accelerator 176 * 177 * a keyboard accelerator 178 * 179 * The “position” attribute determines where a constructed widget is positioned 180 * wrt. to its siblings in the partially constructed tree. If it is 181 * “top”, the widget is prepended, otherwise it is appended. 182 * 183 * # UI Merging # {#UI-Merging} 184 * 185 * The most remarkable feature of #GtkUIManager is that it can overlay a set 186 * of menuitems and toolitems over another one, and demerge them later. 187 * 188 * Merging is done based on the names of the XML elements. Each element is 189 * identified by a path which consists of the names of its anchestors, separated 190 * by slashes. For example, the menuitem named “Left” in the example above 191 * has the path `/ui/menubar/JustifyMenu/Left` and the 192 * toolitem with the same name has path 193 * `/ui/toolbar1/JustifyToolItems/Left`. 194 * 195 * # Accelerators # 196 * 197 * Every action has an accelerator path. Accelerators are installed together 198 * with menuitem proxies, but they can also be explicitly added with 199 * <accelerator> elements in the UI definition. This makes it possible to 200 * have accelerators for actions even if they have no visible proxies. 201 * 202 * # Smart Separators # {#Smart-Separators} 203 * 204 * The separators created by #GtkUIManager are “smart”, i.e. they do not show up 205 * in the UI unless they end up between two visible menu or tool items. Separators 206 * which are located at the very beginning or end of the menu or toolbar 207 * containing them, or multiple separators next to each other, are hidden. This 208 * is a useful feature, since the merging of UI elements from multiple sources 209 * can make it hard or impossible to determine in advance whether a separator 210 * will end up in such an unfortunate position. 211 * 212 * For separators in toolbars, you can set `expand="true"` to 213 * turn them from a small, visible separator to an expanding, invisible one. 214 * Toolitems following an expanding separator are effectively right-aligned. 215 * 216 * # Empty Menus 217 * 218 * Submenus pose similar problems to separators inconnection with merging. It is 219 * impossible to know in advance whether they will end up empty after merging. 220 * #GtkUIManager offers two ways to treat empty submenus: 221 * 222 * - make them disappear by hiding the menu item they’re attached to 223 * 224 * - add an insensitive “Empty” item 225 * 226 * The behaviour is chosen based on the “hide_if_empty” property of the action 227 * to which the submenu is associated. 228 * 229 * # GtkUIManager as GtkBuildable # {#GtkUIManager-BUILDER-UI} 230 * 231 * The GtkUIManager implementation of the GtkBuildable interface accepts 232 * GtkActionGroup objects as <child> elements in UI definitions. 233 * 234 * A GtkUIManager UI definition as described above can be embedded in 235 * an GtkUIManager <object> element in a GtkBuilder UI definition. 236 * 237 * The widgets that are constructed by a GtkUIManager can be embedded in 238 * other parts of the constructed user interface with the help of the 239 * “constructor” attribute. See the example below. 240 * 241 * ## An embedded GtkUIManager UI definition 242 * 243 * |[ 244 * <object class="GtkUIManager" id="uiman"> 245 * <child> 246 * <object class="GtkActionGroup" id="actiongroup"> 247 * <child> 248 * <object class="GtkAction" id="file"> 249 * <property name="label">_File</property> 250 * </object> 251 * </child> 252 * </object> 253 * </child> 254 * <ui> 255 * <menubar name="menubar1"> 256 * <menu action="file"> 257 * </menu> 258 * </menubar> 259 * </ui> 260 * </object> 261 * <object class="GtkWindow" id="main-window"> 262 * <child> 263 * <object class="GtkMenuBar" id="menubar1" constructor="uiman"/> 264 * </child> 265 * </object> 266 * ]| 267 */ 268 public class UIManager : ObjectG, BuildableIF 269 { 270 /** the main Gtk struct */ 271 protected GtkUIManager* gtkUIManager; 272 273 /** Get the main Gtk struct */ 274 public GtkUIManager* getUIManagerStruct(bool transferOwnership = false) 275 { 276 if (transferOwnership) 277 ownedRef = false; 278 return gtkUIManager; 279 } 280 281 /** the main Gtk struct as a void* */ 282 protected override void* getStruct() 283 { 284 return cast(void*)gtkUIManager; 285 } 286 287 /** 288 * Sets our main struct and passes it to the parent class. 289 */ 290 public this (GtkUIManager* gtkUIManager, bool ownedRef = false) 291 { 292 this.gtkUIManager = gtkUIManager; 293 super(cast(GObject*)gtkUIManager, ownedRef); 294 } 295 296 // add the Buildable capabilities 297 mixin BuildableT!(GtkUIManager); 298 299 300 /** */ 301 public static GType getType() 302 { 303 return gtk_ui_manager_get_type(); 304 } 305 306 /** 307 * Creates a new ui manager object. 308 * 309 * Returns: a new ui manager object. 310 * 311 * Since: 2.4 312 * 313 * Throws: ConstructionException GTK+ fails to create the object. 314 */ 315 public this() 316 { 317 auto p = gtk_ui_manager_new(); 318 319 if(p is null) 320 { 321 throw new ConstructionException("null returned by new"); 322 } 323 324 this(cast(GtkUIManager*) p, true); 325 } 326 327 /** 328 * Adds a UI element to the current contents of @manager. 329 * 330 * If @type is %GTK_UI_MANAGER_AUTO, GTK+ inserts a menuitem, toolitem or 331 * separator if such an element can be inserted at the place determined by 332 * @path. Otherwise @type must indicate an element that can be inserted at 333 * the place determined by @path. 334 * 335 * If @path points to a menuitem or toolitem, the new element will be inserted 336 * before or after this item, depending on @top. 337 * 338 * Params: 339 * mergeId = the merge id for the merged UI, see gtk_ui_manager_new_merge_id() 340 * path = a path 341 * name = the name for the added UI element 342 * action = the name of the action to be proxied, or %NULL to add a separator 343 * type = the type of UI element to add. 344 * top = if %TRUE, the UI element is added before its siblings, otherwise it 345 * is added after its siblings. 346 * 347 * Since: 2.4 348 */ 349 public void addUi(uint mergeId, string path, string name, string action, GtkUIManagerItemType type, bool top) 350 { 351 gtk_ui_manager_add_ui(gtkUIManager, mergeId, Str.toStringz(path), Str.toStringz(name), Str.toStringz(action), type, top); 352 } 353 354 /** 355 * Parses a file containing a [UI definition][XML-UI] and 356 * merges it with the current contents of @manager. 357 * 358 * Params: 359 * filename = the name of the file to parse 360 * 361 * Returns: The merge id for the merged UI. The merge id can be used 362 * to unmerge the UI with gtk_ui_manager_remove_ui(). If an error occurred, 363 * the return value is 0. 364 * 365 * Since: 2.4 366 * 367 * Throws: GException on failure. 368 */ 369 public uint addUiFromFile(string filename) 370 { 371 GError* err = null; 372 373 auto p = gtk_ui_manager_add_ui_from_file(gtkUIManager, Str.toStringz(filename), &err); 374 375 if (err !is null) 376 { 377 throw new GException( new ErrorG(err) ); 378 } 379 380 return p; 381 } 382 383 /** 384 * Parses a resource file containing a [UI definition][XML-UI] and 385 * merges it with the current contents of @manager. 386 * 387 * Params: 388 * resourcePath = the resource path of the file to parse 389 * 390 * Returns: The merge id for the merged UI. The merge id can be used 391 * to unmerge the UI with gtk_ui_manager_remove_ui(). If an error occurred, 392 * the return value is 0. 393 * 394 * Since: 3.4 395 * 396 * Throws: GException on failure. 397 */ 398 public uint addUiFromResource(string resourcePath) 399 { 400 GError* err = null; 401 402 auto p = gtk_ui_manager_add_ui_from_resource(gtkUIManager, Str.toStringz(resourcePath), &err); 403 404 if (err !is null) 405 { 406 throw new GException( new ErrorG(err) ); 407 } 408 409 return p; 410 } 411 412 /** 413 * Parses a string containing a [UI definition][XML-UI] and merges it with 414 * the current contents of @manager. An enclosing <ui> element is added if 415 * it is missing. 416 * 417 * Params: 418 * buffer = the string to parse 419 * length = the length of @buffer (may be -1 if @buffer is nul-terminated) 420 * 421 * Returns: The merge id for the merged UI. The merge id can be used 422 * to unmerge the UI with gtk_ui_manager_remove_ui(). If an error occurred, 423 * the return value is 0. 424 * 425 * Since: 2.4 426 * 427 * Throws: GException on failure. 428 */ 429 public uint addUiFromString(string buffer, ptrdiff_t length) 430 { 431 GError* err = null; 432 433 auto p = gtk_ui_manager_add_ui_from_string(gtkUIManager, Str.toStringz(buffer), length, &err); 434 435 if (err !is null) 436 { 437 throw new GException( new ErrorG(err) ); 438 } 439 440 return p; 441 } 442 443 /** 444 * Makes sure that all pending updates to the UI have been completed. 445 * 446 * This may occasionally be necessary, since #GtkUIManager updates the 447 * UI in an idle function. A typical example where this function is 448 * useful is to enforce that the menubar and toolbar have been added to 449 * the main window before showing it: 450 * |[<!-- language="C" --> 451 * gtk_container_add (GTK_CONTAINER (window), vbox); 452 * g_signal_connect (merge, "add-widget", 453 * G_CALLBACK (add_widget), vbox); 454 * gtk_ui_manager_add_ui_from_file (merge, "my-menus"); 455 * gtk_ui_manager_add_ui_from_file (merge, "my-toolbars"); 456 * gtk_ui_manager_ensure_update (merge); 457 * gtk_widget_show (window); 458 * ]| 459 * 460 * Since: 2.4 461 */ 462 public void ensureUpdate() 463 { 464 gtk_ui_manager_ensure_update(gtkUIManager); 465 } 466 467 /** 468 * Returns the #GtkAccelGroup associated with @manager. 469 * 470 * Returns: the #GtkAccelGroup. 471 * 472 * Since: 2.4 473 */ 474 public AccelGroup getAccelGroup() 475 { 476 auto p = gtk_ui_manager_get_accel_group(gtkUIManager); 477 478 if(p is null) 479 { 480 return null; 481 } 482 483 return ObjectG.getDObject!(AccelGroup)(cast(GtkAccelGroup*) p); 484 } 485 486 /** 487 * Looks up an action by following a path. See gtk_ui_manager_get_widget() 488 * for more information about paths. 489 * 490 * Params: 491 * path = a path 492 * 493 * Returns: the action whose proxy widget is found by following the path, 494 * or %NULL if no widget was found. 495 * 496 * Since: 2.4 497 */ 498 public Action getAction(string path) 499 { 500 auto p = gtk_ui_manager_get_action(gtkUIManager, Str.toStringz(path)); 501 502 if(p is null) 503 { 504 return null; 505 } 506 507 return ObjectG.getDObject!(Action)(cast(GtkAction*) p); 508 } 509 510 /** 511 * Returns the list of action groups associated with @manager. 512 * 513 * Returns: a #GList of 514 * action groups. The list is owned by GTK+ 515 * and should not be modified. 516 * 517 * Since: 2.4 518 */ 519 public ListG getActionGroups() 520 { 521 auto p = gtk_ui_manager_get_action_groups(gtkUIManager); 522 523 if(p is null) 524 { 525 return null; 526 } 527 528 return new ListG(cast(GList*) p); 529 } 530 531 /** 532 * Returns whether menus generated by this #GtkUIManager 533 * will have tearoff menu items. 534 * 535 * Deprecated: Tearoff menus are deprecated and should not 536 * be used in newly written code. 537 * 538 * Returns: whether tearoff menu items are added 539 * 540 * Since: 2.4 541 */ 542 public bool getAddTearoffs() 543 { 544 return gtk_ui_manager_get_add_tearoffs(gtkUIManager) != 0; 545 } 546 547 /** 548 * Obtains a list of all toplevel widgets of the requested types. 549 * 550 * Params: 551 * types = specifies the types of toplevel widgets to include. Allowed 552 * types are #GTK_UI_MANAGER_MENUBAR, #GTK_UI_MANAGER_TOOLBAR and 553 * #GTK_UI_MANAGER_POPUP. 554 * 555 * Returns: a newly-allocated #GSList of 556 * all toplevel widgets of the requested types. Free the returned list with g_slist_free(). 557 * 558 * Since: 2.4 559 */ 560 public ListSG getToplevels(GtkUIManagerItemType types) 561 { 562 auto p = gtk_ui_manager_get_toplevels(gtkUIManager, types); 563 564 if(p is null) 565 { 566 return null; 567 } 568 569 return new ListSG(cast(GSList*) p); 570 } 571 572 /** 573 * Creates a [UI definition][XML-UI] of the merged UI. 574 * 575 * Returns: A newly allocated string containing an XML representation of 576 * the merged UI. 577 * 578 * Since: 2.4 579 */ 580 public string getUi() 581 { 582 auto retStr = gtk_ui_manager_get_ui(gtkUIManager); 583 584 scope(exit) Str.freeString(retStr); 585 return Str.toString(retStr); 586 } 587 588 /** 589 * Looks up a widget by following a path. 590 * The path consists of the names specified in the XML description of the UI. 591 * separated by “/”. Elements which don’t have a name or action attribute in 592 * the XML (e.g. <popup>) can be addressed by their XML element name 593 * (e.g. "popup"). The root element ("/ui") can be omitted in the path. 594 * 595 * Note that the widget found by following a path that ends in a <menu>; 596 * element is the menuitem to which the menu is attached, not the menu it 597 * manages. 598 * 599 * Also note that the widgets constructed by a ui manager are not tied to 600 * the lifecycle of the ui manager. If you add the widgets returned by this 601 * function to some container or explicitly ref them, they will survive the 602 * destruction of the ui manager. 603 * 604 * Params: 605 * path = a path 606 * 607 * Returns: the widget found by following the path, 608 * or %NULL if no widget was found 609 * 610 * Since: 2.4 611 */ 612 public Widget getWidget(string path) 613 { 614 auto p = gtk_ui_manager_get_widget(gtkUIManager, Str.toStringz(path)); 615 616 if(p is null) 617 { 618 return null; 619 } 620 621 return ObjectG.getDObject!(Widget)(cast(GtkWidget*) p); 622 } 623 624 /** 625 * Inserts an action group into the list of action groups associated 626 * with @manager. Actions in earlier groups hide actions with the same 627 * name in later groups. 628 * 629 * If @pos is larger than the number of action groups in @manager, or 630 * negative, @action_group will be inserted at the end of the internal 631 * list. 632 * 633 * Params: 634 * actionGroup = the action group to be inserted 635 * pos = the position at which the group will be inserted. 636 * 637 * Since: 2.4 638 */ 639 public void insertActionGroup(ActionGroup actionGroup, int pos) 640 { 641 gtk_ui_manager_insert_action_group(gtkUIManager, (actionGroup is null) ? null : actionGroup.getActionGroupStruct(), pos); 642 } 643 644 /** 645 * Returns an unused merge id, suitable for use with 646 * gtk_ui_manager_add_ui(). 647 * 648 * Returns: an unused merge id. 649 * 650 * Since: 2.4 651 */ 652 public uint newMergeId() 653 { 654 return gtk_ui_manager_new_merge_id(gtkUIManager); 655 } 656 657 /** 658 * Removes an action group from the list of action groups associated 659 * with @manager. 660 * 661 * Params: 662 * actionGroup = the action group to be removed 663 * 664 * Since: 2.4 665 */ 666 public void removeActionGroup(ActionGroup actionGroup) 667 { 668 gtk_ui_manager_remove_action_group(gtkUIManager, (actionGroup is null) ? null : actionGroup.getActionGroupStruct()); 669 } 670 671 /** 672 * Unmerges the part of @manager's content identified by @merge_id. 673 * 674 * Params: 675 * mergeId = a merge id as returned by gtk_ui_manager_add_ui_from_string() 676 * 677 * Since: 2.4 678 */ 679 public void removeUi(uint mergeId) 680 { 681 gtk_ui_manager_remove_ui(gtkUIManager, mergeId); 682 } 683 684 /** 685 * Sets the “add_tearoffs” property, which controls whether menus 686 * generated by this #GtkUIManager will have tearoff menu items. 687 * 688 * Note that this only affects regular menus. Generated popup 689 * menus never have tearoff menu items. 690 * 691 * Deprecated: Tearoff menus are deprecated and should not 692 * be used in newly written code. 693 * 694 * Params: 695 * addTearoffs = whether tearoff menu items are added 696 * 697 * Since: 2.4 698 */ 699 public void setAddTearoffs(bool addTearoffs) 700 { 701 gtk_ui_manager_set_add_tearoffs(gtkUIManager, addTearoffs); 702 } 703 704 protected class OnActionsChangedDelegateWrapper 705 { 706 void delegate(UIManager) dlg; 707 gulong handlerId; 708 709 this(void delegate(UIManager) dlg) 710 { 711 this.dlg = dlg; 712 onActionsChangedListeners ~= this; 713 } 714 715 void remove(OnActionsChangedDelegateWrapper source) 716 { 717 foreach(index, wrapper; onActionsChangedListeners) 718 { 719 if (wrapper.handlerId == source.handlerId) 720 { 721 onActionsChangedListeners[index] = null; 722 onActionsChangedListeners = std.algorithm.remove(onActionsChangedListeners, index); 723 break; 724 } 725 } 726 } 727 } 728 OnActionsChangedDelegateWrapper[] onActionsChangedListeners; 729 730 /** 731 * The ::actions-changed signal is emitted whenever the set of actions 732 * changes. 733 * 734 * Since: 2.4 735 */ 736 gulong addOnActionsChanged(void delegate(UIManager) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 737 { 738 auto wrapper = new OnActionsChangedDelegateWrapper(dlg); 739 wrapper.handlerId = Signals.connectData( 740 this, 741 "actions-changed", 742 cast(GCallback)&callBackActionsChanged, 743 cast(void*)wrapper, 744 cast(GClosureNotify)&callBackActionsChangedDestroy, 745 connectFlags); 746 return wrapper.handlerId; 747 } 748 749 extern(C) static void callBackActionsChanged(GtkUIManager* uimanagerStruct, OnActionsChangedDelegateWrapper wrapper) 750 { 751 wrapper.dlg(wrapper.outer); 752 } 753 754 extern(C) static void callBackActionsChangedDestroy(OnActionsChangedDelegateWrapper wrapper, GClosure* closure) 755 { 756 wrapper.remove(wrapper); 757 } 758 759 protected class OnAddWidgetDelegateWrapper 760 { 761 void delegate(Widget, UIManager) dlg; 762 gulong handlerId; 763 764 this(void delegate(Widget, UIManager) dlg) 765 { 766 this.dlg = dlg; 767 onAddWidgetListeners ~= this; 768 } 769 770 void remove(OnAddWidgetDelegateWrapper source) 771 { 772 foreach(index, wrapper; onAddWidgetListeners) 773 { 774 if (wrapper.handlerId == source.handlerId) 775 { 776 onAddWidgetListeners[index] = null; 777 onAddWidgetListeners = std.algorithm.remove(onAddWidgetListeners, index); 778 break; 779 } 780 } 781 } 782 } 783 OnAddWidgetDelegateWrapper[] onAddWidgetListeners; 784 785 /** 786 * The ::add-widget signal is emitted for each generated menubar and toolbar. 787 * It is not emitted for generated popup menus, which can be obtained by 788 * gtk_ui_manager_get_widget(). 789 * 790 * Params: 791 * widget = the added widget 792 * 793 * Since: 2.4 794 */ 795 gulong addOnAddWidget(void delegate(Widget, UIManager) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 796 { 797 auto wrapper = new OnAddWidgetDelegateWrapper(dlg); 798 wrapper.handlerId = Signals.connectData( 799 this, 800 "add-widget", 801 cast(GCallback)&callBackAddWidget, 802 cast(void*)wrapper, 803 cast(GClosureNotify)&callBackAddWidgetDestroy, 804 connectFlags); 805 return wrapper.handlerId; 806 } 807 808 extern(C) static void callBackAddWidget(GtkUIManager* uimanagerStruct, GtkWidget* widget, OnAddWidgetDelegateWrapper wrapper) 809 { 810 wrapper.dlg(ObjectG.getDObject!(Widget)(widget), wrapper.outer); 811 } 812 813 extern(C) static void callBackAddWidgetDestroy(OnAddWidgetDelegateWrapper wrapper, GClosure* closure) 814 { 815 wrapper.remove(wrapper); 816 } 817 818 protected class OnConnectProxyDelegateWrapper 819 { 820 void delegate(Action, Widget, UIManager) dlg; 821 gulong handlerId; 822 823 this(void delegate(Action, Widget, UIManager) dlg) 824 { 825 this.dlg = dlg; 826 onConnectProxyListeners ~= this; 827 } 828 829 void remove(OnConnectProxyDelegateWrapper source) 830 { 831 foreach(index, wrapper; onConnectProxyListeners) 832 { 833 if (wrapper.handlerId == source.handlerId) 834 { 835 onConnectProxyListeners[index] = null; 836 onConnectProxyListeners = std.algorithm.remove(onConnectProxyListeners, index); 837 break; 838 } 839 } 840 } 841 } 842 OnConnectProxyDelegateWrapper[] onConnectProxyListeners; 843 844 /** 845 * The ::connect-proxy signal is emitted after connecting a proxy to 846 * an action in the group. 847 * 848 * This is intended for simple customizations for which a custom action 849 * class would be too clumsy, e.g. showing tooltips for menuitems in the 850 * statusbar. 851 * 852 * Params: 853 * action = the action 854 * proxy = the proxy 855 * 856 * Since: 2.4 857 */ 858 gulong addOnConnectProxy(void delegate(Action, Widget, UIManager) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 859 { 860 auto wrapper = new OnConnectProxyDelegateWrapper(dlg); 861 wrapper.handlerId = Signals.connectData( 862 this, 863 "connect-proxy", 864 cast(GCallback)&callBackConnectProxy, 865 cast(void*)wrapper, 866 cast(GClosureNotify)&callBackConnectProxyDestroy, 867 connectFlags); 868 return wrapper.handlerId; 869 } 870 871 extern(C) static void callBackConnectProxy(GtkUIManager* uimanagerStruct, GtkAction* action, GtkWidget* proxy, OnConnectProxyDelegateWrapper wrapper) 872 { 873 wrapper.dlg(ObjectG.getDObject!(Action)(action), ObjectG.getDObject!(Widget)(proxy), wrapper.outer); 874 } 875 876 extern(C) static void callBackConnectProxyDestroy(OnConnectProxyDelegateWrapper wrapper, GClosure* closure) 877 { 878 wrapper.remove(wrapper); 879 } 880 881 protected class OnDisconnectProxyDelegateWrapper 882 { 883 void delegate(Action, Widget, UIManager) dlg; 884 gulong handlerId; 885 886 this(void delegate(Action, Widget, UIManager) dlg) 887 { 888 this.dlg = dlg; 889 onDisconnectProxyListeners ~= this; 890 } 891 892 void remove(OnDisconnectProxyDelegateWrapper source) 893 { 894 foreach(index, wrapper; onDisconnectProxyListeners) 895 { 896 if (wrapper.handlerId == source.handlerId) 897 { 898 onDisconnectProxyListeners[index] = null; 899 onDisconnectProxyListeners = std.algorithm.remove(onDisconnectProxyListeners, index); 900 break; 901 } 902 } 903 } 904 } 905 OnDisconnectProxyDelegateWrapper[] onDisconnectProxyListeners; 906 907 /** 908 * The ::disconnect-proxy signal is emitted after disconnecting a proxy 909 * from an action in the group. 910 * 911 * Params: 912 * action = the action 913 * proxy = the proxy 914 * 915 * Since: 2.4 916 */ 917 gulong addOnDisconnectProxy(void delegate(Action, Widget, UIManager) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 918 { 919 auto wrapper = new OnDisconnectProxyDelegateWrapper(dlg); 920 wrapper.handlerId = Signals.connectData( 921 this, 922 "disconnect-proxy", 923 cast(GCallback)&callBackDisconnectProxy, 924 cast(void*)wrapper, 925 cast(GClosureNotify)&callBackDisconnectProxyDestroy, 926 connectFlags); 927 return wrapper.handlerId; 928 } 929 930 extern(C) static void callBackDisconnectProxy(GtkUIManager* uimanagerStruct, GtkAction* action, GtkWidget* proxy, OnDisconnectProxyDelegateWrapper wrapper) 931 { 932 wrapper.dlg(ObjectG.getDObject!(Action)(action), ObjectG.getDObject!(Widget)(proxy), wrapper.outer); 933 } 934 935 extern(C) static void callBackDisconnectProxyDestroy(OnDisconnectProxyDelegateWrapper wrapper, GClosure* closure) 936 { 937 wrapper.remove(wrapper); 938 } 939 940 protected class OnPostActivateDelegateWrapper 941 { 942 void delegate(Action, UIManager) dlg; 943 gulong handlerId; 944 945 this(void delegate(Action, UIManager) dlg) 946 { 947 this.dlg = dlg; 948 onPostActivateListeners ~= this; 949 } 950 951 void remove(OnPostActivateDelegateWrapper source) 952 { 953 foreach(index, wrapper; onPostActivateListeners) 954 { 955 if (wrapper.handlerId == source.handlerId) 956 { 957 onPostActivateListeners[index] = null; 958 onPostActivateListeners = std.algorithm.remove(onPostActivateListeners, index); 959 break; 960 } 961 } 962 } 963 } 964 OnPostActivateDelegateWrapper[] onPostActivateListeners; 965 966 /** 967 * The ::post-activate signal is emitted just after the @action 968 * is activated. 969 * 970 * This is intended for applications to get notification 971 * just after any action is activated. 972 * 973 * Params: 974 * action = the action 975 * 976 * Since: 2.4 977 */ 978 gulong addOnPostActivate(void delegate(Action, UIManager) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 979 { 980 auto wrapper = new OnPostActivateDelegateWrapper(dlg); 981 wrapper.handlerId = Signals.connectData( 982 this, 983 "post-activate", 984 cast(GCallback)&callBackPostActivate, 985 cast(void*)wrapper, 986 cast(GClosureNotify)&callBackPostActivateDestroy, 987 connectFlags); 988 return wrapper.handlerId; 989 } 990 991 extern(C) static void callBackPostActivate(GtkUIManager* uimanagerStruct, GtkAction* action, OnPostActivateDelegateWrapper wrapper) 992 { 993 wrapper.dlg(ObjectG.getDObject!(Action)(action), wrapper.outer); 994 } 995 996 extern(C) static void callBackPostActivateDestroy(OnPostActivateDelegateWrapper wrapper, GClosure* closure) 997 { 998 wrapper.remove(wrapper); 999 } 1000 1001 protected class OnPreActivateDelegateWrapper 1002 { 1003 void delegate(Action, UIManager) dlg; 1004 gulong handlerId; 1005 1006 this(void delegate(Action, UIManager) dlg) 1007 { 1008 this.dlg = dlg; 1009 onPreActivateListeners ~= this; 1010 } 1011 1012 void remove(OnPreActivateDelegateWrapper source) 1013 { 1014 foreach(index, wrapper; onPreActivateListeners) 1015 { 1016 if (wrapper.handlerId == source.handlerId) 1017 { 1018 onPreActivateListeners[index] = null; 1019 onPreActivateListeners = std.algorithm.remove(onPreActivateListeners, index); 1020 break; 1021 } 1022 } 1023 } 1024 } 1025 OnPreActivateDelegateWrapper[] onPreActivateListeners; 1026 1027 /** 1028 * The ::pre-activate signal is emitted just before the @action 1029 * is activated. 1030 * 1031 * This is intended for applications to get notification 1032 * just before any action is activated. 1033 * 1034 * Params: 1035 * action = the action 1036 * 1037 * Since: 2.4 1038 */ 1039 gulong addOnPreActivate(void delegate(Action, UIManager) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 1040 { 1041 auto wrapper = new OnPreActivateDelegateWrapper(dlg); 1042 wrapper.handlerId = Signals.connectData( 1043 this, 1044 "pre-activate", 1045 cast(GCallback)&callBackPreActivate, 1046 cast(void*)wrapper, 1047 cast(GClosureNotify)&callBackPreActivateDestroy, 1048 connectFlags); 1049 return wrapper.handlerId; 1050 } 1051 1052 extern(C) static void callBackPreActivate(GtkUIManager* uimanagerStruct, GtkAction* action, OnPreActivateDelegateWrapper wrapper) 1053 { 1054 wrapper.dlg(ObjectG.getDObject!(Action)(action), wrapper.outer); 1055 } 1056 1057 extern(C) static void callBackPreActivateDestroy(OnPreActivateDelegateWrapper wrapper, GClosure* closure) 1058 { 1059 wrapper.remove(wrapper); 1060 } 1061 }