diff --git a/ChangeLog b/ChangeLog index fe9e992217..d65c6f4744 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +Thu Feb 19 05:40:51 1998 Tim Janik + + * gtk/gtknotebook.h: + * gtk/gtknotebook.c: + applied gtk-hamann_jeske-980218-0.patch.gz, a patch from + Lars Hamann and Stefan Jeske which introduces major + usability improvements. + fixed bugs are: + - container border_width>0 does now work correctly for show_tabs==TRUE + and for tab_pos=GTK_POS_BOTTOM/GTK_POS_RIGHT. + - toggleing visibility of the tab labels works now. + - emission of GtkNotebook:switch_page and all page changes + also the signature for the GtkNotebook:switch_page signal changed, + callbacks should now look like: + gint notebook_switch_page (GtkWidget *widget, GtkNotebookPage *page, + gint page_num, gpointer data); + Wed Feb 18 01:09:56 PST 1998 Jay Painter * gdk/gdk.c: fixed ambigous else compiler warning * gtk/gtkgamma.c: fixed ambigous else compiler warning diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index fe9e992217..d65c6f4744 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,20 @@ +Thu Feb 19 05:40:51 1998 Tim Janik + + * gtk/gtknotebook.h: + * gtk/gtknotebook.c: + applied gtk-hamann_jeske-980218-0.patch.gz, a patch from + Lars Hamann and Stefan Jeske which introduces major + usability improvements. + fixed bugs are: + - container border_width>0 does now work correctly for show_tabs==TRUE + and for tab_pos=GTK_POS_BOTTOM/GTK_POS_RIGHT. + - toggleing visibility of the tab labels works now. + - emission of GtkNotebook:switch_page and all page changes + also the signature for the GtkNotebook:switch_page signal changed, + callbacks should now look like: + gint notebook_switch_page (GtkWidget *widget, GtkNotebookPage *page, + gint page_num, gpointer data); + Wed Feb 18 01:09:56 PST 1998 Jay Painter * gdk/gdk.c: fixed ambigous else compiler warning * gtk/gtkgamma.c: fixed ambigous else compiler warning diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index fe9e992217..d65c6f4744 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,20 @@ +Thu Feb 19 05:40:51 1998 Tim Janik + + * gtk/gtknotebook.h: + * gtk/gtknotebook.c: + applied gtk-hamann_jeske-980218-0.patch.gz, a patch from + Lars Hamann and Stefan Jeske which introduces major + usability improvements. + fixed bugs are: + - container border_width>0 does now work correctly for show_tabs==TRUE + and for tab_pos=GTK_POS_BOTTOM/GTK_POS_RIGHT. + - toggleing visibility of the tab labels works now. + - emission of GtkNotebook:switch_page and all page changes + also the signature for the GtkNotebook:switch_page signal changed, + callbacks should now look like: + gint notebook_switch_page (GtkWidget *widget, GtkNotebookPage *page, + gint page_num, gpointer data); + Wed Feb 18 01:09:56 PST 1998 Jay Painter * gdk/gdk.c: fixed ambigous else compiler warning * gtk/gtkgamma.c: fixed ambigous else compiler warning diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index fe9e992217..d65c6f4744 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,20 @@ +Thu Feb 19 05:40:51 1998 Tim Janik + + * gtk/gtknotebook.h: + * gtk/gtknotebook.c: + applied gtk-hamann_jeske-980218-0.patch.gz, a patch from + Lars Hamann and Stefan Jeske which introduces major + usability improvements. + fixed bugs are: + - container border_width>0 does now work correctly for show_tabs==TRUE + and for tab_pos=GTK_POS_BOTTOM/GTK_POS_RIGHT. + - toggleing visibility of the tab labels works now. + - emission of GtkNotebook:switch_page and all page changes + also the signature for the GtkNotebook:switch_page signal changed, + callbacks should now look like: + gint notebook_switch_page (GtkWidget *widget, GtkNotebookPage *page, + gint page_num, gpointer data); + Wed Feb 18 01:09:56 PST 1998 Jay Painter * gdk/gdk.c: fixed ambigous else compiler warning * gtk/gtkgamma.c: fixed ambigous else compiler warning diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index fe9e992217..d65c6f4744 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,20 @@ +Thu Feb 19 05:40:51 1998 Tim Janik + + * gtk/gtknotebook.h: + * gtk/gtknotebook.c: + applied gtk-hamann_jeske-980218-0.patch.gz, a patch from + Lars Hamann and Stefan Jeske which introduces major + usability improvements. + fixed bugs are: + - container border_width>0 does now work correctly for show_tabs==TRUE + and for tab_pos=GTK_POS_BOTTOM/GTK_POS_RIGHT. + - toggleing visibility of the tab labels works now. + - emission of GtkNotebook:switch_page and all page changes + also the signature for the GtkNotebook:switch_page signal changed, + callbacks should now look like: + gint notebook_switch_page (GtkWidget *widget, GtkNotebookPage *page, + gint page_num, gpointer data); + Wed Feb 18 01:09:56 PST 1998 Jay Painter * gdk/gdk.c: fixed ambigous else compiler warning * gtk/gtkgamma.c: fixed ambigous else compiler warning diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index fe9e992217..d65c6f4744 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,20 @@ +Thu Feb 19 05:40:51 1998 Tim Janik + + * gtk/gtknotebook.h: + * gtk/gtknotebook.c: + applied gtk-hamann_jeske-980218-0.patch.gz, a patch from + Lars Hamann and Stefan Jeske which introduces major + usability improvements. + fixed bugs are: + - container border_width>0 does now work correctly for show_tabs==TRUE + and for tab_pos=GTK_POS_BOTTOM/GTK_POS_RIGHT. + - toggleing visibility of the tab labels works now. + - emission of GtkNotebook:switch_page and all page changes + also the signature for the GtkNotebook:switch_page signal changed, + callbacks should now look like: + gint notebook_switch_page (GtkWidget *widget, GtkNotebookPage *page, + gint page_num, gpointer data); + Wed Feb 18 01:09:56 PST 1998 Jay Painter * gdk/gdk.c: fixed ambigous else compiler warning * gtk/gtkgamma.c: fixed ambigous else compiler warning diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index fe9e992217..d65c6f4744 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,20 @@ +Thu Feb 19 05:40:51 1998 Tim Janik + + * gtk/gtknotebook.h: + * gtk/gtknotebook.c: + applied gtk-hamann_jeske-980218-0.patch.gz, a patch from + Lars Hamann and Stefan Jeske which introduces major + usability improvements. + fixed bugs are: + - container border_width>0 does now work correctly for show_tabs==TRUE + and for tab_pos=GTK_POS_BOTTOM/GTK_POS_RIGHT. + - toggleing visibility of the tab labels works now. + - emission of GtkNotebook:switch_page and all page changes + also the signature for the GtkNotebook:switch_page signal changed, + callbacks should now look like: + gint notebook_switch_page (GtkWidget *widget, GtkNotebookPage *page, + gint page_num, gpointer data); + Wed Feb 18 01:09:56 PST 1998 Jay Painter * gdk/gdk.c: fixed ambigous else compiler warning * gtk/gtkgamma.c: fixed ambigous else compiler warning diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c index ee96fc7d69..a638472e1d 100644 --- a/gtk/gtknotebook.c +++ b/gtk/gtknotebook.c @@ -17,11 +17,20 @@ */ #include "gtknotebook.h" #include "gtksignal.h" +#include "gtkmain.h" +#include "gtkmenu.h" +#include "gtkmenuitem.h" +#include "gtklabel.h" +#include +#include -#define CHILD_SPACING 2 #define TAB_OVERLAP 2 #define TAB_CURVATURE 1 +#define ARROW_SIZE 11 +#define ARROW_SPACING 3 +#define NOTEBOOK_INIT_SCROLL_DELAY (200) +#define NOTEBOOK_SCROLL_DELAY (100) enum { @@ -29,52 +38,106 @@ enum { LAST_SIGNAL }; -typedef void (*GtkNotebookSignal) (GtkObject *object, - gpointer arg1, - gpointer data); +enum { + STEP_PREV, + STEP_NEXT +}; -static void gtk_notebook_class_init (GtkNotebookClass *klass); -static void gtk_notebook_init (GtkNotebook *notebook); -static void gtk_notebook_map (GtkWidget *widget); -static void gtk_notebook_unmap (GtkWidget *widget); -static void gtk_notebook_realize (GtkWidget *widget); -static void gtk_notebook_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_notebook_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static void gtk_notebook_paint (GtkWidget *widget, - GdkRectangle *area); -static void gtk_notebook_draw (GtkWidget *widget, - GdkRectangle *area); -static gint gtk_notebook_expose (GtkWidget *widget, - GdkEventExpose *event); -static gint gtk_notebook_button_press (GtkWidget *widget, - GdkEventButton *event); -static void gtk_notebook_add (GtkContainer *container, - GtkWidget *widget); -static void gtk_notebook_remove (GtkContainer *container, - GtkWidget *widget); -static void gtk_notebook_foreach (GtkContainer *container, - GtkCallback callback, - gpointer callback_data); -static void gtk_notebook_switch_page (GtkNotebook *notebook, - GtkNotebookPage *page); -static void gtk_notebook_draw_tab (GtkNotebook *notebook, - GtkNotebookPage *page, - GdkRectangle *area); -static void gtk_notebook_pages_allocate (GtkNotebook *notebook, - GtkAllocation *allocation); -static void gtk_notebook_page_allocate (GtkNotebook *notebook, - GtkNotebookPage *page, - GtkAllocation *allocation); +typedef void (*GtkNotebookSignal) (GtkObject *object, + GtkNotebookPage *arg1, + gint arg2, + gpointer data); -static void gtk_real_notebook_switch_page (GtkNotebook *notebook, - GtkNotebookPage *page); +static void gtk_notebook_class_init (GtkNotebookClass *klass); +static void gtk_notebook_init (GtkNotebook *notebook); +static void gtk_notebook_destroy (GtkObject *object); +static void gtk_notebook_map (GtkWidget *widget); +static void gtk_notebook_unmap (GtkWidget *widget); +static void gtk_notebook_realize (GtkWidget *widget); +static void gtk_notebook_panel_realize (GtkNotebook *notebook); +static void gtk_notebook_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_notebook_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void gtk_notebook_paint (GtkWidget *widget, + GdkRectangle *area); +static void gtk_notebook_draw (GtkWidget *widget, + GdkRectangle *area); +static gint gtk_notebook_expose (GtkWidget *widget, + GdkEventExpose *event); +static gint gtk_notebook_button_press (GtkWidget *widget, + GdkEventButton *event); +static gint gtk_notebook_button_release (GtkWidget *widget, + GdkEventButton *event); +static gint gtk_notebook_enter_notify (GtkWidget *widget, + GdkEventCrossing *event); +static gint gtk_notebook_leave_notify (GtkWidget *widget, + GdkEventCrossing *event); +static gint gtk_notebook_motion_notify (GtkWidget *widget, + GdkEventMotion *event); +static gint gtk_notebook_key_press (GtkWidget *widget, + GdkEventKey *event); +static void gtk_notebook_add (GtkContainer *container, + GtkWidget *widget); +static void gtk_notebook_remove (GtkContainer *container, + GtkWidget *widget); +static void gtk_notebook_real_remove (GtkNotebook *notebook, + GList *list, + gint page_num); +static void gtk_notebook_foreach (GtkContainer *container, + GtkCallback callback, + gpointer callback_data); +static void gtk_notebook_switch_page (GtkNotebook *notebook, + GtkNotebookPage *page, + gint page_num); +static void gtk_notebook_draw_tab (GtkNotebook *notebook, + GtkNotebookPage *page, + GdkRectangle *area); +static gint gtk_notebook_focus_in (GtkWidget *widget, + GdkEventFocus *event); +static gint gtk_notebook_focus_out (GtkWidget *widget, + GdkEventFocus *event); +static void gtk_notebook_draw_focus (GtkWidget *widget); +static void gtk_notebook_focus_changed (GtkNotebook *notebook, + GtkNotebookPage *old_page); +static void gtk_notebook_pages_allocate (GtkNotebook *notebook, + GtkAllocation *allocation); +static void gtk_notebook_page_allocate (GtkNotebook *notebook, + GtkNotebookPage *page, + GtkAllocation *allocation); +static void gtk_notebook_draw_arrow (GtkNotebook *notebook, + guint arrow); +static gint gtk_notebook_timer (GtkNotebook *notebook); +static gint gtk_notebook_focus (GtkContainer *container, + GtkDirectionType direction); +static gint gtk_notebook_page_select (GtkNotebook *notebook); +static void gtk_notebook_calc_tabs (GtkNotebook *notebook, + GList *start, + GList **end, + gint *tab_space, + guint direction); +static void gtk_notebook_expose_tabs (GtkNotebook *notebook); +static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook, + GList *new_child); +static void gtk_real_notebook_switch_page (GtkNotebook *notebook, + GtkNotebookPage *page); +static void gtk_notebook_marshal_signal (GtkObject *object, + GtkSignalFunc func, + gpointer func_data, + GtkArg *args); +static void gtk_notebook_menu_switch_page (GtkWidget *widget, + GtkNotebookPage *page); +static void gtk_notebook_update_labels (GtkNotebook *notebook, + GList *list, + gint page_num); +static void gtk_notebook_menu_detacher (GtkWidget *widget, + GtkMenu *menu); +static void gtk_notebook_menu_label_unparent (GtkWidget *widget, + gpointer data); +static void gtk_notebook_menu_item_create (GtkNotebook *notebook, + GtkNotebookPage *page, + gint position); -static void gtk_notebook_marshal_signal (GtkObject *object, - GtkSignalFunc func, - gpointer func_data, - GtkArg *args); static GtkContainerClass *parent_class = NULL; static gint notebook_signals[LAST_SIGNAL] = { 0 }; @@ -122,11 +185,14 @@ gtk_notebook_class_init (GtkNotebookClass *class) object_class->type, GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page), gtk_notebook_marshal_signal, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); + GTK_TYPE_NONE, 2, + GTK_TYPE_POINTER, + GTK_TYPE_INT); gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL); + object_class->destroy = gtk_notebook_destroy; + widget_class->map = gtk_notebook_map; widget_class->unmap = gtk_notebook_unmap; widget_class->realize = gtk_notebook_realize; @@ -135,10 +201,19 @@ gtk_notebook_class_init (GtkNotebookClass *class) widget_class->draw = gtk_notebook_draw; widget_class->expose_event = gtk_notebook_expose; widget_class->button_press_event = gtk_notebook_button_press; + widget_class->button_release_event = gtk_notebook_button_release; + widget_class->enter_notify_event = gtk_notebook_enter_notify; + widget_class->leave_notify_event = gtk_notebook_leave_notify; + widget_class->motion_notify_event = gtk_notebook_motion_notify; + widget_class->key_press_event = gtk_notebook_key_press; + widget_class->focus_in_event = gtk_notebook_focus_in; + widget_class->focus_out_event = gtk_notebook_focus_out; + widget_class->draw_focus = gtk_notebook_draw_focus; container_class->add = gtk_notebook_add; container_class->remove = gtk_notebook_remove; container_class->foreach = gtk_notebook_foreach; + container_class->focus = gtk_notebook_focus; class->switch_page = gtk_real_notebook_switch_page; } @@ -146,11 +221,24 @@ gtk_notebook_class_init (GtkNotebookClass *class) static void gtk_notebook_init (GtkNotebook *notebook) { + GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS); + notebook->cur_page = NULL; notebook->children = NULL; + notebook->first_tab = NULL; + notebook->focus_tab = NULL; + notebook->panel = NULL; + notebook->menu = NULL; + + notebook->tab_border = 3; notebook->show_tabs = TRUE; notebook->show_border = TRUE; notebook->tab_pos = GTK_POS_TOP; + notebook->scrollable = FALSE; + notebook->in_child = 0; + notebook->click_child = 0; + notebook->button = 0; + notebook->need_timer = 0; } GtkWidget* @@ -159,6 +247,23 @@ gtk_notebook_new () return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ())); } +static void +gtk_notebook_destroy (GtkObject *object) +{ + GtkNotebook *notebook; + + g_return_if_fail (object != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (object)); + + notebook = GTK_NOTEBOOK (object); + + if (notebook->menu) + gtk_notebook_popup_disable (notebook); + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + void gtk_notebook_append_page (GtkNotebook *notebook, GtkWidget *child, @@ -167,9 +272,21 @@ gtk_notebook_append_page (GtkNotebook *notebook, g_return_if_fail (notebook != NULL); g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); g_return_if_fail (child != NULL); - g_return_if_fail (tab_label != NULL); - gtk_notebook_insert_page (notebook, child, tab_label, -1); + gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1); +} + +void +gtk_notebook_append_page_menu (GtkNotebook *notebook, + GtkWidget *child, + GtkWidget *tab_label, + GtkWidget *menu_label) +{ + g_return_if_fail (notebook != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + g_return_if_fail (child != NULL); + + gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1); } void @@ -180,9 +297,21 @@ gtk_notebook_prepend_page (GtkNotebook *notebook, g_return_if_fail (notebook != NULL); g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); g_return_if_fail (child != NULL); - g_return_if_fail (tab_label != NULL); - gtk_notebook_insert_page (notebook, child, tab_label, 0); + gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0); +} + +void +gtk_notebook_prepend_page_menu (GtkNotebook *notebook, + GtkWidget *child, + GtkWidget *tab_label, + GtkWidget *menu_label) +{ + g_return_if_fail (notebook != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + g_return_if_fail (child != NULL); + + gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0); } void @@ -190,6 +319,20 @@ gtk_notebook_insert_page (GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label, gint position) +{ + g_return_if_fail (notebook != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + g_return_if_fail (child != NULL); + + gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position); +} + +void +gtk_notebook_insert_page_menu (GtkNotebook *notebook, + GtkWidget *child, + GtkWidget *tab_label, + GtkWidget *menu_label, + gint position) { GtkNotebookPage *page; gint nchildren; @@ -197,17 +340,17 @@ gtk_notebook_insert_page (GtkNotebook *notebook, g_return_if_fail (notebook != NULL); g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); g_return_if_fail (child != NULL); - g_return_if_fail (tab_label != NULL); page = g_new (GtkNotebookPage, 1); page->child = child; - page->tab_label = tab_label; page->requisition.width = 0; page->requisition.height = 0; page->allocation.x = 0; page->allocation.y = 0; page->allocation.width = 0; page->allocation.height = 0; + page->default_menu = FALSE; + page->default_tab = FALSE; nchildren = g_list_length (notebook->children); if ((position < 0) || (position > nchildren)) @@ -215,12 +358,40 @@ gtk_notebook_insert_page (GtkNotebook *notebook, notebook->children = g_list_insert (notebook->children, page, position); - if (!notebook->cur_page) - notebook->cur_page = page; + if (!tab_label) + { + tab_label = gtk_label_new (""); + page->default_tab = TRUE; + } + page->tab_label = tab_label; + page->menu_label = menu_label; + + if (!menu_label) + page->default_menu = TRUE; + else + { + gtk_widget_ref (page->menu_label); + gtk_object_sink (GTK_OBJECT(page->menu_label)); + } + + if (notebook->menu) + gtk_notebook_menu_item_create (notebook, page, position); + + gtk_notebook_update_labels + (notebook, g_list_nth (notebook->children, position), position + 1); + + if (!notebook->first_tab) + notebook->first_tab = notebook->children; + + if (!notebook->focus_tab) + notebook->focus_tab = notebook->children; - gtk_widget_show (tab_label); gtk_widget_set_parent (child, GTK_WIDGET (notebook)); gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook)); + gtk_widget_show (tab_label); + + if (!notebook->cur_page) + gtk_notebook_switch_page (notebook, page, 0); if (GTK_WIDGET_VISIBLE (notebook)) { @@ -228,7 +399,6 @@ gtk_notebook_insert_page (GtkNotebook *notebook, !GTK_WIDGET_REALIZED (child)) gtk_widget_realize (child); - if (GTK_WIDGET_MAPPED (notebook) && !GTK_WIDGET_MAPPED (child) && notebook->cur_page == page) gtk_widget_map (child); @@ -250,31 +420,115 @@ void gtk_notebook_remove_page (GtkNotebook *notebook, gint page_num) { - GtkNotebookPage *page; - GList *tmp_list; + GList *list; g_return_if_fail (notebook != NULL); g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); - tmp_list = g_list_nth (notebook->children, page_num); - if (tmp_list) - { - page = tmp_list->data; + if ((list = g_list_nth (notebook->children, page_num))) + gtk_notebook_real_remove (notebook, list, page_num); +} - if (notebook->cur_page == page) - gtk_notebook_prev_page (notebook); - if (notebook->cur_page == page) - notebook->cur_page = NULL; - - gtk_widget_unparent (page->child); - gtk_widget_unparent (page->tab_label); - - notebook->children = g_list_remove_link (notebook->children, tmp_list); - g_list_free (tmp_list); - g_free (page); +static void +gtk_notebook_add (GtkContainer *container, + GtkWidget *widget) +{ + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (container)); + g_return_if_fail (widget != NULL); + + gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget, + NULL, NULL, -1); +} + +static void +gtk_notebook_remove (GtkContainer *container, + GtkWidget *widget) +{ + GtkNotebook *notebook; + GtkNotebookPage *page; + GList *children; + gint page_num; + + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (container)); + g_return_if_fail (widget != NULL); + + notebook = GTK_NOTEBOOK (container); + + children = notebook->children; + page_num = 0; + while (children) + { + page = children->data; + if (page->child == widget) + { + gtk_notebook_real_remove (notebook, children, page_num); + break; + } + page_num++; + children = children->next; } } +static void +gtk_notebook_real_remove (GtkNotebook *notebook, + GList *list, + gint page_num) +{ + GtkNotebookPage *page; + GList * next_list; + + if (list->prev) + { + next_list = list->prev; + page_num--; + } + else if (list->next) + { + next_list = list->next; + page_num++; + } + else + next_list = NULL; + + if (notebook->cur_page == list->data) + { + if (next_list) + { + page = next_list->data; + gtk_notebook_switch_page (notebook, page, page_num); + } + else + notebook->cur_page = NULL; + } + + if (list == notebook->first_tab) + notebook->first_tab = next_list; + if (list == notebook->focus_tab) + notebook->focus_tab = next_list; + + page = list->data; + + gtk_widget_unparent (page->child); + gtk_widget_unparent (page->tab_label); + + if (notebook->menu) + { + gtk_container_remove (GTK_CONTAINER (notebook->menu), + page->menu_label->parent); + gtk_widget_queue_resize (notebook->menu); + } + if (!page->default_menu) + gtk_widget_unref (page->menu_label); + + gtk_notebook_update_labels (notebook, list->next, page_num + 1); + + notebook->children = g_list_remove_link (notebook->children, list); + g_list_free (list); + g_free (page); +} + gint gtk_notebook_current_page (GtkNotebook *notebook) { @@ -312,18 +566,14 @@ void gtk_notebook_set_page (GtkNotebook *notebook, gint page_num) { - GtkNotebookPage *page; - GList *tmp_list; + GList *list; g_return_if_fail (notebook != NULL); g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); - tmp_list = g_list_nth (notebook->children, page_num); - if (tmp_list) - { - page = tmp_list->data; - gtk_notebook_switch_page (notebook, page); - } + if ((list = g_list_nth (notebook->children, page_num))) + gtk_notebook_switch_page (notebook, + ((GtkNotebookPage *)(list->data)), page_num); } void @@ -331,27 +581,37 @@ gtk_notebook_next_page (GtkNotebook *notebook) { GtkNotebookPage *page; GList *children; + gint num; g_return_if_fail (notebook != NULL); g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); children = notebook->children; + num = 0; while (children) { - page = children->data; - - if (notebook->cur_page == page) - { - children = children->next; - if (!children) - children = notebook->children; - page = children->data; - - gtk_notebook_switch_page (notebook, page); - } - + if (notebook->cur_page == children->data) + break; children = children->next; + num++; } + + if (!children) + return; + + if (children->next) + { + children = children->next; + num++; + } + else + { + children = notebook->children; + num = 0; + } + + page = children->data; + gtk_notebook_switch_page (notebook, page, num); } void @@ -359,29 +619,115 @@ gtk_notebook_prev_page (GtkNotebook *notebook) { GtkNotebookPage *page; GList *children; + gint num; g_return_if_fail (notebook != NULL); g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + children = notebook->children; + num = 0; + while (children) + { + if (notebook->cur_page == children->data) + break; + children = children->next; + num++; + } + + if (!children) + return; + + if (children->prev) + { + children = children->prev; + num--; + } + else + { + while (children->next) + { + children = children->next; + num++; + } + } + + page = children->data; + gtk_notebook_switch_page (notebook, page, num); +} + +static void +gtk_notebook_foreach (GtkContainer *container, + GtkCallback callback, + gpointer callback_data) +{ + GtkNotebook *notebook; + GtkNotebookPage *page; + GList *children; + + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (container)); + g_return_if_fail (callback != NULL); + + notebook = GTK_NOTEBOOK (container); + children = notebook->children; while (children) { page = children->data; - - if (notebook->cur_page == page) - { - children = children->prev; - if (!children) - children = g_list_last (notebook->children); - page = children->data; - - gtk_notebook_switch_page (notebook, page); - } - children = children->next; + (* callback) (page->child, callback_data); } } +static void +gtk_notebook_expose_tabs (GtkNotebook *notebook) +{ + GtkWidget *widget; + GtkNotebookPage *page; + GdkEventExpose event; + gint border; + + widget = GTK_WIDGET (notebook); + border = GTK_CONTAINER (notebook)->border_width; + + page = notebook->first_tab->data; + + event.type = GDK_EXPOSE; + event.window = widget->window; + event.count = 0; + event.area.x = border; + event.area.y = border; + + switch (notebook->tab_pos) + { + case GTK_POS_BOTTOM: + event.area.y = widget->allocation.height - border + - page->allocation.height - widget->style->klass->ythickness; + if (notebook->first_tab->data != notebook->cur_page) + event.area.y -= widget->style->klass->ythickness; + case GTK_POS_TOP: + event.area.width = widget->allocation.width - 2 * border; + event.area.height = page->allocation.height + + widget->style->klass->ythickness; + if (notebook->first_tab->data != notebook->cur_page) + event.area.height += widget->style->klass->ythickness; + break; + case GTK_POS_RIGHT: + event.area.x = widget->allocation.width - border + - page->allocation.width - widget->style->klass->xthickness; + if (notebook->first_tab->data != notebook->cur_page) + event.area.x -= widget->style->klass->xthickness; + case GTK_POS_LEFT: + event.area.width = page->allocation.width + + widget->style->klass->xthickness; + event.area.height = widget->allocation.height - 2 * border; + if (notebook->first_tab->data != notebook->cur_page) + event.area.width += widget->style->klass->xthickness; + break; + } + gtk_widget_event (widget, (GdkEvent *) &event); +} + void gtk_notebook_set_tab_pos (GtkNotebook *notebook, GtkPositionType pos) @@ -394,7 +740,11 @@ gtk_notebook_set_tab_pos (GtkNotebook *notebook, notebook->tab_pos = pos; if (GTK_WIDGET_VISIBLE (notebook)) - gtk_widget_queue_resize (GTK_WIDGET (notebook)); + { + gtk_widget_queue_resize (GTK_WIDGET (notebook)); + if (notebook->panel) + gdk_window_clear (notebook->panel); + } } } @@ -402,16 +752,44 @@ void gtk_notebook_set_show_tabs (GtkNotebook *notebook, gint show_tabs) { + GtkNotebookPage *page; + GList *children; + g_return_if_fail (notebook != NULL); g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); - if (notebook->show_tabs != show_tabs) - { - notebook->show_tabs = show_tabs; + if (notebook->show_tabs == show_tabs || !GTK_WIDGET_VISIBLE (notebook)) + return; - if (GTK_WIDGET_VISIBLE (notebook)) - gtk_widget_queue_resize (GTK_WIDGET (notebook)); + notebook->show_tabs = show_tabs; + children = notebook->children; + + if (!show_tabs) + { + GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS); + + while (children) + { + page = children->data; + children = children->next; + gtk_widget_hide (page->tab_label); + } + + if (notebook->panel) + gdk_window_hide (notebook->panel); } + else + { + GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS); + + while (children) + { + page = children->data; + children = children->next; + gtk_widget_show (page->tab_label); + } + } + gtk_widget_queue_resize (GTK_WIDGET (notebook)); } void @@ -430,6 +808,26 @@ gtk_notebook_set_show_border (GtkNotebook *notebook, } } +void +gtk_notebook_set_scrollable (GtkNotebook *notebook, + gint scrollable) +{ + g_return_if_fail (notebook != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + + if (scrollable != notebook->scrollable) + { + if ( (notebook->scrollable = (scrollable != 0)) ) + gtk_notebook_panel_realize (notebook); + else if (notebook->panel) + { + gdk_window_destroy (notebook->panel); + notebook->panel = NULL; + } + gtk_widget_queue_resize (GTK_WIDGET(notebook)); + } +} + static void gtk_notebook_map (GtkWidget *widget) { @@ -445,20 +843,26 @@ gtk_notebook_map (GtkWidget *widget) notebook = GTK_NOTEBOOK (widget); - if (notebook->cur_page && + if (notebook->cur_page && GTK_WIDGET_VISIBLE (notebook->cur_page->child) && !GTK_WIDGET_MAPPED (notebook->cur_page->child)) gtk_widget_map (notebook->cur_page->child); - children = notebook->children; - while (children) + if (notebook->scrollable) + gtk_notebook_pages_allocate (notebook, &(widget->allocation)); + else { - page = children->data; - children = children->next; + children = notebook->children; - if (GTK_WIDGET_VISIBLE (page->child) && - !GTK_WIDGET_MAPPED (page->tab_label)) - gtk_widget_map (page->tab_label); + while (children) + { + page = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (page->child) && + !GTK_WIDGET_MAPPED (page->tab_label)) + gtk_widget_map (page->tab_label); + } } } @@ -470,6 +874,8 @@ gtk_notebook_unmap (GtkWidget *widget) GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); gdk_window_hide (widget->window); + if (GTK_NOTEBOOK(widget)->panel) + gdk_window_hide (GTK_NOTEBOOK(widget)->panel); } static void @@ -494,7 +900,8 @@ gtk_notebook_realize (GtkWidget *widget) attributes.visual = gtk_widget_get_visual (widget); attributes.colormap = gtk_widget_get_colormap (widget); attributes.event_mask = gtk_widget_get_events (widget); - attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK; + attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK; attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; @@ -503,6 +910,53 @@ gtk_notebook_realize (GtkWidget *widget) widget->style = gtk_style_attach (widget->style, widget->window); gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); + + if (notebook->scrollable) + gtk_notebook_panel_realize (notebook); +} + +static void +gtk_notebook_panel_realize (GtkNotebook *notebook) +{ + GtkWidget *widget; + GdkWindowAttr attributes; + gint attributes_mask; + + g_return_if_fail (notebook != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + + widget = GTK_WIDGET (notebook); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = gtk_widget_get_events (widget); + attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK + | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + + attributes.width = 2 * ARROW_SIZE + ARROW_SPACING; + attributes.height = ARROW_SIZE; + + attributes.x = widget->allocation.width - attributes.width - + GTK_CONTAINER (notebook)->border_width; + attributes.y = widget->allocation.height - ARROW_SIZE - + GTK_CONTAINER (notebook)->border_width; + if (notebook->tab_pos == GTK_POS_TOP) + attributes.y = GTK_CONTAINER (notebook)->border_width; + else if (notebook->tab_pos == GTK_POS_LEFT) + attributes.x = widget->allocation.x + + GTK_CONTAINER (notebook)->border_width; + + + notebook->panel = gdk_window_new (widget->window, &attributes, + attributes_mask); + gtk_style_set_background (widget->style, notebook->panel, + GTK_STATE_NORMAL); + gdk_window_set_user_data (notebook->panel, widget); } static void @@ -512,8 +966,6 @@ gtk_notebook_size_request (GtkWidget *widget, GtkNotebook *notebook; GtkNotebookPage *page; GList *children; - gint tab_width; - gint tab_height; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_NOTEBOOK (widget)); @@ -540,93 +992,119 @@ gtk_notebook_size_request (GtkWidget *widget, } } - widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2; - widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2; - - if (notebook->show_tabs) + if (notebook->show_border || notebook->show_tabs) { - widget->requisition.width += GTK_WIDGET (widget)->style->klass->xthickness * 2; - widget->requisition.height += GTK_WIDGET (widget)->style->klass->ythickness * 2; + widget->requisition.width += widget->style->klass->xthickness * 2; + widget->requisition.height += widget->style->klass->ythickness * 2; - tab_width = 0; - tab_height = 0; - - children = notebook->children; - while (children) + if (notebook->show_tabs) { - page = children->data; - children = children->next; - - if (GTK_WIDGET_VISIBLE (page->child)) + gint tab_width = 0; + gint tab_height = 0; + gint tab_max = 0; + + children = notebook->children; + while (children) { - gtk_widget_size_request (page->tab_label, &page->tab_label->requisition); - - page->requisition.width = (page->tab_label->requisition.width + - (GTK_WIDGET (widget)->style->klass->xthickness + - CHILD_SPACING) * 2); - page->requisition.height = (page->tab_label->requisition.height + - (GTK_WIDGET (widget)->style->klass->ythickness + - CHILD_SPACING) * 2); - - switch (notebook->tab_pos) + page = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (page->child)) { - case GTK_POS_TOP: - case GTK_POS_BOTTOM: - page->requisition.width -= TAB_OVERLAP; - page->requisition.height -= GTK_WIDGET (widget)->style->klass->ythickness; + gtk_widget_size_request (page->tab_label, + &page->tab_label->requisition); + + page->requisition.width = + (page->tab_label->requisition.width + + (widget->style->klass->xthickness + notebook->tab_border) + * 2); + page->requisition.height = + (page->tab_label->requisition.height + + (widget->style->klass->ythickness + notebook->tab_border) + * 2); + + switch (notebook->tab_pos) + { + case GTK_POS_TOP: + case GTK_POS_BOTTOM: + page->requisition.width -= TAB_OVERLAP; - tab_width += page->requisition.width; - tab_height = MAX (tab_height, page->requisition.height); - break; - case GTK_POS_LEFT: - case GTK_POS_RIGHT: - page->requisition.width -= GTK_WIDGET (widget)->style->klass->xthickness; - page->requisition.height -= TAB_OVERLAP; + tab_width += page->requisition.width; + tab_height = MAX (tab_height, page->requisition.height); + tab_max = MAX (tab_max, page->requisition.width); + break; + case GTK_POS_LEFT: + case GTK_POS_RIGHT: + page->requisition.height -= TAB_OVERLAP; - tab_width = MAX (tab_width, page->requisition.width); - tab_height += page->requisition.height; - break; + tab_width = MAX (tab_width, page->requisition.width); + tab_height += page->requisition.height; + tab_max = MAX (tab_max, page->requisition.height); + break; + } } } - } - children = notebook->children; - while (children) - { - page = children->data; - children = children->next; + children = notebook->children; - if (GTK_WIDGET_VISIBLE (page->child)) + if (children && children->next && notebook->scrollable) { if ((notebook->tab_pos == GTK_POS_TOP) || (notebook->tab_pos == GTK_POS_BOTTOM)) - page->requisition.height = tab_height; + { + if (widget->requisition.width < tab_width) + { + tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING); + tab_height = MAX (tab_height, ARROW_SIZE); + } + } else - page->requisition.width = tab_width; + { + if (widget->requisition.height < tab_height) + { + tab_height = tab_max + ARROW_SIZE + ARROW_SPACING; + tab_width = MAX (tab_width, + ARROW_SPACING + 2 * ARROW_SIZE); + } + } + } + + while (children) + { + page = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (page->child)) + { + if ((notebook->tab_pos == GTK_POS_TOP) || + (notebook->tab_pos == GTK_POS_BOTTOM)) + page->requisition.height = tab_height; + else + page->requisition.width = tab_width; + } + } + + switch (notebook->tab_pos) + { + case GTK_POS_TOP: + case GTK_POS_BOTTOM: + tab_width += widget->style->klass->xthickness; + widget->requisition.width = MAX (widget->requisition.width, + tab_width); + widget->requisition.height += tab_height; + break; + case GTK_POS_LEFT: + case GTK_POS_RIGHT: + tab_height += widget->style->klass->ythickness; + widget->requisition.width += tab_width; + widget->requisition.height = MAX (widget->requisition.height, + tab_height); + break; } } - - switch (notebook->tab_pos) - { - case GTK_POS_TOP: - case GTK_POS_BOTTOM: - tab_width += GTK_WIDGET (widget)->style->klass->xthickness; - widget->requisition.width = MAX (widget->requisition.width, tab_width); - widget->requisition.height += tab_height; - break; - case GTK_POS_LEFT: - case GTK_POS_RIGHT: - tab_height += GTK_WIDGET (widget)->style->klass->ythickness; - widget->requisition.width += tab_width; - widget->requisition.height = MAX (widget->requisition.height, tab_height); - break; - } - } - else if (notebook->show_border) - { - widget->requisition.width += GTK_WIDGET (widget)->style->klass->xthickness * 2; - widget->requisition.height += GTK_WIDGET (widget)->style->klass->ythickness * 2; } + widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2; + widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2; } static void @@ -658,10 +1136,10 @@ gtk_notebook_size_allocate (GtkWidget *widget, if (notebook->show_tabs || notebook->show_border) { - child_allocation.x += GTK_WIDGET (widget)->style->klass->xthickness; - child_allocation.y += GTK_WIDGET (widget)->style->klass->ythickness; - child_allocation.width -= GTK_WIDGET (widget)->style->klass->xthickness * 2; - child_allocation.height -= GTK_WIDGET (widget)->style->klass->ythickness * 2; + child_allocation.x += widget->style->klass->xthickness; + child_allocation.y += widget->style->klass->ythickness; + child_allocation.width -= widget->style->klass->xthickness * 2; + child_allocation.height -= widget->style->klass->ythickness * 2; if (notebook->show_tabs && notebook->children) { @@ -691,8 +1169,7 @@ gtk_notebook_size_allocate (GtkWidget *widget, gtk_widget_size_allocate (page->child, &child_allocation); } - if (notebook->show_tabs && notebook->children) - gtk_notebook_pages_allocate (notebook, allocation); + gtk_notebook_pages_allocate (notebook, allocation); } } @@ -706,6 +1183,7 @@ gtk_notebook_paint (GtkWidget *widget, GdkPoint points[6]; gint width, height; gint x, y; + gint showarrow; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_NOTEBOOK (widget)); @@ -728,115 +1206,156 @@ gtk_notebook_paint (GtkWidget *widget, if (notebook->show_tabs && notebook->children) { - switch (notebook->tab_pos) + + if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label)) { - case GTK_POS_TOP: - y += notebook->cur_page->allocation.height; - case GTK_POS_BOTTOM: - height -= notebook->cur_page->allocation.height; - break; - case GTK_POS_LEFT: - x += notebook->cur_page->allocation.width; - case GTK_POS_RIGHT: - width -= notebook->cur_page->allocation.width; - break; - } + GtkNotebookPage *page; - switch (notebook->tab_pos) + page = notebook->first_tab->data; + + switch (notebook->tab_pos) + { + case GTK_POS_TOP: + y += page->allocation.height + + widget->style->klass->ythickness; + case GTK_POS_BOTTOM: + height -= page->allocation.height + + widget->style->klass->ythickness; + break; + case GTK_POS_LEFT: + x += page->allocation.width + + widget->style->klass->xthickness; + case GTK_POS_RIGHT: + width -= page->allocation.width + + widget->style->klass->xthickness; + break; + } + gtk_draw_shadow (widget->style, widget->window, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + x, y, width, height); + } + else { - case GTK_POS_TOP: - points[0].x = notebook->cur_page->allocation.x; - points[0].y = y; - points[1].x = x; - points[1].y = y; - points[2].x = x; - points[2].y = y + height - 1; - points[3].x = x + width - 1; - points[3].y = y + height - 1; - points[4].x = x + width - 1; - points[4].y = y; - points[5].x = (notebook->cur_page->allocation.x + - notebook->cur_page->allocation.width - - GTK_WIDGET (notebook)->style->klass->xthickness); - points[5].y = y; + switch (notebook->tab_pos) + { + case GTK_POS_TOP: + y += notebook->cur_page->allocation.height; + case GTK_POS_BOTTOM: + height -= notebook->cur_page->allocation.height; + break; + case GTK_POS_LEFT: + x += notebook->cur_page->allocation.width; + case GTK_POS_RIGHT: + width -= notebook->cur_page->allocation.width; + break; + } - if (points[5].x == (x + width)) - points[5].x -= 1; - break; - case GTK_POS_BOTTOM: - points[0].x = (notebook->cur_page->allocation.x + - notebook->cur_page->allocation.width - - GTK_WIDGET (notebook)->style->klass->xthickness); - points[0].y = y + height - 1; - points[1].x = x + width - 1; - points[1].y = y + height - 1; - points[2].x = x + width - 1; - points[2].y = y; - points[3].x = x; - points[3].y = y; - points[4].x = x; - points[4].y = y + height - 1; - points[5].x = notebook->cur_page->allocation.x; - points[5].y = y + height - 1; + switch (notebook->tab_pos) + { + case GTK_POS_TOP: + points[0].x = notebook->cur_page->allocation.x; + points[0].y = y; + points[1].x = x; + points[1].y = y; + points[2].x = x; + points[2].y = y + height - 1; + points[3].x = x + width - 1; + points[3].y = y + height - 1; + points[4].x = x + width - 1; + points[4].y = y; + points[5].x = (notebook->cur_page->allocation.x + + notebook->cur_page->allocation.width - + widget->style->klass->xthickness); + points[5].y = y; - if (points[0].x == (x + width)) - points[0].x -= 1; - break; - case GTK_POS_LEFT: - points[0].x = x; - points[0].y = (notebook->cur_page->allocation.y + - notebook->cur_page->allocation.height - - GTK_WIDGET (notebook)->style->klass->ythickness); - points[1].x = x; - points[1].y = y + height - 1; - points[2].x = x + width - 1; - points[2].y = y + height - 1; - points[3].x = x + width - 1; - points[3].y = y; - points[4].x = x; - points[4].y = y; - points[5].x = x; - points[5].y = notebook->cur_page->allocation.y; + if (points[5].x == (x + width)) + points[5].x -= 1; + break; + case GTK_POS_BOTTOM: + points[0].x = (notebook->cur_page->allocation.x + + notebook->cur_page->allocation.width - + widget->style->klass->xthickness); + points[0].y = y + height - 1; + points[1].x = x + width - 1; + points[1].y = y + height - 1; + points[2].x = x + width - 1; + points[2].y = y; + points[3].x = x; + points[3].y = y; + points[4].x = x; + points[4].y = y + height - 1; + points[5].x = notebook->cur_page->allocation.x; + points[5].y = y + height - 1; - if (points[0].y == (y + height)) - points[0].y -= 1; - break; - case GTK_POS_RIGHT: - points[0].x = x + width - 1; - points[0].y = notebook->cur_page->allocation.y; - points[1].x = x + width - 1; - points[1].y = y; - points[2].x = x; - points[2].y = y; - points[3].x = x; - points[3].y = y + height - 1; - points[4].x = x + width - 1; - points[4].y = y + height - 1; - points[5].x = x + width - 1; - points[5].y = (notebook->cur_page->allocation.y + - notebook->cur_page->allocation.height - - GTK_WIDGET (notebook)->style->klass->ythickness); + if (points[0].x == (x + width)) + points[0].x -= 1; + break; + case GTK_POS_LEFT: + points[0].x = x; + points[0].y = (notebook->cur_page->allocation.y + + notebook->cur_page->allocation.height - + widget->style->klass->ythickness); + points[1].x = x; + points[1].y = y + height - 1; + points[2].x = x + width - 1; + points[2].y = y + height - 1; + points[3].x = x + width - 1; + points[3].y = y; + points[4].x = x; + points[4].y = y; + points[5].x = x; + points[5].y = notebook->cur_page->allocation.y; + + if (points[0].y == (y + height)) + points[0].y -= 1; + break; + case GTK_POS_RIGHT: + points[0].x = x + width - 1; + points[0].y = notebook->cur_page->allocation.y; + points[1].x = x + width - 1; + points[1].y = y; + points[2].x = x; + points[2].y = y; + points[3].x = x; + points[3].y = y + height - 1; + points[4].x = x + width - 1; + points[4].y = y + height - 1; + points[5].x = x + width - 1; + points[5].y = (notebook->cur_page->allocation.y + + notebook->cur_page->allocation.height - + widget->style->klass->ythickness); - if (points[5].y == (y + height)) - points[5].y -= 1; - break; + if (points[5].y == (y + height)) + points[5].y -= 1; + break; + } + + gtk_draw_polygon (widget->style, widget->window, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + points, 6, FALSE); } - - gtk_draw_polygon (widget->style, widget->window, - GTK_STATE_NORMAL, GTK_SHADOW_OUT, - points, 6, FALSE); - children = g_list_last (notebook->children); + showarrow = FALSE; + while (children) { page = children->data; children = children->prev; - if (notebook->cur_page != page) + if (!GTK_WIDGET_MAPPED (page->tab_label)) + showarrow = TRUE; + else if (notebook->cur_page != page) gtk_notebook_draw_tab (notebook, page, area); } - if (notebook->cur_page) + if (showarrow && notebook->scrollable && notebook->show_tabs) + { + gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT); + gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT); + } + if (notebook->cur_page && + GTK_WIDGET_MAPPED(((GtkNotebookPage *) + (notebook->cur_page))->tab_label)) gtk_notebook_draw_tab (notebook, notebook->cur_page, area); } else if (notebook->show_border) @@ -865,6 +1384,7 @@ gtk_notebook_draw (GtkWidget *widget, notebook = GTK_NOTEBOOK (widget); gtk_notebook_paint (widget, area); + gtk_widget_draw_focus (widget); if (notebook->cur_page && gtk_widget_intersect (notebook->cur_page->child, area, &child_area)) @@ -888,10 +1408,13 @@ gtk_notebook_expose (GtkWidget *widget, notebook = GTK_NOTEBOOK (widget); gtk_notebook_paint (widget, &event->area); + gtk_widget_draw_focus (widget); child_event = *event; - if (notebook->cur_page && GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) && - gtk_widget_intersect (notebook->cur_page->child, &event->area, &child_event.area)) + if (notebook->cur_page && + GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) && + gtk_widget_intersect (notebook->cur_page->child, &event->area, + &child_event.area)) gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event); } @@ -905,104 +1428,340 @@ gtk_notebook_button_press (GtkWidget *widget, GtkNotebook *notebook; GtkNotebookPage *page; GList *children; + gint num; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); - if ((event->type != GDK_BUTTON_PRESS) || - (event->window != widget->window)) + notebook = GTK_NOTEBOOK (widget); + + if (event->type != GDK_BUTTON_PRESS || !notebook->children + || notebook->button) + return FALSE; + + if (!GTK_WIDGET_HAS_FOCUS (widget) && !(GTK_CONTAINER (widget)->focus_child)) + gtk_widget_grab_focus (widget); + + if (event->window == notebook->panel) + { + if (!GTK_WIDGET_HAS_FOCUS (widget)) + { + GTK_CONTAINER (widget)->focus_child = NULL; + gtk_widget_grab_focus (widget); + } + + gtk_grab_add (widget); + notebook->button = event->button; + + if (event->x <= ARROW_SIZE + ARROW_SPACING / 2) + { + notebook->click_child = GTK_ARROW_LEFT; + if (event->button == 1) + { + gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT); + if (!notebook->timer) + { + notebook->timer = gtk_timeout_add + (NOTEBOOK_INIT_SCROLL_DELAY, + (GtkFunction) gtk_notebook_timer, (gpointer) notebook); + notebook->need_timer = TRUE; + } + } + else if (event->button == 2) + gtk_notebook_page_select (GTK_NOTEBOOK(widget)); + else if (event->button == 3) + gtk_notebook_switch_focus_tab (notebook, notebook->children); + gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT); + } + else + { + notebook->click_child = GTK_ARROW_RIGHT; + if (event->button == 1) + { + gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT); + if (!notebook->timer) + { + notebook->timer = gtk_timeout_add + (NOTEBOOK_INIT_SCROLL_DELAY, + (GtkFunction) gtk_notebook_timer, (gpointer) notebook); + notebook->need_timer = TRUE; + } + } + else if (event->button == 2) + gtk_notebook_page_select (GTK_NOTEBOOK(widget)); + else if (event->button == 3) + gtk_notebook_switch_focus_tab (notebook, + g_list_last (notebook->children)); + gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT); + } + } + else if (event->window == widget->window) + { + if (event->button == 3 && notebook->menu) + { + gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL, + NULL, NULL, 3, event->time); + return FALSE; + } + + num = 0; + children = notebook->children; + while (children) + { + page = children->data; + + if (GTK_WIDGET_VISIBLE (page->child) && + GTK_WIDGET_MAPPED (page->tab_label) && + (event->x >= page->allocation.x) && + (event->y >= page->allocation.y) && + (event->x <= (page->allocation.x + page->allocation.width)) && + (event->y <= (page->allocation.y + page->allocation.height))) + { + GTK_CONTAINER (notebook)->focus_child = NULL; + + if (page == notebook->cur_page && + notebook->focus_tab != children && + GTK_WIDGET_HAS_FOCUS (notebook)) + { + GtkNotebookPage *old_page; + + old_page = (GtkNotebookPage *) + (notebook->focus_tab->data); + notebook->focus_tab = children; + gtk_notebook_focus_changed (notebook, old_page); + } + else + { + notebook->focus_tab = children; + gtk_notebook_switch_page (notebook, page, num); + gtk_widget_grab_focus (widget); + } + break; + } + children = children->next; + num++; + } + } + return FALSE; +} + +static gint +gtk_notebook_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + GtkNotebook *notebook; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + if (event->type != GDK_BUTTON_RELEASE) return FALSE; notebook = GTK_NOTEBOOK (widget); - children = notebook->children; - while (children) + if (event->button == notebook->button) { - page = children->data; + guint click_child; - if (GTK_WIDGET_VISIBLE (page->child) && - (event->x >= page->allocation.x) && - (event->y >= page->allocation.y) && - (event->x <= (page->allocation.x + page->allocation.width)) && - (event->y <= (page->allocation.y + page->allocation.height))) + if (notebook->timer) { - gtk_notebook_switch_page (notebook, page); - break; + gtk_timeout_remove (notebook->timer); + notebook->timer = 0; + notebook->need_timer = FALSE; + } + gtk_grab_remove (widget); + click_child = notebook->click_child; + notebook->click_child = 0; + notebook->button = 0; + gtk_notebook_draw_arrow (notebook, click_child); + + } + return FALSE; +} + +static gint +gtk_notebook_enter_notify (GtkWidget *widget, + GdkEventCrossing *event) +{ + GtkNotebook *notebook; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + notebook = GTK_NOTEBOOK (widget); + + if (event->window == notebook->panel) + { + gint x; + gint y; + + gdk_window_get_pointer (notebook->panel, &x, &y, NULL); + + if (x <= ARROW_SIZE + ARROW_SPACING / 2) + { + notebook->in_child = GTK_ARROW_LEFT; + + if (notebook->click_child == 0) + gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT); + } + else + { + notebook->in_child = GTK_ARROW_RIGHT; + + if (notebook->click_child == 0) + gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT); } - children = children->next; } return FALSE; } -static void -gtk_notebook_add (GtkContainer *container, - GtkWidget *widget) -{ - g_warning ("gtk_notebook_add: use gtk_notebook_{append,prepend}_page instead\n"); -} - -static void -gtk_notebook_remove (GtkContainer *container, - GtkWidget *widget) +static gint +gtk_notebook_leave_notify (GtkWidget *widget, + GdkEventCrossing *event) { GtkNotebook *notebook; - GtkNotebookPage *page; - GList *children; - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_NOTEBOOK (container)); - g_return_if_fail (widget != NULL); + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); - notebook = GTK_NOTEBOOK (container); + notebook = GTK_NOTEBOOK (widget); - children = notebook->children; - while (children) + if (event->window == notebook->panel && !notebook->click_child) { - page = children->data; - - if (page->child == widget) + if (notebook->in_child == GTK_ARROW_LEFT) { - gtk_widget_unparent (page->child); - gtk_widget_unparent (page->tab_label); - - notebook->children = g_list_remove_link (notebook->children, children); - g_list_free (children); - g_free (page); - - if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container)) - gtk_widget_queue_resize (GTK_WIDGET (container)); - - break; + notebook->in_child = 0; + gtk_notebook_draw_arrow (notebook,GTK_ARROW_LEFT); + } + else + { + notebook->in_child = 0; + gtk_notebook_draw_arrow (notebook,GTK_ARROW_RIGHT); } - - children = children->next; } + return FALSE; +} + +static gint +gtk_notebook_motion_notify (GtkWidget *widget, + GdkEventMotion *event) +{ + GtkNotebook *notebook; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + notebook = GTK_NOTEBOOK (widget); + + if (notebook->button) + return FALSE; + + if (event->window == notebook->panel) + { + gint x; + + x = event->x; + if (event->is_hint) + gdk_window_get_pointer (notebook->panel, &x, NULL, NULL); + + if (x <= ARROW_SIZE + ARROW_SPACING / 2 && + notebook->in_child == GTK_ARROW_RIGHT) + { + notebook->in_child = GTK_ARROW_LEFT; + gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT); + gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT); + } + else if (x > ARROW_SIZE + ARROW_SPACING / 2 && + notebook->in_child == GTK_ARROW_LEFT) + { + notebook->in_child = GTK_ARROW_RIGHT; + gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT); + gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT); + } + return FALSE; + } + return FALSE; +} + +static gint +gtk_notebook_timer (GtkNotebook *notebook) +{ + g_return_val_if_fail (notebook != NULL, FALSE); + g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE); + + if (notebook->timer) + { + if (notebook->click_child == GTK_ARROW_LEFT) + gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT); + else if (notebook->click_child == GTK_ARROW_RIGHT) + gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT); + + if (notebook->need_timer) + { + notebook->need_timer = FALSE; + notebook->timer = gtk_timeout_add + (NOTEBOOK_SCROLL_DELAY, (GtkFunction) gtk_notebook_timer, + (gpointer) notebook); + return FALSE; + } + return TRUE; + } + return FALSE; } static void -gtk_notebook_foreach (GtkContainer *container, - GtkCallback callback, - gpointer callback_data) +gtk_notebook_draw_arrow (GtkNotebook *notebook, guint arrow) { - GtkNotebook *notebook; - GtkNotebookPage *page; - GList *children; + GtkStateType state_type; + GtkShadowType shadow_type; + GtkWidget *widget; - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_NOTEBOOK (container)); - g_return_if_fail (callback != NULL); + g_return_if_fail (notebook != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + + widget = GTK_WIDGET(notebook); - notebook = GTK_NOTEBOOK (container); - - children = notebook->children; - while (children) + if (GTK_WIDGET_DRAWABLE (notebook)) { - page = children->data; - children = children->next; + if (notebook->in_child == arrow) + { + if (notebook->click_child == arrow) + state_type = GTK_STATE_ACTIVE; + else + state_type = GTK_STATE_PRELIGHT; + } + else + state_type = GTK_STATE_NORMAL; - (* callback) (page->child, callback_data); + if (notebook->click_child == arrow) + shadow_type = GTK_SHADOW_IN; + else + shadow_type = GTK_SHADOW_OUT; + + if (arrow == GTK_ARROW_LEFT) + { + if (notebook->tab_pos == GTK_POS_LEFT || + notebook->tab_pos == GTK_POS_RIGHT) + arrow = GTK_ARROW_UP; + gtk_draw_arrow (widget->style, notebook->panel, state_type, + shadow_type, arrow, TRUE, + 0, 0, ARROW_SIZE, ARROW_SIZE); + } + else + { + if (notebook->tab_pos == GTK_POS_LEFT || + notebook->tab_pos == GTK_POS_RIGHT) + arrow = GTK_ARROW_DOWN; + gtk_draw_arrow (widget->style, notebook->panel, state_type, + shadow_type, arrow, TRUE, ARROW_SIZE + ARROW_SPACING, + 0, ARROW_SIZE, ARROW_SIZE); + } } } @@ -1040,7 +1799,6 @@ gtk_real_notebook_switch_page (GtkNotebook *notebook, } } - static void gtk_notebook_draw_tab (GtkNotebook *notebook, GtkNotebookPage *page, @@ -1050,12 +1808,15 @@ gtk_notebook_draw_tab (GtkNotebook *notebook, GdkRectangle page_area; GtkStateType state_type; GdkPoint points[6]; - gint n; + gint n = 0; g_return_if_fail (notebook != NULL); g_return_if_fail (page != NULL); g_return_if_fail (area != NULL); + if (!GTK_WIDGET_MAPPED (page->tab_label)) + return; + page_area.x = page->allocation.x; page_area.y = page->allocation.y; page_area.width = page->allocation.width; @@ -1068,8 +1829,8 @@ gtk_notebook_draw_tab (GtkNotebook *notebook, switch (notebook->tab_pos) { case GTK_POS_TOP: - if( child_area.x + child_area.width > - page->allocation.x + page->allocation.width - TAB_OVERLAP ) + if (child_area.x + child_area.width > + page->allocation.x + page->allocation.width - TAB_OVERLAP) { points[0].x = page->allocation.x + page->allocation.width - 1; points[0].y = page->allocation.y + page->allocation.height - 1; @@ -1090,9 +1851,11 @@ gtk_notebook_draw_tab (GtkNotebook *notebook, n = 1; } - if( (child_area.x < page->allocation.x + TAB_OVERLAP) && - (page == notebook->cur_page || - page == (GtkNotebookPage *)(notebook->children->data)) ) + if ( (child_area.x < page->allocation.x + TAB_OVERLAP) && + (page == notebook->cur_page || + page == (GtkNotebookPage *)(notebook->children->data) || + (notebook->scrollable && + page == (GtkNotebookPage *)(notebook->first_tab->data))) ) { points[n].x = page->allocation.x + TAB_CURVATURE; points[n++].y = page->allocation.y; @@ -1110,9 +1873,11 @@ gtk_notebook_draw_tab (GtkNotebook *notebook, } break; case GTK_POS_BOTTOM: - if( (child_area.x < page->allocation.x + TAB_OVERLAP) && - (page == notebook->cur_page || - page == (GtkNotebookPage *)(notebook->children->data)) ) + if ( (child_area.x < page->allocation.x + TAB_OVERLAP) && + (page == notebook->cur_page || + page == (GtkNotebookPage *)(notebook->children->data) || + (notebook->scrollable && + page == (GtkNotebookPage *)(notebook->first_tab->data))) ) { points[0].x = page->allocation.x; points[0].y = page->allocation.y; @@ -1132,8 +1897,8 @@ gtk_notebook_draw_tab (GtkNotebook *notebook, n = 1; } - if( child_area.x + child_area.width > - page->allocation.x + page->allocation.width - TAB_OVERLAP ) + if (child_area.x + child_area.width > + page->allocation.x + page->allocation.width - TAB_OVERLAP) { points[n].x = page->allocation.x + page->allocation.width - TAB_CURVATURE - 1; @@ -1154,9 +1919,11 @@ gtk_notebook_draw_tab (GtkNotebook *notebook, } break; case GTK_POS_LEFT: - if( (child_area.y < page->allocation.y + TAB_OVERLAP) && - (page == notebook->cur_page || - page == (GtkNotebookPage *)(notebook->children->data)) ) + if ( (child_area.y < page->allocation.y + TAB_OVERLAP) && + (page == notebook->cur_page || + page == (GtkNotebookPage *)(notebook->children->data) || + (notebook->scrollable && + page == (GtkNotebookPage *)(notebook->first_tab->data))) ) { points[0].x = page->allocation.x + page->allocation.width - 1; points[0].y = page->allocation.y; @@ -1175,8 +1942,8 @@ gtk_notebook_draw_tab (GtkNotebook *notebook, n = 1; } - if( child_area.y + child_area.height > - page->allocation.y + page->allocation.height - TAB_OVERLAP ) + if (child_area.y + child_area.height > + page->allocation.y + page->allocation.height - TAB_OVERLAP) { points[n].x = page->allocation.x; points[n++].y = page->allocation.y + page->allocation.height @@ -1196,8 +1963,8 @@ gtk_notebook_draw_tab (GtkNotebook *notebook, } break; case GTK_POS_RIGHT: - if( child_area.y + child_area.height > - page->allocation.y + page->allocation.height - TAB_OVERLAP ) + if (child_area.y + child_area.height > + page->allocation.y + page->allocation.height - TAB_OVERLAP) { points[0].x = page->allocation.x; points[0].y = page->allocation.y + page->allocation.height - 1; @@ -1219,9 +1986,11 @@ gtk_notebook_draw_tab (GtkNotebook *notebook, n = 1; } - if( (child_area.y < page->allocation.y + TAB_OVERLAP) && - (page == notebook->cur_page || - page == (GtkNotebookPage *)(notebook->children->data)) ) + if ( (child_area.y < page->allocation.y + TAB_OVERLAP) && + (page == notebook->cur_page || + page == (GtkNotebookPage *)(notebook->children->data) || + (notebook->scrollable && + page == (GtkNotebookPage *)(notebook->first_tab->data))) ) { points[n].x = page->allocation.x + page->allocation.width - 1; points[n++].y = page->allocation.y + TAB_CURVATURE; @@ -1244,86 +2013,437 @@ gtk_notebook_draw_tab (GtkNotebook *notebook, widget = GTK_WIDGET(notebook); if (notebook->cur_page == page) - state_type = GTK_STATE_NORMAL; + { + state_type = GTK_STATE_NORMAL; + } else { state_type = GTK_STATE_ACTIVE; - gdk_draw_rectangle (widget->window, widget->style->bg_gc[state_type], TRUE, child_area.x, child_area.y, child_area.width, child_area.height); } - + gtk_draw_polygon (widget->style, widget->window, state_type, GTK_SHADOW_OUT, points, n, FALSE); - + if (gtk_widget_intersect (page->tab_label, area, &child_area)) gtk_widget_draw (page->tab_label, &child_area); } } +static gint +gtk_notebook_focus_in (GtkWidget *widget, + GdkEventFocus *event) +{ + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + if (GTK_CONTAINER (widget)->focus_child) + { + if (gtk_notebook_page_select (GTK_NOTEBOOK (widget))) + return FALSE; + else + GTK_CONTAINER (widget)->focus_child = NULL; + } + + GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); + gtk_widget_draw_focus (widget); + + return FALSE; +} + +static gint +gtk_notebook_focus_out (GtkWidget *widget, + GdkEventFocus *event) +{ + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS); + gtk_widget_draw_focus (widget); + + return FALSE; +} + +static void +gtk_notebook_draw_focus (GtkWidget *widget) +{ + GtkNotebook *notebook; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (widget)); + + notebook = GTK_NOTEBOOK (widget); + + if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs && + notebook->focus_tab) + { + GtkNotebookPage *page; + GdkGC *gc; + + page = notebook->focus_tab->data; + + if (GTK_WIDGET_HAS_FOCUS (widget)) + gc = widget->style->black_gc; + else if (page == notebook->cur_page) + gc = widget->style->bg_gc[GTK_STATE_NORMAL]; + else + gc = widget->style->bg_gc[GTK_STATE_ACTIVE]; + + gdk_draw_rectangle (widget->window, + gc, FALSE, + page->tab_label->allocation.x - 1, + page->tab_label->allocation.y - 1, + page->tab_label->allocation.width + 1, + page->tab_label->allocation.height + 1); + } +} + +static void +gtk_notebook_focus_changed (GtkNotebook *notebook, GtkNotebookPage *old_page) +{ + GtkWidget *widget; + + g_return_if_fail (notebook != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + g_return_if_fail (old_page != NULL); + + widget = GTK_WIDGET (notebook); + + if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs && + notebook->focus_tab) + { + GtkNotebookPage *page; + GdkGC *gc; + + page = notebook->focus_tab->data; + + if (GTK_WIDGET_HAS_FOCUS (widget)) + gc = widget->style->black_gc; + else if (page == notebook->cur_page) + gc = widget->style->bg_gc[GTK_STATE_NORMAL]; + else + gc = widget->style->bg_gc[GTK_STATE_ACTIVE]; + + gdk_draw_rectangle (widget->window, + gc, FALSE, + page->tab_label->allocation.x - 1, + page->tab_label->allocation.y - 1, + page->tab_label->allocation.width + 1, + page->tab_label->allocation.height + 1); + + if (old_page == notebook->cur_page) + gc = widget->style->bg_gc[GTK_STATE_NORMAL]; + else + gc = widget->style->bg_gc[GTK_STATE_ACTIVE]; + + gdk_draw_rectangle (widget->window, + gc, FALSE, + old_page->tab_label->allocation.x - 1, + old_page->tab_label->allocation.y - 1, + old_page->tab_label->allocation.width + 1, + old_page->tab_label->allocation.height + 1); + } +} + +static void +gtk_notebook_calc_tabs (GtkNotebook *notebook, + GList *start, + GList **end, + gint *tab_space, + guint direction) +{ + GtkNotebookPage *page = NULL; + GList *children; + + children = start; + switch (notebook->tab_pos) + { + case GTK_POS_TOP: + case GTK_POS_BOTTOM: + while (children) + { + page = children->data; + *tab_space -= page->requisition.width; + if (*tab_space < 0 || children == *end) + { + if (*tab_space < 0) + { + *tab_space = - (*tab_space + page->requisition.width); + *end = children; + } + break; + } + if (direction == STEP_NEXT) + children = children->next; + else + children = children->prev; + } + break; + case GTK_POS_LEFT: + case GTK_POS_RIGHT: + while (children) + { + page = children->data; + *tab_space -= page->requisition.height; + if (*tab_space < 0 || children == *end) + { + if (*tab_space < 0) + { + *tab_space = - (*tab_space + page->requisition.height); + *end = children; + } + break; + } + if (direction == STEP_NEXT) + children = children->next; + else + children = children->prev; + } + break; + } +} static void gtk_notebook_pages_allocate (GtkNotebook *notebook, GtkAllocation *allocation) { - GtkNotebookPage *page; + GtkWidget *widget; + GtkContainer *container; + GtkNotebookPage *page = NULL; GtkAllocation child_allocation; GList *children; + GList *last_child = NULL; + gint showarrow = FALSE; + gint tab_space = 0; + gint x = 0; + gint y = 0; + gint i; + gint n = 1; + gint old_fill = 0; + gint new_fill = 0; - if (notebook->show_tabs && notebook->children) + if (!notebook->show_tabs || !notebook->children) + return; + + widget = GTK_WIDGET (notebook); + container = GTK_CONTAINER (notebook); + + child_allocation.x = container->border_width; + child_allocation.y = container->border_width; + + switch (notebook->tab_pos) { - child_allocation.x = GTK_CONTAINER (notebook)->border_width; - child_allocation.y = GTK_CONTAINER (notebook)->border_width; - + case GTK_POS_BOTTOM: + child_allocation.y = allocation->height + - notebook->cur_page->requisition.height - container->border_width; + case GTK_POS_TOP: + child_allocation.height = notebook->cur_page->requisition.height; + break; + case GTK_POS_RIGHT: + child_allocation.x = allocation->width + - notebook->cur_page->requisition.width - container->border_width; + case GTK_POS_LEFT: + child_allocation.width = notebook->cur_page->requisition.width; + break; + } + + if (notebook->scrollable) + { + children = notebook->children; switch (notebook->tab_pos) { - case GTK_POS_BOTTOM: - child_allocation.y = allocation->height - notebook->cur_page->requisition.height; case GTK_POS_TOP: - child_allocation.height = notebook->cur_page->requisition.height; + case GTK_POS_BOTTOM: + while (children) + { + page = children->data; + children = children->next; + tab_space += page->requisition.width; + } + if (tab_space > allocation->width - 2 * container->border_width + - TAB_OVERLAP) + { + showarrow = TRUE; + page = notebook->focus_tab->data; + tab_space = allocation->width - TAB_OVERLAP + - page->requisition.width - + 2 * (container->border_width + ARROW_SPACING + ARROW_SIZE); + x = allocation->width - 2 * ARROW_SIZE - ARROW_SPACING + - container->border_width; + page = notebook->children->data; + if (notebook->tab_pos == GTK_POS_TOP) + y = container->border_width + + (page->requisition.height - ARROW_SIZE) / 2; + else + y = allocation->height - container->border_width - + ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2; + } break; - case GTK_POS_RIGHT: - child_allocation.x = allocation->width - notebook->cur_page->requisition.width; case GTK_POS_LEFT: - child_allocation.width = notebook->cur_page->requisition.width; + case GTK_POS_RIGHT: + while (children) + { + page = children->data; + children = children->next; + tab_space += page->requisition.height; + } + if (tab_space > allocation->height - 2 * container->border_width + - TAB_OVERLAP) + { + showarrow = TRUE; + page = notebook->focus_tab->data; + tab_space = allocation->height + - ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP + - 2 * container->border_width - page->requisition.height; + y = allocation->height - container->border_width + - ARROW_SIZE; + page = notebook->children->data; + if (notebook->tab_pos == GTK_POS_LEFT) + x = container->border_width + + (page->requisition.width + - (2 * ARROW_SIZE - ARROW_SPACING)) / 2; + else + x = allocation->width - container->border_width + - (2 * ARROW_SIZE - ARROW_SPACING) + - (page->requisition.width + - (2 * ARROW_SIZE - ARROW_SPACING)) / 2; + } break; } - - children = notebook->children; - while (children) - { - page = children->data; - children = children->next; - - if (GTK_WIDGET_VISIBLE (page->child)) + if (showarrow) /* first_tab <- focus_tab */ + { + children = notebook->focus_tab->prev; + while (children) { - switch (notebook->tab_pos) + if (notebook->first_tab == children) + break; + children = children->prev; + } + + if (!children) + notebook->first_tab = notebook->focus_tab; + else + gtk_notebook_calc_tabs (notebook, notebook->focus_tab->prev, + &(notebook->first_tab), &tab_space, + STEP_PREV); + if (tab_space <= 0) + { + notebook->first_tab = notebook->first_tab->next; + if (!notebook->first_tab) + notebook->first_tab = notebook->focus_tab; + last_child = notebook->focus_tab->next; + } + else /* focus_tab -> end */ + { + if (!notebook->first_tab) + notebook->first_tab = notebook->children; + + children = NULL; + gtk_notebook_calc_tabs (notebook, notebook->focus_tab->next, + &children, &tab_space, STEP_NEXT); + + if (tab_space <= 0) + last_child = children; + else /* start <- first_tab */ { - case GTK_POS_TOP: - case GTK_POS_BOTTOM: - child_allocation.width = page->requisition.width + TAB_OVERLAP; - break; - case GTK_POS_LEFT: - case GTK_POS_RIGHT: - child_allocation.height = page->requisition.height + TAB_OVERLAP; - break; - } - - gtk_notebook_page_allocate (notebook, page, &child_allocation); - - switch (notebook->tab_pos) - { - case GTK_POS_TOP: - case GTK_POS_BOTTOM: - child_allocation.x += child_allocation.width - TAB_OVERLAP; - break; - case GTK_POS_LEFT: - case GTK_POS_RIGHT: - child_allocation.y += child_allocation.height - TAB_OVERLAP; - break; + last_child = NULL; + children = NULL; + gtk_notebook_calc_tabs (notebook,notebook->first_tab->prev, + &children, &tab_space, STEP_PREV); + notebook->first_tab = children->next; } } + gdk_window_move (notebook->panel, x, y); + gdk_window_show (notebook->panel); + + if (tab_space < 0) + { + tab_space = -tab_space; + n = 0; + children = notebook->first_tab; + while (children != last_child) + { + children = children->next; + n++; + } + } + else + tab_space = 0; + + children = notebook->children; + while (children != notebook->first_tab) + { + page = children->data; + children = children->next; + + if (GTK_WIDGET_MAPPED (page->tab_label)) + gtk_widget_unmap (page->tab_label); + + } + children = last_child; + while (children) + { + page = children->data; + children = children->next; + + if (GTK_WIDGET_MAPPED (page->tab_label)) + gtk_widget_unmap (page->tab_label); + } + } + else /* !showarrow */ + { + gdk_window_hide (notebook->panel); + notebook->first_tab = notebook->children; + tab_space = 0; + } + children = notebook->first_tab; + } + else + children = notebook->children; + + i = 1; + while (children != last_child) + { + page = children->data; + children = children->next; + + if (GTK_WIDGET_VISIBLE (page->child)) + { + new_fill = (tab_space * i++) / n; + switch (notebook->tab_pos) + { + case GTK_POS_TOP: + case GTK_POS_BOTTOM: + child_allocation.width = page->requisition.width + + TAB_OVERLAP + new_fill - old_fill; + break; + case GTK_POS_LEFT: + case GTK_POS_RIGHT: + child_allocation.height = page->requisition.height + + TAB_OVERLAP + new_fill - old_fill; + break; + } + old_fill = new_fill; + gtk_notebook_page_allocate (notebook, page, &child_allocation); + + switch (notebook->tab_pos) + { + case GTK_POS_TOP: + case GTK_POS_BOTTOM: + child_allocation.x += child_allocation.width - TAB_OVERLAP; + break; + case GTK_POS_LEFT: + case GTK_POS_RIGHT: + child_allocation.y += child_allocation.height - TAB_OVERLAP; + break; + } + + if (!GTK_WIDGET_MAPPED (page->tab_label)) + gtk_widget_map (page->tab_label); } } } @@ -1365,35 +2485,39 @@ gtk_notebook_page_allocate (GtkNotebook *notebook, switch (notebook->tab_pos) { case GTK_POS_TOP: - child_allocation.x = xthickness + CHILD_SPACING; - child_allocation.y = ythickness + CHILD_SPACING; + child_allocation.x = xthickness + notebook->tab_border; + child_allocation.y = ythickness + notebook->tab_border + + page->allocation.y; child_allocation.width = page->allocation.width - child_allocation.x * 2; - child_allocation.height = page->allocation.height - child_allocation.y; + child_allocation.height = page->allocation.height - ythickness + - 2 * notebook->tab_border; child_allocation.x += page->allocation.x; - child_allocation.y += page->allocation.y; break; case GTK_POS_BOTTOM: - child_allocation.x = xthickness + CHILD_SPACING; - child_allocation.y = ythickness + CHILD_SPACING; + child_allocation.x = xthickness + notebook->tab_border; child_allocation.width = page->allocation.width - child_allocation.x * 2; - child_allocation.height = page->allocation.height - child_allocation.y; + child_allocation.height = page->allocation.height - ythickness + - 2 * notebook->tab_border; child_allocation.x += page->allocation.x; - child_allocation.y = page->allocation.y; + child_allocation.y = page->allocation.y + notebook->tab_border; break; case GTK_POS_LEFT: - child_allocation.x = xthickness + CHILD_SPACING; - child_allocation.y = ythickness + CHILD_SPACING; - child_allocation.width = page->allocation.width - child_allocation.x; - child_allocation.height = page->allocation.height - child_allocation.y * 2; - child_allocation.x += page->allocation.x; + child_allocation.x = xthickness + notebook->tab_border + + page->allocation.x; + child_allocation.y = ythickness + notebook->tab_border; + child_allocation.width = page->allocation.width - xthickness + - 2 * notebook->tab_border; + child_allocation.height = page->allocation.height + - child_allocation.y * 2; child_allocation.y += page->allocation.y; break; case GTK_POS_RIGHT: - child_allocation.x = xthickness + CHILD_SPACING; - child_allocation.y = ythickness + CHILD_SPACING; - child_allocation.width = page->allocation.width - child_allocation.x; - child_allocation.height = page->allocation.height - child_allocation.y * 2; - child_allocation.x = page->allocation.x; + child_allocation.y = ythickness + notebook->tab_border; + child_allocation.width = page->allocation.width - xthickness + - 2 * notebook->tab_border; + child_allocation.height = page->allocation.height + - child_allocation.y * 2; + child_allocation.x = page->allocation.x + notebook->tab_border; child_allocation.y += page->allocation.y; break; } @@ -1402,9 +2526,41 @@ gtk_notebook_page_allocate (GtkNotebook *notebook, } static void -gtk_notebook_switch_page (GtkNotebook *notebook, GtkNotebookPage *page) +gtk_notebook_menu_switch_page (GtkWidget *widget, + GtkNotebookPage *page) { - gtk_signal_emit (GTK_OBJECT (notebook), notebook_signals[SWITCH_PAGE], page); + GtkNotebook *notebook; + GList *children; + gint page_num; + + g_return_if_fail (widget != NULL); + g_return_if_fail (page != NULL); + + notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget + (GTK_MENU (widget->parent))); + page_num = 0; + children = notebook->children; + while (children && children->data != page) + { + children = children->next; + page_num++; + } + + gtk_signal_emit (GTK_OBJECT (notebook), + notebook_signals[SWITCH_PAGE], + page, + page_num); +} + +static void +gtk_notebook_switch_page (GtkNotebook *notebook, + GtkNotebookPage *page, + gint page_num) +{ + gtk_signal_emit (GTK_OBJECT (notebook), + notebook_signals[SWITCH_PAGE], + page, + page_num); } static void @@ -1417,5 +2573,364 @@ gtk_notebook_marshal_signal (GtkObject *object, rfunc = (GtkNotebookSignal) func; - (* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data); + (* rfunc) (object, GTK_VALUE_POINTER (args[0]), GTK_VALUE_INT (args[1]), + func_data); +} + +static gint +gtk_notebook_focus (GtkContainer *container, + GtkDirectionType direction) +{ + GtkNotebook *notebook; + GtkWidget *focus_child; + GtkNotebookPage *page = NULL; + GtkNotebookPage *old_page; + gint return_val; + + g_return_val_if_fail (container != NULL, FALSE); + g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE); + + notebook = GTK_NOTEBOOK(container); + + if (!GTK_WIDGET_SENSITIVE (container) || !notebook->children) + return FALSE; + + focus_child = container->focus_child; + container->focus_child = NULL; + + if (!notebook->show_tabs) + { + if (GTK_WIDGET_VISIBLE (notebook->cur_page->child)) + { + if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child)) + { + if (!focus_child) + { + gtk_widget_grab_focus (notebook->cur_page->child); + return TRUE; + } + } + else if (GTK_IS_CONTAINER (notebook->cur_page->child)) + { + if (gtk_container_focus + (GTK_CONTAINER (notebook->cur_page->child), direction)) + return TRUE; + } + } + return FALSE; + } + + old_page = notebook->focus_tab->data; + return_val = FALSE; + + if (!GTK_WIDGET_HAS_FOCUS (container) && !focus_child) + { + gtk_widget_grab_focus (GTK_WIDGET (container)); + return TRUE; + } + + if (focus_child && focus_child == old_page->child) + { + if (GTK_WIDGET_VISIBLE (old_page->child)) + { + if (GTK_IS_CONTAINER (old_page->child) && + !GTK_WIDGET_HAS_FOCUS (old_page->child)) + { + if (gtk_container_focus (GTK_CONTAINER (old_page->child), + direction)) + return TRUE; + } + gtk_widget_grab_focus (GTK_WIDGET(notebook)); + return TRUE; + } + return FALSE; + } + + switch (direction) + { + case GTK_DIR_TAB_FORWARD: + case GTK_DIR_RIGHT: + case GTK_DIR_DOWN: + if (!notebook->focus_tab->next) + return FALSE; + + notebook->focus_tab = notebook->focus_tab->next; + page = notebook->focus_tab->data; + return_val = TRUE; + break; + case GTK_DIR_TAB_BACKWARD: + case GTK_DIR_LEFT: + case GTK_DIR_UP: + if (!notebook->focus_tab->prev) + return FALSE; + + notebook->focus_tab = notebook->focus_tab->prev; + page = notebook->focus_tab->data; + return_val = TRUE; + break; + } + + if (return_val) + { + if (GTK_WIDGET_MAPPED (page->tab_label)) + gtk_notebook_focus_changed (notebook, old_page); + else + { + gtk_notebook_pages_allocate (notebook, + &(GTK_WIDGET (notebook)->allocation)); + gtk_notebook_expose_tabs (notebook); + } + } + + return return_val; +} + +static gint +gtk_notebook_page_select (GtkNotebook *notebook) +{ + g_return_val_if_fail (notebook != NULL, FALSE); + g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE); + + if (notebook->focus_tab) + { + GtkNotebookPage *page; + GList *children; + gint num; + + page = notebook->focus_tab->data; + + children = notebook->children; + num = 0; + while (children != notebook->focus_tab) + { + children = children->next; + num++; + } + + gtk_notebook_switch_page (notebook, page, num); + + if (GTK_WIDGET_VISIBLE (page->child)) + { + if (GTK_WIDGET_CAN_FOCUS (page->child)) + { + gtk_widget_grab_focus (page->child); + return TRUE; + } + else if (GTK_IS_CONTAINER (page->child)) + { + if (gtk_container_focus (GTK_CONTAINER (page->child), + GTK_DIR_TAB_FORWARD)) + return TRUE; + } + } + } + return FALSE; +} + +static void +gtk_notebook_switch_focus_tab (GtkNotebook *notebook, + GList *new_child) +{ + GtkNotebookPage *old_page; + GtkNotebookPage *page; + + g_return_if_fail (notebook != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + + if (notebook->focus_tab != new_child) + { + old_page = notebook->focus_tab->data; + notebook->focus_tab = new_child; + page = notebook->focus_tab->data; + if (GTK_WIDGET_MAPPED (page->tab_label)) + gtk_notebook_focus_changed (notebook, old_page); + else + { + gtk_notebook_pages_allocate (notebook, + &(GTK_WIDGET (notebook)->allocation)); + gtk_notebook_expose_tabs (notebook); + } + } +} + +static gint +gtk_notebook_key_press (GtkWidget *widget, + GdkEventKey *event) +{ + GtkNotebook *notebook; + GtkDirectionType direction = 0; + gint return_val; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + notebook = GTK_NOTEBOOK (widget); + return_val = TRUE; + + if (!notebook->children || !notebook->show_tabs) + return FALSE; + + switch (event->keyval) + { + case GDK_Up: + direction = GTK_DIR_UP; + break; + case GDK_Left: + direction = GTK_DIR_LEFT; + break; + case GDK_Down: + direction = GTK_DIR_DOWN; + break; + case GDK_Right: + direction = GTK_DIR_RIGHT; + break; + case GDK_Tab: + if (event->state & GDK_SHIFT_MASK) + direction = GTK_DIR_TAB_BACKWARD; + else + direction = GTK_DIR_TAB_FORWARD; + break; + case GDK_Home: + gtk_notebook_switch_focus_tab (notebook, notebook->children); + return TRUE; + case GDK_End: + gtk_notebook_switch_focus_tab (notebook, + g_list_last (notebook->children)); + return TRUE; + case GDK_Return: + case GDK_space: + gtk_notebook_page_select (GTK_NOTEBOOK(widget)); + return TRUE; + default: + return_val = FALSE; + } + if (return_val) + return gtk_container_focus (GTK_CONTAINER (widget), direction); + return return_val; +} + +void +gtk_notebook_set_tab_border (GtkNotebook *notebook, + gint tab_border) +{ + g_return_if_fail (notebook != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + + if (notebook->tab_border != tab_border && tab_border > 0) + { + notebook->tab_border = tab_border; + + if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs) + gtk_widget_queue_resize (GTK_WIDGET (notebook)); + } +} + +static void +gtk_notebook_update_labels (GtkNotebook *notebook, + GList *list, + gint page_num) +{ + GtkNotebookPage *page; + gchar string[32]; + + while (list) + { + page = list->data; + list = list->next; + sprintf (string, "Page %d", page_num); + if (page->default_tab) + gtk_label_set (GTK_LABEL (page->tab_label), string); + if (notebook->menu && page->default_menu) + gtk_label_set (GTK_LABEL (page->menu_label), string); + page_num++; + } +} + +static void +gtk_notebook_menu_item_create (GtkNotebook *notebook, + GtkNotebookPage *page, + gint position) +{ + GtkWidget *menu_item; + + if (page->default_menu) + { + if (GTK_IS_LABEL (page->tab_label)) + page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label); + else + page->menu_label = gtk_label_new (""); + gtk_widget_show (page->menu_label); + } + menu_item = gtk_menu_item_new (); + gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label); + gtk_menu_insert (GTK_MENU (notebook->menu), menu_item, position); + gtk_signal_connect (GTK_OBJECT (menu_item), "activate", + GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), + page); + gtk_widget_show (menu_item); +} + +void +gtk_notebook_popup_enable (GtkNotebook *notebook) +{ + GtkNotebookPage *page; + GList *children; + + g_return_if_fail (notebook != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + + if (notebook->menu) + return; + + notebook->menu = gtk_menu_new (); + + children = notebook->children; + while (children) + { + page = children->data; + children = children->next; + gtk_notebook_menu_item_create (notebook, page, -1); + } + gtk_notebook_update_labels (notebook, notebook->children,1); + + gtk_menu_attach_to_widget (GTK_MENU (notebook->menu), GTK_WIDGET (notebook), + gtk_notebook_menu_detacher); +} + +static void +gtk_notebook_menu_label_unparent (GtkWidget *widget, + gpointer data) +{ + gtk_widget_unparent (GTK_BIN(widget)->child); + GTK_BIN(widget)->child = NULL; +} + +void +gtk_notebook_popup_disable (GtkNotebook *notebook) +{ + g_return_if_fail (notebook != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (notebook)); + + if (!notebook->menu) + return; + + gtk_container_foreach (GTK_CONTAINER (notebook->menu), + (GtkCallback) gtk_notebook_menu_label_unparent, NULL); + gtk_widget_destroy (notebook->menu); +} + +static void +gtk_notebook_menu_detacher (GtkWidget *widget, + GtkMenu *menu) +{ + GtkNotebook *notebook; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_NOTEBOOK (widget)); + + notebook = GTK_NOTEBOOK (widget); + g_return_if_fail (notebook->menu == (GtkWidget*) menu); + + notebook->menu = NULL; } diff --git a/gtk/gtknotebook.h b/gtk/gtknotebook.h index 5cbcf6fc59..e02881b1a0 100644 --- a/gtk/gtknotebook.h +++ b/gtk/gtknotebook.h @@ -43,10 +43,24 @@ struct _GtkNotebook GtkNotebookPage *cur_page; GList *children; + GList *first_tab; + GList *focus_tab; + + GtkWidget *menu; + GdkWindow *panel; + + guint32 timer; + + gint16 tab_border; guint show_tabs : 1; guint show_border : 1; guint tab_pos : 2; + guint scrollable : 1; + guint in_child : 2; + guint click_child : 2; + guint button : 2; + guint need_timer : 1; }; struct _GtkNotebookClass @@ -61,6 +75,9 @@ struct _GtkNotebookPage { GtkWidget *child; GtkWidget *tab_label; + GtkWidget *menu_label; + gint8 default_menu : 1; + gint8 default_tab : 1; GtkRequisition requisition; GtkAllocation allocation; }; @@ -68,30 +85,48 @@ struct _GtkNotebookPage guint gtk_notebook_get_type (void); GtkWidget* gtk_notebook_new (void); -void gtk_notebook_append_page (GtkNotebook *notebook, - GtkWidget *child, - GtkWidget *tab_label); -void gtk_notebook_prepend_page (GtkNotebook *notebook, - GtkWidget *child, - GtkWidget *tab_label); -void gtk_notebook_insert_page (GtkNotebook *notebook, - GtkWidget *child, - GtkWidget *tab_label, - gint position); -void gtk_notebook_remove_page (GtkNotebook *notebook, - gint page_num); -gint gtk_notebook_current_page (GtkNotebook *notebook); -void gtk_notebook_set_page (GtkNotebook *notebook, - gint page_num); -void gtk_notebook_next_page (GtkNotebook *notebook); -void gtk_notebook_prev_page (GtkNotebook *notebook); -void gtk_notebook_set_tab_pos (GtkNotebook *notebook, - GtkPositionType pos); -void gtk_notebook_set_show_tabs (GtkNotebook *notebook, - gint show_tabs); -void gtk_notebook_set_show_border (GtkNotebook *notebook, - gint show_border); - +void gtk_notebook_append_page (GtkNotebook *notebook, + GtkWidget *child, + GtkWidget *tab_label); +void gtk_notebook_append_page_menu (GtkNotebook *notebook, + GtkWidget *child, + GtkWidget *tab_label, + GtkWidget *menu_label); +void gtk_notebook_prepend_page (GtkNotebook *notebook, + GtkWidget *child, + GtkWidget *tab_label); +void gtk_notebook_prepend_page_menu (GtkNotebook *notebook, + GtkWidget *child, + GtkWidget *tab_label, + GtkWidget *menu_label); +void gtk_notebook_insert_page (GtkNotebook *notebook, + GtkWidget *child, + GtkWidget *tab_label, + gint position); +void gtk_notebook_insert_page_menu (GtkNotebook *notebook, + GtkWidget *child, + GtkWidget *tab_label, + GtkWidget *menu_label, + gint position); +void gtk_notebook_remove_page (GtkNotebook *notebook, + gint page_num); +gint gtk_notebook_current_page (GtkNotebook *notebook); +void gtk_notebook_set_page (GtkNotebook *notebook, + gint page_num); +void gtk_notebook_next_page (GtkNotebook *notebook); +void gtk_notebook_prev_page (GtkNotebook *notebook); +void gtk_notebook_set_tab_pos (GtkNotebook *notebook, + GtkPositionType pos); +void gtk_notebook_set_show_tabs (GtkNotebook *notebook, + gint show_tabs); +void gtk_notebook_set_show_border (GtkNotebook *notebook, + gint show_border); +void gtk_notebook_set_scrollable (GtkNotebook *notebook, + gint scrollable); +void gtk_notebook_set_tab_border (GtkNotebook *notebook, + gint border_width); +void gtk_notebook_popup_enable (GtkNotebook *notebook); +void gtk_notebook_popup_disable (GtkNotebook *notebook); #ifdef __cplusplus } diff --git a/gtk/testgtk.c b/gtk/testgtk.c index 1ef4c2b790..3579657c7c 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -28,7 +28,7 @@ destroy_window (GtkWidget *widget, *window = NULL; } -void +static void destroy_tooltips (GtkWidget *widget, GtkWindow **window) { GtkTooltips *tt = gtk_object_get_data (GTK_OBJECT (*window), "tooltips"); @@ -37,7 +37,7 @@ destroy_tooltips (GtkWidget *widget, GtkWindow **window) *window = NULL; } -void +static void button_window (GtkWidget *widget, GtkWidget *button) { @@ -47,7 +47,7 @@ button_window (GtkWidget *widget, gtk_widget_hide (button); } -void +static void create_buttons () { static GtkWidget *window = NULL; @@ -187,7 +187,7 @@ create_buttons () gtk_widget_destroy (window); } -void +static void create_toggle_buttons () { static GtkWidget *window = NULL; @@ -262,7 +262,7 @@ create_toggle_buttons () gtk_widget_destroy (window); } -void +static void create_check_buttons () { static GtkWidget *window = NULL; @@ -337,7 +337,7 @@ create_check_buttons () gtk_widget_destroy (window); } -void +static void create_radio_buttons () { static GtkWidget *window = NULL; @@ -417,12 +417,12 @@ create_radio_buttons () gtk_widget_destroy (window); } -void +static void bbox_widget_destroy (GtkWidget* widget, GtkWidget* todestroy) { } -void +static void create_bbox_window (gint horizontal, char* title, gint pos, @@ -492,7 +492,7 @@ create_bbox_window (gint horizontal, gtk_widget_show (window); } -void +static void test_hbbox () { create_bbox_window (TRUE, "Spread", 50, 40, 85, 28, GTK_BUTTONBOX_SPREAD); @@ -501,7 +501,7 @@ test_hbbox () create_bbox_window (TRUE, "End", 500, 15, 30, 25, GTK_BUTTONBOX_END); } -void +static void test_vbbox () { create_bbox_window (FALSE, "Spread", 50, 40, 85, 25, GTK_BUTTONBOX_SPREAD); @@ -510,7 +510,7 @@ test_vbbox () create_bbox_window (FALSE, "End", 650, 15, 30, 25, GTK_BUTTONBOX_END); } -void +static void create_button_box () { static GtkWidget* window = NULL; @@ -556,7 +556,7 @@ create_button_box () gtk_widget_destroy (window); } -GtkWidget * +static GtkWidget* new_pixmap (char *filename, GdkWindow *window, GdkColor *background) @@ -573,70 +573,70 @@ new_pixmap (char *filename, return wpixmap; } -void +static void set_toolbar_horizontal (GtkWidget *widget, gpointer data) { gtk_toolbar_set_orientation (GTK_TOOLBAR (data), GTK_ORIENTATION_HORIZONTAL); } -void +static void set_toolbar_vertical (GtkWidget *widget, gpointer data) { gtk_toolbar_set_orientation (GTK_TOOLBAR (data), GTK_ORIENTATION_VERTICAL); } -void +static void set_toolbar_icons (GtkWidget *widget, gpointer data) { gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_ICONS); } -void +static void set_toolbar_text (GtkWidget *widget, gpointer data) { gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_TEXT); } -void +static void set_toolbar_both (GtkWidget *widget, gpointer data) { gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH); } -void +static void set_toolbar_small_space (GtkWidget *widget, gpointer data) { gtk_toolbar_set_space_size (GTK_TOOLBAR (data), 5); } -void +static void set_toolbar_big_space (GtkWidget *widget, gpointer data) { gtk_toolbar_set_space_size (GTK_TOOLBAR (data), 10); } -void +static void set_toolbar_enable (GtkWidget *widget, gpointer data) { gtk_toolbar_set_tooltips (GTK_TOOLBAR (data), TRUE); } -void +static void set_toolbar_disable (GtkWidget *widget, gpointer data) { gtk_toolbar_set_tooltips (GTK_TOOLBAR (data), FALSE); } -void +static void create_toolbar (void) { static GtkWidget *window = NULL; @@ -723,7 +723,7 @@ create_toolbar (void) gtk_widget_destroy (window); } -GtkWidget * +static GtkWidget* make_toolbar (GtkWidget *window) { GtkWidget *toolbar; @@ -782,7 +782,7 @@ make_toolbar (GtkWidget *window) return toolbar; } -void +static void create_handle_box () { static GtkWidget* window = NULL; @@ -818,7 +818,7 @@ create_handle_box () } -void +static void reparent_label (GtkWidget *widget, GtkWidget *new_parent) { @@ -829,7 +829,19 @@ reparent_label (GtkWidget *widget, gtk_widget_reparent (label, new_parent); } -void +static void +set_parent_signal (GtkWidget *child, + GtkWidget *old_parent, + gpointer func_data) +{ + g_print ("set_parent for \"%s\": new parent: \"%s\", old parent: \"%s\", data: %d\n", + gtk_type_name (GTK_OBJECT_TYPE (child)), + child->parent ? gtk_type_name (GTK_OBJECT_TYPE (child->parent)) : "NULL", + old_parent ? gtk_type_name (GTK_OBJECT_TYPE (old_parent)) : "NULL", + (gint) func_data); +} + +static void create_reparent () { static GtkWidget *window = NULL; @@ -887,6 +899,10 @@ create_reparent () gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (box3), label, FALSE, TRUE, 0); + gtk_signal_connect (GTK_OBJECT (label), + "set_parent", + GTK_SIGNAL_FUNC (set_parent_signal), + (GtkObject*) 42); gtk_widget_show (label); @@ -935,7 +951,7 @@ create_reparent () gtk_widget_destroy (window); } -void +static void create_pixmap () { static GtkWidget *window = NULL; @@ -1022,7 +1038,7 @@ create_pixmap () gtk_widget_destroy (window); } -void +static void create_tooltips () { static GtkWidget *window = NULL; @@ -1107,7 +1123,7 @@ create_tooltips () gtk_widget_destroy (window); } -GtkWidget* +static GtkWidget* create_menu (int depth) { GtkWidget *menu; @@ -1138,7 +1154,7 @@ create_menu (int depth) return menu; } -void +static void create_menus () { static GtkWidget *window = NULL; @@ -1237,7 +1253,7 @@ create_menus () /* * GtkScrolledWindow */ -void +static void create_scrolled_windows () { static GtkWidget *window; @@ -1309,14 +1325,15 @@ create_scrolled_windows () * GtkEntry */ -void entry_toggle_editable (GtkWidget *checkbutton, - GtkWidget *entry) +static void +entry_toggle_editable (GtkWidget *checkbutton, + GtkWidget *entry) { gtk_entry_set_editable(GTK_ENTRY(entry), GTK_TOGGLE_BUTTON(checkbutton)->active); } -void +static void create_entry () { static GtkWidget *window = NULL; @@ -1408,7 +1425,7 @@ create_entry () /* * GtkList */ -void +static void list_add (GtkWidget *widget, GtkWidget *list) { @@ -1422,7 +1439,7 @@ list_add (GtkWidget *widget, gtk_container_add (GTK_CONTAINER (list), list_item); } -void +static void list_remove (GtkWidget *widget, GtkWidget *list) { @@ -1445,7 +1462,7 @@ list_remove (GtkWidget *widget, g_list_free (clear_list); } -void +static void create_list () { static GtkWidget *window = NULL; @@ -1570,7 +1587,7 @@ create_list () static gint clist_rows = 0; static gint clist_selected_row = 0; -void +static void add1000_clist (GtkWidget *widget, gpointer data) { gint i, row; @@ -1607,7 +1624,7 @@ add1000_clist (GtkWidget *widget, gpointer data) gdk_bitmap_unref (mask); } -void +static void add10000_clist (GtkWidget *widget, gpointer data) { gint i; @@ -1850,7 +1867,7 @@ create_clist () * the rest of the clist configuration */ gtk_clist_set_row_height (GTK_CLIST (clist), 20); - + gtk_signal_connect (GTK_OBJECT (clist), "select_row", (GtkSignalFunc) select_clist, @@ -2411,14 +2428,234 @@ create_text () /* * GtkNotebook */ -void + +GdkPixmap *book_open; +GdkPixmap *book_closed; +GdkBitmap *book_open_mask; +GdkBitmap *book_closed_mask; + +static char * book_open_xpm[] = { +"16 16 11 1", +" c None", +". c #28A22CB228A2", +"X c #FFFFFFFFFFFF", +"o c #F7DEF7DEF7DE", +"O c #000000000000", +"+ c #FFFF6DB60000", +"@ c #CF3CCF3CCF3C", +"# c #FFFFDB6C0000", +"$ c #30C234D330C2", +"% c #C71BC30BC71B", +"& c #D75C6DB60000", +" ", +" .. ", +" .X. ", +" .oO ... ", +" .+Xo. ..oX.. ", +" .+oXo..XXoX.@..", +" .+ooX.@ooXo.@#.", +" .+XXo.@XooX.@+.", +" .+XoX.@XoXo.@#.", +" .+oXo.@oXXX.@+.", +" .++Xo$@oOO..%#.", +" ..+&X.@.O@@@@+.", +" .++........#.", +" .+..+++++++&$", +" .+++.......$.", +" ... "}; + +static char * book_closed_xpm[] = { +"16 16 12 1", +" c None", +". c #000000000000", +"X c #FFFF6DB60000", +"o c #082008200820", +"O c #AEBA00005144", +"+ c #FFFFDB6C0000", +"@ c #AEBA00000000", +"# c #D75CDB6C0000", +"$ c #28A22CB228A2", +"% c #FFFFFFFFFFFF", +"& c #F7DEF7DEF7DE", +"* c #30C234D330C2", +" ", +" .. ", +" ..XX. ", +" ..XXXXX. ", +" o.XXXXXXXX. ", +".O+XXXXXXXXX. ", +"o.@#XXXXXXXXX. ", +".X.O+XXXXXXXXXo ", +".XX.@+XXXXXXXX.$", +"oXXX.O+XXXXX..%$", +" .XXX.@+XX..&&&$", +" .XXX.O..&%&%.*", +" .XX$.&&%&.. ", +" .X$&%&.o ", +" .$%.. ", +" .o "}; + +static void +page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num) +{ + GtkNotebookPage *oldpage; + GtkWidget *pixwid; + + oldpage = GTK_NOTEBOOK (widget)->cur_page; + + if (page == oldpage) + return; + + pixwid = ((GtkBoxChild*)(GTK_BOX (page->tab_label)->children->data))->widget; + gtk_pixmap_set (GTK_PIXMAP (pixwid), book_open, book_open_mask); + pixwid = ((GtkBoxChild*) (GTK_BOX (page->menu_label)->children->data))->widget; + gtk_pixmap_set (GTK_PIXMAP (pixwid), book_open, book_open_mask); + + if (oldpage) + { + pixwid = ((GtkBoxChild*) (GTK_BOX + (oldpage->tab_label)->children->data))->widget; + gtk_pixmap_set (GTK_PIXMAP (pixwid), book_closed, book_closed_mask); + pixwid = ((GtkBoxChild*) (GTK_BOX (oldpage->menu_label)->children->data))->widget; + gtk_pixmap_set (GTK_PIXMAP (pixwid), book_closed, book_closed_mask); + } +} + +static void +create_pages (GtkNotebook *notebook, gint start, gint end) +{ + GtkWidget *child = NULL; + GtkWidget *label; + GtkWidget *entry; + GtkWidget *box; + GtkWidget *hbox; + GtkWidget *label_box; + GtkWidget *menu_box; + GtkWidget *button; + GtkWidget *pixwid; + gint i; + char buffer[32]; + + for (i = start; i <= end; i++) + { + sprintf (buffer, "Page %d", i); + + switch (i%4) + { + case 3: + child = gtk_button_new_with_label (buffer); + gtk_container_border_width (GTK_CONTAINER(child), 10); + break; + case 2: + child = gtk_label_new (buffer); + break; + case 1: + child = gtk_frame_new (buffer); + gtk_container_border_width (GTK_CONTAINER (child), 10); + + box = gtk_vbox_new (TRUE,0); + gtk_container_border_width (GTK_CONTAINER (box), 10); + gtk_container_add (GTK_CONTAINER (child), box); + + label = gtk_label_new (buffer); + gtk_box_pack_start (GTK_BOX(box), label, TRUE, TRUE, 5); + + entry = gtk_entry_new (); + gtk_box_pack_start (GTK_BOX(box), entry, TRUE, TRUE, 5); + + hbox = gtk_hbox_new (TRUE,0); + gtk_box_pack_start (GTK_BOX(box), hbox, TRUE, TRUE, 5); + + button = gtk_button_new_with_label ("Ok"); + gtk_box_pack_start (GTK_BOX(hbox), button, TRUE, TRUE, 5); + + button = gtk_button_new_with_label ("Cancel"); + gtk_box_pack_start (GTK_BOX(hbox), button, TRUE, TRUE, 5); + break; + case 0: + child = gtk_frame_new (buffer); + gtk_container_border_width (GTK_CONTAINER (child), 10); + + label = gtk_label_new (buffer); + gtk_container_add (GTK_CONTAINER (child), label); + break; + } + + gtk_widget_show_all (child); + + label_box = gtk_hbox_new (FALSE, 0); + pixwid = gtk_pixmap_new (book_closed, book_closed_mask); + gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0); + gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1); + label = gtk_label_new (buffer); + gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0); + gtk_widget_show_all (label_box); + + menu_box = gtk_hbox_new (FALSE, 0); + pixwid = gtk_pixmap_new (book_closed, book_closed_mask); + gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0); + gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1); + label = gtk_label_new (buffer); + gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0); + gtk_widget_show_all (menu_box); + + gtk_notebook_append_page_menu (notebook, child, label_box, menu_box); + } +} + +static void rotate_notebook (GtkButton *button, GtkNotebook *notebook) { gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4); } -void +static void +standard_notebook (GtkButton *button, + GtkNotebook *notebook) +{ + gint i; + + gtk_notebook_set_show_tabs (notebook, TRUE); + gtk_notebook_set_scrollable (notebook, FALSE); + if (g_list_length (notebook->children) == 15) + for (i = 0; i < 10; i++) + gtk_notebook_remove_page (notebook, 5); +} + +static void +notabs_notebook (GtkButton *button, + GtkNotebook *notebook) +{ + gint i; + + gtk_notebook_set_show_tabs (notebook, FALSE); + if (g_list_length (notebook->children) == 15) + for (i = 0; i < 10; i++) + gtk_notebook_remove_page (notebook, 5); +} + +static void +scrollable_notebook (GtkButton *button, + GtkNotebook *notebook) +{ + gtk_notebook_set_show_tabs (notebook, TRUE); + gtk_notebook_set_scrollable (notebook, TRUE); + if (g_list_length (notebook->children) == 5) + create_pages (notebook, 6, 15); +} + +static void +notebook_popup (GtkToggleButton *button, + GtkNotebook *notebook) +{ + if (button->active) + gtk_notebook_popup_enable (notebook); + else + gtk_notebook_popup_disable (notebook); +} + +static void create_notebook () { static GtkWidget *window = NULL; @@ -2427,10 +2664,12 @@ create_notebook () GtkWidget *button; GtkWidget *separator; GtkWidget *notebook; - GtkWidget *frame; - GtkWidget *label; - char buffer[32]; - int i; + GtkWidget *omenu; + GtkWidget *menu; + GtkWidget *submenu; + GtkWidget *menuitem; + GSList *group; + GdkColor transparent; if (!window) { @@ -2446,86 +2685,101 @@ create_notebook () gtk_window_set_title (GTK_WINDOW (window), "notebook"); gtk_container_border_width (GTK_CONTAINER (window), 0); - box1 = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (window), box1); - gtk_widget_show (box1); - - - box2 = gtk_vbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (box2), 10); - gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); - gtk_widget_show (box2); - notebook = gtk_notebook_new (); + gtk_signal_connect (GTK_OBJECT (notebook), "switch_page", + GTK_SIGNAL_FUNC (page_switch), NULL); gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP); - gtk_box_pack_start (GTK_BOX (box2), notebook, TRUE, TRUE, 0); - gtk_widget_show (notebook); + gtk_box_pack_start (GTK_BOX (box1), notebook, TRUE, TRUE, 0); + gtk_container_border_width (GTK_CONTAINER (notebook), 10); + book_open = gdk_pixmap_create_from_xpm_d (notebook->window, + &book_open_mask, + &transparent, + book_open_xpm); + book_closed = gdk_pixmap_create_from_xpm_d (notebook->window, + &book_closed_mask, + &transparent, + book_closed_xpm); - for (i = 0; i < 5; i++) - { - sprintf (buffer, "Page %d", i+1); - - frame = gtk_frame_new (buffer); - gtk_container_border_width (GTK_CONTAINER (frame), 10); - gtk_widget_set_usize (frame, 200, 150); - gtk_widget_show (frame); - - label = gtk_label_new (buffer); - gtk_container_add (GTK_CONTAINER (frame), label); - gtk_widget_show (label); - - label = gtk_label_new (buffer); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label); - } - + create_pages (GTK_NOTEBOOK (notebook), 1, 5); separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0); - gtk_widget_show (separator); - - + gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10); + + box2 = gtk_hbox_new (TRUE, 5); + gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0); + + omenu = gtk_option_menu_new (); + menu = gtk_menu_new (); + submenu = NULL; + group = NULL; + + menuitem = gtk_radio_menu_item_new_with_label (group, "Standard"); + gtk_signal_connect_object (GTK_OBJECT (menuitem), "activate", + GTK_SIGNAL_FUNC (standard_notebook), + GTK_OBJECT (notebook)); + group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); + gtk_menu_append (GTK_MENU (menu), menuitem); + gtk_widget_show (menuitem); + menuitem = gtk_radio_menu_item_new_with_label (group, "w/o Tabs"); + gtk_signal_connect_object (GTK_OBJECT (menuitem), "activate", + GTK_SIGNAL_FUNC (notabs_notebook), + GTK_OBJECT (notebook)); + group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); + gtk_menu_append (GTK_MENU (menu), menuitem); + gtk_widget_show (menuitem); + menuitem = gtk_radio_menu_item_new_with_label (group, "Scrollable"); + gtk_signal_connect_object (GTK_OBJECT (menuitem), "activate", + GTK_SIGNAL_FUNC (scrollable_notebook), + GTK_OBJECT (notebook)); + group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); + gtk_menu_append (GTK_MENU (menu), menuitem); + gtk_widget_show (menuitem); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu); + gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, FALSE, 0); + button = gtk_check_button_new_with_label ("enable popup menu"); + gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0); + gtk_signal_connect (GTK_OBJECT(button), "clicked", + GTK_SIGNAL_FUNC (notebook_popup), + GTK_OBJECT (notebook)); + box2 = gtk_hbox_new (FALSE, 10); gtk_container_border_width (GTK_CONTAINER (box2), 10); gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0); - gtk_widget_show (box2); - - + button = gtk_button_new_with_label ("close"); gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC(gtk_widget_destroy), + GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (window)); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); gtk_widget_grab_default (button); - gtk_widget_show (button); button = gtk_button_new_with_label ("next"); gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC(gtk_notebook_next_page), + GTK_SIGNAL_FUNC (gtk_notebook_next_page), GTK_OBJECT (notebook)); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); - gtk_widget_show (button); button = gtk_button_new_with_label ("prev"); gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC(gtk_notebook_prev_page), + GTK_SIGNAL_FUNC (gtk_notebook_prev_page), GTK_OBJECT (notebook)); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); - gtk_widget_show (button); button = gtk_button_new_with_label ("rotate"); gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC(rotate_notebook), + GTK_SIGNAL_FUNC (rotate_notebook), notebook); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); - gtk_widget_show (button); } if (!GTK_WIDGET_VISIBLE (window)) - gtk_widget_show (window); + gtk_widget_show_all (window); else gtk_widget_destroy (window); } diff --git a/tests/testgtk.c b/tests/testgtk.c index 1ef4c2b790..3579657c7c 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -28,7 +28,7 @@ destroy_window (GtkWidget *widget, *window = NULL; } -void +static void destroy_tooltips (GtkWidget *widget, GtkWindow **window) { GtkTooltips *tt = gtk_object_get_data (GTK_OBJECT (*window), "tooltips"); @@ -37,7 +37,7 @@ destroy_tooltips (GtkWidget *widget, GtkWindow **window) *window = NULL; } -void +static void button_window (GtkWidget *widget, GtkWidget *button) { @@ -47,7 +47,7 @@ button_window (GtkWidget *widget, gtk_widget_hide (button); } -void +static void create_buttons () { static GtkWidget *window = NULL; @@ -187,7 +187,7 @@ create_buttons () gtk_widget_destroy (window); } -void +static void create_toggle_buttons () { static GtkWidget *window = NULL; @@ -262,7 +262,7 @@ create_toggle_buttons () gtk_widget_destroy (window); } -void +static void create_check_buttons () { static GtkWidget *window = NULL; @@ -337,7 +337,7 @@ create_check_buttons () gtk_widget_destroy (window); } -void +static void create_radio_buttons () { static GtkWidget *window = NULL; @@ -417,12 +417,12 @@ create_radio_buttons () gtk_widget_destroy (window); } -void +static void bbox_widget_destroy (GtkWidget* widget, GtkWidget* todestroy) { } -void +static void create_bbox_window (gint horizontal, char* title, gint pos, @@ -492,7 +492,7 @@ create_bbox_window (gint horizontal, gtk_widget_show (window); } -void +static void test_hbbox () { create_bbox_window (TRUE, "Spread", 50, 40, 85, 28, GTK_BUTTONBOX_SPREAD); @@ -501,7 +501,7 @@ test_hbbox () create_bbox_window (TRUE, "End", 500, 15, 30, 25, GTK_BUTTONBOX_END); } -void +static void test_vbbox () { create_bbox_window (FALSE, "Spread", 50, 40, 85, 25, GTK_BUTTONBOX_SPREAD); @@ -510,7 +510,7 @@ test_vbbox () create_bbox_window (FALSE, "End", 650, 15, 30, 25, GTK_BUTTONBOX_END); } -void +static void create_button_box () { static GtkWidget* window = NULL; @@ -556,7 +556,7 @@ create_button_box () gtk_widget_destroy (window); } -GtkWidget * +static GtkWidget* new_pixmap (char *filename, GdkWindow *window, GdkColor *background) @@ -573,70 +573,70 @@ new_pixmap (char *filename, return wpixmap; } -void +static void set_toolbar_horizontal (GtkWidget *widget, gpointer data) { gtk_toolbar_set_orientation (GTK_TOOLBAR (data), GTK_ORIENTATION_HORIZONTAL); } -void +static void set_toolbar_vertical (GtkWidget *widget, gpointer data) { gtk_toolbar_set_orientation (GTK_TOOLBAR (data), GTK_ORIENTATION_VERTICAL); } -void +static void set_toolbar_icons (GtkWidget *widget, gpointer data) { gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_ICONS); } -void +static void set_toolbar_text (GtkWidget *widget, gpointer data) { gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_TEXT); } -void +static void set_toolbar_both (GtkWidget *widget, gpointer data) { gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH); } -void +static void set_toolbar_small_space (GtkWidget *widget, gpointer data) { gtk_toolbar_set_space_size (GTK_TOOLBAR (data), 5); } -void +static void set_toolbar_big_space (GtkWidget *widget, gpointer data) { gtk_toolbar_set_space_size (GTK_TOOLBAR (data), 10); } -void +static void set_toolbar_enable (GtkWidget *widget, gpointer data) { gtk_toolbar_set_tooltips (GTK_TOOLBAR (data), TRUE); } -void +static void set_toolbar_disable (GtkWidget *widget, gpointer data) { gtk_toolbar_set_tooltips (GTK_TOOLBAR (data), FALSE); } -void +static void create_toolbar (void) { static GtkWidget *window = NULL; @@ -723,7 +723,7 @@ create_toolbar (void) gtk_widget_destroy (window); } -GtkWidget * +static GtkWidget* make_toolbar (GtkWidget *window) { GtkWidget *toolbar; @@ -782,7 +782,7 @@ make_toolbar (GtkWidget *window) return toolbar; } -void +static void create_handle_box () { static GtkWidget* window = NULL; @@ -818,7 +818,7 @@ create_handle_box () } -void +static void reparent_label (GtkWidget *widget, GtkWidget *new_parent) { @@ -829,7 +829,19 @@ reparent_label (GtkWidget *widget, gtk_widget_reparent (label, new_parent); } -void +static void +set_parent_signal (GtkWidget *child, + GtkWidget *old_parent, + gpointer func_data) +{ + g_print ("set_parent for \"%s\": new parent: \"%s\", old parent: \"%s\", data: %d\n", + gtk_type_name (GTK_OBJECT_TYPE (child)), + child->parent ? gtk_type_name (GTK_OBJECT_TYPE (child->parent)) : "NULL", + old_parent ? gtk_type_name (GTK_OBJECT_TYPE (old_parent)) : "NULL", + (gint) func_data); +} + +static void create_reparent () { static GtkWidget *window = NULL; @@ -887,6 +899,10 @@ create_reparent () gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (box3), label, FALSE, TRUE, 0); + gtk_signal_connect (GTK_OBJECT (label), + "set_parent", + GTK_SIGNAL_FUNC (set_parent_signal), + (GtkObject*) 42); gtk_widget_show (label); @@ -935,7 +951,7 @@ create_reparent () gtk_widget_destroy (window); } -void +static void create_pixmap () { static GtkWidget *window = NULL; @@ -1022,7 +1038,7 @@ create_pixmap () gtk_widget_destroy (window); } -void +static void create_tooltips () { static GtkWidget *window = NULL; @@ -1107,7 +1123,7 @@ create_tooltips () gtk_widget_destroy (window); } -GtkWidget* +static GtkWidget* create_menu (int depth) { GtkWidget *menu; @@ -1138,7 +1154,7 @@ create_menu (int depth) return menu; } -void +static void create_menus () { static GtkWidget *window = NULL; @@ -1237,7 +1253,7 @@ create_menus () /* * GtkScrolledWindow */ -void +static void create_scrolled_windows () { static GtkWidget *window; @@ -1309,14 +1325,15 @@ create_scrolled_windows () * GtkEntry */ -void entry_toggle_editable (GtkWidget *checkbutton, - GtkWidget *entry) +static void +entry_toggle_editable (GtkWidget *checkbutton, + GtkWidget *entry) { gtk_entry_set_editable(GTK_ENTRY(entry), GTK_TOGGLE_BUTTON(checkbutton)->active); } -void +static void create_entry () { static GtkWidget *window = NULL; @@ -1408,7 +1425,7 @@ create_entry () /* * GtkList */ -void +static void list_add (GtkWidget *widget, GtkWidget *list) { @@ -1422,7 +1439,7 @@ list_add (GtkWidget *widget, gtk_container_add (GTK_CONTAINER (list), list_item); } -void +static void list_remove (GtkWidget *widget, GtkWidget *list) { @@ -1445,7 +1462,7 @@ list_remove (GtkWidget *widget, g_list_free (clear_list); } -void +static void create_list () { static GtkWidget *window = NULL; @@ -1570,7 +1587,7 @@ create_list () static gint clist_rows = 0; static gint clist_selected_row = 0; -void +static void add1000_clist (GtkWidget *widget, gpointer data) { gint i, row; @@ -1607,7 +1624,7 @@ add1000_clist (GtkWidget *widget, gpointer data) gdk_bitmap_unref (mask); } -void +static void add10000_clist (GtkWidget *widget, gpointer data) { gint i; @@ -1850,7 +1867,7 @@ create_clist () * the rest of the clist configuration */ gtk_clist_set_row_height (GTK_CLIST (clist), 20); - + gtk_signal_connect (GTK_OBJECT (clist), "select_row", (GtkSignalFunc) select_clist, @@ -2411,14 +2428,234 @@ create_text () /* * GtkNotebook */ -void + +GdkPixmap *book_open; +GdkPixmap *book_closed; +GdkBitmap *book_open_mask; +GdkBitmap *book_closed_mask; + +static char * book_open_xpm[] = { +"16 16 11 1", +" c None", +". c #28A22CB228A2", +"X c #FFFFFFFFFFFF", +"o c #F7DEF7DEF7DE", +"O c #000000000000", +"+ c #FFFF6DB60000", +"@ c #CF3CCF3CCF3C", +"# c #FFFFDB6C0000", +"$ c #30C234D330C2", +"% c #C71BC30BC71B", +"& c #D75C6DB60000", +" ", +" .. ", +" .X. ", +" .oO ... ", +" .+Xo. ..oX.. ", +" .+oXo..XXoX.@..", +" .+ooX.@ooXo.@#.", +" .+XXo.@XooX.@+.", +" .+XoX.@XoXo.@#.", +" .+oXo.@oXXX.@+.", +" .++Xo$@oOO..%#.", +" ..+&X.@.O@@@@+.", +" .++........#.", +" .+..+++++++&$", +" .+++.......$.", +" ... "}; + +static char * book_closed_xpm[] = { +"16 16 12 1", +" c None", +". c #000000000000", +"X c #FFFF6DB60000", +"o c #082008200820", +"O c #AEBA00005144", +"+ c #FFFFDB6C0000", +"@ c #AEBA00000000", +"# c #D75CDB6C0000", +"$ c #28A22CB228A2", +"% c #FFFFFFFFFFFF", +"& c #F7DEF7DEF7DE", +"* c #30C234D330C2", +" ", +" .. ", +" ..XX. ", +" ..XXXXX. ", +" o.XXXXXXXX. ", +".O+XXXXXXXXX. ", +"o.@#XXXXXXXXX. ", +".X.O+XXXXXXXXXo ", +".XX.@+XXXXXXXX.$", +"oXXX.O+XXXXX..%$", +" .XXX.@+XX..&&&$", +" .XXX.O..&%&%.*", +" .XX$.&&%&.. ", +" .X$&%&.o ", +" .$%.. ", +" .o "}; + +static void +page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num) +{ + GtkNotebookPage *oldpage; + GtkWidget *pixwid; + + oldpage = GTK_NOTEBOOK (widget)->cur_page; + + if (page == oldpage) + return; + + pixwid = ((GtkBoxChild*)(GTK_BOX (page->tab_label)->children->data))->widget; + gtk_pixmap_set (GTK_PIXMAP (pixwid), book_open, book_open_mask); + pixwid = ((GtkBoxChild*) (GTK_BOX (page->menu_label)->children->data))->widget; + gtk_pixmap_set (GTK_PIXMAP (pixwid), book_open, book_open_mask); + + if (oldpage) + { + pixwid = ((GtkBoxChild*) (GTK_BOX + (oldpage->tab_label)->children->data))->widget; + gtk_pixmap_set (GTK_PIXMAP (pixwid), book_closed, book_closed_mask); + pixwid = ((GtkBoxChild*) (GTK_BOX (oldpage->menu_label)->children->data))->widget; + gtk_pixmap_set (GTK_PIXMAP (pixwid), book_closed, book_closed_mask); + } +} + +static void +create_pages (GtkNotebook *notebook, gint start, gint end) +{ + GtkWidget *child = NULL; + GtkWidget *label; + GtkWidget *entry; + GtkWidget *box; + GtkWidget *hbox; + GtkWidget *label_box; + GtkWidget *menu_box; + GtkWidget *button; + GtkWidget *pixwid; + gint i; + char buffer[32]; + + for (i = start; i <= end; i++) + { + sprintf (buffer, "Page %d", i); + + switch (i%4) + { + case 3: + child = gtk_button_new_with_label (buffer); + gtk_container_border_width (GTK_CONTAINER(child), 10); + break; + case 2: + child = gtk_label_new (buffer); + break; + case 1: + child = gtk_frame_new (buffer); + gtk_container_border_width (GTK_CONTAINER (child), 10); + + box = gtk_vbox_new (TRUE,0); + gtk_container_border_width (GTK_CONTAINER (box), 10); + gtk_container_add (GTK_CONTAINER (child), box); + + label = gtk_label_new (buffer); + gtk_box_pack_start (GTK_BOX(box), label, TRUE, TRUE, 5); + + entry = gtk_entry_new (); + gtk_box_pack_start (GTK_BOX(box), entry, TRUE, TRUE, 5); + + hbox = gtk_hbox_new (TRUE,0); + gtk_box_pack_start (GTK_BOX(box), hbox, TRUE, TRUE, 5); + + button = gtk_button_new_with_label ("Ok"); + gtk_box_pack_start (GTK_BOX(hbox), button, TRUE, TRUE, 5); + + button = gtk_button_new_with_label ("Cancel"); + gtk_box_pack_start (GTK_BOX(hbox), button, TRUE, TRUE, 5); + break; + case 0: + child = gtk_frame_new (buffer); + gtk_container_border_width (GTK_CONTAINER (child), 10); + + label = gtk_label_new (buffer); + gtk_container_add (GTK_CONTAINER (child), label); + break; + } + + gtk_widget_show_all (child); + + label_box = gtk_hbox_new (FALSE, 0); + pixwid = gtk_pixmap_new (book_closed, book_closed_mask); + gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0); + gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1); + label = gtk_label_new (buffer); + gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0); + gtk_widget_show_all (label_box); + + menu_box = gtk_hbox_new (FALSE, 0); + pixwid = gtk_pixmap_new (book_closed, book_closed_mask); + gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0); + gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1); + label = gtk_label_new (buffer); + gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0); + gtk_widget_show_all (menu_box); + + gtk_notebook_append_page_menu (notebook, child, label_box, menu_box); + } +} + +static void rotate_notebook (GtkButton *button, GtkNotebook *notebook) { gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4); } -void +static void +standard_notebook (GtkButton *button, + GtkNotebook *notebook) +{ + gint i; + + gtk_notebook_set_show_tabs (notebook, TRUE); + gtk_notebook_set_scrollable (notebook, FALSE); + if (g_list_length (notebook->children) == 15) + for (i = 0; i < 10; i++) + gtk_notebook_remove_page (notebook, 5); +} + +static void +notabs_notebook (GtkButton *button, + GtkNotebook *notebook) +{ + gint i; + + gtk_notebook_set_show_tabs (notebook, FALSE); + if (g_list_length (notebook->children) == 15) + for (i = 0; i < 10; i++) + gtk_notebook_remove_page (notebook, 5); +} + +static void +scrollable_notebook (GtkButton *button, + GtkNotebook *notebook) +{ + gtk_notebook_set_show_tabs (notebook, TRUE); + gtk_notebook_set_scrollable (notebook, TRUE); + if (g_list_length (notebook->children) == 5) + create_pages (notebook, 6, 15); +} + +static void +notebook_popup (GtkToggleButton *button, + GtkNotebook *notebook) +{ + if (button->active) + gtk_notebook_popup_enable (notebook); + else + gtk_notebook_popup_disable (notebook); +} + +static void create_notebook () { static GtkWidget *window = NULL; @@ -2427,10 +2664,12 @@ create_notebook () GtkWidget *button; GtkWidget *separator; GtkWidget *notebook; - GtkWidget *frame; - GtkWidget *label; - char buffer[32]; - int i; + GtkWidget *omenu; + GtkWidget *menu; + GtkWidget *submenu; + GtkWidget *menuitem; + GSList *group; + GdkColor transparent; if (!window) { @@ -2446,86 +2685,101 @@ create_notebook () gtk_window_set_title (GTK_WINDOW (window), "notebook"); gtk_container_border_width (GTK_CONTAINER (window), 0); - box1 = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (window), box1); - gtk_widget_show (box1); - - - box2 = gtk_vbox_new (FALSE, 10); - gtk_container_border_width (GTK_CONTAINER (box2), 10); - gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); - gtk_widget_show (box2); - notebook = gtk_notebook_new (); + gtk_signal_connect (GTK_OBJECT (notebook), "switch_page", + GTK_SIGNAL_FUNC (page_switch), NULL); gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP); - gtk_box_pack_start (GTK_BOX (box2), notebook, TRUE, TRUE, 0); - gtk_widget_show (notebook); + gtk_box_pack_start (GTK_BOX (box1), notebook, TRUE, TRUE, 0); + gtk_container_border_width (GTK_CONTAINER (notebook), 10); + book_open = gdk_pixmap_create_from_xpm_d (notebook->window, + &book_open_mask, + &transparent, + book_open_xpm); + book_closed = gdk_pixmap_create_from_xpm_d (notebook->window, + &book_closed_mask, + &transparent, + book_closed_xpm); - for (i = 0; i < 5; i++) - { - sprintf (buffer, "Page %d", i+1); - - frame = gtk_frame_new (buffer); - gtk_container_border_width (GTK_CONTAINER (frame), 10); - gtk_widget_set_usize (frame, 200, 150); - gtk_widget_show (frame); - - label = gtk_label_new (buffer); - gtk_container_add (GTK_CONTAINER (frame), label); - gtk_widget_show (label); - - label = gtk_label_new (buffer); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label); - } - + create_pages (GTK_NOTEBOOK (notebook), 1, 5); separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0); - gtk_widget_show (separator); - - + gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10); + + box2 = gtk_hbox_new (TRUE, 5); + gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0); + + omenu = gtk_option_menu_new (); + menu = gtk_menu_new (); + submenu = NULL; + group = NULL; + + menuitem = gtk_radio_menu_item_new_with_label (group, "Standard"); + gtk_signal_connect_object (GTK_OBJECT (menuitem), "activate", + GTK_SIGNAL_FUNC (standard_notebook), + GTK_OBJECT (notebook)); + group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); + gtk_menu_append (GTK_MENU (menu), menuitem); + gtk_widget_show (menuitem); + menuitem = gtk_radio_menu_item_new_with_label (group, "w/o Tabs"); + gtk_signal_connect_object (GTK_OBJECT (menuitem), "activate", + GTK_SIGNAL_FUNC (notabs_notebook), + GTK_OBJECT (notebook)); + group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); + gtk_menu_append (GTK_MENU (menu), menuitem); + gtk_widget_show (menuitem); + menuitem = gtk_radio_menu_item_new_with_label (group, "Scrollable"); + gtk_signal_connect_object (GTK_OBJECT (menuitem), "activate", + GTK_SIGNAL_FUNC (scrollable_notebook), + GTK_OBJECT (notebook)); + group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); + gtk_menu_append (GTK_MENU (menu), menuitem); + gtk_widget_show (menuitem); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu); + gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, FALSE, 0); + button = gtk_check_button_new_with_label ("enable popup menu"); + gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0); + gtk_signal_connect (GTK_OBJECT(button), "clicked", + GTK_SIGNAL_FUNC (notebook_popup), + GTK_OBJECT (notebook)); + box2 = gtk_hbox_new (FALSE, 10); gtk_container_border_width (GTK_CONTAINER (box2), 10); gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0); - gtk_widget_show (box2); - - + button = gtk_button_new_with_label ("close"); gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC(gtk_widget_destroy), + GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (window)); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); gtk_widget_grab_default (button); - gtk_widget_show (button); button = gtk_button_new_with_label ("next"); gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC(gtk_notebook_next_page), + GTK_SIGNAL_FUNC (gtk_notebook_next_page), GTK_OBJECT (notebook)); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); - gtk_widget_show (button); button = gtk_button_new_with_label ("prev"); gtk_signal_connect_object (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC(gtk_notebook_prev_page), + GTK_SIGNAL_FUNC (gtk_notebook_prev_page), GTK_OBJECT (notebook)); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); - gtk_widget_show (button); button = gtk_button_new_with_label ("rotate"); gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC(rotate_notebook), + GTK_SIGNAL_FUNC (rotate_notebook), notebook); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); - gtk_widget_show (button); } if (!GTK_WIDGET_VISIBLE (window)) - gtk_widget_show (window); + gtk_widget_show_all (window); else gtk_widget_destroy (window); }