Re: range inversion/mapping [patch]



Tim Janik wrote:
> 
> the ranges definitely need a way for the user to hook in and provide
> his own type of mapping. though log/sqrt are usefull mappings, the
> range mapping facilities shouldn't be limited to this fixed set.
> putting gtk_range_set_inverted() and maybe assorted friends is only
> a shortterm kludge, use a user-configurable signal right away and
> don't bloat the API ;)
> 

I have written a patch that implements the mapping via signals.

It has the minor problem that you can only connect one mapping
function to it or else the calculations will be inconsistant
between input mapping and output mapping.  This could be fixed
if there were a way to guarantee that the inputmap and the
outputmap signal handlers would be called in reverse order to
each other.

Jay Cox
jaycox gimp org


Index: gtkrange.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkrange.c,v
retrieving revision 1.44
diff -u -r1.44 gtkrange.c
--- gtkrange.c	2001/02/19 22:51:14	1.44
+++ gtkrange.c	2001/02/22 16:53:21
@@ -40,6 +40,14 @@
   ARG_UPDATE_POLICY
 };
 
+/* Signals */
+enum
+{
+  INPUTMAP,
+  OUTPUTMAP,
+  LAST_SIGNAL
+};
+
 static void gtk_range_class_init               (GtkRangeClass    *klass);
 static void gtk_range_init                     (GtkRange         *range);
 static void gtk_range_set_arg		       (GtkObject        *object,
@@ -96,6 +104,7 @@
 						gint             *bottom);
 
 static GtkWidgetClass *parent_class = NULL;
+static guint range_signals[LAST_SIGNAL] = {0};
 
 
 GtkType
@@ -175,6 +184,20 @@
 			   GTK_TYPE_UPDATE_TYPE,
 			   GTK_ARG_READWRITE,
 			   ARG_UPDATE_POLICY);
+  range_signals[INPUTMAP] =
+    gtk_signal_new ("inputmap",
+		    GTK_RUN_LAST,
+		    GTK_CLASS_TYPE (object_class),
+		    GTK_SIGNAL_OFFSET (GtkRangeClass, inputmap),
+		    gtk_marshal_VOID__POINTER,
+		    GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
+  range_signals[OUTPUTMAP] =
+    gtk_signal_new ("outputmap",
+		    GTK_RUN_LAST,
+		    GTK_CLASS_TYPE (object_class),
+		    GTK_SIGNAL_OFFSET (GtkRangeClass, outputmap),
+		    gtk_marshal_VOID__POINTER,
+		    GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
 }
 
 static void
@@ -483,9 +506,17 @@
 	}
 
       if (range->adjustment->lower != (range->adjustment->upper -
range->adjustment->page_size))
-	x += ((right - left) * (range->adjustment->value - range->adjustment->lower) /
-	      (range->adjustment->upper - range->adjustment->lower -
range->adjustment->page_size));
+        {
+	  double percent = (range->adjustment->value - range->adjustment->lower) /
+			   (range->adjustment->upper - range->adjustment->lower - 
+			    range->adjustment->page_size);
 
+	  gtk_signal_emit (GTK_OBJECT (range), range_signals[OUTPUTMAP],
+			   &percent);
+
+	  x += (right - left) * percent;
+	}
+
       if (x < left)
 	x = left;
       else if (x > right)
@@ -525,8 +556,16 @@
 	}
 
       if (range->adjustment->lower != (range->adjustment->upper -
range->adjustment->page_size))
-	y += ((bottom - top) * (range->adjustment->value - range->adjustment->lower) /
-	      (range->adjustment->upper - range->adjustment->lower -
range->adjustment->page_size));
+        {
+	  double percent = (range->adjustment->value - range->adjustment->lower) /
+			   (range->adjustment->upper - range->adjustment->lower - 
+			    range->adjustment->page_size);
+
+	  gtk_signal_emit (GTK_OBJECT (range), range_signals[OUTPUTMAP],
+			   &percent);
+	  
+	  y += ((bottom - top) * percent);
+	}
 
       if (y < top)
 	y = top;
@@ -648,6 +687,7 @@
   gint left, right;
   gint slider_x, slider_y;
   gint new_pos;
+  double percent;
 
   g_return_if_fail (GTK_IS_RANGE (range));
   g_return_if_fail (GTK_WIDGET_REALIZED (range));
@@ -669,10 +709,16 @@
     new_pos = right;
 
   old_value = range->adjustment->value;
+
+  percent = (new_pos - left) / (double)(right - left);
+
+  gtk_signal_emit (GTK_OBJECT (range), range_signals[INPUTMAP],
+		   &percent);
+
   range->adjustment->value = ((range->adjustment->upper -
 			       range->adjustment->lower -
 			       range->adjustment->page_size) *
-			      (new_pos - left) / (right - left) +
+			      percent +
 			      range->adjustment->lower);
 
   if (range->digits >= 0)
@@ -714,6 +760,7 @@
   gint top, bottom;
   gint slider_x, slider_y;
   gint new_pos;
+  gdouble percent;
 
   g_return_if_fail (GTK_IS_RANGE (range));
   g_return_if_fail (GTK_WIDGET_REALIZED (range));
@@ -737,10 +784,16 @@
     new_pos = bottom;
 
   old_value = range->adjustment->value;
+  
+  percent = (new_pos - top) / (double)(bottom - top);
+
+  gtk_signal_emit (GTK_OBJECT (range), range_signals[INPUTMAP],
+		   &percent);
+
   range->adjustment->value = ((range->adjustment->upper -
 			       range->adjustment->lower -
 			       range->adjustment->page_size) *
-			      (new_pos - top) / (bottom - top) +
+			      percent +
 			      range->adjustment->lower);
 
   if (range->digits >= 0)
Index: gtkrange.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkrange.h,v
retrieving revision 1.14
diff -u -r1.14 gtkrange.h
--- gtkrange.h	2001/02/19 22:51:14	1.14
+++ gtkrange.h	2001/02/22 16:53:21
@@ -114,6 +114,12 @@
 			    gint      xdelta,
 			    gint      ydelta);
   gint (* timer)           (GtkRange *range);
+
+  void (* inputmap)  (GtkRange *range,
+		      gfloat   *value);
+  void (* outputmap) (GtkRange *range,
+		      gfloat   *value);
+
 };


Index: testgtk.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/testgtk.c,v
retrieving revision 1.220
diff -u -r1.220 testgtk.c
--- testgtk.c	2001/02/21 19:59:22	1.220
+++ testgtk.c	2001/02/22 17:01:04
@@ -6268,6 +6268,16 @@
  * GtkRange
  */
 
+void testmap (GtkRange *range, gdouble *value)
+{
+  *value = *value * *value * *value;
+}
+
+void testunmap (GtkRange *range, gdouble *value)
+{
+  *value = pow(*value, 1/3.0);
+}
+
 static void
 create_range_controls (void)
 {
@@ -6337,6 +6347,11 @@
       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
       gtk_widget_show (scale);
       
+      gtk_signal_connect(GTK_OBJECT(scale), "inputmap",
+			 GTK_SIGNAL_FUNC(testmap), 0);
+      gtk_signal_connect(GTK_OBJECT(scale), "outputmap",
+			 GTK_SIGNAL_FUNC(testunmap), 0);
+
       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
       gtk_widget_show (hbox);




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