--- gtk+-2.6.4/gtk/gtkdialog.c 2005-01-20 21:52:15.000000000 +0200 +++ gtk+-2.6.4/gtk/gtkdialog.c 2005-04-06 16:19:36.416002288 +0300 @@ -24,6 +24,9 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +/* Modified for Nokia Oyj during 2002-2003. See CHANGES file for list + * of changes. + */ #include #include "gtkalias.h" #include "gtkbutton.h" @@ -37,11 +40,14 @@ #include "gtkmain.h" #include "gtkintl.h" #include "gtkbindings.h" +#include "gtkalignment.h" #define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_DIALOG, GtkDialogPrivate)) typedef struct { guint ignore_separator : 1; + GtkWidget *first; + GtkWidget *last; } GtkDialogPrivate; typedef struct _ResponseData ResponseData; @@ -77,7 +83,18 @@ static void gtk_dialog_close (GtkDialog *dialog); static ResponseData* get_response_data (GtkWidget *widget, - gboolean create); + gboolean create); + +static gboolean gtk_dialog_handle_focus (GtkWidget *widget, + GtkDirectionType dir, + gpointer user_data); + +static gboolean gtk_dialog_move_to_next_active_button (GList *iter, + gboolean forward); + +static GtkWidget *gtk_dialog_get_first_sensitive (GList *list); +static GtkWidget *gtk_dialog_get_last_sensitive (GList *list); + enum { PROP_0, @@ -195,6 +212,23 @@ 5, G_PARAM_READABLE)); + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("extended_left_border", + _("Content area extra left border"), + _("Width of extra left border around the main dialog area"), + 0, + G_MAXINT, + 0, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("extended_right_border", + _("Content area extra right border"), + _("Width of extra right border around the main dialog area"), + 0, + G_MAXINT, + 0, + G_PARAM_READABLE)); + binding_set = gtk_binding_set_by_class (class); gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, @@ -205,9 +239,15 @@ update_spacings (GtkDialog *dialog) { GtkWidget *widget; + GtkWidget *hbox; + GtkWidget *left_padding; + GtkWidget *right_padding; gint content_area_border; gint button_spacing; gint action_area_border; + + gint extended_left_border; + gint extended_right_border; widget = GTK_WIDGET (dialog); @@ -218,6 +258,10 @@ &button_spacing, "action_area_border", &action_area_border, + "extended_left_border", + &extended_left_border, + "extended_right_border", + &extended_right_border, NULL); gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), @@ -226,12 +270,36 @@ button_spacing); gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), action_area_border); + + if ((extended_left_border == 0) && (extended_right_border == 0)) + /* no extended borders, so we are done */ + return; + + /* extended borders are in use, so reconstruct dialog */ + hbox = gtk_hbox_new(FALSE, 0); + left_padding = gtk_alignment_new(0.0, 0.0, 0.0, 0.0); + right_padding = gtk_alignment_new(0.0, 0.0, 0.0, 0.0); + gtk_widget_set_size_request(left_padding, extended_left_border, 0); + gtk_widget_set_size_request(right_padding, extended_right_border, 0); + + gtk_widget_ref(dialog->vbox); + gtk_container_remove(GTK_CONTAINER(dialog), dialog->vbox); + gtk_container_add(GTK_CONTAINER(hbox), left_padding); + gtk_container_add(GTK_CONTAINER(hbox), dialog->vbox); + gtk_container_add(GTK_CONTAINER(hbox), right_padding); + gtk_container_add(GTK_CONTAINER(dialog), hbox); + gtk_widget_unref(dialog->vbox); + + gtk_widget_show(left_padding); + gtk_widget_show(right_padding); + gtk_widget_show(hbox); } static void gtk_dialog_init (GtkDialog *dialog) { GtkDialogPrivate *priv; + GtkWidget *alignment; priv = GET_PRIVATE (dialog); priv->ignore_separator = FALSE; @@ -250,14 +318,23 @@ gtk_container_add (GTK_CONTAINER (dialog), dialog->vbox); gtk_widget_show (dialog->vbox); + /* Hildon : Here we add an alignment widget to gtk because + * we want that the dialog buttons are all centered. */ + alignment = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_box_pack_end (GTK_BOX (dialog->vbox), alignment, FALSE, TRUE, 0); + dialog->action_area = gtk_hbutton_box_new (); gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog->action_area), GTK_BUTTONBOX_END); - gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->action_area, - FALSE, TRUE, 0); + /* we need add-signal to allocate correct area for childs */ + gtk_container_add (GTK_CONTAINER (alignment), dialog->action_area); + /* gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->action_area, + FALSE, TRUE, 0); */ + gtk_widget_show (dialog->action_area); + gtk_widget_show (alignment); dialog->separator = gtk_hseparator_new (); gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->separator, FALSE, TRUE, 0); @@ -616,9 +693,15 @@ else g_warning ("Only 'activatable' widgets can be packed into the action area of a GtkDialog"); + gtk_container_add(GTK_CONTAINER(dialog->action_area), child); +/* gtk_box_pack_end (GTK_BOX (dialog->action_area), child, FALSE, TRUE, 0); +*/ + + g_signal_connect (child, "focus", + (GCallback)gtk_dialog_handle_focus, (gpointer)dialog); if (response_id == GTK_RESPONSE_HELP) gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (dialog->action_area), child, TRUE); @@ -637,7 +720,7 @@ * you don't need it. * * Return value: the button widget that was added - **/ + **/ /*ROK*/ GtkWidget* gtk_dialog_add_button (GtkDialog *dialog, const gchar *button_text, @@ -653,7 +736,10 @@ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); gtk_widget_show (button); - + + g_signal_connect (button, "focus", + (GCallback)gtk_dialog_handle_focus, + (gpointer)dialog); gtk_dialog_add_action_widget (dialog, button, response_id); @@ -990,6 +1076,8 @@ gulong unmap_handler; gulong destroy_handler; gulong delete_handler; + GtkDialogPrivate *priv; + GList *list = NULL; g_return_val_if_fail (GTK_IS_DIALOG (dialog), -1); @@ -1001,6 +1089,27 @@ if (!GTK_WIDGET_VISIBLE (dialog)) gtk_widget_show (GTK_WIDGET (dialog)); + + priv = GET_PRIVATE (dialog); + list = gtk_container_get_children (GTK_CONTAINER (dialog->vbox)); + priv->first = gtk_dialog_get_first_sensitive (list); + priv->last = gtk_dialog_get_last_sensitive (list); + + if (priv->first) + { + g_signal_connect (priv->first, "focus", + (GCallback)gtk_dialog_handle_focus, + (gpointer)dialog); + } + + if (priv->last) + { + g_signal_connect (priv->last, "focus", + (GCallback)gtk_dialog_handle_focus, + (gpointer)dialog); + } + + g_list_free (list); response_handler = g_signal_connect (dialog, @@ -1236,4 +1345,215 @@ gtk_box_reorder_child (GTK_BOX (dialog->action_area), child, position); } } +static gboolean +gtk_dialog_handle_focus (GtkWidget *widget, + GtkDirectionType dir, + gpointer user_data) + { + GtkDialog *dialog = NULL; + GList *list = NULL; + GList *iter = NULL; + gint i = 0; + gint list_length = 0; + gboolean ret_val = FALSE; + GtkDialogPrivate *priv; + + dialog = GTK_DIALOG(user_data); + list = gtk_container_get_children (GTK_CONTAINER( + GTK_DIALOG(user_data)->action_area)); + iter = list; + priv = GET_PRIVATE (dialog); + + if (GTK_WIDGET_HAS_FOCUS (widget)) + if (widget == priv->first) + { + if (dir == GTK_DIR_UP) + { + ret_val = gtk_dialog_move_to_next_active_button (g_list_last (list), + FALSE); + } + else if (dir == GTK_DIR_DOWN && priv->first == priv->last) + ret_val = gtk_dialog_move_to_next_active_button (list, TRUE); + else if (dir == GTK_DIR_DOWN) + { + } + } + else if (widget == priv->last) + { + if (dir == GTK_DIR_DOWN) + { + ret_val = gtk_dialog_move_to_next_active_button (list, TRUE); + } + else if (dir == GTK_DIR_UP) + { + } + } + else + { + list_length = g_list_length(list); + while (iter != NULL) + { + ++i; + if (iter->data == widget) + { + switch (dir) { + case GTK_DIR_UP: + /* If in the first item -> the default works like it should */ + + if (i > 1) + { + /* If not in the first button, but in the first active + * button, the default should do, else handle movement + * by yourself + */ + ret_val = gtk_dialog_move_to_next_active_button ( + g_list_previous (iter), + FALSE); + } + else + { + /* gtk_widget_grab_focus (priv->last);*/ + g_signal_emit_by_name (dialog, "move-focus", + GTK_DIR_TAB_BACKWARD); + ret_val = TRUE; + } + break; + + /* If in the last item:jump to top, else select previous button */ + case GTK_DIR_DOWN: + if (i < list_length) + { + ret_val = gtk_dialog_move_to_next_active_button ( + g_list_next (iter), + TRUE); + if (!ret_val) + { + g_signal_emit_by_name (dialog, "move-focus", + GTK_DIR_TAB_FORWARD); + ret_val = TRUE; + } + } + else + { + g_signal_emit_by_name (dialog, "move-focus", + GTK_DIR_TAB_FORWARD); + ret_val = TRUE; + } + break; + + case GTK_DIR_TAB_BACKWARD: + case GTK_DIR_TAB_FORWARD: + case GTK_DIR_LEFT: + case GTK_DIR_RIGHT: + default: + break; + } + break; + } + iter = g_list_next(iter); + } + } + + g_list_free (list); + + return ret_val; + } +static gboolean +gtk_dialog_move_to_next_active_button (GList *iter, gboolean forward) +{ + gboolean active; + gboolean visible; + + while (iter) + { + g_object_get (G_OBJECT (iter->data), "sensitive", &active, NULL); + g_object_get (G_OBJECT (iter->data), "visible", &visible, NULL); + if (active && visible) + { + gtk_widget_grab_focus (GTK_WIDGET (iter->data)); + return TRUE; + } + + if (forward) + iter = g_list_next (iter); + else + iter = g_list_previous (iter); + } + + return FALSE; +} +static GtkWidget* +gtk_dialog_get_first_sensitive (GList *list) +{ + GList *sublist = NULL; + GList *iter = NULL; + GtkWidget *widget = NULL; + gboolean active; + gboolean visible; + while (list) + { + widget = GTK_WIDGET (list->data); + if (GTK_IS_CONTAINER (widget)) + { + sublist = gtk_container_get_children (GTK_CONTAINER(widget)); + widget = gtk_dialog_get_first_sensitive (sublist); + g_list_free (sublist); + sublist = NULL; + + if (widget) + return widget; + } + else + { + g_object_get (G_OBJECT (widget), "sensitive", &active, NULL); + g_object_get (G_OBJECT (widget), "visible", &visible, NULL); + if (active && visible && GTK_WIDGET_CAN_FOCUS (widget)) + return widget; + } + + list = g_list_next (list); + } + + return NULL; +} + +static GtkWidget* +gtk_dialog_get_last_sensitive (GList *list) +{ + GList *sublist = NULL; + GtkWidget *widget = NULL; + gboolean active; + gboolean visible; + + list = g_list_last (list); + if (list && list->prev != NULL) + list = g_list_previous (list); + + while (list) + { + widget = GTK_WIDGET (list->data); + if (GTK_IS_CONTAINER (widget)) + { + sublist = gtk_container_get_children (GTK_CONTAINER(widget)); + widget = gtk_dialog_get_last_sensitive (sublist); + g_list_free (sublist); + sublist = NULL; + + if (widget) + return widget; + } + else + { + g_object_get (G_OBJECT (widget), "sensitive", &active, NULL); + g_object_get (G_OBJECT (widget), "visible", &visible, NULL); + if (active && visible && GTK_WIDGET_CAN_FOCUS (widget)) + return widget; + } + + list = g_list_previous (list); + } + + return NULL; +} +