* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#define GTK_MENU_INTERNALS
+
#include <string.h>
#include "gtkaccellabel.h"
#include "gtkmain.h"
+#include "gtkmarshalers.h"
#include "gtkmenu.h"
#include "gtkmenubar.h"
#include "gtkmenuitem.h"
+#include "gtkseparatormenuitem.h"
#include "gtksignal.h"
GdkRectangle *area);
static gint gtk_menu_item_expose (GtkWidget *widget,
GdkEventExpose *event);
+static void gtk_menu_item_parent_set (GtkWidget *widget,
+ GtkWidget *previous_parent);
static void gtk_real_menu_item_select (GtkItem *item);
widget_class->show_all = gtk_menu_item_show_all;
widget_class->hide_all = gtk_menu_item_hide_all;
widget_class->mnemonic_activate = gtk_menu_item_mnemonic_activate;
+ widget_class->parent_set = gtk_menu_item_parent_set;
container_class->forall = gtk_menu_item_forall;
GTK_RUN_FIRST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkMenuItemClass, activate),
- gtk_marshal_VOID__VOID,
+ _gtk_marshal_VOID__VOID,
GTK_TYPE_NONE, 0);
widget_class->activate_signal = menu_item_signals[ACTIVATE];
GTK_RUN_FIRST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkMenuItemClass, toggle_size_request),
- gtk_marshal_NONE__POINTER,
+ _gtk_marshal_VOID__POINTER,
GTK_TYPE_NONE, 1,
GTK_TYPE_POINTER);
GTK_RUN_FIRST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkMenuItemClass, toggle_size_allocate),
- gtk_marshal_NONE__INT,
+ _gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
}
gtk_menu_detach (GTK_MENU (menu_item->submenu));
}
+void _gtk_menu_item_set_placement (GtkMenuItem *menu_item,
+ GtkSubmenuPlacement placement);
+
void
_gtk_menu_item_set_placement (GtkMenuItem *menu_item,
GtkSubmenuPlacement placement)
requisition->width += child_requisition.width;
requisition->height += child_requisition.height;
- }
- if (menu_item->submenu && menu_item->show_submenu_indicator)
- requisition->width += 21;
+ if (menu_item->submenu && menu_item->show_submenu_indicator)
+ requisition->width += child_requisition.height;
+ }
accel_width = 0;
gtk_container_foreach (GTK_CONTAINER (menu_item),
child_allocation.y += widget->allocation.y;
if (menu_item->submenu && menu_item->show_submenu_indicator)
- child_allocation.width -= 21;
-
+ child_allocation.width -= child_allocation.height;
+
gtk_widget_size_allocate (bin->child, &child_allocation);
}
{
GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
- gdk_window_show (menu_item->event_window);
-
GTK_WIDGET_CLASS (parent_class)->map (widget);
+
+ gdk_window_show (menu_item->event_window);
}
static void
GtkShadowType shadow_type;
gint width, height;
gint x, y;
- gint border_width = GTK_CONTAINER (menu_item)->border_width;
+ gint border_width = GTK_CONTAINER (widget)->border_width;
if (GTK_WIDGET_DRAWABLE (widget))
{
if (menu_item->submenu && menu_item->show_submenu_indicator)
{
+ gint arrow_x, arrow_y;
+ gint arrow_size = height - 2 * widget->style->ythickness;
+ gint arrow_extent = arrow_size / 2;
+
shadow_type = GTK_SHADOW_OUT;
if (state_type == GTK_STATE_PRELIGHT)
shadow_type = GTK_SHADOW_IN;
+ arrow_x = x + width - 1 - arrow_size + (arrow_size - arrow_extent) / 2;
+ arrow_y = y + (height - arrow_extent) / 2;
+
gtk_paint_arrow (widget->style, widget->window,
state_type, shadow_type,
area, widget, "menuitem",
GTK_ARROW_RIGHT, TRUE,
- x + width - 15, y + height / 2 - 5, 10, 10);
+ arrow_x, arrow_y,
+ arrow_extent, arrow_extent);
}
else if (!GTK_BIN (menu_item)->child)
{
- gtk_paint_hline (widget->style, widget->window, GTK_STATE_NORMAL,
- area, widget, "menuitem",
- widget->allocation.x, widget->allocation.width,
- widget->allocation.y);
+ gtk_paint_hline (widget->style, widget->window, GTK_STATE_NORMAL,
+ area, widget, "menuitem",
+ widget->allocation.x, widget->allocation.width,
+ widget->allocation.y);
}
}
}
GdkEvent *event = gtk_get_current_event ();
etime = event ? gdk_event_get_time (event) : GDK_CURRENT_TIME;
- if (etime >= last_submenu_deselect_time &&
+ if (event &&
+ etime >= last_submenu_deselect_time &&
last_submenu_deselect_time + SELECT_TIMEOUT > etime)
- menu_item->timer = gtk_timeout_add (SELECT_TIMEOUT - (etime - last_submenu_deselect_time),
- gtk_menu_item_select_timeout,
- menu_item);
+ {
+ if (!menu_item->timer)
+ menu_item->timer = gtk_timeout_add (SELECT_TIMEOUT - (etime - last_submenu_deselect_time),
+ gtk_menu_item_select_timeout,
+ menu_item);
+ if (event &&
+ event->type != GDK_BUTTON_PRESS &&
+ event->type != GDK_ENTER_NOTIFY)
+ menu_item->timer_from_keypress = TRUE;
+ else
+ menu_item->timer_from_keypress = FALSE;
+ }
else
gtk_menu_item_popup_submenu (menu_item);
if (event)
gtk_menu_shell_select_item (GTK_MENU_SHELL (widget->parent), widget);
gtk_menu_item_popup_submenu (widget);
+ _gtk_menu_shell_select_first (GTK_MENU_SHELL (menu_item->submenu));
submenu = GTK_MENU_SHELL (menu_item->submenu);
- if (submenu->children)
- gtk_menu_shell_select_item (submenu, submenu->children->data);
}
}
}
static gint
gtk_menu_item_select_timeout (gpointer data)
{
+ GtkMenuItem *menu_item;
+ GtkWidget *parent;
+
GDK_THREADS_ENTER ();
- gtk_menu_item_popup_submenu (data);
+ menu_item = GTK_MENU_ITEM (data);
+
+ parent = GTK_WIDGET (menu_item)->parent;
+
+ if (parent && GTK_IS_MENU_SHELL (parent) && GTK_MENU_SHELL (parent)->active)
+ {
+ gtk_menu_item_popup_submenu (data);
+ if (menu_item->timer_from_keypress && menu_item->submenu)
+ GTK_MENU_SHELL (menu_item->submenu)->ignore_enter = TRUE;
+ }
GDK_THREADS_LEAVE ();
}
}
+static void
+gtk_menu_item_parent_set (GtkWidget *widget,
+ GtkWidget *previous_parent)
+{
+ GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
+ GtkMenu *menu = GTK_IS_MENU (widget->parent) ? GTK_MENU (widget->parent) : NULL;
+
+ if (menu)
+ _gtk_menu_item_refresh_accel_path (menu_item,
+ menu->accel_path,
+ menu->accel_group,
+ TRUE);
+
+ if (GTK_WIDGET_CLASS (parent_class)->parent_set)
+ GTK_WIDGET_CLASS (parent_class)->parent_set (widget, previous_parent);
+}
+
void
_gtk_menu_item_refresh_accel_path (GtkMenuItem *menu_item,
const gchar *prefix,
GtkWidget *widget;
g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
- g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+ g_return_if_fail (!accel_group || GTK_IS_ACCEL_GROUP (accel_group));
widget = GTK_WIDGET (menu_item);
+ if (!accel_group)
+ {
+ gtk_widget_set_accel_path (widget, NULL, NULL);
+ return;
+ }
+
path = _gtk_widget_get_accel_path (widget);
if (!path) /* no active accel_path yet */
{
path = menu_item->accel_path;
}
if (path)
- _gtk_widget_set_accel_path (widget, path, accel_group);
+ gtk_widget_set_accel_path (widget, path, accel_group);
}
else if (group_changed) /* reinstall accelerators */
- _gtk_widget_set_accel_path (widget, path, accel_group);
+ gtk_widget_set_accel_path (widget, path, accel_group);
}
/**
* gtk_menu_item_set_accel_path
* @menu_item: a valid #GtkMenuItem
- * @accel_path: accelerator path, corresponding to this menu item's funcitonality
+ * @accel_path: accelerator path, corresponding to this menu item's functionality
*
* Set the accelerator path on @menu_item, through which runtime changes of the
* menu item's accelerator caused by the user can be identified and saved to
* gtk_accel_map_add_entry() with the same @accel_path.
* See also gtk_accel_map_add_entry() on the specifics of accelerator paths,
* and gtk_menu_set_accel_path() for a more convenient variant of this function.
+ *
+ * This function is basically a convenience wrapper that handles calling
+ * gtk_widget_set_accel_path() with the appropriate accelerator group for
+ * the menu item.
*/
void
gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
menu_item->accel_path = g_strdup (accel_path);
/* forget accelerators associated with old path */
- _gtk_widget_set_accel_path (widget, NULL, NULL);
+ gtk_widget_set_accel_path (widget, NULL, NULL);
/* install accelerators associated with new path */
- if (widget->parent)
+ if (widget->parent && GTK_IS_MENU (widget->parent))
{
GtkMenu *menu = GTK_MENU (widget->parent);
if (bin->child)
callback (bin->child, callback_data);
}
+
+gboolean
+_gtk_menu_item_is_selectable (GtkWidget *menu_item)
+{
+ if ((!GTK_BIN (menu_item)->child &&
+ G_OBJECT_TYPE (menu_item) == GTK_TYPE_MENU_ITEM) ||
+ GTK_IS_SEPARATOR_MENU_ITEM (menu_item) ||
+ !GTK_WIDGET_IS_SENSITIVE (menu_item) ||
+ !GTK_WIDGET_VISIBLE (menu_item))
+ return FALSE;
+
+ return TRUE;
+}