Patching adding "secondary" area to GtkDialog



[ http://bugzilla.gnome.org/show_bug.cgi?id=56331 ]

The following is a patch from Gregory Merchan, with some
fixes from myself to enable dialogs with buttons like:

 [ Help ]       [  OK  ] [ Cancel ] 

What it does is adds an API call:

/**
 * gtk_dialog_set_response_secondary:
 * @dialog: a #GtkDialog
 * @response_id: a response ID
 * @is_secondary: if %TRUE, the widget identified by @response_id
 *                appears in the secondary set of buttons.
 *
 * Sets whether a widget, identified by @response_id, should 
 * appear in the normal set of buttons, or in a secondary set
 * on the other side of the action area. The secondary area
 * is typically used for the help button.
 **/

And a corresponding:

 dialog->secondary_action_area

button bux, and makes the Help stock item secondary by default.

Known defects are:

 - the padding between the secondary area and the primary area
   is still left even if the secondary area is empty.

 - The buttons in the primary and secondary area are not
   constrained to have the same size.

The only ways I see to fix these are:

 1) Modify the button box to have pack-start and pack-end like
    normal GtkBox; not sure how this would relate to the 
    the GtkButtonBoxStyle style property.

    (SPREAD, EDGE, START, END) 

 2) Use a GtkBox instead of a button box, loosing the minimum-width,
    minimum-height and ipad features of the bbox.

 3) Various hacks that could be done if we had notification
    of changes to container->children(). (Packing directly
    into the action area is an allowed way to work with
    a GtkDialog.

Comments appreciated,
                                        Owen

? docs/reference/gdk/gdk-undocumented.txt
? docs/reference/gdk/docpercentages.pl
? docs/reference/gdk/widget.gnome.org
? docs/reference/gdk-pixbuf/gdk-pixbuf-undocumented.txt
? docs/reference/gtk/gtk-undocumented.txt
? gdk-pixbuf/test-loaders
? modules/linux-fb/.deps
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.2068
diff -u -r1.2068 ChangeLog
--- ChangeLog	2001/06/23 14:32:42	1.2068
+++ ChangeLog	2001/06/23 19:50:58
@@ -1,3 +1,9 @@
+Sat Jun 23 13:11:07 2001  Owen Taylor  <otaylor redhat com>
+
+	* tests/testgtk.c (create_color_selection): Add patch
+	from Gregory Merchan to put Help buttons on the opposite
+	side of dialogs from other buttons. (#56331)
+
 Sat Jun 23 10:27:53 2001  Owen Taylor  <otaylor redhat com>
 
 	* modules/input/gtkimcontextxim.c: Fixup some problems with 
Index: gtk/gtkdialog.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkdialog.c,v
retrieving revision 1.25
diff -u -r1.25 gtkdialog.c
--- gtk/gtkdialog.c	2001/05/25 20:41:41	1.25
+++ gtk/gtkdialog.c	2001/06/23 19:50:59
@@ -28,6 +28,7 @@
 #include "gtkdialog.h"
 #include "gtkhbbox.h"
 #include "gtkhseparator.h"
+#include "gtkhbox.h"
 #include "gtkvbox.h"
 #include "gtksignal.h"
 #include "gdkkeysyms.h"
@@ -57,7 +58,10 @@
                                           GParamSpec       *pspec);
 static void gtk_dialog_style_set         (GtkWidget        *widget,
                                           GtkStyle         *prev_style);
+static void gtk_dialog_show_all          (GtkWidget        *widget);
 
+static GList *gtk_dialog_get_buttons (GtkDialog *dialog);
+
 enum {
   PROP_0,
   PROP_HAS_SEPARATOR
@@ -114,7 +118,8 @@
   
   widget_class->key_press_event = gtk_dialog_key_press;
   widget_class->style_set = gtk_dialog_style_set;
-  
+  widget_class->show_all = gtk_dialog_show_all;
+
   g_object_class_install_property (gobject_class,
                                    PROP_HAS_SEPARATOR,
                                    g_param_spec_boolean ("has_separator",
@@ -180,9 +185,13 @@
 
   gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox),
                                   content_area_border);
+  gtk_box_set_spacing (GTK_BOX (dialog->action_hbox),
+                       button_spacing);
   gtk_box_set_spacing (GTK_BOX (dialog->action_area),
                        button_spacing);
-  gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area),
+  gtk_box_set_spacing (GTK_BOX (dialog->secondary_action_area),
+                       button_spacing);
+  gtk_container_set_border_width (GTK_CONTAINER (dialog->action_hbox),
                                   action_area_border);
 }
 
@@ -204,13 +213,26 @@
   gtk_widget_show (dialog->vbox);
 
   dialog->action_area = gtk_hbutton_box_new ();
-
   gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog->action_area),
                              GTK_BUTTONBOX_END);  
+  gtk_widget_show (dialog->action_area);
 
-  gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->action_area,
+  dialog->secondary_action_area = gtk_hbutton_box_new ();
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog->secondary_action_area),
+			     GTK_BUTTONBOX_START);
+  gtk_widget_show (dialog->secondary_action_area);
+
+  dialog->action_hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (dialog->action_hbox),
+		      dialog->secondary_action_area,
+		      FALSE, TRUE, 0);
+  gtk_box_pack_end (GTK_BOX (dialog->action_hbox),
+		    dialog->action_area,
+		    TRUE, TRUE, 0);
+
+  gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->action_hbox,
                     FALSE, TRUE, 0);
-  gtk_widget_show (dialog->action_area);
+  gtk_widget_show (dialog->action_hbox);
 
   dialog->separator = gtk_hseparator_new ();
   gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->separator, FALSE, TRUE, 0);
@@ -310,6 +332,35 @@
   update_spacings (GTK_DIALOG (widget));
 }
 
+static void
+show_all_foreach (GtkWidget *widget,
+		  gpointer   data)
+{
+  GtkDialog *dialog = GTK_DIALOG (widget);
+
+  if (widget != dialog->separator &&
+      widget != dialog->action_hbox)
+    gtk_widget_show_all (widget);
+}
+
+/* We special-case this to avoid interfering with the
+ * the separator.
+ */
+static void
+gtk_dialog_show_all (GtkWidget *widget)
+{
+  GtkDialog *dialog = GTK_DIALOG (widget);
+
+  gtk_container_foreach (GTK_CONTAINER (dialog->vbox),
+			 show_all_foreach,
+			 dialog);
+
+  gtk_widget_show_all (dialog->secondary_action_area);
+  gtk_widget_show_all (dialog->action_area);
+
+  gtk_widget_show (widget);
+}
+
 GtkWidget*
 gtk_dialog_new (void)
 {
@@ -472,6 +523,7 @@
 {
   ResponseData *ad;
   gint signal_id = 0;
+  GtkWidget *action_area;
   
   g_return_if_fail (GTK_IS_DIALOG (dialog));
   g_return_if_fail (GTK_IS_WIDGET (child));
@@ -500,13 +552,18 @@
   else
     g_warning ("Only 'activatable' widgets can be packed into the action area of a GtkDialog");
 
-  gtk_box_pack_end (GTK_BOX (dialog->action_area),
+  if (response_id == GTK_RESPONSE_HELP)
+    action_area = dialog->secondary_action_area;
+  else
+    action_area = dialog->action_area;
+
+  gtk_box_pack_end (GTK_BOX (action_area),
                     child,
                     FALSE, TRUE, 0);  
 }
 
 /**
- * gtk_dialog_add_button:
+ * Gtk_dialog_add_button:
  * @dialog: a #GtkDialog
  * @button_text: text of button, or stock ID
  * @response_id: response ID for the button
@@ -616,7 +673,7 @@
   GList *children;
   GList *tmp_list;
 
-  children = gtk_container_children (GTK_CONTAINER (dialog));
+  children = gtk_dialog_get_buttons (dialog);
 
   tmp_list = children;
   while (tmp_list != NULL)
@@ -651,7 +708,7 @@
   GList *children;
   GList *tmp_list;
 
-  children = gtk_container_children (GTK_CONTAINER (dialog->action_area));
+  children = gtk_dialog_get_buttons (dialog);
 
   tmp_list = children;
   while (tmp_list != NULL)
@@ -674,7 +731,62 @@
   g_list_free (children);
 }
 
+/**
+ * gtk_dialog_set_response_secondary:
+ * @dialog: a #GtkDialog
+ * @response_id: a response ID
+ * @is_secondary: if %TRUE, the widget identified by @response_id
+ *                appears in the secondary set of buttons.
+ *
+ * Sets whether a widget, identified by @response_id, should 
+ * appear in the normal set of buttons, or in a secondary set
+ * on the other side of the action area. The secondary area
+ * is typically used for the help button.
+ **/
 void
+gtk_dialog_set_response_secondary (GtkDialog *dialog,
+                                   gint       response_id,
+                                   gboolean   is_secondary)
+{
+  GList *children;
+  GList *tmp_list;
+
+  g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+  children = gtk_dialog_get_buttons (dialog);
+
+  tmp_list = children;
+  while (tmp_list != NULL)
+    {
+      GtkWidget *widget = tmp_list->data;
+      ResponseData *rd = g_object_get_data (G_OBJECT (widget),
+                                            "gtk-dialog-response-data");
+      if (rd && rd->response_id == response_id)
+        {
+	  if (is_secondary && (widget->parent == dialog->action_area))
+	    {
+	      gtk_widget_ref (widget);
+	      gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
+	      gtk_box_pack_end (GTK_BOX (dialog->secondary_action_area), widget,
+				FALSE, TRUE, 0);
+	      gtk_widget_unref (widget);
+	    }
+	  else if (!is_secondary && (widget->parent != dialog->action_area))
+	    {
+	      gtk_widget_ref (widget);
+	      gtk_container_remove (GTK_CONTAINER (widget->parent), widget);
+	      gtk_box_pack_end (GTK_BOX (dialog->action_area), widget,
+				FALSE, TRUE, 0);
+	      gtk_widget_unref (widget);
+	    }
+        }
+      tmp_list = g_list_next (tmp_list);
+    }
+
+  g_list_free (children);
+}
+
+void
 gtk_dialog_set_has_separator (GtkDialog *dialog,
                               gboolean   setting)
 {
@@ -883,7 +995,10 @@
 
   return ri.response_id;
 }
-
-
 
-
+static GList *
+gtk_dialog_get_buttons (GtkDialog *dialog)
+{
+  return g_list_concat (gtk_container_children (GTK_CONTAINER (dialog->action_area)),
+			gtk_container_children (GTK_CONTAINER (dialog->secondary_action_area)));
+}
Index: gtk/gtkdialog.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkdialog.h,v
retrieving revision 1.12
diff -u -r1.12 gtkdialog.h
--- gtk/gtkdialog.h	2001/03/07 21:32:51	1.12
+++ gtk/gtkdialog.h	2001/06/23 19:50:59
@@ -99,9 +99,11 @@
 
   GtkWidget *vbox;
   GtkWidget *action_area;
+  GtkWidget *secondary_action_area;
 
   /*< private >*/
   GtkWidget *separator;
+  GtkWidget *action_hbox;
 };
 
 struct _GtkDialogClass
@@ -136,6 +138,9 @@
                                         gboolean   setting);
 void gtk_dialog_set_default_response   (GtkDialog *dialog,
                                         gint       response_id);
+void gtk_dialog_set_response_secondary (GtkDialog *dialog,
+                                        gint       response_id,
+                                        gboolean   is_secondary);
 
 void     gtk_dialog_set_has_separator (GtkDialog *dialog,
                                        gboolean   setting);
Index: tests/testgtk.c
===================================================================
RCS file: /cvs/gnome/gtk+/tests/testgtk.c,v
retrieving revision 1.261
diff -u -r1.261 testgtk.c
--- tests/testgtk.c	2001/06/19 12:54:10	1.261
+++ tests/testgtk.c	2001/06/23 19:51:02
@@ -6143,6 +6143,7 @@
       GtkWidget *check_button;
       
       window = gtk_color_selection_dialog_new ("color selection dialog");
+      gtk_widget_show (GTK_COLOR_SELECTION_DIALOG (window)->help_button);
 
       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]