/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Jsh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-#include "gtkintl.h"
+#include "config.h"
+
+#include "gdk/gdkkeysyms.h"
+
+#undef GTK_DISABLE_DEPRECATED
+
#include "gtkmenu.h"
#include "gtkmenuitem.h"
-#include "gtkoptionmenu.h"
#include "gtkmarshalers.h"
-#include "gtksignal.h"
-#include "gdk/gdkkeysyms.h"
-
+#include "gtkoptionmenu.h"
+#include "gtkprivate.h"
+#include "gtkintl.h"
+#include "gtkalias.h"
-#define CHILD_LEFT_SPACING 5
+#define CHILD_LEFT_SPACING 4
#define CHILD_RIGHT_SPACING 1
#define CHILD_TOP_SPACING 1
#define CHILD_BOTTOM_SPACING 1
gboolean interior_focus;
GtkRequisition indicator_size;
GtkBorder indicator_spacing;
+ gint focus_width;
+ gint focus_pad;
};
-static GtkOptionMenuProps default_props = {
- FALSE,
+static const GtkOptionMenuProps default_props = {
+ TRUE,
{ 7, 13 },
- { 7, 5, 2, 2 } /* Left, right, top, bottom */
+ { 7, 5, 2, 2 }, /* Left, right, top, bottom */
+ 1,
+ 0
};
-static void gtk_option_menu_class_init (GtkOptionMenuClass *klass);
-static void gtk_option_menu_init (GtkOptionMenu *option_menu);
static void gtk_option_menu_destroy (GtkObject *object);
static void gtk_option_menu_set_property (GObject *object,
guint prop_id,
static void gtk_option_menu_hide_all (GtkWidget *widget);
static gboolean gtk_option_menu_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
-static GtkType gtk_option_menu_child_type (GtkContainer *container);
+static GType gtk_option_menu_child_type (GtkContainer *container);
static gint gtk_option_menu_scroll_event (GtkWidget *widget,
GdkEventScroll *event);
enum
{
PROP_0,
- PROP_MENU,
- LAST_PROP
+ PROP_MENU
};
-static GtkButtonClass *parent_class = NULL;
-static guint signals[LAST_SIGNAL] = { 0 };
-
+static guint signals[LAST_SIGNAL] = { 0 };
-GtkType
-gtk_option_menu_get_type (void)
-{
- static GtkType option_menu_type = 0;
-
- if (!option_menu_type)
- {
- static const GtkTypeInfo option_menu_info =
- {
- "GtkOptionMenu",
- sizeof (GtkOptionMenu),
- sizeof (GtkOptionMenuClass),
- (GtkClassInitFunc) gtk_option_menu_class_init,
- (GtkObjectInitFunc) gtk_option_menu_init,
- /* reserved_1 */ NULL,
- /* reserved_2 */ NULL,
- (GtkClassInitFunc) NULL,
- };
-
- option_menu_type = gtk_type_unique (gtk_button_get_type (), &option_menu_info);
- }
-
- return option_menu_type;
-}
+G_DEFINE_TYPE (GtkOptionMenu, gtk_option_menu, GTK_TYPE_BUTTON)
static void
gtk_option_menu_class_init (GtkOptionMenuClass *class)
GObjectClass *gobject_class;
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
- GtkButtonClass *button_class;
GtkContainerClass *container_class;
gobject_class = (GObjectClass*) class;
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
- button_class = (GtkButtonClass*) class;
container_class = (GtkContainerClass*) class;
- parent_class = gtk_type_class (gtk_button_get_type ());
-
signals[CHANGED] =
- g_signal_new ("changed",
+ g_signal_new (I_("changed"),
G_OBJECT_CLASS_TYPE (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkOptionMenuClass, changed),
g_object_class_install_property (gobject_class,
PROP_MENU,
g_param_spec_object ("menu",
- _("Menu"),
- _("The menu of options"),
+ P_("Menu"),
+ P_("The menu of options"),
GTK_TYPE_MENU,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
+ GTK_PARAM_READWRITE));
gtk_widget_class_install_style_property (widget_class,
- g_param_spec_boxed ("indicator_size",
- _("Indicator Size"),
- _("Size of dropdown indicator"),
+ g_param_spec_boxed ("indicator-size",
+ P_("Indicator Size"),
+ P_("Size of dropdown indicator"),
GTK_TYPE_REQUISITION,
- G_PARAM_READABLE));
+ GTK_PARAM_READABLE));
gtk_widget_class_install_style_property (widget_class,
- g_param_spec_boxed ("indicator_spacing",
- _("Indicator Spacing"),
- _("Spacing around indicator"),
+ g_param_spec_boxed ("indicator-spacing",
+ P_("Indicator Spacing"),
+ P_("Spacing around indicator"),
GTK_TYPE_BORDER,
- G_PARAM_READABLE));
+ GTK_PARAM_READABLE));
}
-static GtkType
+static GType
gtk_option_menu_child_type (GtkContainer *container)
{
- return GTK_TYPE_NONE;
+ return G_TYPE_NONE;
}
static void
GtkWidget*
gtk_option_menu_new (void)
{
- return GTK_WIDGET (gtk_type_new (gtk_option_menu_get_type ()));
+ return g_object_new (GTK_TYPE_OPTION_MENU, NULL);
}
GtkWidget*
g_return_if_fail (option_menu->menu == (GtkWidget*) menu);
gtk_option_menu_remove_contents (option_menu);
- gtk_signal_disconnect_by_data (GTK_OBJECT (option_menu->menu),
- option_menu);
+ g_signal_handlers_disconnect_by_func (option_menu->menu,
+ gtk_option_menu_selection_done,
+ option_menu);
+ g_signal_handlers_disconnect_by_func (option_menu->menu,
+ gtk_option_menu_calc_size,
+ option_menu);
option_menu->menu = NULL;
g_object_notify (G_OBJECT (option_menu), "menu");
gtk_option_menu_calc_size (option_menu);
- gtk_signal_connect_after (GTK_OBJECT (option_menu->menu), "selection_done",
- G_CALLBACK (gtk_option_menu_selection_done),
+ g_signal_connect_after (option_menu->menu, "selection-done",
+ G_CALLBACK (gtk_option_menu_selection_done),
+ option_menu);
+ g_signal_connect_swapped (option_menu->menu, "size-request",
+ G_CALLBACK (gtk_option_menu_calc_size),
option_menu);
- gtk_signal_connect_object (GTK_OBJECT (option_menu->menu), "size_request",
- (GtkSignalFunc) gtk_option_menu_calc_size,
- GTK_OBJECT (option_menu));
if (GTK_WIDGET (option_menu)->parent)
gtk_widget_queue_resize (GTK_WIDGET (option_menu));
g_return_if_fail (GTK_IS_OPTION_MENU (option_menu));
if (option_menu->menu)
- gtk_menu_detach (GTK_MENU (option_menu->menu));
+ {
+ if (GTK_MENU_SHELL (option_menu->menu)->active)
+ gtk_menu_shell_cancel (GTK_MENU_SHELL (option_menu->menu));
+
+ gtk_menu_detach (GTK_MENU (option_menu->menu));
+ }
}
void
* items are numbered from top to bottom, starting with 0.
*
* Return value: index of the selected menu item, or -1 if there are no menu items
+ * Deprecated: 2.4: Use #GtkComboBox instead.
**/
gint
gtk_option_menu_get_history (GtkOptionMenu *option_menu)
static void
gtk_option_menu_destroy (GtkObject *object)
{
- GtkOptionMenu *option_menu;
-
- g_return_if_fail (GTK_IS_OPTION_MENU (object));
-
- option_menu = GTK_OPTION_MENU (object);
+ GtkOptionMenu *option_menu = GTK_OPTION_MENU (object);
if (option_menu->menu)
gtk_widget_destroy (option_menu->menu);
- if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+ GTK_OBJECT_CLASS (gtk_option_menu_parent_class)->destroy (object);
}
static void
GtkBorder *indicator_spacing;
gtk_widget_style_get (GTK_WIDGET (option_menu),
- "indicator_size", &indicator_size,
- "indicator_spacing", &indicator_spacing,
- "interior_focus", &props->interior_focus,
+ "indicator-size", &indicator_size,
+ "indicator-spacing", &indicator_spacing,
+ "interior-focus", &props->interior_focus,
+ "focus-line-width", &props->focus_width,
+ "focus-padding", &props->focus_pad,
NULL);
if (indicator_size)
else
props->indicator_spacing = default_props.indicator_spacing;
- g_free (indicator_size);
- g_free (indicator_spacing);
+ gtk_requisition_free (indicator_size);
+ gtk_border_free (indicator_spacing);
}
static void
}
requisition->width = ((GTK_CONTAINER (widget)->border_width +
- GTK_WIDGET (widget)->style->xthickness) * 2 +
+ GTK_WIDGET (widget)->style->xthickness + props.focus_pad) * 2 +
MAX (child_requisition.width, option_menu->width) +
props.indicator_size.width +
props.indicator_spacing.left + props.indicator_spacing.right +
- CHILD_LEFT_SPACING + CHILD_RIGHT_SPACING + 2);
+ CHILD_LEFT_SPACING + CHILD_RIGHT_SPACING + props.focus_width * 2);
requisition->height = ((GTK_CONTAINER (widget)->border_width +
- GTK_WIDGET (widget)->style->ythickness) * 2 +
+ GTK_WIDGET (widget)->style->ythickness + props.focus_pad) * 2 +
MAX (child_requisition.height, option_menu->height) +
- CHILD_TOP_SPACING + CHILD_BOTTOM_SPACING + 2);
+ CHILD_TOP_SPACING + CHILD_BOTTOM_SPACING + props.focus_width * 2);
- tmp = (requisition->height - option_menu->height +
+ tmp = (requisition->height - MAX (child_requisition.height, option_menu->height) +
props.indicator_size.height + props.indicator_spacing.top + props.indicator_spacing.bottom);
requisition->height = MAX (requisition->height, tmp);
}
if (child && GTK_WIDGET_VISIBLE (child))
{
gint xthickness = GTK_WIDGET (widget)->style->xthickness;
-
- child_allocation.x = widget->allocation.x + border_width + xthickness + 1;
- child_allocation.y = widget->allocation.y + 2 * border_width + 1;
- child_allocation.width = MAX (1, (gint)allocation->width - (xthickness + 1) * 2 - border_width * 2 -
+ gint ythickness = GTK_WIDGET (widget)->style->ythickness;
+
+ child_allocation.x = widget->allocation.x + border_width + xthickness + props.focus_width + props.focus_pad + CHILD_LEFT_SPACING;
+ child_allocation.y = widget->allocation.y + border_width + ythickness + props.focus_width + props.focus_pad + CHILD_TOP_SPACING;
+ child_allocation.width = MAX (1, allocation->width - (border_width + xthickness + props.focus_width + props.focus_pad) * 2 -
props.indicator_size.width - props.indicator_spacing.left - props.indicator_spacing.right -
- CHILD_LEFT_SPACING - CHILD_RIGHT_SPACING - 2);
- child_allocation.height = MAX (1, (gint)allocation->height - (border_width + 1) * 2 - border_width * 2 -
- CHILD_TOP_SPACING - CHILD_BOTTOM_SPACING - 2);
- child_allocation.x += CHILD_LEFT_SPACING;
- child_allocation.y += CHILD_TOP_SPACING;
+ CHILD_LEFT_SPACING - CHILD_RIGHT_SPACING);
+ child_allocation.height = MAX (1, allocation->height - (border_width + ythickness + props.focus_width + props.focus_pad) * 2 -
+ CHILD_TOP_SPACING - CHILD_BOTTOM_SPACING);
+
+ if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL)
+ child_allocation.x += props.indicator_size.width + props.indicator_spacing.left + props.indicator_spacing.right;
gtk_widget_size_allocate (child, &child_allocation);
}
GdkRectangle button_area;
GtkOptionMenuProps props;
gint border_width;
+ gint tab_x;
g_return_if_fail (GTK_IS_OPTION_MENU (widget));
g_return_if_fail (area != NULL);
button_area.width = widget->allocation.width - 2 * border_width;
button_area.height = widget->allocation.height - 2 * border_width;
- if (!props.interior_focus)
+ if (!props.interior_focus && GTK_WIDGET_HAS_FOCUS (widget))
{
- button_area.x += 1;
- button_area.y += 1;
- button_area.width -= 2;
- button_area.height -= 2;
+ button_area.x += props.focus_width + props.focus_pad;
+ button_area.y += props.focus_width + props.focus_pad;
+ button_area.width -= 2 * (props.focus_width + props.focus_pad);
+ button_area.height -= 2 * (props.focus_width + props.focus_pad);
}
-
+
gtk_paint_box (widget->style, widget->window,
GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT,
area, widget, "optionmenu",
button_area.x, button_area.y,
button_area.width, button_area.height);
+ if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL)
+ tab_x = button_area.x + props.indicator_spacing.right +
+ widget->style->xthickness;
+ else
+ tab_x = button_area.x + button_area.width -
+ props.indicator_size.width - props.indicator_spacing.right -
+ widget->style->xthickness;
+
gtk_paint_tab (widget->style, widget->window,
GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT,
area, widget, "optionmenutab",
- button_area.x + button_area.width -
- props.indicator_size.width - props.indicator_spacing.right -
- widget->style->xthickness,
+ tab_x,
button_area.y + (button_area.height - props.indicator_size.height) / 2,
props.indicator_size.width, props.indicator_size.height);
{
if (props.interior_focus)
{
- button_area.x += widget->style->xthickness + 1;
- button_area.y += widget->style->ythickness + 1;
- button_area.width -= 2 * (widget->style->xthickness + 1)
- + props.indicator_spacing.left + props.indicator_spacing.right + props.indicator_size.width;
- button_area.height -= 2 * (widget->style->ythickness + 1);
+ button_area.x += widget->style->xthickness + props.focus_pad;
+ button_area.y += widget->style->ythickness + props.focus_pad;
+ button_area.width -= 2 * (widget->style->xthickness + props.focus_pad) +
+ props.indicator_spacing.left +
+ props.indicator_spacing.right +
+ props.indicator_size.width;
+ button_area.height -= 2 * (widget->style->ythickness + props.focus_pad);
+ if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL)
+ button_area.x += props.indicator_spacing.left +
+ props.indicator_spacing.right +
+ props.indicator_size.width;
}
else
{
- button_area.x -= 1;
- button_area.y -= 1;
- button_area.width += 2;
- button_area.height += 2;
+ button_area.x -= props.focus_width + props.focus_pad;
+ button_area.y -= props.focus_width + props.focus_pad;
+ button_area.width += 2 * (props.focus_width + props.focus_pad);
+ button_area.height += 2 * (props.focus_width + props.focus_pad);
}
- gtk_paint_focus (widget->style, widget->window,
+ gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
area, widget, "button",
button_area.x,
button_area.y,
- button_area.width - 1,
- button_area.height - 1);
+ button_area.width,
+ button_area.height);
}
}
}
child_event = *event;
- if (GTK_WIDGET_NO_WINDOW (child) &&
+ if (!gtk_widget_get_has_window (child) &&
gtk_widget_intersect (child, &event->area, &child_event.area))
gtk_widget_event (child, (GdkEvent*) &child_event);
{
g_return_if_fail (GTK_IS_OPTION_MENU (option_menu));
- g_signal_emit (G_OBJECT (option_menu), signals[CHANGED], 0);
+ g_signal_emit (option_menu, signals[CHANGED], 0);
}
static void
if (child)
{
- gtk_widget_ref (child);
+ g_object_ref (child);
gtk_option_menu_remove_contents (option_menu);
gtk_widget_destroy (child);
- gtk_widget_unref (child);
+ g_object_unref (child);
gtk_option_menu_select_first_sensitive (option_menu);
}
option_menu->menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu));
if (option_menu->menu_item)
{
- gtk_widget_ref (option_menu->menu_item);
+ g_object_ref (option_menu->menu_item);
child = GTK_BIN (option_menu->menu_item)->child;
if (child)
{
gtk_widget_reparent (child, GTK_WIDGET (option_menu));
}
- gtk_signal_connect (GTK_OBJECT (option_menu->menu_item), "state_changed",
- GTK_SIGNAL_FUNC (gtk_option_menu_item_state_changed_cb), option_menu);
- gtk_signal_connect (GTK_OBJECT (option_menu->menu_item), "destroy",
- GTK_SIGNAL_FUNC (gtk_option_menu_item_destroy_cb), option_menu);
+ g_signal_connect (option_menu->menu_item, "state-changed",
+ G_CALLBACK (gtk_option_menu_item_state_changed_cb), option_menu);
+ g_signal_connect (option_menu->menu_item, "destroy",
+ G_CALLBACK (gtk_option_menu_item_destroy_cb), option_menu);
gtk_widget_size_request (child, &child_requisition);
gtk_widget_size_allocate (GTK_WIDGET (option_menu),
if (child)
{
gtk_widget_set_sensitive (child, TRUE);
+ gtk_widget_set_state (child, GTK_STATE_NORMAL);
gtk_widget_reparent (child, option_menu->menu_item);
}
- gtk_signal_disconnect_by_func (GTK_OBJECT (option_menu->menu_item),
- GTK_SIGNAL_FUNC (gtk_option_menu_item_state_changed_cb),
- option_menu);
- gtk_signal_disconnect_by_func (GTK_OBJECT (option_menu->menu_item),
- GTK_SIGNAL_FUNC (gtk_option_menu_item_destroy_cb),
- option_menu);
+ g_signal_handlers_disconnect_by_func (option_menu->menu_item,
+ gtk_option_menu_item_state_changed_cb,
+ option_menu);
+ g_signal_handlers_disconnect_by_func (option_menu->menu_item,
+ gtk_option_menu_item_destroy_cb,
+ option_menu);
- gtk_widget_unref (option_menu->menu_item);
+ g_object_unref (option_menu->menu_item);
option_menu->menu_item = NULL;
}
}
if (GTK_WIDGET_VISIBLE (child))
{
- gtk_widget_size_request (child, &child_requisition);
+ GtkWidget *inner = GTK_BIN (child)->child;
- option_menu->width = MAX (option_menu->width, child_requisition.width);
- option_menu->height = MAX (option_menu->height, child_requisition.height);
+ if (inner)
+ {
+ gtk_widget_size_request (inner, &child_requisition);
+
+ option_menu->width = MAX (option_menu->width, child_requisition.width);
+ option_menu->height = MAX (option_menu->height, child_requisition.height);
+ }
}
}
}
active = gtk_menu_get_active (GTK_MENU (option_menu->menu));
gdk_window_get_origin (widget->window, &menu_xpos, &menu_ypos);
+ /* set combo box type hint for menu popup */
+ gtk_window_set_type_hint (GTK_WINDOW (GTK_MENU (option_menu->menu)->toplevel),
+ GDK_WINDOW_TYPE_HINT_COMBO);
+
menu_xpos += widget->allocation.x;
menu_ypos += widget->allocation.y + widget->allocation.height / 2 - 2;
children = children->next;
}
- screen_width = gdk_screen_width ();
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+ menu_xpos = menu_xpos + widget->allocation.width - menu_width;
+
+ /* Clamp the position on screen */
+ screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
if (menu_xpos < 0)
menu_xpos = 0;
if (GTK_WIDGET_VISIBLE (item) && GTK_WIDGET_IS_SENSITIVE (item))
{
gtk_option_menu_set_history (option_menu, index);
+ gtk_menu_item_activate (GTK_MENU_ITEM (item));
break;
}
return TRUE;
}
+#define __GTK_OPTION_MENU_C__
+#include "gtkaliasdef.c"
+