[patch] children of a button should move



[This is also bug #54720]

The child of a button should optionally move when the button is
pressed.  This is necessary to emulate Windows, and IMHO a nice
feature.

? patch
? sgml
? gtk/button.diff
? gtk/gtk.immodules
? gtk/testgtk
? gtk/testrgb
? gtk/gtkbutton.changed.c
? gtk/testselection
? gtk/testtext
? gtk/simple
? gtk/testtextbuffer
? gtk/testcalendar
? gtk/treestoretest
? gtk/gtkbutton.rigtig
? gtk/testinput
Index: gtk/gtkbutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkbutton.c,v
retrieving revision 1.62
diff -u -r1.62 gtkbutton.c
--- gtk/gtkbutton.c	2001/05/01 01:36:32	1.62
+++ gtk/gtkbutton.c	2001/05/15 20:31:52
@@ -61,46 +61,47 @@
   PROP_RELIEF
 };
 
-static void gtk_button_class_init     (GtkButtonClass   *klass);
-static void gtk_button_init           (GtkButton        *button);
-static void gtk_button_set_property   (GObject         *object,
-                                       guint            prop_id,
-                                       const GValue    *value,
-                                       GParamSpec      *pspec);
-static void gtk_button_get_property   (GObject         *object,
-                                       guint            prop_id,
-                                       GValue          *value,
-                                       GParamSpec      *pspec);
-static void gtk_button_realize        (GtkWidget        *widget);
-static void gtk_button_unrealize      (GtkWidget        *widget);
-static void gtk_button_size_request   (GtkWidget        *widget,
-				       GtkRequisition   *requisition);
-static void gtk_button_size_allocate  (GtkWidget        *widget,
-				       GtkAllocation    *allocation);
-static void gtk_button_paint          (GtkWidget        *widget,
-				       GdkRectangle     *area);
-static gint gtk_button_expose         (GtkWidget        *widget,
-				       GdkEventExpose   *event);
-static gint gtk_button_button_press   (GtkWidget        *widget,
-				       GdkEventButton   *event);
-static gint gtk_button_button_release (GtkWidget        *widget,
-				       GdkEventButton   *event);
-static gint gtk_button_key_release    (GtkWidget        *widget,
-				       GdkEventKey      *event);
-static gint gtk_button_enter_notify   (GtkWidget        *widget,
-				       GdkEventCrossing *event);
-static gint gtk_button_leave_notify   (GtkWidget        *widget,
-				       GdkEventCrossing *event);
-static void gtk_button_add            (GtkContainer     *container,
-				       GtkWidget        *widget);
-static void gtk_button_remove         (GtkContainer     *container,
-				       GtkWidget        *widget);
-static void gtk_real_button_pressed   (GtkButton        *button);
-static void gtk_real_button_released  (GtkButton        *button);
-static void gtk_real_button_enter     (GtkButton        *button);
-static void gtk_real_button_leave     (GtkButton        *button);
-static void gtk_real_button_activate (GtkButton         *button);
-static GtkType gtk_button_child_type  (GtkContainer     *container);
+static void     gtk_button_class_init     (GtkButtonClass   *klass);
+static void     gtk_button_init           (GtkButton        *button);
+static void     gtk_button_set_property   (GObject          *object,
+					   guint             prop_id,
+					   const GValue     *value,
+					   GParamSpec       *pspec);
+static void     gtk_button_get_property   (GObject          *object,
+					   guint             prop_id,
+					   GValue           *value,
+					   GParamSpec       *pspec);
+static void     gtk_button_realize        (GtkWidget        *widget);
+static void     gtk_button_unrealize      (GtkWidget        *widget);
+static void     gtk_button_size_request   (GtkWidget        *widget,
+					   GtkRequisition   *requisition);
+static void     gtk_button_size_allocate  (GtkWidget        *widget,
+					   GtkAllocation    *allocation);
+static void     gtk_button_paint          (GtkWidget        *widget,
+					   GdkRectangle     *area);
+static gint     gtk_button_expose         (GtkWidget        *widget,
+					   GdkEventExpose   *event);
+static gint     gtk_button_button_press   (GtkWidget        *widget,
+					   GdkEventButton   *event);
+static gint     gtk_button_button_release (GtkWidget        *widget,
+					   GdkEventButton   *event);
+static gint     gtk_button_key_release    (GtkWidget        *widget,
+					   GdkEventKey      *event);
+static gint     gtk_button_enter_notify   (GtkWidget        *widget,
+					   GdkEventCrossing *event);
+static gint     gtk_button_leave_notify   (GtkWidget        *widget,
+					   GdkEventCrossing *event);
+static void     gtk_button_add            (GtkContainer     *container,
+					   GtkWidget        *widget);
+static void     gtk_button_remove         (GtkContainer     *container,
+					   GtkWidget        *widget);
+static void     gtk_real_button_pressed   (GtkButton        *button);
+static void     gtk_real_button_released  (GtkButton        *button);
+static void     gtk_real_button_enter     (GtkButton        *button);
+static void     gtk_real_button_leave     (GtkButton        *button);
+static void     gtk_real_button_activate  (GtkButton        *button);
+static gboolean gtk_real_button_depressed (GtkButton        *button);
+static GtkType  gtk_button_child_type     (GtkContainer     *container);
 
 static void gtk_button_finish_activate (GtkButton *button,
 					gboolean   do_it);
@@ -172,6 +173,7 @@
   klass->enter = gtk_real_button_enter;
   klass->leave = gtk_real_button_leave;
   klass->activate = gtk_real_button_activate;
+  klass->depressed = gtk_real_button_depressed;
 
   g_object_class_install_property (G_OBJECT_CLASS(object_class),
                                    PROP_LABEL,
@@ -247,6 +249,22 @@
 							       _("Extra space to add for CAN_DEFAULT buttons that is always drawn outside the border"),
 							       GTK_TYPE_BORDER,
 							       G_PARAM_READABLE));
+  gtk_widget_class_install_style_property (widget_class,
+					   g_param_spec_int ("child_displacement_x",
+							     _("Child X Displacement"),
+							     _("How far in the x direction to move the child when the button is depressed"),
+							     G_MININT,
+							     G_MAXINT,
+							     0,
+							     G_PARAM_READABLE));
+  gtk_widget_class_install_style_property (widget_class,
+					   g_param_spec_int ("child_displacement_y",
+							     _("Child Y Displacement"),
+							     _("How far in the y direction to move the child when the button is depressed"),
+							     G_MININT,
+							     G_MAXINT,
+							     0,
+							     G_PARAM_READABLE));
 }
 
 static void
@@ -494,6 +512,21 @@
   return button->relief;
 }
 
+gboolean
+gtk_button_depressed (GtkButton *button)
+{
+  GtkButtonClass *class;
+
+  g_return_val_if_fail (button != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
+
+  class = GTK_BUTTON_GET_CLASS (button);
+
+  if (class->depressed)
+    return class->depressed (button);
+  return FALSE;
+}
+
 static void
 gtk_button_realize (GtkWidget *widget)
 {
@@ -632,9 +665,13 @@
   gint border_width = GTK_CONTAINER (widget)->border_width;
   gint xthickness = GTK_WIDGET (widget)->style->xthickness;
   gint ythickness = GTK_WIDGET (widget)->style->ythickness;
+  gint child_displacement_x;
+  gint child_displacement_y;
   GtkBorder default_border;
 
   gtk_button_get_props (button, &default_border, NULL, NULL);
+  gtk_widget_style_get (widget, "child_displacement_x", &child_displacement_x, NULL);
+  gtk_widget_style_get (widget, "child_displacement_y", &child_displacement_y, NULL);
   
   widget->allocation = *allocation;
 
@@ -663,6 +700,12 @@
 	  child_allocation.height = MAX (1, child_allocation.height - default_border.top - default_border.bottom);
 	}
 
+      if (gtk_button_depressed (button))
+	{
+	  child_allocation.x += child_displacement_x;
+	  child_allocation.y += child_displacement_y;
+	}
+
       gtk_widget_size_allocate (GTK_BIN (button)->child, &child_allocation);
     }
 }
@@ -959,7 +1002,7 @@
   if (GTK_WIDGET_STATE (button) != new_state)
     {
       gtk_widget_set_state (GTK_WIDGET (button), new_state);
-      gtk_widget_queue_draw (GTK_WIDGET (button));
+      gtk_widget_queue_resize (GTK_WIDGET (button));
     }
 }
 
@@ -986,10 +1029,7 @@
       if (GTK_WIDGET_STATE (button) != new_state)
 	{
 	  gtk_widget_set_state (GTK_WIDGET (button), new_state);
-	  /* We _draw () instead of queue_draw so that if the operation
-	   * blocks, the label doesn't vanish.
-	   */
-	  gtk_widget_draw (GTK_WIDGET (button), NULL);
+	  gtk_widget_queue_resize (GTK_WIDGET (button));
 	}
     }
 }
@@ -1010,7 +1050,7 @@
   if (GTK_WIDGET_STATE (button) != new_state)
     {
       gtk_widget_set_state (GTK_WIDGET (button), new_state);
-      gtk_widget_queue_draw (GTK_WIDGET (button));
+      gtk_widget_queue_resize (GTK_WIDGET (button));
     }
 }
 
@@ -1026,11 +1066,20 @@
   if (GTK_WIDGET_STATE (button) != GTK_STATE_NORMAL)
     {
       gtk_widget_set_state (GTK_WIDGET (button), GTK_STATE_NORMAL);
-      gtk_widget_queue_draw (GTK_WIDGET (button));
+      gtk_widget_queue_resize (GTK_WIDGET (button));
     }
 }
 
 static gboolean
+gtk_real_button_depressed (GtkButton *button)
+{
+  g_return_val_if_fail (button != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
+  
+  return GTK_WIDGET_STATE (button) == GTK_STATE_ACTIVE;
+}
+
+static gboolean
 button_activate_timeout (gpointer data)
 {
   gtk_button_finish_activate (data, TRUE);
@@ -1058,6 +1107,7 @@
 						    button);
 	  button->button_down = TRUE;
 	  gtk_widget_set_state (widget, GTK_STATE_ACTIVE);
+	  gtk_widget_queue_resize (GTK_WIDGET (button));
 	}
     }
 }
@@ -1077,6 +1127,7 @@
   button->button_down = FALSE;
   gtk_widget_set_state (GTK_WIDGET (button),
 			button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
+  gtk_widget_queue_resize (GTK_WIDGET (button));
 
   if (do_it)
     gtk_button_clicked (button);
Index: gtk/gtkbutton.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkbutton.h,v
retrieving revision 1.17
diff -u -r1.17 gtkbutton.h
--- gtk/gtkbutton.h	2001/03/23 23:39:23	1.17
+++ gtk/gtkbutton.h	2001/05/15 20:31:52
@@ -73,6 +73,8 @@
   void (* enter)    (GtkButton *button);
   void (* leave)    (GtkButton *button);
   void (* activate) (GtkButton *button);
+
+  gboolean (* depressed) (GtkButton *button);
 };
 
 
@@ -89,7 +91,7 @@
 void           gtk_button_set_relief        (GtkButton      *button,
 					     GtkReliefStyle  newstyle);
 GtkReliefStyle gtk_button_get_relief        (GtkButton      *button);
-
+gboolean       gtk_button_depressed         (GtkButton      *button);
 
 #ifdef __cplusplus
 }
Index: gtk/gtkcheckbutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkcheckbutton.c,v
retrieving revision 1.30
diff -u -r1.30 gtkcheckbutton.c
--- gtk/gtkcheckbutton.c	2001/05/07 15:58:43	1.30
+++ gtk/gtkcheckbutton.c	2001/05/15 20:31:52
@@ -318,6 +318,17 @@
 	  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
 	    child_allocation.x = allocation->x + allocation->width
 	      - (child_allocation.x - allocation->x + child_allocation.width);
+
+	  if (gtk_button_depressed (button))
+	    {
+	      gint child_displacement_x;
+	      gint child_displacement_y;
+	      
+	      gtk_widget_style_get (widget, "child_displacement_x", &child_displacement_x, NULL);
+	      gtk_widget_style_get (widget, "child_displacement_y", &child_displacement_y, NULL);
+	      child_allocation.x += child_displacement_x;
+	      child_allocation.y += child_displacement_y;
+	    }
 	  
 	  gtk_widget_size_allocate (GTK_BIN (button)->child, &child_allocation);
 	}
Index: gtk/gtktogglebutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktogglebutton.c,v
retrieving revision 1.36
diff -u -r1.36 gtktogglebutton.c
--- gtk/gtktogglebutton.c	2001/05/13 22:41:30	1.36
+++ gtk/gtktogglebutton.c	2001/05/15 20:31:52
@@ -60,6 +60,7 @@
 static void gtk_toggle_button_clicked       (GtkButton            *button);
 static void gtk_toggle_button_enter         (GtkButton            *button);
 static void gtk_toggle_button_leave         (GtkButton            *button);
+static gboolean gtk_toggle_button_depressed (GtkButton            *button);
 static void gtk_toggle_button_set_property  (GObject              *object,
 					     guint                 prop_id,
 					     const GValue         *value,
@@ -135,6 +136,7 @@
   button_class->clicked = gtk_toggle_button_clicked;
   button_class->enter = gtk_toggle_button_enter;
   button_class->leave = gtk_toggle_button_leave;
+  button_class->depressed = gtk_toggle_button_depressed;
 
   class->toggled = NULL;
 
@@ -367,7 +369,7 @@
   if (setting != toggle_button->inconsistent)
     {
       toggle_button->inconsistent = setting;
-      gtk_widget_queue_draw (GTK_WIDGET (toggle_button));
+      gtk_widget_queue_resize (GTK_WIDGET (toggle_button));
 
       g_object_notify (G_OBJECT (toggle_button), "inconsistent");      
     }
@@ -534,7 +536,10 @@
     new_state = (button->in_button ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
 
   if (GTK_WIDGET_STATE (button) != new_state)
-    gtk_widget_set_state (GTK_WIDGET (button), new_state);
+    {
+      gtk_widget_set_state (GTK_WIDGET (button), new_state);
+      gtk_widget_queue_resize (GTK_WIDGET (button));
+    }
 }
 
 static void
@@ -564,7 +569,10 @@
 	    new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
 
 	  if (GTK_WIDGET_STATE (button) != new_state)
-	    gtk_widget_set_state (GTK_WIDGET (button), new_state);
+	    {
+	      gtk_widget_set_state (GTK_WIDGET (button), new_state);
+	      gtk_widget_queue_resize (GTK_WIDGET (button));
+	    }
 	}
     }
 }
@@ -588,10 +596,8 @@
   else
     new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
 
-  if (GTK_WIDGET_STATE (button) != new_state)
-    gtk_widget_set_state (GTK_WIDGET (button), new_state);
-  else
-    gtk_widget_queue_draw (GTK_WIDGET (button));
+  gtk_widget_set_state (GTK_WIDGET (button), new_state);
+  gtk_widget_queue_resize (GTK_WIDGET (button));
 
   g_object_notify (G_OBJECT (toggle_button), "active");
 }
@@ -613,7 +619,10 @@
     new_state = (button->button_down ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
 
   if (GTK_WIDGET_STATE (button) != new_state)
-    gtk_widget_set_state (GTK_WIDGET (button), new_state);
+    {
+      gtk_widget_set_state (GTK_WIDGET (button), new_state);
+      gtk_widget_queue_resize (GTK_WIDGET (button));
+    }
 }
 
 static void
@@ -630,7 +639,26 @@
   new_state = (toggle_button->active ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
 
   if (GTK_WIDGET_STATE (button) != new_state)
-    gtk_widget_set_state (GTK_WIDGET (button), new_state);
+    {
+      gtk_widget_set_state (GTK_WIDGET (button), new_state);
+      gtk_widget_queue_resize (GTK_WIDGET (button));
+    }
+}
+
+static gboolean
+gtk_toggle_button_depressed (GtkButton *button)
+{
+  GtkToggleButton *toggle_button;
+
+  g_return_val_if_fail (button != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_TOGGLE_BUTTON (button), FALSE);
+
+  toggle_button = GTK_TOGGLE_BUTTON (button);
+
+  if (toggle_button->inconsistent)
+    return FALSE;
+
+  return GTK_WIDGET_STATE (toggle_button) == GTK_STATE_ACTIVE || toggle_button->active;
 }
 
 static void
Index: tests/testgtkrc
===================================================================
RCS file: /cvs/gnome/gtk+/tests/testgtkrc,v
retrieving revision 1.47
diff -u -r1.47 testgtkrc
--- tests/testgtkrc	2001/04/28 00:12:47	1.47
+++ tests/testgtkrc	2001/05/15 20:31:52
@@ -77,6 +77,8 @@
 
 style "button" = "default"
 {
+  GtkButton::child_displacement_x = 1
+  GtkButton::child_displacement_y = 1
 #  fg[PRELIGHT] = { 1.0, 1.0, 1.0 }
 #  bg[PRELIGHT] = { 0, 0, 0.75 }
 #  bg[PRELIGHT] = { 0.75, 0, 0x00 }
@@ -90,6 +92,12 @@
 #  bg_pixmap[NORMAL] = "check-n.xpm"
 }
 
+style "check_button" = "toggle_button"
+{
+  GtkButton::child_displacement_x = 0
+  GtkButton::child_displacement_y = 0
+}
+
 style "text"
 {
   bg_pixmap[NORMAL] = "marble.xpm"
@@ -136,8 +144,8 @@
 widget_class "GtkDialog" style "window"
 widget_class "GtkFileSelection" style "window"
 widget_class "*Gtk*Scale" style "scale"
-widget_class "*GtkCheckButton*" style "toggle_button"
-widget_class "*GtkRadioButton*" style "toggle_button"
+widget_class "*GtkCheckButton*" style "check_button"
+widget_class "*GtkRadioButton*" style "check_button"
 widget_class "*GtkButton*" style "button"
 widget_class "*Ruler" style "ruler"
 widget_class "*GtkText" style "text"


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