[xiph-commits] r12005 - trunk/sushivision

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Fri Nov 3 15:12:51 PST 2006


Author: xiphmont
Date: 2006-11-03 15:12:47 -0800 (Fri, 03 Nov 2006)
New Revision: 12005

Modified:
   trunk/sushivision/mapping.c
   trunk/sushivision/mapping.h
   trunk/sushivision/panel-2d.c
   trunk/sushivision/panel-2d.h
   trunk/sushivision/plot.c
   trunk/sushivision/plot.h
   trunk/sushivision/slice.c
   trunk/sushivision/slice.h
   trunk/sushivision/slider.c
Log:
Add infinite undo/redo to UI



Modified: trunk/sushivision/mapping.c
===================================================================
--- trunk/sushivision/mapping.c	2006-11-03 17:56:09 UTC (rev 12004)
+++ trunk/sushivision/mapping.c	2006-11-03 23:12:47 UTC (rev 12005)
@@ -295,6 +295,7 @@
 }
 
 void mapping_set_func(mapping *m, int funcnum){
+  m->mapnum = funcnum;
   m->mapfunc = mapfunc[funcnum];
 }
 

Modified: trunk/sushivision/mapping.h
===================================================================
--- trunk/sushivision/mapping.h	2006-11-03 17:56:09 UTC (rev 12004)
+++ trunk/sushivision/mapping.h	2006-11-03 23:12:47 UTC (rev 12005)
@@ -21,7 +21,7 @@
 
 #include <sys/types.h>
 typedef struct {
-
+  int mapnum;
   double low;
   double high;
   double i_range;

Modified: trunk/sushivision/panel-2d.c
===================================================================
--- trunk/sushivision/panel-2d.c	2006-11-03 17:56:09 UTC (rev 12004)
+++ trunk/sushivision/panel-2d.c	2006-11-03 23:12:47 UTC (rev 12005)
@@ -30,6 +30,7 @@
 #include <sys/types.h>
 #include <gtk/gtk.h>
 #include <cairo-ft.h>
+#include <gdk/gdkkeysyms.h>
 #include "sushivision.h"
 #include "mapping.h"
 #include "plot.h"
@@ -38,6 +39,11 @@
 #include "panel-2d.h"
 #include "internal.h"
 
+static void panel2d_undo_log(sushiv_panel_t *p);
+static void panel2d_undo_push(sushiv_panel_t *p);
+static void panel2d_undo_suspend(sushiv_panel_t *p);
+static void panel2d_undo_resume(sushiv_panel_t *p);
+
 static void render_checks(int w, int y, u_int32_t *render){
   int x,j;
   /* default checked background */
@@ -110,6 +116,9 @@
   sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
   int onum = optr - p->objective_list;
 
+  panel2d_undo_push(p);
+  panel2d_undo_suspend(p);
+
   mapping_set_func(&p2->mappings[onum],gtk_combo_box_get_active(GTK_COMBO_BOX(w)));
   
   //redraw the map slider
@@ -119,15 +128,21 @@
     
   //redraw the plot
   _sushiv_panel_dirty_map(p);
+  panel2d_undo_resume(p);
 }
 
-static void map_callback_2d(void *in){
+static void map_callback_2d(void *in,int buttonstate){
   sushiv_objective_t **optr = (sushiv_objective_t **)in;
   sushiv_objective_t *o = *optr;
   sushiv_panel_t *p = o->panel;
   sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
   int onum = optr - p->objective_list;
 
+  if(buttonstate == 0){
+    panel2d_undo_push(p);
+    panel2d_undo_suspend(p);
+  }
+
   // recache alpha del */
   p2->alphadel[onum] = 
     slider_val_to_del(p2->range_scales[onum],
@@ -135,6 +150,8 @@
 
   //redraw the plot
   _sushiv_panel_dirty_map(p);
+  if(buttonstate == 2)
+    panel2d_undo_resume(p);
 }
 
 static void update_xy_availability(sushiv_panel_t *p){
@@ -151,6 +168,7 @@
       // set the x dim flag
       p2->x_d = p->dimension_list[i];
       p2->x_scale = p2->dim_scales[i];
+      p2->x_dnum = i;
       // set panel x scale to this dim
       p2->x = scalespace_linear(p2->x_d->bracket[0],
 				p2->x_d->bracket[1],
@@ -169,6 +187,7 @@
       // set the y dim
       p2->y_d = p->dimension_list[i];
       p2->y_scale = p2->dim_scales[i];
+      p2->y_dnum = i;
       // set panel y scale to this dim
       p2->y = scalespace_linear(p2->y_d->bracket[0],
 				p2->y_d->bracket[1],
@@ -519,40 +538,48 @@
   plot_set_crosshairs(PLOT(p2->graph),x,y);
 }
 
-static void dim_callback_2d(void *in){
+static void dim_callback_2d(void *in, int buttonstate){
   sushiv_dimension_t **dptr = (sushiv_dimension_t **)in;
   sushiv_dimension_t *d = *dptr;
   sushiv_panel_t *p = d->panel;
   sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
   int dnum = dptr - p->dimension_list;
-
   int axisp = (d == p2->x_d || d == p2->y_d);
 
+  if(buttonstate == 0){
+    panel2d_undo_push(p);
+    panel2d_undo_suspend(p);
+  }
+
   d->val = slider_get_value(p2->dim_scales[dnum],1);
 
   if(!axisp){
     // mid slider of a non-axis dimension changed, rerender
     _mark_recompute_2d(p);
-    return;
   }else{
     // mid slider of an axis dimension changed, move crosshairs
     update_crosshairs(p);
   }
 
+  if(buttonstate == 2)
+    panel2d_undo_resume(p);
 }
 
-static void bracket_callback_2d(void *in){
+static void bracket_callback_2d(void *in, int buttonstate){
   sushiv_dimension_t **dptr = (sushiv_dimension_t **)in;
   sushiv_dimension_t *d = *dptr;
   sushiv_panel_t *p = d->panel;
   sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
   int dnum = dptr - p->dimension_list;
-
   int axisp = (d == p2->x_d || d == p2->y_d);
-
   double lo = slider_get_value(p2->dim_scales[dnum],0);
   double hi = slider_get_value(p2->dim_scales[dnum],2);
 
+  if(buttonstate == 0){
+    panel2d_undo_push(p);
+    panel2d_undo_suspend(p);
+  }
+
   if(axisp){  
     double xy_p = d == p2->x_d;
     scalespace s = scalespace_linear(lo,hi,(xy_p?p2->data_w:p2->data_h),
@@ -567,26 +594,38 @@
   if(axisp)
     _mark_recompute_2d(p);
  
+  if(buttonstate == 2)
+    panel2d_undo_resume(p);
 }
 
 static void dimchange_callback_2d(GtkWidget *button,gpointer in){
   sushiv_panel_t *p = (sushiv_panel_t *)in;
   sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
+
   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))){
+
+    panel2d_undo_push(p);
+    panel2d_undo_suspend(p);
+
     update_xy_availability(p);
     update_crosshairs(p);
     plot_unset_box(PLOT(p2->graph));
     _mark_recompute_2d(p);
+
+    panel2d_undo_resume(p);
   }
 }
 
 static void crosshairs_callback(void *in){
   sushiv_panel_t *p = (sushiv_panel_t *)in;
   sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
-  double x=PLOT(p2->graph)->selx_val;
-  double y=PLOT(p2->graph)->sely_val;
+  double x=PLOT(p2->graph)->selx;
+  double y=PLOT(p2->graph)->sely;
   int i;
   
+  panel2d_undo_push(p);
+  panel2d_undo_suspend(p);
+
   for(i=0;i<p->dimensions;i++){
     sushiv_dimension_t *d = p->dimension_list[i];
     sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
@@ -595,6 +634,7 @@
     if(d == p2->y_d)
       slider_set_value(p2->dim_scales[i],1,y);
   }
+  panel2d_undo_resume(p);
 }
 
 static void box_callback(void *in){
@@ -606,10 +646,14 @@
   double corners[4];
   plot_box_vals(plot,corners);
 
+  panel2d_undo_push(p);
+  panel2d_undo_suspend(p);
+
   slider_set_value(p2->x_scale,0,corners[0]);
   slider_set_value(p2->x_scale,2,corners[1]);
   slider_set_value(p2->y_scale,0,corners[2]);
   slider_set_value(p2->y_scale,2,corners[3]);
+  panel2d_undo_resume(p);
 
 }
 
@@ -750,12 +794,228 @@
   return 1;
 }
 
+static void panel2d_undo_suspend(sushiv_panel_t *p){
+  sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
+  p2->undo_suspend++;
+}
+
+static void panel2d_undo_resume(sushiv_panel_t *p){
+  sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
+  p2->undo_suspend--;
+  if(p2->undo_suspend<0){
+    fprintf(stderr,"Internal error: undo suspend refcount count < 0\n");
+    p2->undo_suspend=0;
+  }
+
+  if(p2->undo_suspend==0)
+    panel2d_undo_log(p);
+}
+
+static void panel2d_undo_log(sushiv_panel_t *p){
+  sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
+  Plot *plot = PLOT(p2->graph);
+  sushiv_panel2d_undo_t *u;
+  int i;
+
+  if(!p2->undo_stack)
+    p2->undo_stack = calloc(2,sizeof(*p2->undo_stack));
+
+  // alloc new undo
+  u = p2->undo_stack[p2->undo_level];
+  if(!u){
+    u = p2->undo_stack[p2->undo_level]= calloc(1,sizeof(*u));
+    u->mappings =  calloc(p->objectives,sizeof(*u->mappings));
+    u->obj_vals[0] =  calloc(p->objectives,sizeof(**u->obj_vals));
+    u->obj_vals[1] =  calloc(p->objectives,sizeof(**u->obj_vals));
+    u->obj_vals[2] =  calloc(p->objectives,sizeof(**u->obj_vals));
+    u->dim_vals[0] =  calloc(p->dimensions,sizeof(**u->dim_vals));
+    u->dim_vals[1] =  calloc(p->dimensions,sizeof(**u->dim_vals));
+    u->dim_vals[2] =  calloc(p->dimensions,sizeof(**u->dim_vals));
+  }
+
+  // populate undo
+  for(i=0;i<p->objectives;i++){
+    u->mappings[i] = p2->mappings[i].mapnum;
+    u->obj_vals[0][i] = slider_get_value(p2->range_scales[i],0);
+    u->obj_vals[1][i] = slider_get_value(p2->range_scales[i],1);
+    u->obj_vals[2][i] = slider_get_value(p2->range_scales[i],2);
+  }
+
+  for(i=0;i<p->dimensions;i++){
+    u->dim_vals[0][i] = slider_get_value(p2->dim_scales[i],0);
+    u->dim_vals[1][i] = slider_get_value(p2->dim_scales[i],1);
+    u->dim_vals[2][i] = slider_get_value(p2->dim_scales[i],2);
+  }
+  
+  u->x_d = p2->x_dnum;
+  u->y_d = p2->y_dnum;
+  plot_box_vals(plot,u->box);  
+  u->box_active = plot->box_active;
+}
+
+static void panel2d_undo_restore(sushiv_panel_t *p){
+  sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
+  sushiv_panel2d_undo_t *u = p2->undo_stack[p2->undo_level];
+  Plot *plot = PLOT(p2->graph);
+  int i;
+  int remap_flag=0;
+  int recomp_flag=0;
+
+  // go in through widgets
+  for(i=0;i<p->objectives;i++){
+    if(gtk_combo_box_get_active(GTK_COMBO_BOX(p2->range_pulldowns[i])) != u->mappings[i] ||
+       slider_get_value(p2->range_scales[i],0)!=u->obj_vals[0][i] ||
+       slider_get_value(p2->range_scales[i],1)!=u->obj_vals[1][i] ||
+       slider_get_value(p2->range_scales[i],2)!=u->obj_vals[2][i]){ 
+      remap_flag = 1;
+    }
+
+    gtk_combo_box_set_active(GTK_COMBO_BOX(p2->range_pulldowns[i]),u->mappings[i]);
+    slider_set_value(p2->range_scales[i],0,u->obj_vals[0][i]);
+    slider_set_value(p2->range_scales[i],1,u->obj_vals[1][i]);
+    slider_set_value(p2->range_scales[i],2,u->obj_vals[2][i]);
+  }
+
+  for(i=0;i<p->dimensions;i++){
+    if(slider_get_value(p2->dim_scales[i],0)!=u->dim_vals[0][i] ||
+       slider_get_value(p2->dim_scales[i],1)!=u->dim_vals[1][i] ||
+       slider_get_value(p2->dim_scales[i],2)!=u->dim_vals[2][i]){
+      if(i==u->x_d || i==u->y_d)
+	recomp_flag=1;
+    }
+    slider_set_value(p2->dim_scales[i],0,u->dim_vals[0][i]);
+    slider_set_value(p2->dim_scales[i],1,u->dim_vals[1][i]);
+    slider_set_value(p2->dim_scales[i],2,u->dim_vals[2][i]);
+  }
+
+  if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p2->dim_xb[u->x_d]))){
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p2->dim_xb[u->x_d]),TRUE);
+    recomp_flag=1;
+  }
+  if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p2->dim_yb[u->y_d]))){
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p2->dim_yb[u->y_d]),TRUE);
+    recomp_flag=1;
+  }
+
+  update_xy_availability(p);
+
+  if(u->box_active)
+    plot_box_set(plot,u->box);
+  else
+    plot_unset_box(plot);
+
+  if(recomp_flag)
+    _mark_recompute_2d(p);
+  else if(remap_flag)
+    _sushiv_panel_dirty_map(p);
+  else
+    plot_expose_request(plot);
+}
+
+static void panel2d_undo_push(sushiv_panel_t *p){
+  sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
+  sushiv_panel2d_undo_t *u;
+  int i;
+  
+  if(p2->undo_suspend)return;
+
+  panel2d_undo_log(p);
+
+  if(p2->undo_stack[p2->undo_level+1]){
+    /* pop levels above this one */
+    i=p2->undo_level+1;
+    while(p2->undo_stack[i]){
+      u = p2->undo_stack[i];
+      if(u->mappings) free(u->mappings);
+      if(u->obj_vals[0]) free(u->obj_vals[0]);
+      if(u->obj_vals[1]) free(u->obj_vals[1]);
+      if(u->obj_vals[2]) free(u->obj_vals[2]);
+      if(u->dim_vals[0]) free(u->dim_vals[0]);
+      if(u->dim_vals[1]) free(u->dim_vals[1]);
+      if(u->dim_vals[2]) free(u->dim_vals[2]);
+      free(u);
+      p2->undo_stack[i]= NULL;
+      i++;
+    }
+  }
+
+  // realloc stack 
+  p2->undo_stack = realloc(p2->undo_stack,(p2->undo_level+3)*sizeof(*p2->undo_stack));
+  p2->undo_level++;
+  p2->undo_stack[p2->undo_level]=0;
+  p2->undo_stack[p2->undo_level+1]=0;
+
+}
+
+static void panel2d_undo_up(sushiv_panel_t *p){
+  sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
+  
+  if(!p2->undo_stack)return;
+  if(!p2->undo_stack[p2->undo_level])return;
+  if(!p2->undo_stack[p2->undo_level+1])return;
+
+  p2->undo_level++;
+  panel2d_undo_suspend(p);
+  panel2d_undo_restore(p);
+  panel2d_undo_resume(p);
+
+}
+
+static void panel2d_undo_down(sushiv_panel_t *p){
+  sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
+
+  if(!p2->undo_stack)return;
+  if(!p2->undo_level)return;
+ 
+  panel2d_undo_log(p);
+  p2->undo_level--;
+
+  panel2d_undo_suspend(p);
+  panel2d_undo_restore(p);
+  panel2d_undo_resume(p);
+}
+
+static gboolean panel2d_keypress(GtkWidget *widget,
+				 GdkEventKey *event,
+				 gpointer in){
+  sushiv_panel_t *p = (sushiv_panel_t *)in;
+  //  sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
+  
+  if(event->state&GDK_MOD1_MASK) return FALSE;
+  if(event->state&GDK_CONTROL_MASK)return FALSE;
+  
+  /* non-control keypresses */
+  switch(event->keyval){
+    
+  case GDK_Q:
+  case GDK_q:
+    // quit
+    _sushiv_clean_exit(SIGINT);
+    return TRUE;
+
+  case GDK_BackSpace:
+    // undo 
+    panel2d_undo_down(p);
+    return TRUE;
+
+  case GDK_r:
+    // redo
+    panel2d_undo_up(p);
+    return TRUE;
+  }
+
+
+  return FALSE;
+}
+
 void _sushiv_realize_panel2d(sushiv_panel_t *p){
   sushiv_panel2d_t *p2 = (sushiv_panel2d_t *)p->internal;
   int i;
   int lo = p->scale_val_list[0];
   int hi = p->scale_val_list[p->scale_vals-1];
 
+  panel2d_undo_suspend(p);
+
   p2->toplevel = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   g_signal_connect_swapped (G_OBJECT (p2->toplevel), "delete-event",
 			    G_CALLBACK (_sushiv_clean_exit), (void *)SIGINT);
@@ -777,6 +1037,7 @@
 
   /* objective sliders */
   p2->range_scales = calloc(p->objectives,sizeof(*p2->range_scales));
+  p2->range_pulldowns = calloc(p->objectives,sizeof(*p2->range_pulldowns));
   p2->alphadel = calloc(p->objectives,sizeof(*p2->alphadel));
   p2->mappings = calloc(p->objectives,sizeof(*p2->mappings));
   for(i=0;i<p->objectives;i++){
@@ -799,6 +1060,7 @@
 			G_CALLBACK (mapchange_callback_2d), p->objective_list+i);
       gtk_table_attach(GTK_TABLE(p2->top_table),menu,4,5,i+1,i+2,
 		       GTK_SHRINK,GTK_SHRINK,5,0);
+      p2->range_pulldowns[i] = menu;
     }
 
     /* the range mapping slices/slider */ 
@@ -893,10 +1155,13 @@
   }
   update_xy_availability(p);
 
+  g_signal_connect (G_OBJECT (p2->toplevel), "key-press-event",
+                    G_CALLBACK (panel2d_keypress), p);
 
   gtk_widget_realize(p2->toplevel);
   gtk_widget_realize(p2->graph);
   gtk_widget_show_all(p2->toplevel);
+  panel2d_undo_resume(p);
 }
 
 int sushiv_new_panel_2d(sushiv_instance_t *s,
@@ -922,3 +1187,4 @@
   return 0;
 }
 
+

Modified: trunk/sushivision/panel-2d.h
===================================================================
--- trunk/sushivision/panel-2d.h	2006-11-03 17:56:09 UTC (rev 12004)
+++ trunk/sushivision/panel-2d.h	2006-11-03 23:12:47 UTC (rev 12005)
@@ -19,6 +19,20 @@
  * 
  */
 
+// undo history
+typedef struct sushiv_panel2d_undo {
+  int *mappings;
+
+  double *obj_vals[3];
+  double *dim_vals[3];
+  
+  int x_d;
+  int y_d;
+
+  double box[4];
+  int box_active;
+} sushiv_panel2d_undo_t;
+
 typedef struct sushiv_panel2d {
 
   GtkWidget *toplevel;
@@ -47,9 +61,16 @@
   sushiv_dimension_t *y_d;
   Slider *x_scale;
   Slider *y_scale;
+  int x_dnum; // number of dimension within panel, not global instance
+  int y_dnum; // number of dimension within panel, not global instance
 
   int last_line;
   int dirty_flag;
+
+  sushiv_panel2d_undo_t **undo_stack;
+  int undo_level;
+  int undo_suspend;
+
 } sushiv_panel2d_t;
 
 extern void _sushiv_realize_panel2d(sushiv_panel_t *p);

Modified: trunk/sushivision/plot.c
===================================================================
--- trunk/sushivision/plot.c	2006-11-03 17:56:09 UTC (rev 12004)
+++ trunk/sushivision/plot.c	2006-11-03 23:12:47 UTC (rev 12005)
@@ -190,13 +190,26 @@
 
 }
 
+static void box_corners(Plot *p, double vals[4]){
+  double x1 = scalespace_pixel(&p->x,p->box_x1);
+  double x2 = scalespace_pixel(&p->x,p->box_x2);
+  double y1 = scalespace_pixel(&p->y,p->box_y1);
+  double y2 = scalespace_pixel(&p->y,p->box_y2);
+
+  vals[0] = (x1<x2 ? x1 : x2);
+  vals[1] = (y1<y2 ? y1 : y2);
+  vals[2] = fabs(x1-x2);
+  vals[3] = fabs(y1-y2);
+}
+
 static int inside_box(Plot *p, int x, int y){
-  int bx = (p->boxA_x<p->boxB_x ? p->boxA_x : p->boxB_x)+.5;
-  int by = (p->boxA_y<p->boxB_y ? p->boxA_y : p->boxB_y)+.5;
-  int bw = abs(p->boxA_x-p->boxB_x);
-  int bh = abs(p->boxA_y-p->boxB_y);
+  double vals[4];
+  box_corners(p,vals);
   
-  return (x >= bx && x <= bx+bw && y >= by && y <= by+bh);
+  return (x >= vals[0] && 
+	  x <= vals[0]+vals[2] && 
+	  y >= vals[1] && 
+	  y <= vals[1]+vals[3]);
 }
 
 static void plot_draw (Plot *p,
@@ -216,27 +229,29 @@
     cairo_fill(c);
     
     // transient foreground
-    cairo_set_source_rgba(c,1.,1.,1.,.8);
-    cairo_set_line_width(c,1.);
-    cairo_move_to(c,0,p->sely+.5);
-    cairo_line_to(c,widget->allocation.width,p->sely+.5);
-    cairo_move_to(c,p->selx+.5,0);
-    cairo_line_to(c,p->selx+.5,widget->allocation.height);
-    cairo_stroke(c);
+    {
+      double sx = scalespace_pixel(&p->x,p->selx);
+      double sy = widget->allocation.height-scalespace_pixel(&p->y,p->sely);
+      cairo_set_source_rgba(c,1.,1.,1.,.8);
+      cairo_set_line_width(c,1.);
+      cairo_move_to(c,0,sy+.5);
+      cairo_line_to(c,widget->allocation.width,sy+.5);
+      cairo_move_to(c,sx+.5,0);
+      cairo_line_to(c,sx+.5,widget->allocation.height);
+      cairo_stroke(c);
+    }
 
     if(p->box_active){
-      int bx = (p->boxA_x<p->boxB_x ? p->boxA_x : p->boxB_x);
-      int by = (p->boxA_y<p->boxB_y ? p->boxA_y : p->boxB_y);
-      int bw = abs(p->boxA_x-p->boxB_x)+1;
-      int bh = abs(p->boxA_y-p->boxB_y)+1;
+      double vals[4];
+      box_corners(p,vals);
 
-      cairo_rectangle(c,bx,by,bw,bh);	
+      cairo_rectangle(c,vals[0],vals[1],vals[2]+1,vals[3]+1);	
       if(p->box_active>1)
 	cairo_set_source_rgba(c,1.,1.,.6,.4);
       else
 	cairo_set_source_rgba(c,1.,1.,1.,.3);
       cairo_fill(c);
-      cairo_rectangle(c,bx+.5,by+.5,bw-1,bh-1);
+      cairo_rectangle(c,vals[0]+.5,vals[1]+.5,vals[2],vals[3]);
       if(p->box_active>1)
 	cairo_set_source_rgba(c,1.,1.,.6,.9);
       else
@@ -364,36 +379,42 @@
 
   int x = event->x;
   int y = event->y;
+  int bx = scalespace_pixel(&p->x,p->box_x1);
+  int by = scalespace_pixel(&p->y,p->box_y1);
 
   if(p->button_down){
-    if(abs(p->boxA_x - x)>5 ||
-       abs(p->boxA_y - y)>5)
+    if(abs(bx - x)>5 ||
+       abs(by - y)>5)
       p->box_active = 1;
     
-    
     if(p->box_active){
-      int bx = (p->boxA_x<p->boxB_x ? p->boxA_x : p->boxB_x);
-      int by = (p->boxA_y<p->boxB_y ? p->boxA_y : p->boxB_y);
-      int bw = abs(p->boxA_x-p->boxB_x)+1;
-      int bh = abs(p->boxA_y-p->boxB_y)+1;
-      plot_expose_request_partial(p,bx,by,bw,bh);
+      double vals[4];
+      box_corners(p,vals);
+      plot_expose_request_partial(p,
+				  (int)(vals[0]),
+				  (int)(vals[1]),
+				  (int)(vals[2]+2),
+				  (int)(vals[3]+2));
     }
     
-    p->boxB_x = x;
-    p->boxB_y = y;
+    p->box_x2 = scalespace_value(&p->x,x);
+    p->box_y2 = scalespace_value(&p->y,y);
   }
   
   if(p->box_active){
+    double vals[4];
+    box_corners(p,vals);
+    
     if(inside_box(p,x,y) && !p->button_down)
       p->box_active = 2;
     else
       p->box_active = 1;
     
-    int bx = (p->boxA_x<p->boxB_x ? p->boxA_x : p->boxB_x);
-    int by = (p->boxA_y<p->boxB_y ? p->boxA_y : p->boxB_y);
-    int bw = abs(p->boxA_x-p->boxB_x)+1;
-    int bh = abs(p->boxA_y-p->boxB_y)+1;
-    plot_expose_request_partial(p,bx,by,bw,bh);
+    plot_expose_request_partial(p,
+				(int)(vals[0]),
+				(int)(vals[1]),
+				(int)(vals[2]+2),
+				(int)(vals[3]+2));
   }
 
   return TRUE;
@@ -412,8 +433,8 @@
     p->box_active=0;
 
   }else{
-    p->boxA_x = event->x;
-    p->boxA_y = event->y;
+    p->box_x1 = scalespace_value(&p->x,event->x);
+    p->box_y1 = scalespace_value(&p->y,event->y);
     p->box_active = 0;
     p->button_down=1; 
   }
@@ -425,11 +446,9 @@
   Plot *p = PLOT (widget);
   plot_expose_request(p);
 
-  if(!p->box_active){
-    p->selx = event->x;
-    p->sely = event->y;
-    p->selx_val = scalespace_value(&p->x,p->selx);
-    p->sely_val = scalespace_value(&p->y,widget->allocation.height-p->sely);
+  if(!p->box_active && p->button_down){
+    p->selx = scalespace_value(&p->x,event->x);
+    p->sely = scalespace_value(&p->y,widget->allocation.height-event->y);
 
     if(p->crosshairs_callback)
       p->crosshairs_callback(p->cross_data);
@@ -565,7 +584,6 @@
 void plot_set_x_scale(Plot *p, scalespace x){
   scalespace temp = p->x;
   p->x = x;
-  p->selx = scalespace_pixel(&p->x,p->selx_val);
   if(memcmp(&temp,&p->x,sizeof(temp)))
     plot_draw_scales(p);
 }
@@ -574,7 +592,6 @@
   GtkWidget *widget = GTK_WIDGET(p);
   scalespace temp = p->y;
   p->y = y;
-  p->sely = widget->allocation.height - scalespace_pixel(&p->y,p->sely_val);
   if(memcmp(&temp,&p->y,sizeof(temp)))
     plot_draw_scales(p);
 }
@@ -603,27 +620,38 @@
 
 void plot_set_crosshairs(Plot *p, double x, double y){
   gdk_threads_enter();
-  p->selx_val = x;
-  p->sely_val = y;
-  p->selx = scalespace_pixel(&p->x,x);
-  p->sely = GTK_WIDGET(p)->allocation.height - scalespace_pixel(&p->y,y);
+  p->selx = x;
+  p->sely = y;
 
   plot_expose_request(p);
   gdk_threads_leave();
 }
 
 void plot_unset_box(Plot *p){
+  gdk_threads_enter();
   p->box_active = 0;
+  gdk_threads_leave();
 }
 
 void plot_box_vals(Plot *p, double ret[4]){
-  int bx1 = (p->boxA_x<p->boxB_x ? p->boxA_x : p->boxB_x);
-  int by1 = (p->boxA_y<p->boxB_y ? p->boxA_y : p->boxB_y);
-  int bx2 = abs(p->boxA_x-p->boxB_x)+bx1+1;
-  int by2 = abs(p->boxA_y-p->boxB_y)+by1+1;
-  
-  ret[0] = scalespace_value(&p->x,bx1);
-  ret[1] = scalespace_value(&p->x,bx2);
-  ret[2] = scalespace_value(&p->y,by1);
-  ret[3] = scalespace_value(&p->y,by2);
+  gdk_threads_enter();
+  ret[0] = (p->box_x1<p->box_x2?p->box_x1:p->box_x2);
+  ret[1] = (p->box_x1>p->box_x2?p->box_x1:p->box_x2);
+
+  ret[2] = (p->box_y1<p->box_y2?p->box_y1:p->box_y2);
+  ret[3] = (p->box_y1>p->box_y2?p->box_y1:p->box_y2);
+  gdk_threads_leave();
 }
+
+void plot_box_set(Plot *p, double vals[4]){
+  gdk_threads_enter();
+
+  p->box_x1=vals[0];
+  p->box_x2=vals[1];
+  p->box_y1=vals[2];
+  p->box_y2=vals[3];
+  p->box_active = 1;
+
+  plot_expose_request(p);
+  gdk_threads_leave();
+}

Modified: trunk/sushivision/plot.h
===================================================================
--- trunk/sushivision/plot.h	2006-11-03 17:56:09 UTC (rev 12004)
+++ trunk/sushivision/plot.h	2006-11-03 23:12:47 UTC (rev 12005)
@@ -51,15 +51,13 @@
   char *namex;
   char *namey;
 
-  double selx_val;
-  double sely_val;
   double selx;
   double sely;
 
-  double boxA_x;
-  double boxA_y;
-  double boxB_x;
-  double boxB_y;
+  double box_x1;
+  double box_y1;
+  double box_x2;
+  double box_y2;
   int box_active;
   void *box_data;
   void (*box_callback)(void *);
@@ -99,3 +97,4 @@
 void plot_draw_scales(Plot *p);
 void plot_unset_box(Plot *p);
 void plot_box_vals(Plot *p, double ret[4]);
+void plot_box_set(Plot *p, double vals[4]);

Modified: trunk/sushivision/slice.c
===================================================================
--- trunk/sushivision/slice.c	2006-11-03 17:56:09 UTC (rev 12004)
+++ trunk/sushivision/slice.c	2006-11-03 23:12:47 UTC (rev 12005)
@@ -232,7 +232,7 @@
   return m_type;
 }
 
-GtkWidget* slice_new (void (*callback)(void *), void *data){
+GtkWidget* slice_new (void (*callback)(void *,int), void *data){
   GtkWidget *ret= GTK_WIDGET (g_object_new (slice_get_type (), NULL));
   Slice *s=SLICE(ret);
   s->callback = callback;
@@ -252,6 +252,6 @@
   s->thumb_val=v;
   slider_vals_bound(s->slider,s->slicenum);
   
-  if(s->callback)s->callback(s->callback_data);
+  if(s->callback)s->callback(s->callback_data,5);
   draw_and_expose(w);
 }

Modified: trunk/sushivision/slice.h
===================================================================
--- trunk/sushivision/slice.h	2006-11-03 17:56:09 UTC (rev 12004)
+++ trunk/sushivision/slice.h	2006-11-03 23:12:47 UTC (rev 12005)
@@ -54,7 +54,7 @@
   int    thumb_grab;
   double thumb_val;
 
-  void (*callback)(void *);
+  void (*callback)(void *,int);
   void *callback_data;
 
 };
@@ -65,7 +65,7 @@
 };
 
 extern GType slice_get_type        (void);
-extern GtkWidget* slice_new (void (*callback)(void *), void *data);
+extern GtkWidget* slice_new (void (*callback)(void *,int), void *data);
 extern void slice_set_active(Slice *s, int activep);
 extern void slice_thumb_set(Slice *s,float v);
 

Modified: trunk/sushivision/slider.c
===================================================================
--- trunk/sushivision/slider.c	2006-11-03 17:56:09 UTC (rev 12004)
+++ trunk/sushivision/slider.c	2006-11-03 23:12:47 UTC (rev 12005)
@@ -29,6 +29,8 @@
 #include "slice.h"
 #include "slider.h"
 
+static double val_to_pixel(Slider *s, double val);
+
 static int total_slice_width(Slider *s){
   int i;
   int count=0;
@@ -163,7 +165,7 @@
  
   // lines & labels
   for(i=0;i<s->labels;i++){
-    int x=rint(((float)i)/(s->labels-1)*(s->w - s->xpad*2 -1))+s->xpad;
+    int x=val_to_pixel(s,s->label_vals[i])+.5;
     int y=s->h-s->ypad-1.5;
     
     cairo_move_to(c,x+.5,s->ypad+2);
@@ -297,6 +299,7 @@
   for(i=0;i<s->num_slices;i++){
     GtkWidget *sl = s->slices[i];
     double x = val_to_pixel(s,((Slice *)(s->slices[i]))->thumb_val)+.5;
+
     double rad = 2.;
     
     float y = rint(h/2)+.5;
@@ -637,6 +640,7 @@
       sl->thumb_focus=1;
       gtk_widget_grab_focus(GTK_WIDGET(sl));
 
+      if(sl->callback)sl->callback(sl->callback_data,0);
       slider_motion(s,slicenum,x,y);
     }
   }
@@ -648,10 +652,33 @@
   int i;
   for(i=0;i<s->num_slices;i++){
     Slice *sl = SLICE(s->slices[i]);
-    sl->thumb_grab=0;
+
+    if(sl->thumb_grab){
+      sl->thumb_grab=0;
+      if(sl->callback)sl->callback(sl->callback_data,2);
+    }
   }
 }
 
+static void update_gradient(Slider *s){
+  if(s->gradient){
+    Slice *sl = SLICE(s->slices[0]);
+    Slice *sh = SLICE(s->slices[s->num_slices-1]);
+    double ldel = slider_val_to_del(s,sl->thumb_val);
+    double hdel = slider_val_to_del(s,sh->thumb_val);
+    
+    if(s->gradient->low != ldel ||
+       s->gradient->high != hdel){
+      
+      mapping_set_lo(s->gradient,ldel);
+      mapping_set_hi(s->gradient,hdel);
+      slider_draw_background(s);
+      slider_draw(s);
+    }
+    slider_expose(s);
+  }
+}
+
 void slider_motion(Slider *s,int slicenum,int x,int y){
   int altered=0;
   int i;
@@ -667,24 +694,12 @@
   }
 
   // did a gradient get altered?
-  if(s->gradient && s->num_slices>=2){
-    Slice *sl = SLICE(s->slices[0]);
-    Slice *sh = SLICE(s->slices[s->num_slices-1]);
-    double ldel = slider_val_to_del(s,sl->thumb_val);
-    double hdel = slider_val_to_del(s,sh->thumb_val);
+  update_gradient(s);
 
-    if(s->gradient->low != ldel ||
-       s->gradient->high != hdel){
-
-      mapping_set_lo(s->gradient,ldel);
-      mapping_set_hi(s->gradient,hdel);
-      slider_draw_background(s);
-    }
-  }
   if(altered){
     Slice *sl = SLICE(s->slices[altered-1]);
     
-    if(sl->callback)sl->callback(sl->callback_data);
+    if(sl->callback)sl->callback(sl->callback_data,1);
     slider_draw(s);
     slider_expose(s);
   }else{
@@ -756,4 +771,5 @@
   if(thumbnum < 0)return;
   w = s->slices[thumbnum];
   slice_thumb_set(SLICE(w),v);
+  update_gradient(s);
 }



More information about the commits mailing list