diff options
author | Elliot Lee <sopwith@src.gnome.org> | 1998-01-08 04:13:13 +0000 |
---|---|---|
committer | Elliot Lee <sopwith@src.gnome.org> | 1998-01-08 04:13:13 +0000 |
commit | 5eee6416f547be6ff94599f27582c1862fd6d397 (patch) | |
tree | abb3b8277a1408d6f91e82479b8aa593ecd2c638 /gtk | |
parent | 4ccc005197e8cf1ecdd1b32a68e8a346a5f164db (diff) | |
download | gdk-pixbuf-5eee6416f547be6ff94599f27582c1862fd6d397.tar.gz |
New widget (GtkComboBox) and fixed gdk_window_init to initialize gdk_root_parent some more
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/Makefile.am | 2 | ||||
-rw-r--r-- | gtk/gtk.h | 1 | ||||
-rw-r--r-- | gtk/gtkcombobox.c | 393 | ||||
-rw-r--r-- | gtk/gtkcombobox.h | 66 | ||||
-rw-r--r-- | gtk/gtkmain.c | 9 | ||||
-rw-r--r-- | gtk/gtkmain.h | 2 | ||||
-rw-r--r-- | gtk/testgtk.c | 17 |
7 files changed, 484 insertions, 6 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am index ff0c18e2b..a6ace7c35 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -18,6 +18,7 @@ libgtk_la_SOURCES = \ gtkcheckmenuitem.c \ gtkclist.c \ gtkcolorsel.c \ + gtkcombobox.c \ gtkcontainer.c \ gtkcurve.c \ gtkdata.c \ @@ -106,6 +107,7 @@ gtkinclude_HEADERS = \ gtkcheckmenuitem.h \ gtkclist.h \ gtkcolorsel.h \ + gtkcombobox.h \ gtkcontainer.h \ gtkcurve.h \ gtkdata.h \ @@ -33,6 +33,7 @@ #include <gtk/gtkcheckmenuitem.h> #include <gtk/gtkclist.h> #include <gtk/gtkcolorsel.h> +#include <gtk/gtkcombobox.h> #include <gtk/gtkcontainer.h> #include <gtk/gtkcurve.h> #include <gtk/gtkdata.h> diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c new file mode 100644 index 000000000..a9e101ff2 --- /dev/null +++ b/gtk/gtkcombobox.c @@ -0,0 +1,393 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * Copyright (C) 1998 Elliot Lee + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* NOTES about this widget: + It would be nice if we kept track of the last menu item that + people selected, so that we could allow choosing text by using + up/down arrows. +*/ +#include <ctype.h> +#include <string.h> +#include "gdk/gdkx.h" +#include "gdk/gdkkeysyms.h" +#include "gdk/gdki18n.h" +#include "gtkcombobox.h" +#include "gtkmain.h" +#include "gtksignal.h" +#include "gtkmenu.h" +#include "gtkmenuitem.h" +#include "gtklabel.h" +#include "gtkbin.h" + +#define ARROW_SIZE_X 20 +#define ARROW_SIZE_Y 20 +#define ARROW_PADDING 4 + +static void gtk_combo_box_class_init (GtkComboBoxClass *class); +static void gtk_combo_box_init (GtkComboBox *combobox); +static void gtk_combo_box_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_combo_box_size_allocate(GtkWidget *widget, + GtkAllocation *allocation); +static void gtk_combo_box_draw (GtkWidget *widget, + GdkRectangle *area); +static void gtk_combo_box_draw_arrow (GtkWidget *widget); +static gint gtk_combo_box_expose (GtkWidget *object, + GdkEventExpose *event); +static void gtk_combo_box_destroy (GtkObject *object); +#if 0 +static gint gtk_combo_box_key_press (GtkWidget *widget, + GdkEventKey *event); +#endif +static gint gtk_combo_box_button_press (GtkWidget *widget, + GdkEventButton *event); +static void gtk_combo_box_realize (GtkWidget *widget); +static void gtk_combo_box_item_activate(GtkWidget *widget, + GtkComboBox *cb); +static void gtk_combo_box_set_down (GtkWidget *widget, + GtkComboBox *cb); +static void gtk_combo_box_set_up (GtkWidget *widget, + GtkComboBox *cb); + +static GtkEntryClass *parent_class = NULL; + +guint +gtk_combo_box_get_type () +{ + static guint combo_box_type = 0; + + if (!combo_box_type) + { + GtkTypeInfo combo_box_info = + { + "GtkComboBox", + sizeof (GtkComboBox), + sizeof (GtkComboBoxClass), + (GtkClassInitFunc) gtk_combo_box_class_init, + (GtkObjectInitFunc) gtk_combo_box_init, + (GtkArgFunc) NULL, + }; + + combo_box_type = gtk_type_unique (gtk_entry_get_type (), &combo_box_info); + } + + return combo_box_type; +} + +static void +gtk_combo_box_class_init (GtkComboBoxClass *class) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + object_class = (GtkObjectClass *) class; + widget_class = (GtkWidgetClass *) class; + + parent_class = gtk_type_class (gtk_entry_get_type ()); + + object_class->destroy = gtk_combo_box_destroy; + + widget_class->button_press_event = gtk_combo_box_button_press; +#if 0 + widget_class->key_press_event = gtk_combo_box_key_press; +#endif + widget_class->size_request = gtk_combo_box_size_request; + widget_class->size_allocate = gtk_combo_box_size_allocate; + widget_class->draw = gtk_combo_box_draw; + widget_class->expose_event = gtk_combo_box_expose; + widget_class->realize = gtk_combo_box_realize; + +} + +static void +gtk_combo_box_init (GtkComboBox *combobox) +{ + GTK_WIDGET_SET_FLAGS (combobox, GTK_CAN_FOCUS); + + combobox->popdown = NULL; + combobox->menu_is_down = FALSE; +} + +GtkWidget* +gtk_combo_box_new (GList *popdown_strings) +{ + GtkWidget *retval = GTK_WIDGET (gtk_type_new (gtk_combo_box_get_type ())); + if(popdown_strings) + gtk_combo_box_set_popdown_strings(GTK_COMBO_BOX(retval), popdown_strings); + return retval; +} + +GtkWidget* +gtk_combo_box_new_with_max_length (GList *popdown_strings, + guint16 max) +{ + GtkWidget *retval; + retval = GTK_WIDGET(gtk_type_new (gtk_combo_box_get_type ())); + GTK_ENTRY(retval)->text_max_length = max; + if(popdown_strings) + gtk_combo_box_set_popdown_strings(GTK_COMBO_BOX(retval), popdown_strings); + return retval; +} + +void +gtk_combo_box_set_popdown_strings(GtkComboBox *combobox, + GList *popdown_strings) +{ + GList *t; + + g_return_if_fail(combobox != NULL); + g_return_if_fail(popdown_strings != NULL); + if(combobox->popdown) + gtk_widget_destroy(combobox->popdown); + + combobox->popdown = gtk_menu_new(); + gtk_signal_connect(GTK_OBJECT(combobox->popdown), + "show", + GTK_SIGNAL_FUNC(gtk_combo_box_set_down), + combobox); + gtk_signal_connect(GTK_OBJECT(combobox->popdown), + "hide", + GTK_SIGNAL_FUNC(gtk_combo_box_set_up), + combobox); + + for(t = popdown_strings; t; t = t->next) + { + GtkWidget *mitem; + mitem = gtk_menu_item_new_with_label(t->data); + gtk_widget_show(mitem); + gtk_menu_append(GTK_MENU(combobox->popdown), mitem); + gtk_signal_connect(GTK_OBJECT(mitem), "activate", + GTK_SIGNAL_FUNC(gtk_combo_box_item_activate), + combobox); + } + + if(GTK_WIDGET_REALIZED(combobox)) + gtk_widget_set_usize(combobox->popdown, + GTK_WIDGET(combobox)->requisition.width, + -1); +} + +static void +gtk_combo_box_realize(GtkWidget *widget) +{ + GtkComboBox *cb; + + g_return_if_fail(widget != NULL); + g_return_if_fail(GTK_IS_COMBO_BOX(widget)); + + cb = GTK_COMBO_BOX(widget); + GTK_WIDGET_CLASS(parent_class)->realize(widget); + gdk_window_set_background (GTK_WIDGET(widget)->window, + &widget->style->bg[GTK_WIDGET_STATE(widget)]); + + if(cb->popdown) + { + gtk_widget_set_usize(cb->popdown, + widget->requisition.width, + -1); + } +} + +static void +gtk_combo_box_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_COMBO_BOX (widget)); + g_return_if_fail (requisition != NULL); + + GTK_WIDGET_CLASS(parent_class)->size_request(widget, requisition); + + requisition->width += ARROW_SIZE_X; + if(requisition->height < ARROW_SIZE_Y) + requisition->height = ARROW_SIZE_Y; +} + +static void +gtk_combo_box_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkComboBox *cb; + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_COMBO_BOX (widget)); + g_return_if_fail (allocation != NULL); + + cb = GTK_COMBO_BOX(widget); + + widget->allocation = *allocation; + + GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation); +#define INNER_BORDER 2 + gdk_window_resize(GTK_ENTRY(widget)->text_area, + allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2 - ARROW_SIZE_X, + widget->requisition.height - (widget->style->klass->ythickness + INNER_BORDER) * 2); +} + +static void +gtk_combo_box_draw_arrow (GtkWidget *widget) +{ + gint sx, sy; + + sx = widget->allocation.width - ARROW_SIZE_X; + sy = ARROW_PADDING; + widget->style->klass->draw_arrow(widget->style, + widget->window, + GTK_WIDGET_STATE(widget), + GTK_SHADOW_OUT, + GTK_ARROW_DOWN, TRUE, + sx, sy, + ARROW_SIZE_X - ARROW_PADDING, + ARROW_SIZE_Y - ARROW_PADDING - 2); +} + +static void +gtk_combo_box_draw (GtkWidget *widget, + GdkRectangle *area) +{ + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_COMBO_BOX (widget)); + g_return_if_fail (area != NULL); + + if (GTK_WIDGET_DRAWABLE (widget)) + { + gtk_combo_box_draw_arrow(widget); + GTK_WIDGET_CLASS(parent_class)->draw(widget, area); + } +} + +static gint +gtk_combo_box_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + gint retval; + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + gtk_combo_box_draw_arrow(widget); + retval = GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event); + return retval; +} + +static void +gtk_combo_box_position_menu(GtkMenu *menu, + gint *x, + gint *y, + gpointer user_data) +{ + GtkComboBox *cb; + GtkWidget *widget; + gint rootw, rooth, wy; + + g_return_if_fail(user_data != NULL); + g_return_if_fail(GTK_IS_COMBO_BOX(user_data)); + + cb = GTK_COMBO_BOX(user_data); + widget = GTK_WIDGET(user_data); + + gdk_window_get_origin(widget->window, x, &wy); + *y = wy + widget->allocation.height; + + gdk_window_get_size(GDK_ROOT_PARENT(), &rootw, &rooth); + + /* This check isn't perfect - what if the menu is too big to fit on + the screen going either up or down? *sigh* not a perfect + world, I guess */ + if((*y + GTK_WIDGET(menu)->requisition.height) > rooth) + *y = wy - GTK_WIDGET(menu)->requisition.height; +} + +static void +gtk_combo_box_set_down (GtkWidget *widget, + GtkComboBox *cb) +{ + g_return_if_fail(GTK_IS_COMBO_BOX(cb)); + + cb->menu_is_down = TRUE; +} + +static void +gtk_combo_box_set_up (GtkWidget *widget, + GtkComboBox *cb) +{ + g_return_if_fail(GTK_IS_COMBO_BOX(cb)); + + cb->menu_is_down = FALSE; +} + +static gint +gtk_combo_box_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + GtkComboBox *cb; + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + cb = GTK_COMBO_BOX(widget); + + if(event->window == widget->window + && event->x > (widget->allocation.width - ARROW_SIZE_X) + && event->x < widget->allocation.width + && event->button == 1) + { + gtk_menu_popup(GTK_MENU(cb->popdown), + NULL, NULL, + gtk_combo_box_position_menu, + cb, event->button, + event->time); + return TRUE; + } + else + return GTK_WIDGET_CLASS(parent_class)->button_press_event(widget, event); +} + +#if 0 +static gint +gtk_combo_box_key_press (GtkWidget *widget, + GdkEventKey *event) +{ + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event); +} +#endif + +static void +gtk_combo_box_destroy(GtkObject *object) +{ + GtkComboBox *cb; + g_return_if_fail(GTK_IS_COMBO_BOX(object)); + + cb = GTK_COMBO_BOX(object); + if(cb->popdown) + gtk_widget_destroy(cb->popdown); + + GTK_OBJECT_CLASS(parent_class)->destroy(object); +} + +static void gtk_combo_box_item_activate(GtkWidget *widget, + GtkComboBox *cb) +{ + char *newtext = GTK_LABEL(GTK_BIN(widget)->child)->label; + + gtk_entry_set_text(GTK_ENTRY(cb), newtext); +} diff --git a/gtk/gtkcombobox.h b/gtk/gtkcombobox.h new file mode 100644 index 000000000..4aab5548c --- /dev/null +++ b/gtk/gtkcombobox.h @@ -0,0 +1,66 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __GTK_COMBO_H__ +#define __GTK_COMBO_H__ + + +#include <gdk/gdk.h> +#include <gtk/gtkentry.h> + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GTK_COMBO_BOX(obj) GTK_CHECK_CAST (obj, gtk_combo_box_get_type (), GtkComboBox) +#define GTK_COMBO_BOX_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_combo_box_get_type (), GtkComboBoxClass) +#define GTK_IS_COMBO_BOX(obj) GTK_CHECK_TYPE (obj, gtk_combo_box_get_type ()) + + +typedef struct _GtkComboBox GtkComboBox; +typedef struct _GtkComboBoxClass GtkComboBoxClass; + +struct _GtkComboBox +{ + GtkEntry parent_widget; + GtkWidget *popdown; + gboolean menu_is_down; +}; + +struct _GtkComboBoxClass +{ + GtkEntryClass parent_class; +}; + + +guint gtk_combo_box_get_type (void); +/* These GList's should be lists of strings that should be placed + in the popdown menu */ +GtkWidget* gtk_combo_box_new (GList *popdown_strings); +GtkWidget* gtk_combo_box_new_with_max_length (GList *popdown_strings, + guint16 max); +void gtk_combo_box_set_popdown_strings(GtkComboBox *combobox, + GList *popdown_strings); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GTK_ENTRY_H__ */ diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 9c6c58aaa..482712b1a 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -222,8 +222,13 @@ gtk_main_quit () done = TRUE; } +gint gtk_main_iteration () +{ + return gtk_main_iteration_do(TRUE); +} + gint -gtk_main_iteration () +gtk_main_iteration_do (gboolean blocking) { GtkWidget *event_widget; GtkWidget *grab_widget; @@ -267,7 +272,7 @@ gtk_main_iteration () */ gtk_handle_timer (); - event = gdk_event_get (); + if(blocking) event = gdk_event_get (); } /* "gdk_event_get" can return FALSE if the timer goes off diff --git a/gtk/gtkmain.h b/gtk/gtkmain.h index ae588d4d2..708b2c1d6 100644 --- a/gtk/gtkmain.h +++ b/gtk/gtkmain.h @@ -38,6 +38,8 @@ void gtk_main (void); guint gtk_main_level (void); void gtk_main_quit (void); gint gtk_main_iteration (void); +/* gtk_main_iteration() calls gtk_main_iteration_do(TRUE) */ +gint gtk_main_iteration_do (gboolean blocking); gint gtk_true (void); gint gtk_false (void); diff --git a/gtk/testgtk.c b/gtk/testgtk.c index 9c6aaf795..d3d9a46e2 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -20,7 +20,6 @@ #include "gtk.h" #include "../gdk/gdk.h" #include "../gdk/gdkx.h" -#include "gtkhandlebox.h" void destroy_window (GtkWidget *widget, @@ -1346,12 +1345,16 @@ create_entry () GtkWidget *box1; GtkWidget *box2; GtkWidget *editable_check; - GtkWidget *entry; + GtkWidget *entry, *cb; GtkWidget *button; GtkWidget *separator; + GList *cbitems = NULL; - /* if (!window) */ + if (!window) { + cbitems = g_list_append(cbitems, "item1"); + cbitems = g_list_append(cbitems, "item2"); + cbitems = g_list_append(cbitems, "and item3"); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_signal_connect (GTK_OBJECT (window), "destroy", @@ -1376,13 +1379,19 @@ create_entry () gtk_widget_show (box2); entry = gtk_entry_new (); - /* gtk_widget_set_usize (entry, 0, 25); */ gtk_entry_set_text (GTK_ENTRY (entry), "hello world"); gtk_entry_select_region (GTK_ENTRY (entry), 0, GTK_ENTRY(entry)->text_length); gtk_box_pack_start (GTK_BOX (box2), entry, TRUE, TRUE, 0); gtk_widget_show (entry); + cb = gtk_combo_box_new (cbitems); + gtk_entry_set_text (GTK_ENTRY (cb), "hello world"); + gtk_entry_select_region (GTK_ENTRY (cb), + 0, GTK_ENTRY(entry)->text_length); + gtk_box_pack_start (GTK_BOX (box2), cb, TRUE, TRUE, 0); + gtk_widget_show (cb); + editable_check = gtk_check_button_new_with_label("Editable"); gtk_box_pack_start (GTK_BOX (box2), editable_check, TRUE, TRUE, 0); gtk_signal_connect (GTK_OBJECT(editable_check), "toggled", |