[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