Re: Table menu patch for GtkMenu
- From: Kristian Rietveld <kris gtk org>
- To: Owen Taylor <otaylor redhat com>
- Cc: GTK Development list <gtk-devel-list gnome org>
- Subject: Re: Table menu patch for GtkMenu
- Date: 24 Jul 2003 06:09:39 +0200
On Tue, 2003-07-15 at 16:34, Owen Taylor wrote:
> The API is basically fine, though I'd like to see some explanation
> of what "gtk_menu_occupied" is for, but I have various large-scale
gtk_menu_occupied() was for checking if a given place is already
occupied by a menu item. But now I moved to child properties, as you
suggested, this function is no longer needed. So now it only appears as
a GtkComboBox internal.
> thoughts about the implementation:
I think I addressed all of your comments in the new patch, which I've
attached. Some notes:
- in the size requisition/allocation algorithm, the width is
homogeneous, but the height is not. Why is this? For example, think of a
menu with usual text items and a separator item. Then the separator item
*has* to have another height then the text items in order to look nice.
- Now we have child properties, we can basically drop the
gtk_menu_attach() function. In that case, we need to make GtkMenu to
connect to each notify signal of all of the attach properties. Do we
want to do this? Isn't this too much overhead? It doesn't sound like a
good idea to me.
I hope this new patch comes closer to what you are expecting.
thanks,
-Kris
Index: gtkmenu.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenu.c,v
retrieving revision 1.134
diff -u -p -r1.134 gtkmenu.c
--- gtkmenu.c 13 Jul 2003 02:42:40 -0000 1.134
+++ gtkmenu.c 23 Jul 2003 23:17:07 -0000
@@ -74,10 +74,18 @@ struct _GtkMenuPrivate
gboolean have_position;
gint x;
gint y;
+
+ /* info used for the table */
+ guint rows;
+ guint columns;
+ GList *child_info;
+
+ guint *height;
};
enum {
MOVE_SCROLL,
+ MOVE_LEFT_RIGHT,
LAST_SIGNAL
};
@@ -88,14 +96,14 @@ enum {
static void gtk_menu_class_init (GtkMenuClass *klass);
static void gtk_menu_init (GtkMenu *menu);
-static void gtk_menu_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_menu_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
+static void gtk_menu_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_menu_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
static void gtk_menu_destroy (GtkObject *object);
static void gtk_menu_finalize (GObject *object);
static void gtk_menu_realize (GtkWidget *widget);
@@ -146,8 +154,15 @@ static void gtk_menu_style_set
static gboolean gtk_menu_focus (GtkWidget *widget,
GtkDirectionType direction);
static gint gtk_menu_get_popup_delay (GtkMenuShell *menu_shell);
+static void gtk_menu_move_current (GtkMenuShell *menu_shell,
+ GtkMenuDirectionType direction);
static void gtk_menu_real_move_scroll (GtkMenu *menu,
GtkScrollType type);
+static GtkWidget *find_child (GList *children,
+ int row,
+ int col);
+static void gtk_menu_real_move_left_right (GtkMenu *menu,
+ GtkMenuDirectionType dir);
static void gtk_menu_stop_navigating_submenu (GtkMenu *menu);
static gboolean gtk_menu_stop_navigating_submenu_cb (gpointer user_data);
@@ -179,6 +194,8 @@ static void _gtk_menu_refresh_accel_path
static GtkMenuShellClass *parent_class = NULL;
static const gchar *attach_data_key = "gtk-menu-attach-data";
+#define CHILD_INFO_KEY "gtk-menu-child-info"
+
static guint menu_signals[LAST_SIGNAL] = { 0 };
GtkMenuPrivate *
@@ -256,6 +273,15 @@ gtk_menu_class_init (GtkMenuClass *class
_gtk_marshal_VOID__ENUM,
G_TYPE_NONE, 1,
GTK_TYPE_SCROLL_TYPE);
+ menu_signals[MOVE_LEFT_RIGHT] =
+ _gtk_binding_signal_new ("move_left_right",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gtk_menu_real_move_left_right),
+ NULL, NULL,
+ _gtk_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_MENU_DIRECTION_TYPE);
g_object_class_install_property (gobject_class,
PROP_TEAROFF_TITLE,
@@ -319,6 +345,7 @@ gtk_menu_class_init (GtkMenuClass *class
menu_shell_class->select_item = gtk_menu_select_item;
menu_shell_class->insert = gtk_menu_real_insert;
menu_shell_class->get_popup_delay = gtk_menu_get_popup_delay;
+ menu_shell_class->move_current = gtk_menu_move_current;
binding_set = gtk_binding_set_by_class (class);
gtk_binding_entry_add_signal (binding_set,
@@ -401,6 +428,16 @@ gtk_menu_class_init (GtkMenuClass *class
"move_scroll", 1,
GTK_TYPE_SCROLL_TYPE,
GTK_SCROLL_PAGE_DOWN);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_Left, 0,
+ "move_left_right", 1,
+ GTK_TYPE_MENU_DIRECTION_TYPE,
+ GTK_MENU_DIR_PREV);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_Right, 0,
+ "move_left_right", 1,
+ GTK_TYPE_MENU_DIRECTION_TYPE,
+ GTK_MENU_DIR_NEXT);
gtk_settings_install_property (g_param_spec_boolean ("gtk-can-change-accels",
_("Can change accelerators"),
@@ -768,10 +805,33 @@ gtk_menu_real_insert (GtkMenuShell *
GtkWidget *child,
gint position)
{
+ gint i;
+ GList *list;
+
if (GTK_WIDGET_REALIZED (menu_shell))
gtk_widget_set_parent_window (child, GTK_MENU (menu_shell)->bin_window);
GTK_MENU_SHELL_CLASS (parent_class)->insert (menu_shell, child, position);
+
+ if (position < 0)
+ {
+ i = g_list_length (menu_shell->children) - 1;
+ gtk_menu_attach (GTK_MENU (menu_shell), child, 0, 1, i, i + 1);
+
+ return;
+ }
+
+ i = position;
+ list = g_list_nth (menu_shell->children, position);
+
+ do
+ {
+ gtk_menu_attach (GTK_MENU (menu_shell), list->data, 0, 1, i, i + 1);
+
+ list = list->next;
+ i++;
+ }
+ while (list);
}
static void
@@ -1020,7 +1080,6 @@ gtk_menu_popup (GtkMenu *menu,
if (xgrab_shell == widget)
popup_grab_on_window (widget->window, activate_time); /* Should always succeed */
-
gtk_grab_add (GTK_WIDGET (menu));
}
@@ -1534,6 +1593,7 @@ gtk_menu_realize (GtkWidget *widget)
attributes.colormap = gtk_widget_get_colormap (widget);
attributes.event_mask = gtk_widget_get_events (widget);
+
attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK |
GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK );
@@ -1674,6 +1734,7 @@ static void
gtk_menu_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
+ gint i;
GtkMenu *menu;
GtkMenuShell *menu_shell;
GtkWidget *child;
@@ -1682,12 +1743,14 @@ gtk_menu_size_request (GtkWidget *w
guint max_accel_width;
guint vertical_padding;
GtkRequisition child_requisition;
+ GtkMenuPrivate *priv;
g_return_if_fail (GTK_IS_MENU (widget));
g_return_if_fail (requisition != NULL);
menu = GTK_MENU (widget);
menu_shell = GTK_MENU_SHELL (widget);
+ priv = gtk_menu_get_private (menu);
requisition->width = 0;
requisition->height = 0;
@@ -1695,35 +1758,73 @@ gtk_menu_size_request (GtkWidget *w
max_toggle_size = 0;
max_accel_width = 0;
+ g_free (priv->height);
+ priv->height = g_new0 (guint, priv->rows);
+
children = menu_shell->children;
while (children)
{
+ gint toggle_size;
+ guint l, r, t, b;
+
child = children->data;
children = children->next;
- if (GTK_WIDGET_VISIBLE (child))
- {
- gint toggle_size;
+ if (! GTK_WIDGET_VISIBLE (child))
+ continue;
- /* It's important to size_request the child
- * before doing the toggle size request, in
- * case the toggle size request depends on the size
- * request of a child of the child (e.g. for ImageMenuItem)
- */
-
- GTK_MENU_ITEM (child)->show_submenu_indicator = TRUE;
- gtk_widget_size_request (child, &child_requisition);
-
- requisition->width = MAX (requisition->width, child_requisition.width);
- requisition->height += child_requisition.height;
+ g_object_get (child,
+ "left_attach", &l,
+ "right_attach", &r,
+ "top_attach", &t,
+ "bottom_attach", &b,
+ NULL);
+
+ /* It's important to size_request the child
+ * before doing the toggle size request, in
+ * case the toggle size request depends on the size
+ * request of a child of the child (e.g. for ImageMenuItem)
+ */
- gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), &toggle_size);
- max_toggle_size = MAX (max_toggle_size, toggle_size);
- max_accel_width = MAX (max_accel_width, GTK_MENU_ITEM (child)->accelerator_width);
- }
+ GTK_MENU_ITEM (child)->show_submenu_indicator = TRUE;
+ gtk_widget_size_request (child, &child_requisition);
+
+ gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), &toggle_size);
+ max_toggle_size = MAX (max_toggle_size, toggle_size);
+ max_accel_width = MAX (max_accel_width,
+ GTK_MENU_ITEM (child)->accelerator_width);
+
+ /* handle all different span types */
+ if (l == (r - 1))
+ {
+ /* spans a single column */
+ requisition->width = MAX (requisition->width,
+ child_requisition.width);
+ }
+ else
+ {
+ gint part = child_requisition.width / (r - l);
+ requisition->width = MAX (requisition->width, part);
+ }
+
+
+ if (t == (b - 1))
+ {
+ /* spans a single row */
+ priv->height[t] = MAX (priv->height[t], child_requisition.height);
+ }
+ else
+ {
+ gint part = child_requisition.height / (b - t);
+ priv->height[t] = MAX (priv->height[t], part);
+ }
}
+ for (i = 0; i < priv->rows; i++)
+ requisition->height += priv->height[i];
+
requisition->width += max_toggle_size + max_accel_width;
+ requisition->width *= priv->columns;
requisition->width += (GTK_CONTAINER (menu)->border_width +
widget->style->xthickness) * 2;
@@ -1749,6 +1850,8 @@ gtk_menu_size_allocate (GtkWidget *w
GtkMenuShell *menu_shell;
GtkWidget *child;
GtkAllocation child_allocation;
+ GtkRequisition child_requisition;
+ GtkMenuPrivate *priv;
GList *children;
gint x, y;
gint width, height;
@@ -1759,8 +1862,10 @@ gtk_menu_size_allocate (GtkWidget *w
menu = GTK_MENU (widget);
menu_shell = GTK_MENU_SHELL (widget);
+ priv = gtk_menu_get_private (menu);
widget->allocation = *allocation;
+ gtk_widget_get_child_requisition (GTK_WIDGET (menu), &child_requisition);
gtk_widget_style_get (GTK_WIDGET (menu),
"vertical-padding", &vertical_padding,
@@ -1772,6 +1877,9 @@ gtk_menu_size_allocate (GtkWidget *w
width = MAX (1, allocation->width - x * 2);
height = MAX (1, allocation->height - y * 2);
+ child_requisition.width -= x * 2;
+ child_requisition.height -= y * 2;
+
if (menu_shell->active)
gtk_menu_scroll_to (menu, menu->scroll_offset);
@@ -1799,41 +1907,60 @@ gtk_menu_size_allocate (GtkWidget *w
if (menu_shell->children)
{
- child_allocation.x = 0;
- child_allocation.y = 0;
- child_allocation.width = width;
-
+ gint base_width = width / priv->columns;
+
children = menu_shell->children;
while (children)
{
child = children->data;
children = children->next;
-
+
if (GTK_WIDGET_VISIBLE (child))
{
- GtkRequisition child_requisition;
- gtk_widget_get_child_requisition (child, &child_requisition);
-
- child_allocation.height = child_requisition.height;
+ gint i;
+ guint l, r, t, b;
+
+ g_object_get (child,
+ "left_attach", &l,
+ "right_attach", &r,
+ "top_attach", &t,
+ "bottom_attach", &b,
+ NULL);
+
+ child_allocation.width = (r - l) * base_width;
+ child_allocation.height = 0;
+ child_allocation.x = l * child_allocation.width;
+ child_allocation.y = 0;
+
+ for (i = 0; i < b; i++)
+ {
+ if (i < t)
+ child_allocation.y += priv->height[i];
+ else
+ child_allocation.height += priv->height[i];
+ }
gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child),
menu->toggle_size);
gtk_widget_size_allocate (child, &child_allocation);
gtk_widget_queue_draw (child);
-
- child_allocation.y += child_allocation.height;
}
}
/* Resize the item window */
if (GTK_WIDGET_REALIZED (widget))
{
- gdk_window_resize (menu->bin_window,
- child_allocation.width,
- child_allocation.y);
- }
+ gint i;
+ gint width, height;
+
+ for (i = 0; i < priv->rows; i++)
+ height += priv->height[i];
+ width = priv->columns * child_allocation.width;
+
+ gdk_window_resize (menu->bin_window, width, height);
+ }
if (menu->tearoff_active)
{
@@ -2978,6 +3105,7 @@ gtk_menu_scroll_item_visible (GtkMenuShe
GtkWidget *menu_item)
{
GtkMenu *menu;
+ GtkMenuPrivate *priv;
gint child_offset, child_height;
gint width, height;
gint y;
@@ -2985,6 +3113,11 @@ gtk_menu_scroll_item_visible (GtkMenuShe
gboolean last_child = 0;
menu = GTK_MENU (menu_shell);
+ priv = gtk_menu_get_private (menu);
+
+ /* disable scrolling stuff for table menus */
+ if (priv->rows && priv->columns)
+ return;
/* We need to check if the selected item fully visible.
* If not we need to scroll the menu so that it becomes fully
@@ -3164,6 +3297,93 @@ gtk_menu_set_screen (GtkMenu *menu,
}
}
+static void
+gtk_menu_resize (GtkMenu *menu,
+ guint rows,
+ guint columns)
+{
+ GtkMenuPrivate *priv;
+
+ g_return_if_fail (rows > 0 && rows < 65536);
+ g_return_if_fail (columns > 0 && columns < 65536);
+
+ rows = MAX (rows, 1);
+ columns = MAX (columns, 1);
+
+ priv = gtk_menu_get_private (menu);
+
+ if (rows != priv->rows || columns != priv->columns)
+ {
+ GList *list;
+
+ for (list = priv->child_info; list; list = list->next)
+ {
+ guint b, r;
+
+ g_object_get (list->data,
+ "bottom_attach", &b,
+ "right_attach", &r,
+ NULL);
+
+ rows = MAX (rows, b);
+ columns = MAX (columns, r);
+ }
+
+ if (rows != priv->rows)
+ {
+ priv->rows = rows;
+ /* FIXME: notify? */
+ }
+
+ if (columns != priv->columns)
+ {
+ priv->columns = columns;
+ /* FIXME: notify? */
+ }
+ }
+}
+
+void
+gtk_menu_attach (GtkMenu *menu,
+ GtkWidget *child,
+ guint left_attach,
+ guint right_attach,
+ guint top_attach,
+ guint bottom_attach)
+{
+ GList *i;
+ GtkMenuPrivate *priv;
+
+ g_return_if_fail (GTK_IS_MENU (menu));
+ g_return_if_fail (GTK_IS_MENU_ITEM (child));
+
+ g_return_if_fail (left_attach < right_attach);
+ g_return_if_fail (top_attach < bottom_attach);
+
+ for (i = GTK_MENU_SHELL (menu)->children; i; i = i->next)
+ if (i->data == child)
+ break;
+
+ if (!i)
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), child);
+
+ priv = gtk_menu_get_private (menu);
+
+ g_object_set (child,
+ "left_attach", left_attach,
+ "right_attach", right_attach,
+ "top_attach", top_attach,
+ "bottom_attach", bottom_attach,
+ NULL);
+
+ if (right_attach >= priv->columns)
+ gtk_menu_resize (menu, priv->rows?priv->rows:1, right_attach);
+
+ if (bottom_attach >= priv->rows)
+ gtk_menu_resize (menu, bottom_attach, priv->columns?priv->columns:1);
+
+ gtk_widget_queue_draw (GTK_WIDGET (menu));
+}
static gint
gtk_menu_get_popup_delay (GtkMenuShell *menu_shell)
@@ -3177,6 +3397,79 @@ gtk_menu_get_popup_delay (GtkMenuShell *
return popup_delay;
}
+static void
+gtk_menu_move_current (GtkMenuShell *menu_shell,
+ GtkMenuDirectionType direction)
+{
+ GtkMenuPrivate *priv = gtk_menu_get_private (GTK_MENU (menu_shell));
+
+ /* special case next/prev here if it's not a regular menu and also
+ * disable the regular left/right bindings
+ */
+ if (menu_shell->active_menu_item &&
+ (priv->rows > 1 || priv->columns > 1))
+ {
+ GtkWidget *match = NULL;
+ guint l, r, t, b;
+ int i;
+
+ g_object_get (menu_shell->active_menu_item,
+ "left_attach", &l,
+ "right_attach", &r,
+ "top_attach", &t,
+ "bottom_attach", &b,
+ NULL);
+
+ if (direction == GTK_MENU_DIR_NEXT)
+ {
+ for (i = b; i < priv->rows; i++)
+ {
+ match = find_child (menu_shell->children, i, l);
+ if (match && _gtk_menu_item_is_selectable (match))
+ break;
+ }
+
+ if (!match)
+ {
+ /* wrap around */
+ for (i = 0; i < b; i++)
+ {
+ match = find_child (menu_shell->children, i, l);
+ if (match && _gtk_menu_item_is_selectable (match))
+ break;
+ }
+ }
+ }
+ else if (direction == GTK_MENU_DIR_PREV)
+ {
+ for (i = t - 1; i >= 0; i--)
+ {
+ match = find_child (menu_shell->children, i, l);
+ if (match && _gtk_menu_item_is_selectable (match))
+ break;
+ }
+
+ if (!match)
+ {
+ /* wrap around */
+ for (i = priv->rows; i >= b; i--)
+ {
+ match = find_child (menu_shell->children, i, l);
+ if (match && _gtk_menu_item_is_selectable (match))
+ break;
+ }
+ }
+ }
+
+ if (match)
+ gtk_menu_shell_select_item (menu_shell, match);
+
+ return;
+ }
+
+ GTK_MENU_SHELL_CLASS (parent_class)->move_current (menu_shell, direction);
+}
+
static gint
get_visible_size (GtkMenu *menu)
{
@@ -3308,4 +3601,101 @@ gtk_menu_real_move_scroll (GtkMenu
default:
break;
}
+}
+
+static GtkWidget *
+find_child (GList *children,
+ int row,
+ int col)
+{
+ GList *i;
+
+ for (i = children; i; i = i->next)
+ {
+ guint t, l;
+
+ g_object_get (i->data,
+ "top_attach", &t,
+ "left_attach", &l,
+ NULL);
+
+ if (t == row && l == col)
+ return GTK_WIDGET (i->data);
+ }
+
+ return NULL;
+}
+
+static void
+gtk_menu_real_move_left_right (GtkMenu *menu,
+ GtkMenuDirectionType dir)
+{
+ GtkMenuPrivate *priv;
+ GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu);
+
+ gint i;
+ guint l, r, t, b;
+ GtkWidget *match = NULL;
+
+ if (!menu_shell->active_menu_item)
+ {
+ match = find_child (menu_shell->children, 0, 0);
+ if (match)
+ gtk_menu_shell_select_item (menu_shell, match);
+
+ return;
+ }
+
+ priv = gtk_menu_get_private (menu);
+
+ g_object_get (menu_shell->active_menu_item,
+ "left_attach", &l,
+ "right_attach", &r,
+ "top_attach", &t,
+ "bottom_attach", &b,
+ NULL);
+
+ if (dir == GTK_MENU_DIR_PREV)
+ {
+ for (i = l - 1; i >= 0; i--)
+ {
+ match = find_child (menu_shell->children, t, i);
+ if (match && _gtk_menu_item_is_selectable (match))
+ break;
+ }
+
+ if (!match)
+ {
+ /* wrap around */
+ for (i = priv->columns; i >= r; i--)
+ {
+ match = find_child (menu_shell->children, t, i);
+ if (match && _gtk_menu_item_is_selectable (match))
+ break;
+ }
+ }
+ }
+ else if (dir == GTK_MENU_DIR_NEXT)
+ {
+ for (i = r; i < priv->columns; i++)
+ {
+ match = find_child (menu_shell->children, t, i);
+ if (match && _gtk_menu_item_is_selectable (match))
+ break;
+ }
+
+ if (!match)
+ {
+ /* wrap around */
+ for (i = 0; i < r; i++)
+ {
+ match = find_child (menu_shell->children, t, i);
+ if (match && _gtk_menu_item_is_selectable (match))
+ break;
+ }
+ }
+ }
+
+ if (match)
+ gtk_menu_shell_select_item (GTK_MENU_SHELL (menu), match);
}
Index: gtkmenu.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenu.h,v
retrieving revision 1.34
diff -u -p -r1.34 gtkmenu.h
--- gtkmenu.h 8 Nov 2002 19:41:42 -0000 1.34
+++ gtkmenu.h 23 Jul 2003 23:17:07 -0000
@@ -188,6 +188,19 @@ void gtk_menu_reorder_child
void gtk_menu_set_screen (GtkMenu *menu,
GdkScreen *screen);
+
+void gtk_menu_attach (GtkMenu *menu,
+ GtkWidget *child,
+ guint left_attach,
+ guint right_attach,
+ guint top_attach,
+ guint bottom_attach);
#ifndef GTK_DISABLE_DEPRECATED
#define gtk_menu_append(menu,child) gtk_menu_shell_append ((GtkMenuShell *)(menu),(child))
#define gtk_menu_prepend(menu,child) gtk_menu_shell_prepend ((GtkMenuShell *)(menu),(child))
Index: gtkmenuitem.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenuitem.c,v
retrieving revision 1.101
diff -u -p -r1.101 gtkmenuitem.c
--- gtkmenuitem.c 13 Jul 2003 02:42:40 -0000 1.101
+++ gtkmenuitem.c 23 Jul 2003 23:17:16 -0000
@@ -34,10 +34,12 @@
#include "gtkmenubar.h"
#include "gtkmenuitem.h"
#include "gtkseparatormenuitem.h"
+#include "gtkintl.h"
#define MENU_ITEM_CLASS(w) GTK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass)
-enum {
+enum
+{
ACTIVATE,
ACTIVATE_ITEM,
TOGGLE_SIZE_REQUEST,
@@ -45,9 +47,34 @@ enum {
LAST_SIGNAL
};
+enum
+{
+ PROP_0,
+ PROP_LEFT_ATTACH,
+ PROP_RIGHT_ATTACH,
+ PROP_TOP_ATTACH,
+ PROP_BOTTOM_ATTACH
+};
+
+struct _GtkMenuItemPrivate
+{
+ guint left_attach;
+ guint right_attach;
+ guint top_attach;
+ guint bottom_attach;
+};
+
static void gtk_menu_item_class_init (GtkMenuItemClass *klass);
static void gtk_menu_item_init (GtkMenuItem *menu_item);
+static void gtk_menu_item_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gtk_menu_item_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
static void gtk_menu_item_destroy (GtkObject *object);
static void gtk_menu_item_finalize (GObject *object);
static void gtk_menu_item_size_request (GtkWidget *widget,
@@ -133,6 +160,8 @@ gtk_menu_item_class_init (GtkMenuItemCla
parent_class = g_type_class_peek_parent (klass);
gobject_class->finalize = gtk_menu_item_finalize;
+ gobject_class->get_property = gtk_menu_item_get_property;
+ gobject_class->set_property = gtk_menu_item_set_property;
object_class->destroy = gtk_menu_item_destroy;
@@ -234,6 +263,40 @@ gtk_menu_item_class_init (GtkMenuItemCla
G_MAXINT,
10,
G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_LEFT_ATTACH,
+ g_param_spec_uint ("left_attach",
+ _("Left Attach"),
+ _("Left attach position of the menu item"),
+ 0, UINT_MAX, 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_RIGHT_ATTACH,
+ g_param_spec_uint ("right_attach",
+ _("Right Attach"),
+ _("Right attach position of the menu item"),
+ 0, UINT_MAX, 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_TOP_ATTACH,
+ g_param_spec_uint ("top_attach",
+ _("Top Attach"),
+ _("Top attach position of the menu item"),
+ 0, UINT_MAX, 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_BOTTOM_ATTACH,
+ g_param_spec_uint ("bottom_attach",
+ _("Bottom Attach"),
+ _("Bottom attach position of the menu item"),
+ 0, UINT_MAX, 0,
+ G_PARAM_READWRITE));
+
+ g_type_class_add_private (gobject_class, sizeof (GtkMenuItemPrivate));
}
static void
@@ -253,6 +316,62 @@ gtk_menu_item_init (GtkMenuItem *menu_it
menu_item->right_justify = FALSE;
menu_item->timer = 0;
+}
+
+static void
+gtk_menu_item_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkMenuItemPrivate *priv = GTK_MENU_ITEM_GET_PRIVATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_LEFT_ATTACH:
+ priv->left_attach = g_value_get_uint (value);
+ break;
+ case PROP_RIGHT_ATTACH:
+ priv->right_attach = g_value_get_uint (value);
+ break;
+ case PROP_TOP_ATTACH:
+ priv->top_attach = g_value_get_uint (value);
+ break;
+ case PROP_BOTTOM_ATTACH:
+ priv->bottom_attach = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_menu_item_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkMenuItemPrivate *priv = GTK_MENU_ITEM_GET_PRIVATE (object);
+
+ switch (prop_id)
+ {
+ case PROP_LEFT_ATTACH:
+ g_value_set_uint (value, priv->left_attach);
+ break;
+ case PROP_RIGHT_ATTACH:
+ g_value_set_uint (value, priv->right_attach);
+ break;
+ case PROP_TOP_ATTACH:
+ g_value_set_uint (value, priv->top_attach);
+ break;
+ case PROP_BOTTOM_ATTACH:
+ g_value_set_uint (value, priv->bottom_attach);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
GtkWidget*
Index: gtkmenuitem.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenuitem.h,v
retrieving revision 1.27
diff -u -p -r1.27 gtkmenuitem.h
--- gtkmenuitem.h 5 Oct 2002 01:51:16 -0000 1.27
+++ gtkmenuitem.h 23 Jul 2003 23:17:16 -0000
@@ -43,10 +43,12 @@ extern "C" {
#define GTK_IS_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_MENU_ITEM))
#define GTK_IS_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_MENU_ITEM))
#define GTK_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_MENU_ITEM, GtkMenuItemClass))
+#define GTK_MENU_ITEM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_MENU_ITEM, GtkMenuItemPrivate))
-typedef struct _GtkMenuItem GtkMenuItem;
-typedef struct _GtkMenuItemClass GtkMenuItemClass;
+typedef struct _GtkMenuItem GtkMenuItem;
+typedef struct _GtkMenuItemClass GtkMenuItemClass;
+typedef struct _GtkMenuItemPrivate GtkMenuItemPrivate;
struct _GtkMenuItem
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]