# HG changeset patch # User Frank Benoit # Date 1200042258 -3600 # Node ID 8e9ea24111fd4b7ef1ba0e4cc7caf5633be9af7a # Parent f646579f309cac84e97c53d01a0c051794ca5f9d Menu, MenuItem diff -r f646579f309c -r 8e9ea24111fd dwt/SWT.d --- a/dwt/SWT.d Fri Jan 11 08:34:26 2008 +0100 +++ b/dwt/SWT.d Fri Jan 11 10:04:18 2008 +0100 @@ -3417,7 +3417,7 @@ return "Unknown error"; //$NON-NLS-1$ } -/++ + /** * Returns the NLS'ed message for the given argument. * @@ -3429,9 +3429,11 @@ * */ public static char[] getMessage(char[] key) { - return Compatibility.getMessage(key); + // PORTING_FIXME: Implement + return null; + //return Compatibility.getMessage(key); } -++/ + /** * Returns the SWT platform name. * Examples: "win32", "motif", "gtk", "photon", "carbon" diff -r f646579f309c -r 8e9ea24111fd dwt/internal/gtk/OS.d --- a/dwt/internal/gtk/OS.d Fri Jan 11 08:34:26 2008 +0100 +++ b/dwt/internal/gtk/OS.d Fri Jan 11 10:04:18 2008 +0100 @@ -135,6 +135,15 @@ public alias dwt.internal.c.gtk.GtkMisc GtkMisc; public alias dwt.internal.c.gtk.GtkImage GtkImage; public alias dwt.internal.c.gtk.GtkPlug GtkPlug; +public alias dwt.internal.c.gtk.GtkMenu GtkMenu; +public alias dwt.internal.c.gtk.GtkBin GtkBin; +public alias dwt.internal.c.gtk.GtkRadioMenuItem GtkRadioMenuItem; +public alias dwt.internal.c.gtk.GtkMenuShell GtkMenuShell; +public alias dwt.internal.c.gtk.GtkCheckMenuItem GtkCheckMenuItem; +public alias dwt.internal.c.gtk.GtkAccelLabel GtkAccelLabel; +public alias dwt.internal.c.gtk.GtkImageMenuItem GtkImageMenuItem; +public alias dwt.internal.c.gtk.GtkMenuItem GtkMenuItem; +public alias dwt.internal.c.gtk.GtkIMMulticontext GtkIMMulticontext; public alias dwt.internal.c.Xlib.XErrorEvent XErrorEvent; public alias dwt.internal.c.Xlib.XExposeEvent XExposeEvent; @@ -1841,9 +1850,9 @@ /* Field accessors */ - void GTK_ACCEL_LABEL_SET_ACCEL_STRING( GtkAccelLabel *arg0, gchar * arg1 ) + static void GTK_ACCEL_LABEL_SET_ACCEL_STRING( GtkAccelLabel *arg0, gchar * arg1 ) { arg0.accel_string = arg1; } - gchar* GTK_ACCEL_LABEL_GET_ACCEL_STRING( GtkAccelLabel* arg0) + static gchar* GTK_ACCEL_LABEL_GET_ACCEL_STRING( GtkAccelLabel* arg0) { return arg0.accel_string; } static GtkWidget* GTK_SCROLLED_WINDOW_HSCROLLBAR( GtkScrolledWindow* arg0 ) diff -r f646579f309c -r 8e9ea24111fd dwt/widgets/Display.d --- a/dwt/widgets/Display.d Fri Jan 11 08:34:26 2008 +0100 +++ b/dwt/widgets/Display.d Fri Jan 11 10:04:18 2008 +0100 @@ -2644,10 +2644,28 @@ return result [0]; } -int /*long*/ menuPositionProcMeth (GtkWidget * menu, int /*long*/ x, int /*long*/ y, int /*long*/ push_in, int /*long*/ user_data) { - Widget widget = getWidget (menu); + +package void doMenuPositionProc( GtkMenu* window, bool hasLocation ){ + /* + * Bug in GTK. The timestamp passed into gtk_menu_popup is used + * to perform an X pointer grab. It cannot be zero, else the grab + * will fail. The fix is to ensure that the timestamp of the last + * event processed is used. + */ + OS.gtk_menu_popup (window, null, null, + hasLocation ? &menuPositionProcFunc : null, + cast(void*)this, 0, getLastEventTime() ); +} + +private static extern(C) void menuPositionProcFunc (GtkMenu* menu, int* x, int* y, int* push_in, void* user_data) { + auto display = cast(Display)user_data; + display.menuPositionProc( menu, x, y, push_in, null ); +} + +void menuPositionProc (GtkMenu* menu, int* x, int* y, int* push_in, void* user_data) { + Widget widget = getWidget (cast(GtkWidget*)menu); if (widget is null) return 0; - return widget.menuPositionProc (menu, x, y, push_in, user_data); + widget.menuPositionProc (menu, x, y, push_in, user_data); } /** diff -r f646579f309c -r 8e9ea24111fd dwt/widgets/Menu.d --- a/dwt/widgets/Menu.d Fri Jan 11 08:34:26 2008 +0100 +++ b/dwt/widgets/Menu.d Fri Jan 11 10:04:18 2008 +0100 @@ -10,25 +10,22 @@ *******************************************************************************/ module dwt.widgets.Menu; +import dwt.SWT; +import dwt.internal.gtk.OS; +import dwt.events.MenuListener; +import dwt.events.HelpListener; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.widgets.ImageList; +import dwt.widgets.TypedListener; +import dwt.widgets.Event; +import dwt.widgets.MenuItem; +import dwt.widgets.Widget; import dwt.widgets.Control; import dwt.widgets.Decorations; -import dwt.internal.gtk.OS; +import dwt.widgets.Shell; -class Menu : Control { - bool isDisposed(); - void dispose(); - void _setVisible (bool visible); - void createIMMenu (GtkIMContext* imHandle) ; - void addAccelerators(GtkAccelGroup*); - void fixMenus (Decorations newParent) ; -} - -/+++ -import dwt.internal.*; -import dwt.internal.gtk.*; -import dwt.*; -import dwt.events.*; -import dwt.graphics.*; +import tango.stdc.stringz; /** * Instances of this class are user interface objects that contain @@ -47,12 +44,14 @@ * IMPORTANT: This class is not intended to be subclassed. *

*/ -public class Menu extends Widget { +public class Menu : Widget { int x, y; - boolean hasLocation; + bool hasLocation; MenuItem cascade, selectedItem; Decorations parent; - int /*long*/ imItem, imSeparator, imHandle; + GtkWidget* imItem; + GtkWidget* imSeparator; + GtkIMContext* imHandle; ImageList imageList; /** @@ -74,7 +73,7 @@ * @see Widget#checkSubclass * @see Widget#getStyle */ -public Menu (Control parent) { +public this (Control parent) { this (checkNull (parent).menuShell (), SWT.POP_UP); } @@ -109,7 +108,7 @@ * @see Widget#checkSubclass * @see Widget#getStyle */ -public Menu (Decorations parent, int style) { +public this (Decorations parent, int style) { super (parent, checkStyle (style)); this.parent = parent; createWidget (0); @@ -135,7 +134,7 @@ * @see Widget#checkSubclass * @see Widget#getStyle */ -public Menu (Menu parentMenu) { +public this (Menu parentMenu) { this (checkNull (parentMenu).parent, SWT.DROP_DOWN); } @@ -159,22 +158,22 @@ * @see Widget#checkSubclass * @see Widget#getStyle */ -public Menu (MenuItem parentItem) { +public this (MenuItem parentItem) { this (checkNull (parentItem).parent); } static Control checkNull (Control control) { - if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (control is null) SWT.error (SWT.ERROR_NULL_ARGUMENT); return control; } static Menu checkNull (Menu menu) { - if (menu == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (menu is null) SWT.error (SWT.ERROR_NULL_ARGUMENT); return menu; } static MenuItem checkNull (MenuItem item) { - if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + if (item is null) SWT.error (SWT.ERROR_NULL_ARGUMENT); return item; } @@ -182,31 +181,30 @@ return checkBits (style, SWT.POP_UP, SWT.BAR, SWT.DROP_DOWN, 0, 0, 0); } -void _setVisible (boolean visible) { - if (visible == OS.GTK_WIDGET_MAPPED (handle)) return; +void _setVisible (bool visible) { + if (visible is OS.GTK_WIDGET_MAPPED (handle)) return; if (visible) { sendEvent (SWT.Show); - if (getItemCount () != 0) { - if ((OS.GTK_VERSION >= OS.VERSION (2, 8, 0))) { - OS.gtk_menu_shell_set_take_focus (handle, false); + if (getItemCount () !is 0) { + if ((OS.GTK_VERSION >= OS.buildVERSION (2, 8, 0))) { + OS.gtk_menu_shell_set_take_focus (cast(GtkMenuShell*)handle, false); } - int /*long*/ address = hasLocation ? display.menuPositionProc: 0; /* * Bug in GTK. The timestamp passed into gtk_menu_popup is used * to perform an X pointer grab. It cannot be zero, else the grab * will fail. The fix is to ensure that the timestamp of the last * event processed is used. */ - OS.gtk_menu_popup (handle, 0, 0, address, 0, 0, display.getLastEventTime ()); + getDisplay().doMenuPositionProc( cast(GtkMenu*)handle, hasLocation ); } else { sendEvent (SWT.Hide); } } else { - OS.gtk_menu_popdown (handle); + OS.gtk_menu_popdown (cast(GtkMenu*)handle); } } -void addAccelerators (int /*long*/ accelGroup) { +void addAccelerators (GtkAccelGroup* accelGroup) { MenuItem [] items = getItems (); for (int i = 0; i < items.length; i++) { MenuItem item = items[i]; @@ -235,7 +233,7 @@ */ public void addMenuListener (MenuListener listener) { checkWidget(); - if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); TypedListener typedListener = new TypedListener (listener); addListener (SWT.Hide,typedListener); addListener (SWT.Show,typedListener); @@ -262,53 +260,53 @@ */ public void addHelpListener (HelpListener listener) { checkWidget(); - if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); TypedListener typedListener = new TypedListener (listener); addListener (SWT.Help, typedListener); } void createHandle (int index) { state |= HANDLE; - if ((style & SWT.BAR) != 0) { + if ((style & SWT.BAR) !is 0) { handle = OS.gtk_menu_bar_new (); - if (handle == 0) error (SWT.ERROR_NO_HANDLES); - int /*long*/ vboxHandle = parent.vboxHandle; - OS.gtk_container_add (vboxHandle, handle); - OS.gtk_box_set_child_packing (vboxHandle, handle, false, true, 0, OS.GTK_PACK_START); + if (handle is null) error (SWT.ERROR_NO_HANDLES); + auto vboxHandle = parent.vboxHandle; + OS.gtk_container_add (cast(GtkContainer*)vboxHandle, handle); + OS.gtk_box_set_child_packing (cast(GtkBox*)vboxHandle, handle, false, true, 0, OS.GTK_PACK_START); } else { handle = OS.gtk_menu_new (); - if (handle == 0) error (SWT.ERROR_NO_HANDLES); + if (handle is null) error (SWT.ERROR_NO_HANDLES); } } -void createIMMenu (int /*long*/ imHandle) { - if (this.imHandle == imHandle) return; +void createIMMenu (GtkIMContext* imHandle) { + if (this.imHandle is imHandle) return; this.imHandle = imHandle; - if (imHandle == 0) { - if (imItem != 0) { + if (imHandle is null) { + if (imItem !is null) { OS.gtk_widget_destroy (imItem); - imItem = 0; + imItem = null; } - if (imSeparator != 0) { + if (imSeparator !is null) { OS.gtk_widget_destroy (imSeparator); - imSeparator = 0; + imSeparator = null; } return; } - if (imSeparator == 0) { + if (imSeparator is null) { imSeparator = OS.gtk_separator_menu_item_new (); OS.gtk_widget_show (imSeparator); - OS.gtk_menu_shell_insert (handle, imSeparator, -1); + OS.gtk_menu_shell_insert (cast(GtkMenuShell*)handle, imSeparator, -1); } - if (imItem == 0) { - byte[] buffer = Converter.wcsToMbcs (null, SWT.getMessage("SWT_InputMethods"), true); + if (imItem is null) { + char* buffer = toStringz( SWT.getMessage("SWT_InputMethods")); imItem = OS.gtk_image_menu_item_new_with_label (buffer); OS.gtk_widget_show (imItem); - OS.gtk_menu_shell_insert (handle, imItem, -1); + OS.gtk_menu_shell_insert (cast(GtkMenuShell*)handle, imItem, -1); } - int /*long*/ imSubmenu = OS.gtk_menu_new (); - OS.gtk_im_multicontext_append_menuitems (imHandle, imSubmenu); - OS.gtk_menu_item_set_submenu (imItem, imSubmenu); + auto imSubmenu = OS.gtk_menu_new (); + OS.gtk_im_multicontext_append_menuitems (cast(GtkIMMulticontext*)imHandle, cast(GtkMenuShell*)imSubmenu); + OS.gtk_menu_item_set_submenu (cast(GtkMenuItem*)imItem, imSubmenu); } void createWidget (int index) { @@ -332,11 +330,11 @@ if (!OS.GTK_WIDGET_MAPPED (handle)) { return new Rectangle (0, 0, 0, 0); } - int /*long*/ window = OS.GTK_WIDGET_WINDOW (handle); - int [] origin_x = new int [1], origin_y = new int [1]; - OS.gdk_window_get_origin (window, origin_x, origin_y); - int x = origin_x [0] + OS.GTK_WIDGET_X (handle); - int y = origin_y [0] + OS.GTK_WIDGET_Y (handle); + auto window = OS.GTK_WIDGET_WINDOW (handle); + int origin_x, origin_y; + OS.gdk_window_get_origin (window, &origin_x, &origin_y); + int x = origin_x + OS.GTK_WIDGET_X (handle); + int y = origin_y + OS.GTK_WIDGET_Y (handle); int width = OS.GTK_WIDGET_WIDTH (handle); int height = OS.GTK_WIDGET_HEIGHT (handle); return new Rectangle (x, y, width, height); @@ -374,7 +372,7 @@ * * @see #isEnabled */ -public boolean getEnabled () { +public bool getEnabled () { checkWidget(); return OS.GTK_WIDGET_SENSITIVE (handle); } @@ -396,16 +394,16 @@ */ public MenuItem getItem (int index) { checkWidget(); - int /*long*/ list = OS.gtk_container_get_children (handle); - if (list == 0) error (SWT.ERROR_CANNOT_GET_ITEM); + auto list = OS.gtk_container_get_children (cast(GtkContainer*)handle); + if (list is null) error (SWT.ERROR_CANNOT_GET_ITEM); int count = OS.g_list_length (list); - if (imSeparator != 0) count--; - if (imItem != 0) count--; + if (imSeparator !is null) count--; + if (imItem !is null) count--; if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE); - int /*long*/ data = OS.g_list_nth_data (list, index); + auto data = cast(GtkWidget*)OS.g_list_nth_data (list, index); OS.g_list_free (list); - if (data == 0) error (SWT.ERROR_CANNOT_GET_ITEM); - return (MenuItem) display.getWidget (data); + if (data is null) error (SWT.ERROR_CANNOT_GET_ITEM); + return cast(MenuItem) display.getWidget (data); } /** @@ -420,12 +418,12 @@ */ public int getItemCount () { checkWidget(); - int /*long*/ list = OS.gtk_container_get_children (handle); - if (list == 0) return 0; + auto list = OS.gtk_container_get_children (cast(GtkContainer*)handle); + if (list is null) return 0; int count = OS.g_list_length (list); OS.g_list_free (list); - if (imSeparator != 0) count--; - if (imItem != 0) count--; + if (imSeparator !is null) count--; + if (imItem !is null) count--; return count; } @@ -447,20 +445,20 @@ */ public MenuItem [] getItems () { checkWidget(); - int /*long*/ list = OS.gtk_container_get_children (handle); - if (list == 0) return new MenuItem [0]; + auto list = OS.gtk_container_get_children (cast(GtkContainer*)handle); + if (list is null) return new MenuItem [0]; int count = OS.g_list_length (list); - if (imSeparator != 0) count--; - if (imItem != 0) count--; + if (imSeparator !is null) count--; + if (imItem !is null) count--; MenuItem [] items = new MenuItem [count]; int index = 0; for (int i=0; i 0) { - for (int i=0; i 0) { + for (int i=0; iERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * */ -public boolean getVisible () { +public bool getVisible () { checkWidget(); - if ((style & SWT.POP_UP) != 0) { + if ((style & SWT.POP_UP) !is 0) { Menu [] popups = display.popups; - if (popups != null) { + if (popups !is null) { for (int i=0; i= OS.VERSION (2, 6, 0)) { + if (OS.GTK_VERSION >= OS.buildVERSION (2, 6, 0)) { sendEvent (SWT.Hide); } else { /* @@ -600,8 +598,8 @@ return 0; } -int /*long*/ gtk_show (int /*long*/ widget) { - if ((style & SWT.POP_UP) != 0) { +override int /*long*/ gtk_show (GtkWidget* widget) { + if ((style & SWT.POP_UP) !is 0) { display.activeShell = getShell (); return 0; } @@ -610,9 +608,9 @@ } -int /*long*/ gtk_show_help (int /*long*/ widget, int /*long*/ helpType) { +override int /*long*/ gtk_show_help (GtkWidget* widget, int /*long*/ helpType) { if (sendHelpEvent (helpType)) { - OS.gtk_menu_shell_deactivate (handle); + OS.gtk_menu_shell_deactivate (cast(GtkMenuShell*)handle); return 1; } return 0; @@ -644,10 +642,10 @@ */ public int indexOf (MenuItem item) { checkWidget(); - if (item == null) error (SWT.ERROR_NULL_ARGUMENT); + if (item is null) error (SWT.ERROR_NULL_ARGUMENT); MenuItem [] items = getItems (); for (int i=0; i screenHeight && reqy - requisition.height >= 0) { @@ -714,22 +712,21 @@ } int screenWidth = OS.gdk_screen_width (); int reqx = this.x; - if ((style & SWT.RIGHT_TO_LEFT) != 0) { + if ((style & SWT.RIGHT_TO_LEFT) !is 0) { if (reqx - requisition.width >= 0) reqx -= requisition.width; } else { if (reqx + requisition.width > screenWidth) reqx -= requisition.width; } - if (x != 0) OS.memmove (x, new int [] {reqx}, 4); - if (y != 0) OS.memmove (y, new int [] {reqy}, 4); - if (push_in != 0) OS.memmove (push_in, new int [] {1}, 4); - return 0; + if (x !is null) *x = reqx; + if (y !is null) *y = reqy; + if (push_in !is null) *push_in = 1; } -void releaseChildren (boolean destroy) { +void releaseChildren (bool destroy) { MenuItem [] items = getItems (); for (int i=0; iERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * */ -public void setEnabled (boolean enabled) { +public void setEnabled (bool enabled) { checkWidget(); if (enabled) { OS.GTK_WIDGET_SET_FLAGS (handle, OS.GTK_SENSITIVE); @@ -891,7 +890,7 @@ */ public void setLocation (int x, int y) { checkWidget(); - if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return; + if ((style & (SWT.BAR | SWT.DROP_DOWN)) !is 0) return; this.x = x; this.y = y; hasLocation = true; @@ -923,13 +922,13 @@ */ public void setLocation (Point location) { checkWidget(); - if (location == null) error (SWT.ERROR_NULL_ARGUMENT); + if (location is null) error (SWT.ERROR_NULL_ARGUMENT); setLocation (location.x, location.y); } void setOrientation() { - if ((parent.style & SWT.RIGHT_TO_LEFT) != 0) { - if (handle != 0) OS.gtk_widget_set_direction (handle, OS.GTK_TEXT_DIR_RTL); + if ((parent.style & SWT.RIGHT_TO_LEFT) !is 0) { + if (handle !is null) OS.gtk_widget_set_direction (handle, OS.GTK_TEXT_DIR_RTL); } } @@ -949,9 +948,9 @@ *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • * */ -public void setVisible (boolean visible) { +public void setVisible (bool visible) { checkWidget(); - if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return; + if ((style & (SWT.BAR | SWT.DROP_DOWN)) !is 0) return; if (visible) { display.addPopup (this); } else { @@ -960,4 +959,3 @@ } } } -+++/ \ No newline at end of file diff -r f646579f309c -r 8e9ea24111fd dwt/widgets/MenuItem.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/widgets/MenuItem.d Fri Jan 11 10:04:18 2008 +0100 @@ -0,0 +1,885 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +module dwt.widgets.MenuItem; + + +import dwt.widgets.Menu; +import dwt.widgets.Item; +import dwt.widgets.Decorations; +import dwt.graphics.Rectangle; +import dwt.graphics.Image; +import dwt.widgets.ImageList; +import dwt.SWT; +import dwt.internal.gtk.OS; +import dwt.events.ArmListener; +import dwt.events.HelpListener; +import dwt.events.SelectionListener; +import dwt.events.SelectionEvent; +import dwt.widgets.TypedListener; +import dwt.widgets.Event; +import dwt.widgets.Display; + +import tango.stdc.stringz; +import tango.text.Util; + +/** + * Instances of this class represent a selectable user interface object + * that issues notification when pressed and released. + *
    + *
    Styles:
    + *
    CHECK, CASCADE, PUSH, RADIO, SEPARATOR
    + *
    Events:
    + *
    Arm, Help, Selection
    + *
    + *

    + * Note: Only one of the styles CHECK, CASCADE, PUSH, RADIO and SEPARATOR + * may be specified. + *

    + * IMPORTANT: This class is not intended to be subclassed. + *

    + */ +public class MenuItem : Item { + Menu parent, menu; + GtkAccelGroup* groupHandle; + int accelerator; + +/** + * Constructs a new instance of this class given its parent + * (which must be a Menu) and a style value + * describing its behavior and appearance. The item is added + * to the end of the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a menu control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#CHECK + * @see SWT#CASCADE + * @see SWT#PUSH + * @see SWT#RADIO + * @see SWT#SEPARATOR + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public this (Menu parent, int style) { + super (parent, checkStyle (style)); + this.parent = parent; + createWidget (parent.getItemCount ()); +} + +/** + * Constructs a new instance of this class given its parent + * (which must be a Menu), a style value + * describing its behavior and appearance, and the index + * at which to place it in the items maintained by its parent. + *

    + * The style value is either one of the style constants defined in + * class SWT which is applicable to instances of this + * class, or must be built by bitwise OR'ing together + * (that is, using the int "|" operator) two or more + * of those SWT style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + *

    + * + * @param parent a menu control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * @param index the zero-relative index to store the receiver in its parent + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the parent is null
    • + *
    • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)
    • + *
    + * @exception SWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
    • + *
    • ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
    • + *
    + * + * @see SWT#CHECK + * @see SWT#CASCADE + * @see SWT#PUSH + * @see SWT#RADIO + * @see SWT#SEPARATOR + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public this (Menu parent, int style, int index) { + super (parent, checkStyle (style)); + this.parent = parent; + int count = parent.getItemCount (); + if (!(0 <= index && index <= count)) { + error (SWT.ERROR_INVALID_RANGE); + } + createWidget (index); +} + +void addAccelerator (GtkAccelGroup* accelGroup) { + updateAccelerator (accelGroup, true); +} + +void addAccelerators (GtkAccelGroup* accelGroup) { + addAccelerator (accelGroup); + if (menu !is null) menu.addAccelerators (accelGroup); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the arm events are generated for the control, by sending + * it one of the messages defined in the ArmListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ArmListener + * @see #removeArmListener + */ +public void addArmListener (ArmListener listener) { + checkWidget(); + if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Arm, typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the help events are generated for the control, by sending + * it one of the messages defined in the HelpListener + * interface. + * + * @param listener the listener which should be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see HelpListener + * @see #removeHelpListener + */ +public void addHelpListener (HelpListener listener) { + checkWidget(); + if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Help, typedListener); +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when the menu item is selected by the user, by sending + * it one of the messages defined in the SelectionListener + * interface. + *

    + * When widgetSelected is called, the stateMask field of the event object is valid. + * widgetDefaultSelected is not called. + *

    + * + * @param listener the listener which should be notified when the menu item is selected by the user + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #removeSelectionListener + * @see SelectionEvent + */ +public void addSelectionListener (SelectionListener listener) { + checkWidget(); + if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener(listener); + addListener (SWT.Selection,typedListener); + addListener (SWT.DefaultSelection,typedListener); +} + +static int checkStyle (int style) { + return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.CASCADE, 0); +} + +protected void checkSubclass () { + if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); +} + +void createHandle (int index) { + state |= HANDLE; + char [] buffer = "\0"; + int bits = SWT.CHECK | SWT.RADIO | SWT.PUSH | SWT.SEPARATOR; + switch (style & bits) { + case SWT.SEPARATOR: + handle = OS.gtk_separator_menu_item_new (); + break; + case SWT.RADIO: + /* + * Feature in GTK. In GTK, radio button must always be part of + * a radio button group. In a GTK radio group, one button is always + * selected. This means that it is not possible to have a single + * radio button that is unselected. This is necessary to allow + * applications to implement their own radio behavior or use radio + * buttons outside of radio groups. The fix is to create a hidden + * radio button for each radio button we create and add them + * to the same group. This allows the visible button to be + * unselected. + */ + groupHandle = cast(GtkAccelGroup*) OS.gtk_radio_menu_item_new (null); + if (groupHandle is null) error (SWT.ERROR_NO_HANDLES); + OS.g_object_ref (groupHandle); + OS.gtk_object_sink (cast(GtkObject*)groupHandle); + auto group = OS.gtk_radio_menu_item_get_group (cast(GtkRadioMenuItem*) groupHandle); + handle = OS.gtk_radio_menu_item_new_with_label (group, buffer.ptr); + break; + case SWT.CHECK: + handle = OS.gtk_check_menu_item_new_with_label (buffer.ptr); + break; + case SWT.PUSH: + default: + handle = OS.gtk_image_menu_item_new_with_label (buffer.ptr); + break; + } + if (handle is null) error (SWT.ERROR_NO_HANDLES); + if ((style & SWT.SEPARATOR) is 0) { + auto label = OS.gtk_bin_get_child (cast(GtkBin*)handle); + OS.gtk_accel_label_set_accel_widget (cast(GtkAccelLabel*)label, null); + } + auto parentHandle = parent.handle; + bool enabled = OS.GTK_WIDGET_SENSITIVE (parentHandle); + if (!enabled) OS.GTK_WIDGET_SET_FLAGS (parentHandle, OS.GTK_SENSITIVE); + OS.gtk_menu_shell_insert (cast(GtkMenuShell*)parentHandle, handle, index); + if (!enabled) OS.GTK_WIDGET_UNSET_FLAGS (parentHandle, OS.GTK_SENSITIVE); + OS.gtk_widget_show (handle); +} + +void fixMenus (Decorations newParent) { + if (menu !is null) menu.fixMenus (newParent); +} + +/** + * Returns the widget accelerator. An accelerator is the bit-wise + * OR of zero or more modifier masks and a key. Examples: + * SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2. + * The default value is zero, indicating that the menu item does + * not have an accelerator. + * + * @return the accelerator or 0 + * + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public int getAccelerator () { + checkWidget(); + return accelerator; +} + +GtkAccelGroup* getAccelGroup () { + Menu menu = parent; + while (menu !is null && menu.cascade !is null) { + menu = menu.cascade.parent; + } + if (menu is null) return null; + Decorations shell = menu.parent; + return shell.menuBar is menu ? shell.accelGroup : null; +} + +/*public*/ Rectangle getBounds () { + checkWidget(); + if (!OS.GTK_WIDGET_MAPPED (handle)) { + return new Rectangle (0, 0, 0, 0); + } + int x = OS.GTK_WIDGET_X (handle); + int y = OS.GTK_WIDGET_Y (handle); + int width = OS.GTK_WIDGET_WIDTH (handle); + int height = OS.GTK_WIDGET_HEIGHT (handle); + return new Rectangle (x, y, width, height); +} + +/** + * Returns true if the receiver is enabled, and + * false otherwise. A disabled menu item is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #isEnabled + */ +public bool getEnabled () { + checkWidget(); + return OS.GTK_WIDGET_SENSITIVE (handle); +} + +/** + * Returns the receiver's cascade menu if it has one or null + * if it does not. Only CASCADE menu items can have + * a pull down menu. The sequence of key strokes, button presses + * and/or button releases that are used to request a pull down + * menu is platform specific. + * + * @return the receiver's menu + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Menu getMenu () { + checkWidget(); + return menu; +} + +/** + * Returns the receiver's parent, which must be a Menu. + * + * @return the receiver's parent + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public Menu getParent () { + checkWidget(); + return parent; +} + +/** + * Returns true if the receiver is selected, + * and false otherwise. + *

    + * When the receiver is of type CHECK or RADIO, + * it is selected when it is checked. + * + * @return the selection state + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public bool getSelection () { + checkWidget(); + if ((style & (SWT.CHECK | SWT.RADIO)) is 0) return false; + return cast(bool)OS.gtk_check_menu_item_get_active(cast(GtkCheckMenuItem*)handle); +} + +override int /*long*/ gtk_activate (GtkWidget* widget) { + if ((style & SWT.CASCADE) !is 0 && menu !is null) return 0; + /* + * Bug in GTK. When an ancestor menu is disabled and + * the user types an accelerator key, GTK delivers the + * the activate signal even though the menu item cannot + * be invoked using the mouse. The fix is to ignore + * activate signals when an ancestor menu is disabled. + */ + if (!isEnabled ()) return 0; + Event event = new Event (); + auto ptr = OS.gtk_get_current_event (); + if (ptr !is null) { + GdkEvent* gdkEvent = ptr; + switch (gdkEvent.type) { + case OS.GDK_KEY_PRESS: + case OS.GDK_KEY_RELEASE: + case OS.GDK_BUTTON_PRESS: + case OS.GDK_2BUTTON_PRESS: + case OS.GDK_BUTTON_RELEASE: { + int state; + OS.gdk_event_get_state (ptr, &state); + setInputState (event, state); + break; + } + } + OS.gdk_event_free (ptr); + } + if ((style & SWT.RADIO) !is 0) { + if ((parent.getStyle () & SWT.NO_RADIO_GROUP) is 0) { + selectRadio (); + } + } + postEvent (SWT.Selection, event); + return 0; +} + +override int /*long*/ gtk_select (int /*long*/ item) { + parent.selectedItem = this; + sendEvent (SWT.Arm); + return 0; +} + +override int /*long*/ gtk_show_help (GtkWidget* widget, int /*long*/ helpType) { + bool handled = hooks (SWT.Help); + if (handled) { + postEvent (SWT.Help); + } else { + handled = parent.sendHelpEvent (helpType); + } + if (handled) { + OS.gtk_menu_shell_deactivate (cast(GtkMenuShell*)parent.handle); + return 1; + } + return 0; +} + +void hookEvents () { + super.hookEvents (); + OS.g_signal_connect_closure (handle, OS.activate.ptr, display.closures [ACTIVATE], false); + OS.g_signal_connect_closure (handle, OS.select.ptr, display.closures [SELECT], false); + OS.g_signal_connect_closure_by_id (handle, display.signalIds [SHOW_HELP], 0, display.closures [SHOW_HELP], false); +} + +/** + * Returns true if the receiver is enabled and all + * of the receiver's ancestors are enabled, and false + * otherwise. A disabled menu item is typically not selectable from the + * user interface and draws with an inactive or "grayed" look. + * + * @return the receiver's enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #getEnabled + */ +public bool isEnabled () { + return getEnabled () && parent.isEnabled (); +} + +void releaseChildren (bool destroy) { + if (menu !is null) { + menu.release (false); + menu = null; + } + super.releaseChildren (destroy); +} + +void releaseParent () { + super.releaseParent (); + if (menu !is null) { + if (menu.selectedItem is this) menu.selectedItem = null; + menu.dispose (); + } + menu = null; +} + +void releaseWidget () { + super.releaseWidget (); + auto accelGroup = getAccelGroup (); + if (accelGroup !is null) removeAccelerator (accelGroup); + if (groupHandle !is null) OS.g_object_unref (groupHandle); + groupHandle = null; + accelerator = 0; + parent = null; +} + +void removeAccelerator (GtkAccelGroup* accelGroup) { + updateAccelerator (accelGroup, false); +} + +void removeAccelerators (GtkAccelGroup* accelGroup) { + removeAccelerator (accelGroup); + if (menu !is null) menu.removeAccelerators (accelGroup); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the arm events are generated for the control. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see ArmListener + * @see #addArmListener + */ +public void removeArmListener (ArmListener listener) { + checkWidget(); + if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable is null) return; + eventTable.unhook (SWT.Arm, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the help events are generated for the control. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see HelpListener + * @see #addHelpListener + */ +public void removeHelpListener (HelpListener listener) { + checkWidget(); + if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable is null) return; + eventTable.unhook (SWT.Help, listener); +} + +/** + * Removes the listener from the collection of listeners who will + * be notified when the control is selected by the user. + * + * @param listener the listener which should no longer be notified + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see SelectionListener + * @see #addSelectionListener + */ +public void removeSelectionListener (SelectionListener listener) { + checkWidget(); + if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable is null) return; + eventTable.unhook (SWT.Selection, listener); + eventTable.unhook (SWT.DefaultSelection,listener); +} +void selectRadio () { + int index = 0; + MenuItem [] items = parent.getItems (); + while (index < items.length && items [index] !is this) index++; + int i = index - 1; + while (i >= 0 && items [i].setRadioSelection (false)) --i; + int j = index + 1; + while (j < items.length && items [j].setRadioSelection (false)) j++; + setSelection (true); +} +/** + * Sets the widget accelerator. An accelerator is the bit-wise + * OR of zero or more modifier masks and a key. Examples: + * SWT.MOD1 | SWT.MOD2 | 'T', SWT.MOD3 | SWT.F2. + * SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2. + * The default value is zero, indicating that the menu item does + * not have an accelerator. + * + * @param accelerator an integer that is the bit-wise OR of masks and a key + * + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setAccelerator (int accelerator) { + checkWidget(); + if (this.accelerator is accelerator) return; + auto accelGroup = getAccelGroup (); + if (accelGroup !is null) removeAccelerator (accelGroup); + this.accelerator = accelerator; + if (accelGroup !is null) addAccelerator (accelGroup); +} + +/** + * Enables the receiver if the argument is true, + * and disables it otherwise. A disabled menu item is typically + * not selectable from the user interface and draws with an + * inactive or "grayed" look. + * + * @param enabled the new enabled state + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setEnabled (bool enabled) { + checkWidget(); + if (OS.GTK_WIDGET_SENSITIVE (handle) is enabled) return; + auto accelGroup = getAccelGroup (); + if (accelGroup !is null) removeAccelerator (accelGroup); + OS.gtk_widget_set_sensitive (handle, enabled); + if (accelGroup !is null) addAccelerator (accelGroup); +} + +/** + * Sets the image the receiver will display to the argument. + *

    + * Note: This operation is a hint and is not supported on + * platforms that do not have this concept (for example, Windows NT). + *

    + * + * @param image the image to display + * + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setImage (Image image) { + checkWidget(); + if ((style & SWT.SEPARATOR) !is 0) return; + super.setImage (image); + if (!OS.GTK_IS_IMAGE_MENU_ITEM (cast(GTypeInstance*)handle)) return; + if (image !is null) { + ImageList imageList = parent.imageList; + if (imageList is null) imageList = parent.imageList = new ImageList (); + int imageIndex = imageList.indexOf (image); + if (imageIndex is -1) { + imageIndex = imageList.add (image); + } else { + imageList.put (imageIndex, image); + } + auto pixbuf = imageList.getPixbuf (imageIndex); + auto imageHandle = OS.gtk_image_new_from_pixbuf (pixbuf); + OS.gtk_image_menu_item_set_image (cast(GtkImageMenuItem*)handle, imageHandle); + OS.gtk_widget_show (imageHandle); + } else { + OS.gtk_image_menu_item_set_image (cast(GtkImageMenuItem*)handle, null); + } +} + +/** + * Sets the receiver's pull down menu to the argument. + * Only CASCADE menu items can have a + * pull down menu. The sequence of key strokes, button presses + * and/or button releases that are used to request a pull down + * menu is platform specific. + *

    + * Note: Disposing of a menu item that has a pull down menu + * will dispose of the menu. To avoid this behavior, set the + * menu to null before the menu item is disposed. + *

    + * + * @param menu the new pull down menu + * + * @exception IllegalArgumentException
      + *
    • ERROR_MENU_NOT_DROP_DOWN - if the menu is not a drop down menu
    • + *
    • ERROR_MENUITEM_NOT_CASCADE - if the menu item is not a CASCADE
    • + *
    • ERROR_INVALID_ARGUMENT - if the menu has been disposed
    • + *
    • ERROR_INVALID_PARENT - if the menu is not in the same widget tree
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setMenu (Menu menu) { + checkWidget (); + + /* Check to make sure the new menu is valid */ + if ((style & SWT.CASCADE) is 0) { + error (SWT.ERROR_MENUITEM_NOT_CASCADE); + } + if (menu !is null) { + if ((menu.style & SWT.DROP_DOWN) is 0) { + error (SWT.ERROR_MENU_NOT_DROP_DOWN); + } + if (menu.parent !is parent.parent) { + error (SWT.ERROR_INVALID_PARENT); + } + } + + /* Assign the new menu */ + Menu oldMenu = this.menu; + if (oldMenu is menu) return; + auto accelGroup = getAccelGroup (); + if (accelGroup !is null) removeAccelerators (accelGroup); + if (oldMenu !is null) { + oldMenu.cascade = null; + /* + * Add a reference to the menu we are about + * to replace or GTK will destroy it. + */ + OS.g_object_ref (oldMenu.handle); + OS.gtk_menu_item_remove_submenu (cast(GtkMenuItem*)handle); + } + if ((this.menu = menu) !is null) { + menu.cascade = this; + OS.gtk_menu_item_set_submenu (cast(GtkMenuItem*)handle, menu.handle); + } + if (accelGroup !is null) addAccelerators (accelGroup); +} + +void setOrientation() { + if ((parent.style & SWT.RIGHT_TO_LEFT) !is 0) { + if (handle !is null) { + OS.gtk_widget_set_direction (handle, OS.GTK_TEXT_DIR_RTL); + OS.gtk_container_forall (cast(GtkContainer*)handle, cast(GtkCallback)&Display.setDirectionProcFunc, cast(void*)OS.GTK_TEXT_DIR_RTL); + } + } +} + +bool setRadioSelection (bool value) { + if ((style & SWT.RADIO) is 0) return false; + if (getSelection () !is value) { + setSelection (value); + postEvent (SWT.Selection); + } + return true; +} + +/** + * Sets the selection state of the receiver. + *

    + * When the receiver is of type CHECK or RADIO, + * it is selected when it is checked. + * + * @param selected the new selection state + * + * @exception SWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + */ +public void setSelection (bool selected) { + checkWidget(); + if ((style & (SWT.CHECK | SWT.RADIO)) is 0) return; + OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, cast(void*)ACTIVATE); + OS.gtk_check_menu_item_set_active (cast(GtkCheckMenuItem*)handle, selected); + if ((style & SWT.RADIO) !is 0) OS.gtk_check_menu_item_set_active (cast(GtkCheckMenuItem*)groupHandle, !selected); + OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, null, null, cast(void*)ACTIVATE); +} + +/** + * Sets the receiver's text. The string may include + * the mnemonic character and accelerator text. + *

    + * Mnemonics are indicated by an '&' that causes the next + * character to be the mnemonic. When the user presses a + * key sequence that matches the mnemonic, a selection + * event occurs. On most platforms, the mnemonic appears + * underlined but may be emphasised in a platform specific + * manner. The mnemonic indicator character '&' can be + * escaped by doubling it in the string, causing a single + * '&' to be displayed. + *

    + *

    + * Accelerator text is indicated by the '\t' character. + * On platforms that support accelerator text, the text + * that follows the '\t' character is displayed to the user, + * typically indicating the key stroke that will cause + * the item to become selected. On most platforms, the + * accelerator text appears right aligned in the menu. + * Setting the accelerator text does not install the + * accelerator key sequence. The accelerator key sequence + * is installed using #setAccelerator. + *

    + * + * @param string the new text + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the text is null
    • + *
    + * @exception SWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #setAccelerator + */ +public void setText (char[] string) { + checkWidget(); + if (string is null) error (SWT.ERROR_NULL_ARGUMENT); + if ((style & SWT.SEPARATOR) !is 0) return; + if (text ==/*eq*/ string) return; + super.setText (string); + char[] accelString = ""; + int index = locate( string, '\t'); + if( index == string.length ) index = -1; + if (index !is -1) { + accelString = string[ index .. string.length ]; + string = string[ 0 .. index ]; + } + char [] chars = fixMnemonic (string); + char* buffer = toStringz( chars ); + auto label = OS.gtk_bin_get_child (cast(GtkBin*)handle); + OS.gtk_label_set_text_with_mnemonic (cast(GtkLabel*)label, buffer); + + auto ptr = cast(char*)OS.g_malloc (accelString.length + 1); + ptr[ 0 .. accelString.length ] = accelString; + ptr[ accelString.length ] = '\0'; + + auto oldPtr = OS.GTK_ACCEL_LABEL_GET_ACCEL_STRING (cast(GtkAccelLabel*)label); + OS.GTK_ACCEL_LABEL_SET_ACCEL_STRING (cast(GtkAccelLabel*)label, ptr); + if (oldPtr !is null) OS.g_free (oldPtr); +} + +void updateAccelerator (GtkAccelGroup* accelGroup, bool add) { + if (accelerator is 0 || !getEnabled ()) return; + int mask = 0; + if ((accelerator & SWT.ALT) !is 0) mask |= OS.GDK_MOD1_MASK; + if ((accelerator & SWT.SHIFT) !is 0) mask |= OS.GDK_SHIFT_MASK; + if ((accelerator & SWT.CONTROL) !is 0) mask |= OS.GDK_CONTROL_MASK; + int keysym = accelerator & SWT.KEY_MASK; + int newKey = Display.untranslateKey (keysym); + if (newKey !is 0) { + keysym = newKey; + } else { + switch (keysym) { + case '\r': keysym = OS.GDK_Return; break; + default: keysym = Display.wcsToMbcs (cast(char) keysym); + } + } + /* When accel_key is zero, it causes GTK warnings */ + if (keysym !is 0) { + if (add) { + OS.gtk_widget_add_accelerator (handle, OS.activate.ptr, accelGroup, keysym, mask, OS.GTK_ACCEL_VISIBLE); + } else { + OS.gtk_widget_remove_accelerator (handle, accelGroup, keysym, mask); + } + } +} +} diff -r f646579f309c -r 8e9ea24111fd dwt/widgets/Widget.d --- a/dwt/widgets/Widget.d Fri Jan 11 08:34:26 2008 +0100 +++ b/dwt/widgets/Widget.d Fri Jan 11 10:04:18 2008 +0100 @@ -915,8 +915,7 @@ return 0; } -int /*long*/ menuPositionProc (GtkWidget * menu, int /*long*/ x, int /*long*/ y, int /*long*/ push_in, int /*long*/ user_data) { - return 0; +void menuPositionProc (GtkMenu* menu, int* x, int* y, int* push_in, void* user_data) { } bool mnemonicHit (GtkWidget* mnemonicHandle, char key) { diff -r f646579f309c -r 8e9ea24111fd todo.txt --- a/todo.txt Fri Jan 11 08:34:26 2008 +0100 +++ b/todo.txt Fri Jan 11 10:04:18 2008 +0100 @@ -18,7 +18,7 @@ * accessibility package (independant) * Shell -EventTable, Menu, Tray +EventTable Questions: Whats needed at minimum to make a test with empty window? @@ -96,14 +96,14 @@ widgets/FontDialog widgets/Group widgets/ImageList // OK -widgets/Item +widgets/Item // OK widgets/Label widgets/Layout widgets/Link widgets/List widgets/Listener // OK -widgets/Menu -widgets/MenuItem +widgets/Menu // OK +widgets/MenuItem // OK widgets/MessageBox widgets/Monitor widgets/ProgressBar @@ -124,10 +124,10 @@ widgets/Text widgets/ToolBar widgets/ToolItem -widgets/ToolTip +widgets/ToolTip // OK widgets/Tracker -widgets/Tray -widgets/TrayItem +widgets/Tray // OK +widgets/TrayItem // OK widgets/Tree widgets/TreeColumn widgets/TreeItem