/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.widgets;


import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gtk.*;

/**
 * Instances of this class represent a selectable user interface object
 * that issues notification when pressed and released.
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>CHECK, CASCADE, PUSH, RADIO, SEPARATOR</dd>
 * <dt><b>Events:</b></dt>
 * <dd>Arm, Help, Selection</dd>
 * </dl>
 * <p>
 * Note: Only one of the styles CHECK, CASCADE, PUSH, RADIO and SEPARATOR
 * may be specified.
 * </p><p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 *
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 * @noextend This class is not intended to be subclassed by clients.
 */
public class MenuItem extends Item {
	Menu parent, menu;
	long groupHandle, labelHandle, imageHandle;

	/** Feature in Gtk: as of Gtk version 3.10 GtkImageMenuItem is deprecated,
	 * meaning that MenuItems in SWT with images can no longer be GtkImageMenuItems
	 * after Gtk3.10. The solution to this is to create a GtkMenuItem, add a GtkBox
	 * as its child, and pack that box with a GtkLabel and GtkImage. This reproduces
	 * the functionality of a GtkImageMenuItem and allows SWT to retain image support
	 * for MenuItems.
	 *
	 * For more information see:
	 * https://developer.gnome.org/gtk3/stable/GtkImageMenuItem.html#GtkImageMenuItem.description
	 * Bug 470298
	 */
	long boxHandle;

	int accelerator, userId;
	String toolTipText;

	/** GTK4 only fields */
	long modelHandle, actionHandle, shortcutHandle;
	int parentMenuPosition;
	String actionName;

/**
 * Constructs a new instance of this class given its parent
 * (which must be a <code>Menu</code>) and a style value
 * describing its behavior and appearance. The item is added
 * to the end of the items maintained by its parent.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * lists the style constants that are applicable to the class.
 * Style bits are also inherited from superclasses.
 * </p>
 *
 * @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 <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 *
 * @see SWT#CHECK
 * @see SWT#CASCADE
 * @see SWT#PUSH
 * @see SWT#RADIO
 * @see SWT#SEPARATOR
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public MenuItem (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 <code>Menu</code>), a style value
 * describing its behavior and appearance, and the index
 * at which to place it in the items maintained by its parent.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * lists the style constants that are applicable to the class.
 * Style bits are also inherited from superclasses.
 * </p>
 *
 * @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 <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 *
 * @see SWT#CHECK
 * @see SWT#CASCADE
 * @see SWT#PUSH
 * @see SWT#RADIO
 * @see SWT#SEPARATOR
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public MenuItem (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 (long accelGroup) {
	updateAccelerator (accelGroup, true);
}

void addAccelerators (long accelGroup) {
	addAccelerator(accelGroup);
	if (menu != 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 <code>ArmListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see ArmListener
 * @see #removeArmListener
 */
public void addArmListener (ArmListener listener) {
	checkWidget();
	if (listener == 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 <code>HelpListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see HelpListener
 * @see #removeHelpListener
 */
public void addHelpListener (HelpListener listener) {
	checkWidget();
	if (listener == 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 <code>SelectionListener</code>
 * interface.
 * <p>
 * When <code>widgetSelected</code> is called, the stateMask field of the event object is valid.
 * <code>widgetDefaultSelected</code> is not called.
 * </p>
 * <p>
 * When the <code>SWT.RADIO</code> style bit is set, the <code>widgetSelected</code> method is
 * also called when the receiver loses selection because another item in the same radio group
 * was selected by the user. During <code>widgetSelected</code> the application can use
 * <code>getSelection()</code> to determine the current selected state of the receiver.
 * </p>
 *
 * @param listener the listener which should be notified when the menu item is selected by the user
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see SelectionListener
 * @see #removeSelectionListener
 * @see SelectionEvent
 */
public void addSelectionListener (SelectionListener listener) {
	checkWidget();
	if (listener == 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);
}

@Override
protected void checkSubclass () {
	if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
}

@Override
void createHandle (int index) {
	state |= HANDLE;
	byte [] buffer = new byte [1];
	int bits = SWT.CHECK | SWT.RADIO | SWT.PUSH | SWT.SEPARATOR | SWT.CASCADE;

	if (GTK.GTK4) {
		modelHandle = OS.g_menu_new();

		switch (style & bits) {
			case SWT.SEPARATOR:
				handle = OS.g_menu_item_new_section(null, modelHandle);
				parent.sectionModelHandle = modelHandle;
				break;
			case SWT.RADIO:
				Menu popoverMenuWidget = parent;
				while (popoverMenuWidget.actionGroup == 0) {
					popoverMenuWidget = popoverMenuWidget.cascade.parent;
				}

				long stringVariantType = OS.g_variant_type_new(OS.G_VARIANT_TYPE_STRING);
				actionHandle = OS.g_simple_action_new_stateful(
						Converter.javaStringToCString(String.valueOf(this.hashCode())),
						stringVariantType,
						OS.g_variant_new_string(Converter.javaStringToCString("untoggled")));
				OS.g_action_map_add_action(popoverMenuWidget.actionGroup, actionHandle);
				actionName = String.valueOf(popoverMenuWidget.hashCode()) + "." + String.valueOf(this.hashCode()) + "::toggled";
				handle = OS.g_menu_item_new(null, Converter.javaStringToCString(actionName));
				OS.g_variant_type_free(stringVariantType);
				break;
			case SWT.CASCADE:
				handle = OS.g_menu_item_new_submenu(null, modelHandle);
				break;
			case SWT.PUSH:
			default:
				popoverMenuWidget = parent;
				while (popoverMenuWidget.actionGroup == 0) {
					popoverMenuWidget = popoverMenuWidget.cascade.parent;
				}

				actionHandle = OS.g_simple_action_new(Converter.javaStringToCString(String.valueOf(this.hashCode())), 0);
				OS.g_action_map_add_action(popoverMenuWidget.actionGroup, actionHandle);
				actionName = String.valueOf(popoverMenuWidget.hashCode()) + "." + String.valueOf(this.hashCode());
				handle = OS.g_menu_item_new(null, Converter.javaStringToCString(actionName));
				break;
		}

		if ((style & SWT.SEPARATOR) != 0) {
			OS.g_menu_insert_item(parent.modelHandle, index, handle);
		} else {
			OS.g_menu_insert_item(parent.sectionModelHandle, index, handle);
		}

		parentMenuPosition = index;
		parent.items.add(this);
	} else {
		switch (style & bits) {
			case SWT.SEPARATOR:
				handle = GTK.gtk_separator_menu_item_new ();
				if (handle == 0) error (SWT.ERROR_NO_HANDLES);
				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 = GTK.gtk_radio_menu_item_new (0);
				if (groupHandle == 0) error (SWT.ERROR_NO_HANDLES);
				OS.g_object_ref_sink (groupHandle);
				long group = GTK.gtk_radio_menu_item_get_group (groupHandle);
				handle = GTK.gtk_radio_menu_item_new (group);
				if (handle == 0) error (SWT.ERROR_NO_HANDLES);

				labelHandle = GTK.gtk_accel_label_new (buffer);
				if (labelHandle == 0) error (SWT.ERROR_NO_HANDLES);

				boxHandle = gtk_box_new (GTK.GTK_ORIENTATION_HORIZONTAL, false, 6);
				if (boxHandle == 0) error (SWT.ERROR_NO_HANDLES);

				if (OS.SWT_PADDED_MENU_ITEMS) {
					imageHandle = GTK.gtk_image_new ();
					if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
				}
				break;
			case SWT.CHECK:
				handle = GTK.gtk_check_menu_item_new ();
				if (handle == 0) error (SWT.ERROR_NO_HANDLES);

				labelHandle = GTK.gtk_accel_label_new (buffer);
				if (labelHandle == 0) error (SWT.ERROR_NO_HANDLES);

				boxHandle = gtk_box_new (GTK.GTK_ORIENTATION_HORIZONTAL, false, 6);
				if (boxHandle == 0) error (SWT.ERROR_NO_HANDLES);

				if (OS.SWT_PADDED_MENU_ITEMS) {
					imageHandle = GTK.gtk_image_new ();
					if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
				}
				break;
			// This case now needs to be handled due to double padding. When double padded
			// menus are used, the "head" menu item (such as File, Edit, Help, etc.) should
			// not be padded. We only care about this in Gtk3.
			case SWT.CASCADE:
				handle = GTK.gtk_menu_item_new ();
				if (handle == 0) error (SWT.ERROR_NO_HANDLES);

				labelHandle = GTK.gtk_accel_label_new (buffer);
				if (labelHandle == 0) error (SWT.ERROR_NO_HANDLES);

				boxHandle = gtk_box_new (GTK.GTK_ORIENTATION_HORIZONTAL, false, 6);
				if (boxHandle == 0) error (SWT.ERROR_NO_HANDLES);
				if ((parent.style & bits) == SWT.BAR) {
					break;
				}
				if (OS.SWT_PADDED_MENU_ITEMS) {
					imageHandle = GTK.gtk_image_new ();
					if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
				}
				break;
			case SWT.PUSH:
			default:
				handle = GTK.gtk_menu_item_new ();
				if (handle == 0) error (SWT.ERROR_NO_HANDLES);

				labelHandle = GTK.gtk_accel_label_new (buffer);
				if (labelHandle == 0) error (SWT.ERROR_NO_HANDLES);

				boxHandle = gtk_box_new (GTK.GTK_ORIENTATION_HORIZONTAL, false, 6);
				if (boxHandle == 0) error (SWT.ERROR_NO_HANDLES);

				if (OS.SWT_PADDED_MENU_ITEMS) {
					imageHandle = GTK.gtk_image_new ();
					if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
				}
				break;
		}
		if (imageHandle != 0) {
			if (OS.SWT_PADDED_MENU_ITEMS) {
				GTK.gtk_image_set_pixel_size (imageHandle, 16);
			}
			if (GTK.GTK4) {
				GTK.gtk_box_append(boxHandle, imageHandle);
			} else {
				GTK.gtk_container_add (boxHandle, imageHandle);
				GTK.gtk_widget_show (imageHandle);
			}
		}
		if (labelHandle != 0) {
			GTK.gtk_label_set_xalign (labelHandle, 0);
			GTK.gtk_widget_set_halign (labelHandle, GTK.GTK_ALIGN_FILL);
			gtk_box_pack_end (boxHandle, labelHandle, true, true, 0);
			GTK.gtk_widget_show (labelHandle);
		}
		if (boxHandle != 0) {
			if (GTK.GTK4) {
				// TODO: need to implement how menu items will be populated, currently no value for handle
			} else {
				GTK.gtk_container_add (handle, boxHandle);
				GTK.gtk_widget_show (boxHandle);
			}
		}
		if ((style & SWT.SEPARATOR) == 0) {
			if (boxHandle == 0) {
				labelHandle = GTK.gtk_bin_get_child (handle);
			}
			GTK.gtk_accel_label_set_accel_widget (labelHandle, 0);
		}
		long parentHandle = parent.handle;
		boolean enabled = GTK.gtk_widget_get_sensitive (parentHandle);
		if (!enabled) GTK.gtk_widget_set_sensitive (parentHandle, true);
		GTK.gtk_menu_shell_insert (parentHandle, handle, index);
		if (!enabled) GTK.gtk_widget_set_sensitive (parentHandle, false);
		GTK.gtk_widget_show (handle);
	}
}

void fixMenus (Decorations newParent) {
	if (menu != null && !menu.isDisposed() && !newParent.isDisposed()) menu.fixMenus (newParent);
}

/**
 * Returns the widget accelerator.  An accelerator is the bit-wise
 * OR of zero or more modifier masks and a key. Examples:
 * <code>SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2</code>.
 * The default value is zero, indicating that the menu item does
 * not have an accelerator.
 *
 * @return the accelerator or 0
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getAccelerator () {
	checkWidget();
	return accelerator;
}

long getAccelGroup () {
	Menu menu = parent;
	while (menu != null && menu.cascade != null) {
		menu = menu.cascade.parent;
	}
	if (menu == null) return 0;
	Decorations shell = menu.parent;
	if (shell == null) return 0;
	return shell.menuBar == menu ? shell.accelGroup : 0;
}

/*public*/ Rectangle getBounds () {
	checkWidget();
	if (!GTK.gtk_widget_get_mapped (handle)) {
		return new Rectangle (0, 0, 0, 0);
	}
	GtkAllocation allocation = new GtkAllocation ();
	GTK.gtk_widget_get_allocation (handle, allocation);
	int x = allocation.x;
	int y = allocation.y;
	int width = allocation.width;
	int height = allocation.height;
	return new Rectangle (x, y, width, height);
}

/**
 * Returns <code>true</code> if the receiver is enabled, and
 * <code>false</code> 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 <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #isEnabled
 */
public boolean getEnabled () {
	checkWidget();

	if (GTK.GTK4) {
		return OS.g_action_get_enabled(actionHandle);
	} else {
		return GTK.gtk_widget_get_sensitive(handle);
	}
}

/**
 * Gets the identifier associated with the receiver.
 *
 * @return the receiver's identifier
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.7
 */
public int getID () {
	checkWidget();
	return userId;
}

/**
 * Returns the receiver's cascade menu if it has one or null
 * if it does not. Only <code>CASCADE</code> 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 <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Menu getMenu () {
	checkWidget();
	return menu;
}

@Override
String getNameText () {
	if ((style & SWT.SEPARATOR) != 0) return "|";
	return super.getNameText ();
}

/**
 * Returns the receiver's parent, which must be a <code>Menu</code>.
 *
 * @return the receiver's parent
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Menu getParent () {
	checkWidget();
	return parent;
}

/**
 * Returns <code>true</code> if the receiver is selected,
 * and false otherwise.
 * <p>
 * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
 * it is selected when it is checked.
 *
 * @return the selection state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public boolean getSelection () {
	checkWidget();
	if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return false;

	if (GTK.GTK4) {
		long gVariantState = OS.g_action_get_state(actionHandle);
		String stateString = Converter.cCharPtrToJavaString(OS.g_variant_get_string(gVariantState, null), false);
		return stateString.equals("toggled");
	} else {
		return GTK.gtk_check_menu_item_get_active(handle);
	}
}

/**
 * Returns the receiver's tool tip text, or null if it has not been set.
 *
 * @return the receiver's tool tip text
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.104
 */
public String getToolTipText () {
	checkWidget();
	return toolTipText;
}

@Override
long gtk_activate (long widget) {
	if ((style & SWT.CASCADE) != 0 && menu != 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;
	if ((style & SWT.RADIO) != 0) {
		if ((parent.getStyle () & SWT.NO_RADIO_GROUP) == 0) {
			selectRadio ();
		}
	}

	sendSelectionEvent (SWT.Selection);
	return 0;
}

@Override
long gtk_select (long item) {
	parent.selectedItem = this;
	sendEvent (SWT.Arm);
	return 0;
}

@Override
long gtk_show_help (long widget, long helpType) {
	boolean handled = hooks (SWT.Help);
	if (handled) {
		postEvent (SWT.Help);
	} else {
		handled = parent.sendHelpEvent (helpType);
	}
	if (handled) {
		// TODO: GTK4 there is no idea of a menu shell
		GTK.gtk_menu_shell_deactivate (parent.handle);
		return 1;
	}
	return 0;
}

@Override
void hookEvents () {
	super.hookEvents ();

	if (GTK.GTK4) {
		if ((style & SWT.SEPARATOR) == 0) {
			OS.g_signal_connect(actionHandle, OS.activate, display.activateProc, handle);
		}
	} else {
		OS.g_signal_connect_closure(handle, OS.activate, display.getClosure (ACTIVATE), false);
		OS.g_signal_connect_closure (handle, OS.select, display.getClosure (SELECT), false);
		OS.g_signal_connect_closure_by_id (handle, display.signalIds [SHOW_HELP], 0, display.getClosure (SHOW_HELP), false);
	}
}

/**
 * Returns <code>true</code> if the receiver is enabled and all
 * of the receiver's ancestors are enabled, and <code>false</code>
 * 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 <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #getEnabled
 */
public boolean isEnabled () {
	return getEnabled () && parent.isEnabled ();
}

@Override
void releaseChildren (boolean destroy) {
	if (menu != null) {
		menu.release (false);
		menu = null;
	}
	super.releaseChildren (destroy);
}

@Override
void releaseParent () {
	super.releaseParent ();
	if (menu != null) {
		if (menu.selectedItem == this) menu.selectedItem = null;
		menu.dispose ();
	}
	menu = null;
}

@Override
void releaseWidget () {
	super.releaseWidget ();
	long accelGroup = getAccelGroup ();
	if (accelGroup != 0) removeAccelerator (accelGroup);
	if (groupHandle != 0) OS.g_object_unref (groupHandle);
	groupHandle = 0;
	accelerator = 0;
	parent = null;
}

void removeAccelerator (long accelGroup) {
	updateAccelerator (accelGroup, false);
}

void removeAccelerators (long accelGroup) {
	removeAccelerator (accelGroup);
	if (menu != 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 <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see ArmListener
 * @see #addArmListener
 */
public void removeArmListener (ArmListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == 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 <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see HelpListener
 * @see #addHelpListener
 */
public void removeHelpListener (HelpListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == 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 <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see SelectionListener
 * @see #addSelectionListener
 */
public void removeSelectionListener (SelectionListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Selection, listener);
	eventTable.unhook (SWT.DefaultSelection,listener);
}
@Override
void reskinChildren (int flags) {
	if (menu != null) {
		menu.reskin (flags);
	}
	super.reskinChildren (flags);
}
void selectRadio () {
	int index = 0;
	MenuItem [] items = parent.getItems ();
	while (index < items.length && items [index] != 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:
 * <code>SWT.MOD1 | SWT.MOD2 | 'T', SWT.MOD3 | SWT.F2</code>.
 * <code>SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2</code>.
 * 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 <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setAccelerator (int accelerator) {
	checkWidget();
	if (this.accelerator == accelerator) return;

	if (GTK.GTK4) {
		if (shortcutHandle != 0) {
			GTK.gtk_shortcut_controller_remove_shortcut(parent.shortcutController, shortcutHandle);
		}

		this.accelerator = accelerator;
		addShortcut(accelerator);
	} else {
		long accelGroup = getAccelGroup();
		if (accelGroup != 0) removeAccelerator(accelGroup);
		this.accelerator = accelerator;
		if (accelGroup != 0) addAccelerator(accelGroup);
	}
}

void addShortcut(int accelerator) {
	if (accelerator == 0 || !getEnabled()) return;
	if ((accelerator & SWT.COMMAND) != 0) return;

	int mask = 0;
	if ((accelerator & SWT.ALT) != 0) mask |= GDK.GDK_MOD1_MASK;
	if ((accelerator & SWT.SHIFT) != 0) mask |= GDK.GDK_SHIFT_MASK;
	if ((accelerator & SWT.CONTROL) != 0) mask |= GDK.GDK_CONTROL_MASK;

	int keyval = accelerator & SWT.KEY_MASK;
	int newKey = Display.untranslateKey (keyval);
	if (newKey != 0) {
		keyval = newKey;
	} else {
		switch (keyval) {
			case '\r': keyval = GDK.GDK_Return; break;
			default: keyval = Converter.wcsToMbcs ((char) keyval);
		}
	}

	if (keyval != 0) {
		shortcutHandle = GTK.gtk_shortcut_new(
				GTK.gtk_keyval_trigger_new(keyval, mask),
				GTK.gtk_named_action_new(Converter.javaStringToCString(actionName))
			);
		if (shortcutHandle == 0) error(SWT.ERROR_NO_HANDLES);
		GTK.gtk_shortcut_controller_add_shortcut(parent.shortcutController, shortcutHandle);
	}
}

/**
 * Enables the receiver if the argument is <code>true</code>,
 * 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 <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setEnabled (boolean enabled) {
	checkWidget();

	if (GTK.GTK4) {
		OS.g_simple_action_set_enabled(actionHandle, enabled);
	} else {
		if (GTK.gtk_widget_get_sensitive(handle) == enabled) return;
		long accelGroup = getAccelGroup();
		if (accelGroup != 0) removeAccelerator(accelGroup);
		GTK.gtk_widget_set_sensitive(handle, enabled);
		if (accelGroup != 0) addAccelerator(accelGroup);
	}
}

/**
 * Sets the identifier associated with the receiver to the argument.
 *
 * @param id the new identifier. This must be a non-negative value. System-defined identifiers are negative values.
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 *    <li>ERROR_INVALID_ARGUMENT - if called with an negative-valued argument.</li>
 * </ul>
 *
 * @since 3.7
 */
public void setID (int id) {
	checkWidget();
	if (id < 0) error(SWT.ERROR_INVALID_ARGUMENT);
	userId = id;
}

/**
 * Sets the receiver's image to the argument, which may be
 * null indicating that no image should be displayed.
 * <p>
 * Note: This operation is a <em>HINT</em> and is not supported on
 * platforms that do not have this concept (for example, Windows NT).
 * Furthermore, some platforms (such as GTK2), cannot display both
 * a check box and an image at the same time.  Instead, they hide
 * the image and display the check box. Some platforms (such as GTK3)
 * support images alongside check boxes.
 * </p>
 *
 * @param image the image to display on the receiver (may be null)
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
@Override
public void setImage (Image image) {
	checkWidget();
	if ((style & SWT.SEPARATOR) != 0) return;
	super.setImage (image);

	if (image != null) {
		ImageList imageList = parent.imageList;
		if (imageList == null) imageList = parent.imageList = new ImageList ();
		int imageIndex = imageList.indexOf (image);
		long pixbuf = 0;
		if (imageIndex == -1) {
			imageIndex = imageList.add (image);
			pixbuf = imageList.getPixbuf (imageIndex);
			/*
			 * Bug in GTK the default renderer does scale again on pixbuf.
			 * Need to scaledown here and no need to scaledown id device scale is 1
			 *
			 * We should resize pixbuf and update pixbuf array in the imagelist only if
			 * the image is added to the imagelist in this call. If the image is already
			 * add imageList.getPixbuf returns resized pixbuf.
			 */
			if (DPIUtil.useCairoAutoScale()) {
				Rectangle imgSize = image.getBounds();
				long scaledPixbuf = GDK.gdk_pixbuf_scale_simple(pixbuf, imgSize.width, imgSize.height, GDK.GDK_INTERP_BILINEAR);
				if (scaledPixbuf !=0) {
					pixbuf = scaledPixbuf;
				}
				imageList.replacePixbuf(imageIndex, pixbuf);
			}
		} else {
			imageList.put (imageIndex, image);
			pixbuf = imageList.getPixbuf (imageIndex);
		}

		if (!GTK.GTK4 && !GTK.GTK_IS_MENU_ITEM (handle)) return;
		if (OS.SWT_PADDED_MENU_ITEMS && imageHandle != 0) {
			GTK.gtk_image_set_from_surface(imageHandle, image.surface);
		} else {
			if (imageHandle == 0 && boxHandle != 0) {
				imageHandle = GTK.gtk_image_new_from_pixbuf (pixbuf);
				GTK.gtk_container_add (boxHandle, imageHandle);
				GTK.gtk_box_reorder_child (boxHandle, imageHandle, 0);
			} else {
				GTK.gtk_image_set_from_surface(imageHandle, image.surface);
			}
			if (boxHandle == 0) error (SWT.ERROR_NO_HANDLES);
		}
		if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
		GTK.gtk_widget_show (imageHandle);
	} else {
		if (imageHandle != 0 && boxHandle != 0) {
			if (OS.SWT_PADDED_MENU_ITEMS) {
				GTK.gtk_container_remove(boxHandle, imageHandle);
				imageHandle = GTK.gtk_image_new ();
				if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
				GTK.gtk_image_set_pixel_size (imageHandle, 16);
				GTK.gtk_container_add (boxHandle, imageHandle);
				GTK.gtk_widget_show (imageHandle);
			} else {
				GTK.gtk_container_remove(boxHandle, imageHandle);
				imageHandle = 0;
			}
		}
	}
}

/**
 * Sets the receiver's pull down menu to the argument.
 * Only <code>CASCADE</code> 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.
 * <p>
 * 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.
 * </p>
 *
 * @param menu the new pull down menu
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_MENU_NOT_DROP_DOWN - if the menu is not a drop down menu</li>
 *    <li>ERROR_MENUITEM_NOT_CASCADE - if the menu item is not a <code>CASCADE</code></li>
 *    <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
 *    <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setMenu (Menu menu) {
	checkWidget ();

	/* Check to make sure the new menu is valid */
	if ((style & SWT.CASCADE) == 0) {
		error (SWT.ERROR_MENUITEM_NOT_CASCADE);
	}
	if (menu != null) {
		if ((menu.style & SWT.DROP_DOWN) == 0) {
			error (SWT.ERROR_MENU_NOT_DROP_DOWN);
		}
		if (menu.parent != parent.parent) {
			error (SWT.ERROR_INVALID_PARENT);
		}
	}

	/* Assign the new menu */
	Menu oldMenu = this.menu;
	if (oldMenu == menu) return;

	if (GTK.GTK4) {
		if (menu != null) {
			menu.cascade = this;
			OS.g_menu_item_set_submenu(handle, menu.modelHandle);
		} else {
			oldMenu.cascade = null;
			OS.g_menu_item_set_submenu(handle, 0);
		}

		OS.g_menu_remove(parent.sectionModelHandle, parentMenuPosition);
		OS.g_menu_insert_item(parent.sectionModelHandle, parentMenuPosition, handle);
	} else {
		long accelGroup = getAccelGroup ();
		if (accelGroup != 0) removeAccelerators (accelGroup);
		if (oldMenu != 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);
			GTK.gtk_menu_item_set_submenu (handle, 0);
		}
		if ((this.menu = menu) != null) {
			menu.cascade = this;
			GTK.gtk_menu_item_set_submenu (handle, menu.handle);
		}
		if (accelGroup != 0) addAccelerators (accelGroup);
	}
}

@Override
void setOrientation (boolean create) {
	super.setOrientation (create);
	if ((parent.style & SWT.RIGHT_TO_LEFT) != 0 || !create) {
		int dir = (parent.style & SWT.RIGHT_TO_LEFT) != 0 ? GTK.GTK_TEXT_DIR_RTL : GTK.GTK_TEXT_DIR_LTR;
		GTK.gtk_widget_set_direction (handle, dir);
		GTK.gtk_container_forall (handle, display.setDirectionProc, dir);
		if (menu != null) menu._setOrientation (parent.style & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT));
	}
}

boolean setRadioSelection (boolean value) {
	if ((style & SWT.RADIO) == 0) return false;
	if (getSelection () != value) {
		setSelection (value);
		sendSelectionEvent (SWT.Selection);
	}
	return true;
}

/**
 * Sets the selection state of the receiver.
 * <p>
 * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
 * it is selected when it is checked.
 *
 * @param selected the new selection state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setSelection (boolean selected) {
	checkWidget();
	if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return;

	if (GTK.GTK4) {
		OS.g_simple_action_set_state(actionHandle, OS.g_variant_new_string(Converter.javaStringToCString(selected ? "toggled" : "untoggled")));
	} else {
		OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, ACTIVATE);
		GTK.gtk_check_menu_item_set_active (handle, selected);
		if ((style & SWT.RADIO) != 0) GTK.gtk_check_menu_item_set_active (groupHandle, !selected);
		OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, ACTIVATE);
	}
}

/**
 * Sets the receiver's text. The string may include
 * the mnemonic character and accelerator text.
 * <p>
 * Mnemonics are indicated by an '&amp;' 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 '&amp;' can be
 * escaped by doubling it in the string, causing a single
 * '&amp;' to be displayed.
 * </p>
 * <p>
 * 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.
 * </p>
 *
 * @param string the new text
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the text is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #setAccelerator
 */
@Override
public void setText (String string) {
	checkWidget();
	if (string == null) error(SWT.ERROR_NULL_ARGUMENT);
	if ((style & SWT.SEPARATOR) != 0) return;
	if (text.equals(string)) return;
	super.setText(string);

	int index = string.indexOf('\t');
	if (index != -1) {
		string = string.substring(0, index);
	}
	char[] chars = fixMnemonic(string);
	byte[] buffer = Converter.wcsToMbcs(chars, true);

	if (GTK.GTK4) {
		OS.g_menu_item_set_label(handle, buffer);
		MaskKeysym maskKeysym = getMaskKeysym();
		if (maskKeysym != null) {
			OS.g_menu_item_set_attribute(handle,
					Converter.javaStringToCString("accel"),
					Converter.javaStringToCString("s"),
					GTK.gtk_accelerator_name(maskKeysym.keysym, maskKeysym.mask)
				);
		}
		OS.g_menu_remove(parent.sectionModelHandle, parentMenuPosition);
		OS.g_menu_insert_item(parent.sectionModelHandle, parentMenuPosition, handle);
	} else {
		if (labelHandle != 0 && GTK.GTK_IS_LABEL (labelHandle)) {
			GTK.gtk_label_set_text_with_mnemonic (labelHandle, buffer);
			if (GTK.GTK_IS_ACCEL_LABEL (labelHandle)) {
				MaskKeysym maskKeysym = getMaskKeysym();
				if (maskKeysym != null) {
					GTK.gtk_accel_label_set_accel_widget (labelHandle, handle);
					GTK.gtk_accel_label_set_accel (labelHandle,
							maskKeysym.keysym, maskKeysym.mask);
				}
				// A workaround for Ubuntu Unity global menu
				OS.g_signal_emit_by_name(handle, OS.accel_closures_changed);
			}
		}
	}
}

/**
 * Sets the receiver's tool tip text to the argument, which
 * may be null indicating that the default tool tip for the
 * control will be shown. For a menu item that has a default
 * tool tip, setting
 * the tool tip text to an empty string replaces the default,
 * causing no tool tip text to be shown.
 * <p>
 * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
 * To display a single '&amp;' in the tool tip, the character '&amp;' can be
 * escaped by doubling it in the string.
 * </p>
 * <p>
 * NOTE: Tooltips are currently not shown for top-level menu items in the
 * {@link Shell#setMenuBar(Menu) shell menubar} on Windows, Mac, and Ubuntu Unity desktop.
 * </p>
 * <p>
 * NOTE: This operation is a hint and behavior is platform specific, on Windows
 * for CJK-style mnemonics of the form " (&amp;C)" at the end of the tooltip text
 * are not shown in tooltip.
 * </p>
 * @param toolTip the new tool tip text (or null)
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.104
 */
public void setToolTipText (String toolTip) {
	checkWidget();
	if (toolTip != null && (toolTip.trim().length() == 0 || toolTip.equals (toolTipText))) return;

	this.parent.getShell().setToolTipText (handle, (toolTipText = toolTip));
}

void updateAccelerator (long accelGroup, boolean add) {
	if (accelerator == 0 || !getEnabled ()) return;
	if ((accelerator & SWT.COMMAND) != 0) return;
	int mask = 0;
	if ((accelerator & SWT.ALT) != 0) mask |= GDK.GDK_MOD1_MASK;
	if ((accelerator & SWT.SHIFT) != 0) mask |= GDK.GDK_SHIFT_MASK;
	if ((accelerator & SWT.CONTROL) != 0) mask |= GDK.GDK_CONTROL_MASK;
	int keysym = accelerator & SWT.KEY_MASK;
	int newKey = Display.untranslateKey (keysym);
	if (newKey != 0) {
		keysym = newKey;
	} else {
		switch (keysym) {
			case '\r': keysym = GDK.GDK_Return; break;
			default: keysym = Converter.wcsToMbcs ((char) keysym);
		}
	}
	/* When accel_key is zero, it causes GTK warnings */
	if (keysym != 0) {
		if (add) {
			GTK.gtk_widget_add_accelerator(handle, OS.activate, accelGroup, keysym, mask, GTK.GTK_ACCEL_VISIBLE);
		} else {
			GTK.gtk_widget_remove_accelerator(handle, accelGroup, keysym, mask);
		}
	}
}

private class MaskKeysym {
	int mask = 0;
	int keysym = 0;
}

private MaskKeysym getMaskKeysym() {
	if (text == null) return null;
	MaskKeysym maskKeysym = new MaskKeysym();
	int accelIndex = text.indexOf ('\t');
	if (accelIndex == -1) return null;
	int start = accelIndex + 1;
	int plusIndex = text.indexOf('+', start);
	while (plusIndex != -1) {
		String maskStr = text.substring(start, plusIndex);
		if (maskStr.equals("Ctrl")) maskKeysym.mask |= GDK.GDK_CONTROL_MASK;
		if (maskStr.equals("Shift")) maskKeysym.mask |= GDK.GDK_SHIFT_MASK;
		if (maskStr.equals("Alt")) maskKeysym.mask |= GDK.GDK_MOD1_MASK;
		start = plusIndex + 1;
		plusIndex = text.indexOf('+', start);
	}
	if ("Enter".equals(text.substring(start))) {
		maskKeysym.keysym = GDK.GDK_ISO_Enter;
	}
	switch (text.length() - start) {
		case 1:
			maskKeysym.keysym = text.charAt(start);
			maskKeysym.keysym = Converter.wcsToMbcs ((char) maskKeysym.keysym);
			break;
		case 2:
			if (text.charAt(start) == 'F') {
				switch (text.charAt(start + 1)) {
					case '1': maskKeysym.keysym = GDK.GDK_F1; break;
					case '2': maskKeysym.keysym = GDK.GDK_F2; break;
					case '3': maskKeysym.keysym = GDK.GDK_F3; break;
					case '4': maskKeysym.keysym = GDK.GDK_F4; break;
					case '5': maskKeysym.keysym = GDK.GDK_F5; break;
					case '6': maskKeysym.keysym = GDK.GDK_F6; break;
					case '7': maskKeysym.keysym = GDK.GDK_F7; break;
					case '8': maskKeysym.keysym = GDK.GDK_F8; break;
					case '9': maskKeysym.keysym = GDK.GDK_F9; break;
				}
			}
			break;
		case 3:
			if (text.charAt(start) == 'F' && text.charAt(start + 1) == '1') {
				switch (text.charAt(start + 2)) {
					case '0': maskKeysym.keysym = GDK.GDK_F10; break;
					case '1': maskKeysym.keysym = GDK.GDK_F11; break;
					case '2': maskKeysym.keysym = GDK.GDK_F12; break;
					case '3': maskKeysym.keysym = GDK.GDK_F13; break;
					case '4': maskKeysym.keysym = GDK.GDK_F14; break;
					case '5': maskKeysym.keysym = GDK.GDK_F15; break;
				}
			}
			break;
	}
	return maskKeysym;
}
boolean updateAcceleratorText (boolean show) {
	if (accelerator != 0) return false;
	MaskKeysym maskKeysym = null;
	if (show) {
		maskKeysym = getMaskKeysym();
	}
	if (maskKeysym == null) return true;
	if (maskKeysym.keysym != 0) {
		long accelGroup = getAccelGroup ();
		if (show) {
			GTK.gtk_widget_add_accelerator (handle, OS.activate, accelGroup, maskKeysym.keysym, maskKeysym.mask, GTK.GTK_ACCEL_VISIBLE);
		} else {
			GTK.gtk_widget_remove_accelerator (handle, accelGroup, maskKeysym.keysym, maskKeysym.mask);
		}
	}
	return maskKeysym.keysym != 0;
}

@Override
long dpiChanged(long object, long arg0) {
	super.dpiChanged(object, arg0);

	if (image != null) {
		image.internal_gtk_refreshImageForZoom();
		setImage(image);
	}

	return 0;
}

}
