/*******************************************************************************
 * Copyright (c) 2000, 2018 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
 *******************************************************************************/
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 are user interface objects that contain
 * menu items.
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>BAR, DROP_DOWN, POP_UP, NO_RADIO_GROUP</dd>
 * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
 * <dt><b>Events:</b></dt>
 * <dd>Help, Hide, Show </dd>
 * </dl>
 * <p>
 * Note: Only one of BAR, DROP_DOWN and POP_UP may be specified.
 * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT 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/snippets/#menu">Menu snippets</a>
 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
 * @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 Menu extends Widget {
	int x, y;
	boolean hasLocation;
	MenuItem cascade, selectedItem;
	Decorations parent;
	long /*int*/ imItem, imSeparator, imHandle;
	ImageList imageList;
	int poppedUpCount;

/**
 * Constructs a new instance of this class given its parent,
 * and sets the style for the instance so that the instance
 * will be a popup menu on the given parent's shell.
 * <p>
 * After constructing a menu, it can be set into its parent
 * using <code>parent.setMenu(menu)</code>.  In this case, the parent may
 * be any control in the same widget tree as the parent.
 * </p>
 *
 * @param parent a control which will be the parent of the new instance (cannot be null)
 *
 * @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#POP_UP
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public Menu (Control parent) {
	this (checkNull (parent).menuShell (), SWT.POP_UP);
}

/**
 * Constructs a new instance of this class given its parent
 * (which must be a <code>Decorations</code>) and a style value
 * describing its behavior and appearance.
 * <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><p>
 * After constructing a menu or menuBar, it can be set into its parent
 * using <code>parent.setMenu(menu)</code> or <code>parent.setMenuBar(menuBar)</code>.
 * </p>
 *
 * @param parent a decorations control which will be the parent of the new instance (cannot be null)
 * @param style the style of menu 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#BAR
 * @see SWT#DROP_DOWN
 * @see SWT#POP_UP
 * @see SWT#NO_RADIO_GROUP
 * @see SWT#LEFT_TO_RIGHT
 * @see SWT#RIGHT_TO_LEFT
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public Menu (Decorations parent, int style) {
	super (parent, checkStyle (style));
	this.parent = parent;
	createWidget (0);
}

/**
 * Constructs a new instance of this class given its parent
 * (which must be a <code>Menu</code>) and sets the style
 * for the instance so that the instance will be a drop-down
 * menu on the given parent's parent.
 * <p>
 * After constructing a drop-down menu, it can be set into its parentMenu
 * using <code>parentMenu.setMenu(menu)</code>.
 * </p>
 *
 * @param parentMenu a menu which will be the parent of the new instance (cannot be null)
 *
 * @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#DROP_DOWN
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public Menu (Menu parentMenu) {
	this (checkNull (parentMenu).parent, SWT.DROP_DOWN);
}

/**
 * Constructs a new instance of this class given its parent
 * (which must be a <code>MenuItem</code>) and sets the style
 * for the instance so that the instance will be a drop-down
 * menu on the given parent's parent menu.
 * <p>
 * After constructing a drop-down menu, it can be set into its parentItem
 * using <code>parentItem.setMenu(menu)</code>.
 * </p>
 *
 * @param parentItem a menu item which will be the parent of the new instance (cannot be null)
 *
 * @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#DROP_DOWN
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public Menu (MenuItem parentItem) {
	this (checkNull (parentItem).parent);
}

static Control checkNull (Control control) {
	if (control == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	return control;
}

static Menu checkNull (Menu menu) {
	if (menu == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	return menu;
}

static MenuItem checkNull (MenuItem item) {
	if (item == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
	return item;
}

static int checkStyle (int style) {
	return checkBits (style, SWT.POP_UP, SWT.BAR, SWT.DROP_DOWN, 0, 0, 0);
}

void _setVisible (boolean visible) {
	if (visible == GTK.gtk_widget_get_mapped (handle)) return;
	if (visible) {
		sendEvent (SWT.Show);
		if (getItemCount () != 0) {
			/*
			* Feature in GTK. ON_TOP shells will send out
			* SWT.Deactivate whenever a context menu is shown.
			* The fix is to prevent the menu from taking focus
			* when it is being shown in an ON_TOP shell.
			*/
			if ((parent._getShell ().style & SWT.ON_TOP) != 0) {
				GTK.gtk_menu_shell_set_take_focus (handle, false);
			}
			if (GTK.GTK_VERSION < OS.VERSION(3, 22, 0)) {
				long /*int*/ address = 0;
				hasLocation = false;
				long /*int*/ data = 0;
				/*
				* Popup-menu to the status icon should be aligned to
				* Tray rather than to cursor position. There is a
				* possibility (unlikely) that TrayItem might have
				* been disposed in the listener, for which case
				* the menu should be shown in the cursor position.
				*/
				TrayItem item = display.currentTrayItem;
				if (item != null && !item.isDisposed()) {
					 data = item.handle;
					 address = GTK.gtk_status_icon_position_menu_func ();
				}
				/*
				* 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.
				*/
				GTK.gtk_menu_popup (handle, 0, 0, address, data, 0, display.getLastEventTime ());
			}
			else {
				/*
				 *  GTK Feature: gtk_menu_popup is deprecated as of GTK3.22 and the new method gtk_menu_popup_at_pointer
				 *  requires an event to hook on to. This requires the popup & events related to the menu be handled
				 *  immediately and not as a post event in display, requiring the current event.
				 */
				long /*int*/ eventPtr = GTK.gtk_get_current_event();
				if (eventPtr == 0) {
					eventPtr = GDK.gdk_event_new(GDK.GDK_BUTTON_PRESS);
					GdkEventButton event = new GdkEventButton ();
					event.type = GDK.GDK_BUTTON_PRESS;
					// Only assign a window on X11, as on Wayland the window is that of the mouse pointer
					if (OS.isX11()) {
						event.window = OS.g_object_ref(GTK.gtk_widget_get_window (getShell().handle));
					}
					event.device = GDK.gdk_get_pointer(GDK.gdk_display_get_default ());
					event.time = display.getLastEventTime ();
					OS.memmove (eventPtr, event, GdkEventButton.sizeof);
				}
				adjustParentWindow(eventPtr);
				verifyMenuPosition(getItemCount());
				GTK.gtk_menu_popup_at_pointer (handle, eventPtr);
				GDK.gdk_event_free (eventPtr);
			}
			poppedUpCount = getItemCount();
		} else {
			sendEvent (SWT.Hide);
		}
	} else {
		GTK.gtk_menu_popdown (handle);
	}
}

void addAccelerators (long /*int*/ accelGroup) {
	MenuItem [] items = getItems ();
	for (int i = 0; i < items.length; i++) {
		MenuItem item = items[i];
		item.addAccelerators (accelGroup);
	}
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when menus are hidden or shown, by sending it
 * one of the messages defined in the <code>MenuListener</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 MenuListener
 * @see #removeMenuListener
 */
public void addMenuListener (MenuListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Hide,typedListener);
	addListener (SWT.Show,typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when 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);
}

@Override
void createHandle (int index) {
	state |= HANDLE;
	if ((style & SWT.BAR) != 0) {
		handle = GTK.gtk_menu_bar_new ();
		if (handle == 0) error (SWT.ERROR_NO_HANDLES);
		long /*int*/ vboxHandle = parent.vboxHandle;
		GTK.gtk_container_add (vboxHandle, handle);
		GTK.gtk_box_set_child_packing (vboxHandle, handle, false, true, 0, GTK.GTK_PACK_START);
	} else {
		handle = GTK.gtk_menu_new ();
		if (handle == 0) error (SWT.ERROR_NO_HANDLES);
	}
}

void createIMMenu (long /*int*/ imHandle) {
	boolean showInputMethod = false;
	long /*int*/ settings = GTK.gtk_settings_get_default ();
	if (settings != 0 && GTK.GTK_VERSION < OS.VERSION (3, 10, 0)) {
		int [] buffer = new int [1];
		OS.g_object_get (settings, GTK.gtk_show_input_method_menu, buffer, 0);
		showInputMethod = buffer[0] != 0;
	}
	if (imHandle == 0 || !showInputMethod) {
		this.imHandle = 0;
		if (imItem != 0) {
			GTK.gtk_widget_destroy (imItem);
			imItem = 0;
		}
		if (imSeparator != 0) {
			GTK.gtk_widget_destroy (imSeparator);
			imSeparator = 0;
		}
		return;
	}
	if (this.imHandle == imHandle) return;
	this.imHandle = imHandle;

	if (imSeparator == 0) {
		imSeparator = GTK.gtk_separator_menu_item_new ();
		GTK.gtk_widget_show (imSeparator);
		GTK.gtk_menu_shell_insert (handle, imSeparator, -1);
	}
	if (imItem == 0) {
		byte[] buffer = Converter.wcsToMbcs (SWT.getMessage("SWT_InputMethods"), true);
		if (GTK.GTK3) {
			imItem = GTK.gtk_menu_item_new ();
			if (imItem == 0) error (SWT.ERROR_NO_HANDLES);
			long /*int*/ imageHandle = 0;
			long /*int*/ labelHandle = GTK.gtk_accel_label_new (buffer);
			if (labelHandle == 0) error (SWT.ERROR_NO_HANDLES);
			if (GTK.GTK_VERSION >= OS.VERSION (3, 16, 0)) {
				GTK.gtk_label_set_xalign (labelHandle, 0);
				GTK.gtk_widget_set_halign (labelHandle, GTK.GTK_ALIGN_FILL);
			} else {
				GTK.gtk_misc_set_alignment(labelHandle, 0, 0);
			}
			long /*int*/ boxHandle = gtk_box_new (GTK.GTK_ORIENTATION_HORIZONTAL, false, 0);
			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);
				GTK.gtk_image_set_pixel_size (imageHandle, 16);
				if (boxHandle != 0) {
					GTK.gtk_container_add (boxHandle, imageHandle);
					GTK.gtk_widget_show (imageHandle);
				}
			}
			if (labelHandle != 0 && boxHandle != 0) {
				GTK.gtk_box_pack_end (boxHandle, labelHandle, true, true, 0);
				GTK.gtk_widget_show (labelHandle);
			}
			if (boxHandle != 0) {
				GTK.gtk_container_add (imItem, boxHandle);
				GTK.gtk_widget_show (boxHandle);
			}
		} else {
			imItem = GTK.gtk_image_menu_item_new_with_label (buffer);
			if (imItem == 0) error (SWT.ERROR_NO_HANDLES);
		}
		GTK.gtk_widget_show (imItem);
		GTK.gtk_menu_shell_insert (handle, imItem, -1);
	}
	long /*int*/ imSubmenu = GTK.gtk_menu_new ();
	GTK.gtk_im_multicontext_append_menuitems (imHandle, imSubmenu);
	GTK.gtk_menu_item_set_submenu (imItem, imSubmenu);
}

@Override
void createWidget (int index) {
	checkOrientation (parent);
	super.createWidget (index);
	parent.addMenu (this);
}

void fixMenus (Decorations newParent) {
	if (isDisposed()) {
		return;
	}
	MenuItem [] items = getItems ();
	for (int i=0; i<items.length; i++) {
		items [i].fixMenus (newParent);
	}
	parent.removeMenu (this);
	newParent.addMenu (this);
	this.parent = newParent;
}

/*public*/ Rectangle getBounds () {
	checkWidget();
	if (!GTK.gtk_widget_get_mapped (handle)) {
		return new Rectangle (0, 0, 0, 0);
	}
	long /*int*/ window = gtk_widget_get_window (handle);
	int [] origin_x = new int [1], origin_y = new int [1];
	GDK.gdk_window_get_origin (window, origin_x, origin_y);
	GtkAllocation allocation = new GtkAllocation ();
	GTK.gtk_widget_get_allocation (handle, allocation);
	int x = origin_x [0] + allocation.x;
	int y = origin_y [0] + allocation.y;
	int width = allocation.width;
	int height = allocation.height;
	return new Rectangle (x, y, width, height);
}

/**
 * Returns the default menu item or null if none has
 * been previously set.
 *
 * @return the default menu item.
 *
 * </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 MenuItem getDefaultItem () {
	checkWidget();
	return null;
}

/**
 * Returns <code>true</code> if the receiver is enabled, and
 * <code>false</code> otherwise. A disabled menu 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();
	return GTK.gtk_widget_get_sensitive (handle);
}

/**
 * Returns the item at the given, zero-relative index in the
 * receiver. Throws an exception if the index is out of range.
 *
 * @param index the index of the item to return
 * @return the item at the given index
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</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 MenuItem getItem (int index) {
	checkWidget();
	long /*int*/ list = GTK.gtk_container_get_children (handle);
	if (list == 0) error (SWT.ERROR_CANNOT_GET_ITEM);
	int count = OS.g_list_length (list);
	if (imSeparator != 0) count--;
	if (imItem != 0) count--;
	if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
	long /*int*/ data = 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);
}

/**
 * Returns the number of items contained in the receiver.
 *
 * @return the number of items
 *
 * @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 getItemCount () {
	checkWidget();
	long /*int*/ list = GTK.gtk_container_get_children (handle);
	if (list == 0) return 0;
	int count = OS.g_list_length (list);
	OS.g_list_free (list);
	if (imSeparator != 0) count--;
	if (imItem != 0) count--;
	return Math.max (0, count);
}

/**
 * Returns a (possibly empty) array of <code>MenuItem</code>s which
 * are the items in the receiver.
 * <p>
 * Note: This is not the actual structure used by the receiver
 * to maintain its list of items, so modifying the array will
 * not affect the receiver.
 * </p>
 *
 * @return the items in the receiver
 *
 * @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 MenuItem [] getItems () {
	checkWidget();
	long /*int*/ list = GTK.gtk_container_get_children (handle);
	if (list == 0) return new MenuItem [0];
	long /*int*/ originalList = list;
	int count = OS.g_list_length (list);
	if (imSeparator != 0) count--;
	if (imItem != 0) count--;
	MenuItem [] items = new MenuItem [count];
	int index = 0;
	for (int i=0; i<count; i++) {
		long /*int*/ data = OS.g_list_data (list);
		MenuItem item = (MenuItem) display.getWidget (data);
		if (item != null) items [index++] = item;
		list = OS.g_list_next (list);
	}
	OS.g_list_free (originalList);
	if (index != items.length) {
		MenuItem [] newItems = new MenuItem [index];
		System.arraycopy (items, 0, newItems, 0, index);
		items = newItems;
	}
	return items;
}

@Override
String getNameText () {
	String result = "";
	MenuItem [] items = getItems ();
	int length = items.length;
	if (length > 0) {
		for (int i=0; i<length-1; i++) {
			result = result + items [i].getNameText() + ", ";
		}
		result = result + items [length-1].getNameText ();
	}
	return result;
}

/**
 * Returns the orientation of the receiver, which will be one of the
 * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
 *
 * @return the orientation style
 *
 * @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 getOrientation () {
	checkWidget();
	return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
}

/**
 * Returns the receiver's parent, which must be a <code>Decorations</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 Decorations getParent () {
	checkWidget();
	return parent;
}

/**
 * Returns the receiver's parent item, which must be a
 * <code>MenuItem</code> or null when the receiver is a
 * root.
 *
 * @return the receiver's parent item
 *
 * @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 MenuItem getParentItem () {
	checkWidget();
	return cascade;
}

/**
 * Returns the receiver's parent item, which must be a
 * <code>Menu</code> or null when the receiver is a
 * root.
 *
 * @return the receiver's parent item
 *
 * @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 getParentMenu () {
	checkWidget();
	if (cascade == null) return null;
	return cascade.getParent ();
}

/**
 * Returns the receiver's shell. For all controls other than
 * shells, this simply returns the control's nearest ancestor
 * shell. Shells return themselves, even if they are children
 * of other shells. Returns null if receiver or its ancestor
 * is the application menubar.
 *
 * @return the receiver's shell 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>
 *
 * @see #getParent
 */
public Shell getShell () {
	checkWidget();
	return parent.getShell ();
}

/**
 * Returns <code>true</code> if the receiver is visible, and
 * <code>false</code> otherwise.
 * <p>
 * If one of the receiver's ancestors is not visible or some
 * other condition makes the receiver not visible, this method
 * may still indicate that it is considered visible even though
 * it may not actually be showing.
 * </p>
 *
 * @return the receiver's visibility 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 getVisible () {
	checkWidget();
	if ((style & SWT.POP_UP) != 0) {
		Menu [] popups = display.popups;
		if (popups != null) {
			for (int i=0; i<popups.length; i++) {
				if (popups [i] == this) return true;
			}
		}
	}
	return GTK.gtk_widget_get_mapped (handle);
}

@Override
long /*int*/ gtk_hide (long /*int*/ widget) {
	if ((style & SWT.POP_UP) != 0) {
		if (display.activeShell != null) {
			display.activeShell = getShell ();
			display.activeShell.ignoreFocusOut = false;
		}
	}
	sendEvent (SWT.Hide);
	if (OS.ubuntu_menu_proxy_get() != 0) {
		MenuItem[] items = getItems();
		for (int i=0; i<items.length; i++) {
			MenuItem item = items [i];
			if (item.updateAcceleratorText(false)) continue;
		}
	}
	return 0;
}

@Override
long /*int*/ gtk_show (long /*int*/ widget) {
	if ((style & SWT.POP_UP) != 0) {
		if (display.activeShell != null) {
			display.activeShell = getShell ();
			display.activeShell.ignoreFocusOut = true;
		}
		return 0;
	}
	sendEvent (SWT.Show);
	if (OS.ubuntu_menu_proxy_get() != 0) {
		MenuItem[] items = getItems();
		for (int i=0; i<items.length; i++) {
			MenuItem item = items [i];
			if (item.updateAcceleratorText(true)) continue;
		}
	}
	return 0;
}


@Override
long /*int*/ gtk_show_help (long /*int*/ widget, long /*int*/ helpType) {
	if (sendHelpEvent (helpType)) {
		GTK.gtk_menu_shell_deactivate (handle);
		return 1;
	}
	return 0;
}

@Override
void hookEvents () {
	super.hookEvents ();
	OS.g_signal_connect_closure_by_id (handle, display.signalIds [SHOW], 0, display.getClosure (SHOW), false);
	OS.g_signal_connect_closure_by_id (handle, display.signalIds [HIDE], 0, display.getClosure (HIDE), false);
	OS.g_signal_connect_closure_by_id (handle, display.signalIds [SHOW_HELP], 0, display.getClosure (SHOW_HELP), false);
}

/**
 * Searches the receiver's list starting at the first item
 * (index 0) until an item is found that is equal to the
 * argument, and returns the index of that item. If no item
 * is found, returns -1.
 *
 * @param item the search item
 * @return the index of the item
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the item 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>
 */
public int indexOf (MenuItem item) {
	checkWidget();
	if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
	MenuItem [] items = getItems ();
	for (int i=0; i<items.length; i++) {
		if (items [i] == item) return i;
	}
	return -1;
}

/**
 * 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 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 () {
	checkWidget();
	Menu parentMenu = getParentMenu ();
	if (parentMenu == null) {
		return getEnabled () && parent.isEnabled ();
	}
	return getEnabled () && parentMenu.isEnabled ();
}

/**
 * Returns <code>true</code> if the receiver is visible and all
 * of the receiver's ancestors are visible and <code>false</code>
 * otherwise.
 *
 * @return the receiver's visibility 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 #getVisible
 */
public boolean isVisible () {
	checkWidget();
	return getVisible ();
}

@Override
void releaseChildren (boolean destroy) {
	MenuItem [] items = getItems ();
	for (int i=0; i<items.length; i++) {
		MenuItem item = items [i];
		if (item != null && !item.isDisposed ()) {
			item.release (false);
		}
	}
	super.releaseChildren (destroy);
}

@Override
void releaseParent () {
	super.releaseParent ();
	if (cascade != null) cascade.setMenu (null);
	if ((style & SWT.BAR) != 0 && this == parent.menuBar) {
		parent.setMenuBar (null);
	}  else {
		if ((style & SWT.POP_UP) != 0) {
			display.removePopup (this);
		}
	}
}

@Override
void releaseWidget () {
	super.releaseWidget ();
	if (parent != null) parent.removeMenu (this);
	parent = null;
	cascade = null;
	imItem = imSeparator = imHandle = 0;
	if (imageList != null) imageList.dispose ();
	imageList = null;
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the menu 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 MenuListener
 * @see #addMenuListener
 */
public void removeMenuListener (MenuListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Hide, listener);
	eventTable.unhook (SWT.Show, listener);
}

void removeAccelerators (long /*int*/ accelGroup) {
	MenuItem [] items = getItems ();
	for (int i = 0; i < items.length; i++) {
		MenuItem item = items[i];
		item.removeAccelerators (accelGroup);
	}
}

/**
 * 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);
}

@Override
void reskinChildren (int flags) {
	MenuItem [] items = getItems ();
	for (int i=0; i<items.length; i++) {
		MenuItem item = items [i];
		item.reskin (flags);
	}
	super.reskinChildren (flags);
}

boolean sendHelpEvent (long /*int*/ helpType) {
	if (selectedItem != null && !selectedItem.isDisposed()) {
		if (selectedItem.hooks (SWT.Help)) {
			selectedItem.postEvent (SWT.Help);
			return true;
		}
	}
	if (hooks (SWT.Help)) {
		postEvent (SWT.Help);
		return true;
	}
	return parent.sendHelpEvent (helpType);
}

/**
 * Sets the default menu item to the argument or removes
 * the default emphasis when the argument is <code>null</code>.
 *
 * @param item the default menu item or null
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the menu item has been disposed</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 setDefaultItem (MenuItem item) {
	checkWidget();
}

/**
 * Enables the receiver if the argument is <code>true</code>,
 * and disables it otherwise. A disabled menu 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();
	GTK.gtk_widget_set_sensitive (handle, enabled);
}

/**
 * Sets the location of the receiver, which must be a popup,
 * to the point specified by the arguments which are relative
 * to the display.
 * <p>
 * Note that this is different from most widgets where the
 * location of the widget is relative to the parent.
 * </p><p>
 * Also note that the actual location of the menu is dependent
 * on platform specific behavior. For example: on Linux with
 * Wayland this operation is a hint due to lack of global
 * coordinates.
 * </p>
 *
 * @param x the new x coordinate for the receiver
 * @param y the new y coordinate for the receiver
 *
 * @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 setLocation (int x, int y) {
	checkWidget ();
	setLocation (new Point (x, y));
}

void setLocationInPixels (int x, int y) {
	checkWidget();
	if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
	this.x = x;
	this.y = y;
	hasLocation = true;
}

/**
 * Sets the location of the receiver, which must be a popup,
 * to the point specified by the argument which is relative
 * to the display.
 * <p>
 * Note that this is different from most widgets where the
 * location of the widget is relative to the parent.
 * </p><p>
 * Note that the platform window manager ultimately has control
 * over the location of popup menus.
 * </p>
 *
 * @param location the new location for the receiver
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the point 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>
 *
 * @since 2.1
 */
public void setLocation (Point location) {
	checkWidget ();
	setLocationInPixels (DPIUtil.autoScaleUp (location));
}

void setLocationInPixels (Point location) {
	checkWidget();
	if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
	setLocationInPixels (location.x, location.y);
}

/**
 * Sets the orientation of the receiver, which must be one
 * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
 * <p>
 *
 * @param orientation new orientation style
 *
 * @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 void setOrientation (int orientation) {
    checkWidget ();
    if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
    _setOrientation (orientation);
}

void _setOrientation (int orientation) {
    int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
    if ((orientation & flags) == 0 || (orientation & flags) == flags) return;
    style &= ~flags;
    style |= orientation & flags;
    setOrientation (false);
}

@Override
void setOrientation (boolean create) {
    if ((style & SWT.RIGHT_TO_LEFT) != 0 || !create) {
    	int dir = (style & SWT.RIGHT_TO_LEFT) != 0 ? GTK.GTK_TEXT_DIR_RTL : GTK.GTK_TEXT_DIR_LTR;
        if (handle != 0) GTK.gtk_widget_set_direction (handle, dir);
        MenuItem [] items = getItems ();
        for (int i = 0; i < items.length; i++) {
            items [i].setOrientation (create);
        }
    }
}

/**
 * Lack of absolute coordinates make Wayland event windows inaccurate.
 * Currently the best approach is to the use the GdkWindow of the mouse
 * pointer. See bug 530059 and 532074.<p>
 *
 * @param eventPtr a pointer to the GdkEvent
 */
void adjustParentWindow (long /*int*/ eventPtr) {
	if (!OS.isX11()) {
		long /*int*/ display = GDK.gdk_display_get_default ();
		long /*int*/ pointer = GDK.gdk_get_pointer(display);
		long /*int*/ deviceWindow = GDK.gdk_device_get_window_at_position(pointer, null, null);
		OS.g_object_ref(deviceWindow);
		int eventType = GDK.gdk_event_get_event_type(eventPtr);
		switch (eventType) {
			case GDK.GDK_BUTTON_PRESS:
				GdkEventButton eventButton = new GdkEventButton();
				OS.memmove (eventButton, eventPtr, GdkEventButton.sizeof);
				eventButton.window = deviceWindow;
				OS.memmove(eventPtr, eventButton, GdkEventButton.sizeof);
				break;
			case GDK.GDK_KEY_PRESS:
				GdkEventKey eventKey = new GdkEventKey();
				OS.memmove (eventKey, eventPtr, GdkEventKey.sizeof);
				eventKey.window = deviceWindow;
				OS.memmove(eventPtr, eventKey, GdkEventKey.sizeof);
				break;
		}
	}
	return;
}

/**
 * Feature in GTK3 on X11: context menus in SWT are populated
 * dynamically, sometimes asynchronously outside of SWT
 * (i.e. in Platform UI). This means that items are added and
 * removed just before the menu is shown. This method of
 * changing the menu content can sometimes cause sizing issues
 * internally in GTK, specifically with the height of the
 * toplevel GdkWindow. <p>
 *
 * The fix is to cache the number of items popped up previously,
 * and if the number of items in the current menu (to be popped up)
 * is different, then:<ul>
 *     <li>get the preferred height of the menu</li>
 *     <li>set the toplevel GdkWindow to that height</li></ul>
 *
 * @param itemCount the current number of items in the menu, just
 * before it's about to be shown/popped-up
 */
void verifyMenuPosition (int itemCount) {
	if (GTK.GTK3 && OS.isX11()) {
		if (itemCount != poppedUpCount && poppedUpCount != 0) {
			int [] naturalHeight = new int [1];
			/*
			 * We need to "show" the menu before fetching the preferred height.
			 * Note, this does not actually pop-up the menu.
			 */
			GTK.gtk_widget_show(handle);
			/*
			 * Menus are height-for-width only: use gtk_widget_get_preferred_height()
			 * instead of gtk_widget_get_preferred_size().
			 */
			GTK.gtk_widget_get_preferred_height(handle, null, naturalHeight);
			if (naturalHeight[0] > 0) {
				long /*int*/ topLevelWidget = GTK.gtk_widget_get_toplevel(handle);
				long /*int*/ topLevelWindow = GTK.gtk_widget_get_window(topLevelWidget);
				int width = GDK.gdk_window_get_width(topLevelWindow);
				GDK.gdk_window_resize(topLevelWindow, width, naturalHeight[0]);
			}
		}
	}
	return;
}

/**
 * Marks the receiver as visible if the argument is <code>true</code>,
 * and marks it invisible otherwise.
 * <p>
 * If one of the receiver's ancestors is not visible or some
 * other condition makes the receiver not visible, marking
 * it visible may not actually cause it to be displayed.
 * </p>
 *
 * @param visible the new visibility 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 setVisible (boolean visible) {
	checkWidget();
	if ((style & (SWT.BAR | SWT.DROP_DOWN)) != 0) return;
	if (visible) {
		display.addPopup (this);
	} else {
		display.removePopup (this);
		_setVisible (false);
	}
}
}

