attach/detach to menu widget via

Tue Feb  3 15:09:55 1998  Tim Janik  <timj@gimp.org>

        * gtk/gtkoptionmenu.h:
        * gtk/gtkoptionmenu.c: attach/detach to menu widget via

        * gtk/gtkmenu.h:
        * gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget
          and gtk_menu_detach that correspond to the action of
          gtk_widget_set_parent and gtk_widget_unparent.

        * gtk/widget.c: few fixups.
This commit is contained in:
Tim Janik 1998-02-03 14:13:05 +00:00 committed by Tim Janik
parent a8629917ae
commit b45cd0430c
15 changed files with 239 additions and 37 deletions

View File

@ -1,3 +1,15 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget
and gtk_menu_detach that correspond to the action of
gtk_widget_set_parent and gtk_widget_unparent.
* gtk/widget.c: few fixups.
Tue Feb 3 00:12:00 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtktable.c
Fixed problem with division by zero in row/column-spanned

View File

@ -1,3 +1,15 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget
and gtk_menu_detach that correspond to the action of
gtk_widget_set_parent and gtk_widget_unparent.
* gtk/widget.c: few fixups.
Tue Feb 3 00:12:00 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtktable.c
Fixed problem with division by zero in row/column-spanned

View File

@ -1,3 +1,15 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget
and gtk_menu_detach that correspond to the action of
gtk_widget_set_parent and gtk_widget_unparent.
* gtk/widget.c: few fixups.
Tue Feb 3 00:12:00 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtktable.c
Fixed problem with division by zero in row/column-spanned

View File

@ -1,3 +1,15 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget
and gtk_menu_detach that correspond to the action of
gtk_widget_set_parent and gtk_widget_unparent.
* gtk/widget.c: few fixups.
Tue Feb 3 00:12:00 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtktable.c
Fixed problem with division by zero in row/column-spanned

View File

@ -1,3 +1,15 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget
and gtk_menu_detach that correspond to the action of
gtk_widget_set_parent and gtk_widget_unparent.
* gtk/widget.c: few fixups.
Tue Feb 3 00:12:00 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtktable.c
Fixed problem with division by zero in row/column-spanned

View File

@ -1,3 +1,15 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget
and gtk_menu_detach that correspond to the action of
gtk_widget_set_parent and gtk_widget_unparent.
* gtk/widget.c: few fixups.
Tue Feb 3 00:12:00 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtktable.c
Fixed problem with division by zero in row/column-spanned

View File

@ -1,3 +1,15 @@
Tue Feb 3 15:09:55 1998 Tim Janik <timj@gimp.org>
* gtk/gtkoptionmenu.h:
* gtk/gtkoptionmenu.c: attach/detach to menu widget via
* gtk/gtkmenu.h:
* gtk/gtkmenu.c: new functions gtk_menu_attach_to_widget
and gtk_menu_detach that correspond to the action of
gtk_widget_set_parent and gtk_widget_unparent.
* gtk/widget.c: few fixups.
Tue Feb 3 00:12:00 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtktable.c
Fixed problem with division by zero in row/column-spanned

3
TODO
View File

@ -26,9 +26,6 @@ BUGS
* GtkOptionMenu needs to reference its curent GtkMenuItem.
* Right after creation of an option menu, the first selected menu item is
placed too low (is this still true?).
* GtkMenu needs to properly unref() accelerator tables upon destroy.
* Display of GtkToggleButton is messed up if GtkContainer::container_width

View File

@ -802,6 +802,7 @@ gtk_button_remove (GtkContainer *container,
g_return_if_fail (container != NULL);
g_return_if_fail (GTK_IS_BUTTON (container));
g_return_if_fail (widget != NULL);
button = GTK_BUTTON (container);

View File

@ -1045,7 +1045,7 @@ gtk_file_selection_update_history_menu (GtkFileSelection *fs,
fs->history_menu = gtk_menu_new();
current_dir = g_strdup(current_directory);
current_dir = g_strdup (current_directory);
dir_len = strlen (current_dir);

View File

@ -1150,9 +1150,7 @@ gtk_propagate_event (GtkWidget *widget,
while (!handled_event && tmp)
{
gtk_widget_ref (tmp);
handled_event = (GTK_OBJECT_DESTROYED (tmp) ||
!GTK_WIDGET_IS_SENSITIVE (tmp) ||
gtk_widget_event (tmp, event));
handled_event = !GTK_WIDGET_IS_SENSITIVE (tmp) || gtk_widget_event (tmp, event);
parent = tmp->parent;
gtk_widget_unref (tmp);
tmp = parent;

View File

@ -26,6 +26,15 @@
#define MENU_ITEM_CLASS(w) GTK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass)
typedef struct _GtkMenuAttachData GtkMenuAttachData;
struct _GtkMenuAttachData
{
GtkWidget *attach_widget;
GtkMenuDetachFunc detacher;
};
static void gtk_menu_class_init (GtkMenuClass *klass);
static void gtk_menu_init (GtkMenu *menu);
static void gtk_menu_destroy (GtkObject *object);
@ -52,6 +61,8 @@ static void gtk_menu_show_all (GtkWidget *widget);
static void gtk_menu_hide_all (GtkWidget *widget);
static GtkMenuShellClass *parent_class = NULL;
static const gchar *attach_data_key = "gtk-menu-attach-data";
guint
gtk_menu_get_type ()
@ -125,19 +136,103 @@ gtk_menu_init (GtkMenu *menu)
GTK_MENU_SHELL (menu)->menu_flag = TRUE;
gtk_container_register_toplevel (GTK_CONTAINER (menu));
/* we don't need to register as toplevel anymore,
* since there is the attach/detach functionality in place.
* gtk_container_register_toplevel (GTK_CONTAINER (menu));
*/
}
static void
gtk_menu_destroy (GtkObject *object)
{
GtkMenuAttachData *data;
g_return_if_fail (object != NULL);
g_return_if_fail (GTK_IS_MENU (object));
gtk_container_unregister_toplevel (GTK_CONTAINER (object));
gtk_widget_ref (GTK_WIDGET (object));
data = gtk_object_get_data (object, attach_data_key);
if (data)
gtk_menu_detach (GTK_MENU (object));
/* we don't need this:
* gtk_container_unregister_toplevel (GTK_CONTAINER (object));
*/
if (GTK_OBJECT_CLASS (parent_class)->destroy)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
gtk_widget_unref (GTK_WIDGET (object));
}
void
gtk_menu_attach_to_widget (GtkMenu *menu,
GtkWidget *attach_widget,
GtkMenuDetachFunc detacher)
{
GtkMenuAttachData *data;
g_return_if_fail (menu != NULL);
g_return_if_fail (GTK_IS_MENU (menu));
g_return_if_fail (attach_widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (attach_widget));
g_return_if_fail (detacher != NULL);
/* keep this function in sync with gtk_widget_set_parent()
*/
data = gtk_object_get_data (GTK_OBJECT (menu), attach_data_key);
if (data)
{
g_warning ("gtk_menu_attach_to_widget(): menu already attached to %s",
gtk_type_name (GTK_OBJECT_TYPE (data->attach_widget)));
return;
}
gtk_widget_ref (menu);
gtk_object_sink (GTK_OBJECT (menu));
data = g_new (GtkMenuAttachData, 1);
data->attach_widget = attach_widget;
data->detacher = detacher;
gtk_object_set_data (GTK_OBJECT (menu), attach_data_key, data);
if (GTK_WIDGET_STATE (menu) != GTK_STATE_NORMAL)
gtk_widget_set_state (GTK_WIDGET (menu), GTK_STATE_NORMAL);
/* we don't need to set the style here, since
* we are a toplevel widget.
*/
}
void
gtk_menu_detach (GtkMenu *menu)
{
GtkMenuAttachData *data;
g_return_if_fail (menu != NULL);
g_return_if_fail (GTK_IS_MENU (menu));
/* keep this function in sync with gtk_widget_unparent()
*/
data = gtk_object_get_data (GTK_OBJECT (menu), attach_data_key);
if (!data)
{
g_warning ("gtk_menu_detach(): menu is not attached");
return;
}
gtk_object_remove_data (GTK_OBJECT (menu), attach_data_key);
data->detacher (data->attach_widget, menu);
if (GTK_WIDGET_REALIZED (menu))
gtk_widget_unrealize (GTK_WIDGET (menu));
g_free (data);
gtk_widget_unref (GTK_WIDGET (menu));
}
GtkWidget*

View File

@ -37,10 +37,12 @@ extern "C" {
typedef struct _GtkMenu GtkMenu;
typedef struct _GtkMenuClass GtkMenuClass;
typedef void (*GtkMenuPositionFunc) (GtkMenu *menu,
gint *x,
gint *y,
gpointer user_data);
typedef void (*GtkMenuPositionFunc) (GtkMenu *menu,
gint *x,
gint *y,
gpointer user_data);
typedef void (*GtkMenuDetachFunc) (GtkWidget *attach_widget,
GtkMenu *menu);
struct _GtkMenu
{
@ -84,6 +86,10 @@ void gtk_menu_set_active (GtkMenu *menu,
gint index);
void gtk_menu_set_accelerator_table (GtkMenu *menu,
GtkAcceleratorTable *table);
void gtk_menu_attach_to_widget (GtkMenu *menu,
GtkWidget *attach_widget,
GtkMenuDetachFunc detacher);
void gtk_menu_detach (GtkMenu *menu);
#ifdef __cplusplus

View File

@ -136,6 +136,25 @@ gtk_option_menu_get_menu (GtkOptionMenu *option_menu)
return option_menu->menu;
}
static void
gtk_option_menu_detacher (GtkWidget *widget,
GtkMenu *menu)
{
GtkOptionMenu *option_menu;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_OPTION_MENU (widget));
option_menu = GTK_OPTION_MENU (widget);
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);
option_menu->menu = NULL;
}
void
gtk_option_menu_set_menu (GtkOptionMenu *option_menu,
GtkWidget *menu)
@ -148,8 +167,11 @@ gtk_option_menu_set_menu (GtkOptionMenu *option_menu,
if (option_menu->menu != menu)
{
gtk_option_menu_remove_menu (option_menu);
option_menu->menu = menu;
gtk_widget_ref (option_menu->menu);
gtk_menu_attach_to_widget (GTK_MENU (menu),
GTK_WIDGET (option_menu),
gtk_option_menu_detacher);
gtk_option_menu_calc_size (option_menu);
@ -171,14 +193,7 @@ gtk_option_menu_remove_menu (GtkOptionMenu *option_menu)
g_return_if_fail (GTK_IS_OPTION_MENU (option_menu));
if (option_menu->menu)
{
gtk_option_menu_remove_contents (option_menu);
gtk_signal_disconnect_by_data (GTK_OBJECT (option_menu->menu),
option_menu);
gtk_widget_unref (option_menu->menu);
option_menu->menu = NULL;
}
gtk_menu_detach (GTK_MENU (option_menu->menu));
}
void
@ -214,14 +229,8 @@ gtk_option_menu_destroy (GtkObject *object)
option_menu = GTK_OPTION_MENU (object);
/* gtk_option_menu_remove_contents (option_menu);
*/
if (option_menu->menu)
{
gtk_widget_destroy (option_menu->menu);
gtk_widget_unref (option_menu->menu);
option_menu->menu = NULL;
}
gtk_menu_detach (GTK_MENU (option_menu->menu));
if (GTK_OBJECT_CLASS (parent_class)->destroy)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
@ -445,6 +454,7 @@ gtk_option_menu_update_contents (GtkOptionMenu *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);
child = GTK_BIN (option_menu->menu_item)->child;
if (child)
{
@ -477,10 +487,12 @@ gtk_option_menu_remove_contents (GtkOptionMenu *option_menu)
if (GTK_WIDGET (option_menu->menu_item)->state != GTK_BUTTON (option_menu)->child->state)
gtk_widget_set_state (GTK_BUTTON (option_menu)->child,
GTK_WIDGET (option_menu->menu_item)->state);
GTK_WIDGET_UNSET_FLAGS (GTK_BUTTON (option_menu)->child, GTK_MAPPED | GTK_REALIZED);
/* GTK_WIDGET_UNSET_FLAGS (GTK_BUTTON (option_menu)->child, GTK_MAPPED | GTK_REALIZED); */
gtk_widget_unrealize (GTK_BUTTON (option_menu)->child);
gtk_widget_reparent (GTK_BUTTON (option_menu)->child, option_menu->menu_item);
gtk_container_unblock_resize (GTK_CONTAINER (option_menu));
gtk_widget_unref (option_menu->menu_item);
option_menu->menu_item = NULL;
gtk_container_unblock_resize (GTK_CONTAINER (option_menu));
}
}

View File

@ -1054,9 +1054,7 @@ gtk_widget_setv (GtkWidget *widget,
/*****************************************
* gtk_widget_unparent:
* do any cleanup necessary necessary
* before setting parent = NULL.
* In particular, remove the focus
* properly.
* for setting parent = NULL.
*
* arguments:
*
@ -1073,6 +1071,9 @@ gtk_widget_unparent (GtkWidget *widget)
if (widget->parent == NULL)
return;
/* keep this function in sync with gtk_menu_detach()
*/
toplevel = gtk_widget_get_toplevel (widget);
if (GTK_IS_WINDOW (toplevel))
{
@ -1680,7 +1681,7 @@ gtk_widget_event (GtkWidget *widget,
return_val = FALSE;
gtk_signal_emit (GTK_OBJECT (widget), widget_signals[EVENT], event,
&return_val);
if (return_val)
if (return_val || GTK_OBJECT_DESTROYED (widget))
{
gtk_widget_unref (widget);
return TRUE;
@ -1783,13 +1784,16 @@ gtk_widget_event (GtkWidget *widget,
default:
g_warning ("could not determine signal number for event: %d", event->type);
gtk_widget_unref (widget);
return return_val;
return TRUE;
}
if (signal_num != -1)
gtk_signal_emit (GTK_OBJECT (widget), widget_signals[signal_num], event, &return_val);
return_val |= GTK_OBJECT_DESTROYED (widget);
gtk_widget_unref (widget);
return return_val;
}
@ -1858,8 +1862,10 @@ gtk_widget_reparent (GtkWidget *widget,
GtkWidget *new_parent)
{
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (new_parent != NULL);
g_return_if_fail (GTK_IS_CONTAINER (new_parent));
g_return_if_fail (widget->parent != NULL);
if (widget->parent != new_parent)
{
@ -2224,8 +2230,11 @@ gtk_widget_set_parent (GtkWidget *widget,
g_assert (widget->parent == NULL);
g_return_if_fail (parent != NULL);
/* keep this function in sync with gtk_menu_attach_to_widget()
*/
gtk_widget_ref (widget);
gtk_object_sink (GTK_OBJECT(widget));
gtk_object_sink (GTK_OBJECT (widget));
widget->parent = parent;
if (GTK_WIDGET_STATE (parent) != GTK_STATE_NORMAL)