[patch] snap to increment for adjustment



A frequently asked question on the gtkmm list is how to make
an adjustment snap to increments.  Since this functionality already
exists in gtk+ in spinbutton, I would propose that we move the
functionality from spinbutton to adjustment, so that the snap
functionality is available to all widgets.  I have composed and
tested a patch to do that.  I also altered spinbutton to remove
redundant functionality.  Hopefully, it will be considered reasonable 
for inclusion.

If we want to get really fancy we could make a virtual function in 
the adjustment which does the snap and clamp stuff in set_value so 
that one could easily derive a adjustment type.  That way people
who want really strange adjustment snap settings like CD player settings
(1,2,4,6,8) could just derive an adjustment and change the snap
vfunc.  This is not implemented in the patch, but I could add it
if we consider it necessary.

caveats:
--------
-  The old spinbutton did not round but instead truncated.  This
seems a little odd when used with scrollbars.  Switched to round.
- rounding is towards inf.  Should likely change to round
to zero.
-  Did not place EPSILON checking for the snap function. Is it
necessary there? 
-  Although functionality is no longer in spinbutton it is
still a property of a spinbutton and snap_to_tick is there
for backwards compatiblity.
- changed name from snap_to_tick to snap_to_increment as that
it the name of the quantity in adjustment.

Patch is attached below.  It is against gtk+-1.3 cvs.

--Karl

==================================CUT==================================

Index: gtk/gtkadjustment.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkadjustment.c,v
retrieving revision 1.18
diff -u -r1.18 gtkadjustment.c
--- gtk/gtkadjustment.c	2000/07/26 11:32:42	1.18
+++ gtk/gtkadjustment.c	2000/08/28 16:45:34
@@ -104,6 +104,7 @@
   adjustment->step_increment = 0.0;
   adjustment->page_increment = 0.0;
   adjustment->page_size = 0.0;
+  adjustment->snap_to_increment = FALSE;
 }
 
 GtkObject*
@@ -135,6 +136,13 @@
   g_return_if_fail (adjustment != NULL);
   g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
 
+  if (adjustment->snap_to_increment && (adjustment->step_increment > 0.0) )
+    {
+      gfloat snap_value = value/adjustment->step_increment;
+      snap_value += 0.5;
+      value = ((gint) (snap_value)) * adjustment->step_increment;
+    }
+
   value = CLAMP (value, adjustment->lower, adjustment->upper);
 
   if (value != adjustment->value)
@@ -192,3 +200,19 @@
   if (need_emission)
     gtk_adjustment_value_changed (adjustment);
 }
+
+
+void
+gtk_adjustment_set_snap_to_increment (GtkAdjustment *adjustment,
+                                      gboolean       snap)
+{
+  g_return_if_fail (adjustment != NULL);
+  g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+
+  if (adjustment->snap_to_increment != snap)
+    {
+      adjustment->snap_to_increment = snap;
+      gtk_adjustment_set_value (adjustment, adjustment->value);
+    }
+}
+
Index: gtk/gtkadjustment.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkadjustment.h,v
retrieving revision 1.12
diff -u -r1.12 gtkadjustment.h
--- gtk/gtkadjustment.h	2000/07/26 11:32:42	1.12
+++ gtk/gtkadjustment.h	2000/08/28 16:45:34
@@ -58,6 +58,7 @@
   gfloat step_increment;
   gfloat page_increment;
   gfloat page_size;
+  guint snap_to_increment:1;
 };
 
 struct _GtkAdjustmentClass
@@ -81,6 +82,8 @@
 void	   gtk_adjustment_clamp_page		(GtkAdjustment	 *adjustment,
 						 gfloat		  lower,
 						 gfloat		  upper);
+void       gtk_adjustment_set_snap_to_increment (GtkAdjustment   *adjustment,
+                                                 gboolean         snap);
 void	   gtk_adjustment_set_value		(GtkAdjustment	 *adjustment,
 						 gfloat		  value);
 
Index: gtk/gtkspinbutton.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkspinbutton.c,v
retrieving revision 1.43
diff -u -r1.43 gtkspinbutton.c
--- gtk/gtkspinbutton.c	2000/07/26 11:32:50	1.43
+++ gtk/gtkspinbutton.c	2000/08/28 16:45:37
@@ -114,8 +114,6 @@
 static gint gtk_spin_button_scroll         (GtkWidget          *widget,
 					    GdkEventScroll     *event);
 static void gtk_spin_button_activate       (GtkEditable        *editable);
-static void gtk_spin_button_snap           (GtkSpinButton      *spin_button,
-					    gfloat              val);
 static void gtk_spin_button_insert_text    (GtkEditable        *editable,
 					    const gchar        *new_text,
 					    gint                new_text_length,
@@ -329,7 +327,7 @@
       GTK_VALUE_UINT (*arg) = spin_button->digits;
       break;
     case ARG_SNAP_TO_TICKS:
-      GTK_VALUE_BOOL (*arg) = spin_button->snap_to_ticks;
+      GTK_VALUE_BOOL (*arg) = spin_button->adjustment->snap_to_increment;
       break;
     case ARG_NUMERIC:
       GTK_VALUE_BOOL (*arg) = spin_button->numeric;
@@ -371,7 +369,6 @@
   spin_button->digits = 0;
   spin_button->numeric = FALSE;
   spin_button->wrap = FALSE;
-  spin_button->snap_to_ticks = FALSE;
   gtk_spin_button_set_adjustment (spin_button,
 	  (GtkAdjustment*) gtk_adjustment_new (0, 0, 0, 0, 0, 0));
 }
@@ -1178,32 +1175,6 @@
 }
 
 static void
-gtk_spin_button_snap (GtkSpinButton *spin_button,
-		      gfloat         val)
-{
-  gfloat inc;
-  gfloat tmp;
-  
-  inc = spin_button->adjustment->step_increment;
-  tmp = (val - spin_button->adjustment->lower) / inc;
-  if (tmp - floor (tmp) < ceil (tmp) - tmp)
-    val = spin_button->adjustment->lower + floor (tmp) * inc;
-  else
-    val = spin_button->adjustment->lower + ceil (tmp) * inc;
-
-  if (fabs (val - spin_button->adjustment->value) > EPSILON)
-    gtk_adjustment_set_value (spin_button->adjustment, val);
-  else
-    {
-      gint return_val = FALSE;
-      gtk_signal_emit (GTK_OBJECT (spin_button), spinbutton_signals[OUTPUT],
-		       &return_val);
-      if (return_val == FALSE)
-	gtk_spin_button_default_output (spin_button);
-    }
-}
-
-static void
 gtk_spin_button_activate (GtkEditable *editable)
 {
   g_return_if_fail (editable != NULL);
@@ -1559,15 +1530,8 @@
 
   g_return_if_fail (spin_button != NULL);
   g_return_if_fail (GTK_IS_SPIN_BUTTON (spin_button));
-
-  new_val = (snap_to_ticks != 0);
 
-  if (new_val != spin_button->snap_to_ticks)
-    {
-      spin_button->snap_to_ticks = new_val;
-      if (new_val && GTK_EDITABLE (spin_button)->editable)
-	gtk_spin_button_update (spin_button);
-    }
+  gtk_adjustment_set_snap_to_increment (spin_button->adjustment, snap_to_ticks);
 }
 
 void
@@ -1677,19 +1641,14 @@
       return;
     }
 
-  if (spin_button->snap_to_ticks)
-    gtk_spin_button_snap (spin_button, val);
+  if (fabs (val - spin_button->adjustment->value) > EPSILON)
+    gtk_adjustment_set_value (spin_button->adjustment, val);
   else
     {
-      if (fabs (val - spin_button->adjustment->value) > EPSILON)
-	gtk_adjustment_set_value (spin_button->adjustment, val);
-      else
-	{
-	  return_val = FALSE;
-	  gtk_signal_emit (GTK_OBJECT (spin_button), spinbutton_signals[OUTPUT],
-			   &return_val);
-	  if (return_val == FALSE)
-	    gtk_spin_button_default_output (spin_button);
-	}
+      return_val = FALSE;
+      gtk_signal_emit (GTK_OBJECT (spin_button), spinbutton_signals[OUTPUT],
+                       &return_val);
+      if (return_val == FALSE)
+        gtk_spin_button_default_output (spin_button);
     }
 }
Index: gtk/gtkspinbutton.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkspinbutton.h,v
retrieving revision 1.19
diff -u -r1.19 gtkspinbutton.h
--- gtk/gtkspinbutton.h	2000/07/26 11:32:50	1.19
+++ gtk/gtkspinbutton.h	2000/08/28 16:45:37
@@ -97,7 +97,6 @@
   guint digits : 3;
   guint numeric : 1;
   guint wrap : 1;
-  guint snap_to_ticks : 1;
 };
 
 struct _GtkSpinButtonClass
@@ -151,7 +150,7 @@
 
 void		gtk_spin_button_set_shadow_type	   (GtkSpinButton  *spin_button,
 						    GtkShadowType   shadow_type);
-
+/* deprecated, use gtk_adjustment_set_snap_to_increment */
 void		gtk_spin_button_set_snap_to_ticks  (GtkSpinButton  *spin_button,
 						    gboolean	    snap_to_ticks);
 void            gtk_spin_button_update             (GtkSpinButton  *spin_button);





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