[xiph-commits] r12475 - trunk/sushivision
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Thu Feb 15 15:07:43 PST 2007
Author: xiphmont
Date: 2007-02-15 15:07:39 -0800 (Thu, 15 Feb 2007)
New Revision: 12475
Added:
trunk/sushivision/spinner.c
trunk/sushivision/spinner.h
Modified:
trunk/sushivision/Makefile
trunk/sushivision/internal.h
trunk/sushivision/main.c
trunk/sushivision/panel-1d.c
trunk/sushivision/panel-2d.c
trunk/sushivision/panel.c
trunk/sushivision/plot.c
trunk/sushivision/plot.h
Log:
Complete spinner revamp; move it to a minimal position above plot
Also correct several spinner placement bugs that were killing responsiveness
Modified: trunk/sushivision/Makefile
===================================================================
--- trunk/sushivision/Makefile 2007-02-15 03:48:15 UTC (rev 12474)
+++ trunk/sushivision/Makefile 2007-02-15 23:07:39 UTC (rev 12475)
@@ -24,14 +24,14 @@
SOCFLAGS = -fPIC
SOLDFLAGS = -shared -nostdlib -Wl,-soname="lib$(NAME).so.$(MAJOR)"
-SRC = main.c scale.c plot.c slider.c slice.c panel.c panel-1d.c panel-2d.c \
+SRC = main.c scale.c plot.c slider.c slice.c spinner.c panel.c panel-1d.c panel-2d.c \
mapping.c dimension.c function.c objective.c undo.c gtksucks.c \
example_fractal.c example_discrete.c
INC = sushivision.h
MAN =
EXAMPLES = sushivision_fractal sushivision_discrete
EX_OBJ = example_fractal.o example_discrete.o
-OBJ = main.o scale.o plot.o slider.o slice.o panel.o panel-1d.o panel-2d.o \
+OBJ = main.o scale.o plot.o slider.o slice.o spinner.c panel.o panel-1d.o panel-2d.o \
mapping.o dimension.o function.o objective.o undo.o gtksucks.o
LIBS = -lpthread -ldl
CAIROVER = >= 1.0.0
Modified: trunk/sushivision/internal.h
===================================================================
--- trunk/sushivision/internal.h 2007-02-15 03:48:15 UTC (rev 12474)
+++ trunk/sushivision/internal.h 2007-02-15 23:07:39 UTC (rev 12475)
@@ -25,6 +25,7 @@
#include "sushivision.h"
#include "mapping.h"
#include "slice.h"
+#include "spinner.h"
#include "slider.h"
#include "scale.h"
#include "gtksucks.h"
@@ -63,6 +64,7 @@
struct sushiv_panel_internal {
GtkWidget *toplevel;
GtkWidget *graph;
+ Spinner *spinner;
sushiv_dim_widget_t **dim_scales;
int realized;
Modified: trunk/sushivision/main.c
===================================================================
--- trunk/sushivision/main.c 2007-02-15 03:48:15 UTC (rev 12474)
+++ trunk/sushivision/main.c 2007-02-15 23:07:39 UTC (rev 12475)
@@ -117,7 +117,7 @@
if(p->private->realized && p->private->graph){
if(p->private->map_active){
- plot_set_busy(PLOT(p->private->graph));
+ spinner_set_busy(p->private->spinner);
flag |= p->private->map_action(p); // may drop lock internally
if(!p->private->map_active)
set_map_throttle_time(p);
@@ -125,20 +125,20 @@
// pending legend work?
if(p->private->legend_active){
- plot_set_busy(PLOT(p->private->graph));
+ spinner_set_busy(p->private->spinner);
flag |= p->private->legend_action(p); // may drop lock internally
}
// pending computation work?
if(p->private->plot_active){
- plot_set_busy(PLOT(p->private->graph));
+ spinner_set_busy(p->private->spinner);
flag |= p->private->compute_action(p,&c[j][i]); // may drop lock internally
}
if(!p->private->plot_active &&
!p->private->legend_active &&
!p->private->map_active)
- plot_set_idle(PLOT(p->private->graph));
+ spinner_set_idle(p->private->spinner);
}
gdk_threads_leave ();
}
Modified: trunk/sushivision/panel-1d.c
===================================================================
--- trunk/sushivision/panel-1d.c 2007-02-15 03:48:15 UTC (rev 12474)
+++ trunk/sushivision/panel-1d.c 2007-02-15 23:07:39 UTC (rev 12475)
@@ -1250,18 +1250,26 @@
g_signal_connect_swapped (G_OBJECT (p->private->toplevel), "delete-event",
G_CALLBACK (_sushiv_clean_exit), (void *)SIGINT);
- p1->top_table = gtk_table_new(3,4,0);
+ p1->top_table = gtk_table_new(5,3,0);
gtk_container_add (GTK_CONTAINER (p->private->toplevel), p1->top_table);
- gtk_container_set_border_width (GTK_CONTAINER (p->private->toplevel), 5);
+ gtk_container_set_border_width (GTK_CONTAINER (p->private->toplevel), 1);
p1->obj_table = gtk_table_new(p->objectives,5,0);
- gtk_table_attach(GTK_TABLE(p1->top_table),p1->obj_table,0,4,2,3,
+ gtk_table_attach(GTK_TABLE(p1->top_table),p1->obj_table,0,3,3,4,
GTK_EXPAND|GTK_FILL,0,0,5);
+ /* spinner, top bar */
+ {
+ GtkWidget *hbox = gtk_hbox_new(0,0);
+ gtk_table_attach(GTK_TABLE(p1->top_table),hbox,0,4,0,1,GTK_EXPAND|GTK_FILL,0,4,0);
+ gtk_box_pack_end(GTK_BOX(hbox),GTK_WIDGET(p->private->spinner),0,0,0);
+ }
+
+ /* dim table */
p1->dim_table = gtk_table_new(p->dimensions,3,0);
- gtk_table_attach(GTK_TABLE(p1->top_table),p1->dim_table,0,4,3,4,
- GTK_EXPAND|GTK_FILL,0,0,5);
+ gtk_table_attach(GTK_TABLE(p1->top_table),p1->dim_table,0,4,4,5,
+ GTK_EXPAND|GTK_FILL,0,4,4);
/* graph */
{
@@ -1273,8 +1281,11 @@
p->private->graph = GTK_WIDGET(plot_new(recompute_callback_1d,p,
(void *)(void *)crosshair_callback,p,
box_callback,p,flags));
- gtk_table_attach(GTK_TABLE(p1->top_table),p->private->graph,0,4,0,1,
- GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,0,5);
+ gtk_table_attach(GTK_TABLE(p1->top_table),p->private->graph,0,4,1,2,
+ GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,4,1);
+ gtk_table_set_row_spacing(GTK_TABLE(p1->top_table),1,4);
+ gtk_table_set_col_spacing(GTK_TABLE(p1->top_table),2,4);
+
}
/* range slider */
@@ -1288,7 +1299,7 @@
{
GtkWidget *label = gtk_label_new("range");
gtk_misc_set_alignment(GTK_MISC(label),1.,.5);
- gtk_table_attach(GTK_TABLE(p1->top_table),label,0,1,1,2,
+ gtk_table_attach(GTK_TABLE(p1->top_table),label,0,1,2,3,
GTK_FILL,0,10,0);
}
@@ -1296,9 +1307,9 @@
sl[0] = slice_new(map_callback_1d,p);
sl[1] = slice_new(map_callback_1d,p);
- gtk_table_attach(GTK_TABLE(p1->top_table),sl[0],1,2,1,2,
+ gtk_table_attach(GTK_TABLE(p1->top_table),sl[0],1,2,2,3,
GTK_EXPAND|GTK_FILL,0,0,0);
- gtk_table_attach(GTK_TABLE(p1->top_table),sl[1],2,3,1,2,
+ gtk_table_attach(GTK_TABLE(p1->top_table),sl[1],2,3,2,3,
GTK_EXPAND|GTK_FILL,0,0,0);
p1->range_slider = slider_new((Slice **)sl,2,
p1->range_scale->label_list,
@@ -1453,6 +1464,7 @@
gtk_widget_realize(p->private->toplevel);
gtk_widget_realize(p->private->graph);
+ gtk_widget_realize(GTK_WIDGET(p->private->spinner));
gtk_widget_show_all(p->private->toplevel);
_sushiv_panel_undo_resume(p);
Modified: trunk/sushivision/panel-2d.c
===================================================================
--- trunk/sushivision/panel-2d.c 2007-02-15 03:48:15 UTC (rev 12474)
+++ trunk/sushivision/panel-2d.c 2007-02-15 23:07:39 UTC (rev 12475)
@@ -344,16 +344,17 @@
for(i=0;i<ph;i++){
int yend=ynumB[i];
+
+ gdk_threads_enter ();
+ if(plot_serialno != p->private->plot_serialno ||
+ map_serialno != p->private->map_serialno)
+ goto abort;
+ spinner_set_busy(p->private->spinner);
+ gdk_threads_leave();
/* by panel col */
for(j=0;j<pw;j++){
- gdk_threads_enter ();
- if(plot_serialno != p->private->plot_serialno ||
- map_serialno != p->private->map_serialno)
- goto abort;
- gdk_threads_leave();
-
lcolor out = (lcolor){0,0,0,0};
int ydel = ydelA[i];
int y = ynumA[i];
@@ -414,13 +415,15 @@
/* non-resampling render */
for(i=0;i<ph;i++){
int *dline = data+i*dw;
+
+ gdk_threads_enter ();
+ if(plot_serialno != p->private->plot_serialno ||
+ map_serialno != p->private->map_serialno)
+ goto abort;
+ spinner_set_busy(p->private->spinner);
+ gdk_threads_leave();
for(j=0;j<pw;j++){
- gdk_threads_enter ();
- if(plot_serialno != p->private->plot_serialno ||
- map_serialno != p->private->map_serialno)
- goto abort;
- gdk_threads_leave();
lcolor out = (lcolor){0,0,0,0};
l_mapping_calc(map->mapfunc, ol_low, ol_range, dline[j], ol_alpha, 255, &out);
@@ -701,7 +704,8 @@
}
// assumes data is locked
-static void fast_scale_x(int *data,
+static void fast_scale_x(Spinner *sp,
+ int *data,
int w,
int h,
scalespace new,
@@ -737,6 +741,7 @@
for(y=0;y<h;y++){
int *data_line = data+y*w;
+ spinner_set_busy(sp);
for(x=0;x<w;x++){
if(mapbase[x]<0 || mapbase[x]>=(w-1)){
work[x]=-1;
@@ -756,7 +761,8 @@
}
}
-static void fast_scale_y(int *data,
+static void fast_scale_y(Spinner *sp,
+ int *data,
int w,
int h,
scalespace new,
@@ -794,6 +800,7 @@
for(x=0;x<w;x++){
int *data_column = data+x;
int stride = w;
+ spinner_set_busy(sp);
for(y=0;y<h;y++){
if(mapbase[y]<0 || mapbase[y]>=(h-1)){
work[y]=-1;
@@ -816,7 +823,8 @@
}
}
-static void fast_scale(int *newdata,
+static void fast_scale(Spinner *sp,
+ int *newdata,
scalespace xnew,
scalespace ynew,
int *olddata,
@@ -837,33 +845,33 @@
int *old_line = olddata+y*old_w;
memcpy(new_line,old_line,old_w*(sizeof*new_line));
}
- fast_scale_x(newdata,new_w,new_h,xnew,xold);
- fast_scale_y(newdata,new_w,new_h,ynew,yold);
+ fast_scale_x(sp,newdata,new_w,new_h,xnew,xold);
+ fast_scale_y(sp,newdata,new_w,new_h,ynew,yold);
}else{
// scale y in old pane, copy to new, scale x
- fast_scale_y(olddata,old_w,old_h,ynew,yold);
+ fast_scale_y(sp,olddata,old_w,old_h,ynew,yold);
for(y=0;y<new_h;y++){
int *new_line = newdata+y*new_w;
int *old_line = olddata+y*old_w;
memcpy(new_line,old_line,old_w*(sizeof*new_line));
}
- fast_scale_x(newdata,new_w,new_h,xnew,xold);
+ fast_scale_x(sp,newdata,new_w,new_h,xnew,xold);
}
}else{
if(new_h > old_h){
// scale x in old pane, o=copy to new, scale y
- fast_scale_x(olddata,old_w,old_h,xnew,xold);
+ fast_scale_x(sp,olddata,old_w,old_h,xnew,xold);
for(y=0;y<old_h;y++){
int *new_line = newdata+y*new_w;
int *old_line = olddata+y*old_w;
memcpy(new_line,old_line,new_w*(sizeof*new_line));
}
- fast_scale_y(newdata,new_w,new_h,ynew,yold);
+ fast_scale_y(sp,newdata,new_w,new_h,ynew,yold);
}else{
// scale in old pane, copy to new
// also the case where newdata == olddata and the size is unchanged
- fast_scale_x(olddata,old_w,old_h,xnew,xold);
- fast_scale_y(olddata,old_w,old_h,ynew,yold);
+ fast_scale_x(sp,olddata,old_w,old_h,xnew,xold);
+ fast_scale_y(sp,olddata,old_w,old_h,ynew,yold);
if(olddata != newdata){
for(y=0;y<new_h;y++){
int *new_line = newdata+y*new_w;
@@ -1151,7 +1159,7 @@
// zoom scale data in map planes as placeholder for render
if(oldmap){
- fast_scale(newmap, sx_v, sy_v,
+ fast_scale(p->private->spinner,newmap, sx_v, sy_v,
oldmap,old_xv, old_yv);
free(oldmap);
}
@@ -1460,20 +1468,29 @@
g_signal_connect_swapped (G_OBJECT (p->private->toplevel), "delete-event",
G_CALLBACK (_sushiv_clean_exit), (void *)SIGINT);
- p2->top_table = gtk_table_new(2 + p->objectives,5,0);
+ p2->top_table = gtk_table_new(3 + p->objectives,5,0);
gtk_container_add (GTK_CONTAINER (p->private->toplevel), p2->top_table);
- gtk_container_set_border_width (GTK_CONTAINER (p->private->toplevel), 5);
-
+ gtk_container_set_border_width (GTK_CONTAINER (p->private->toplevel), 1);
+
+ /* spinner, top bar */
+ {
+ GtkWidget *hbox = gtk_hbox_new(0,0);
+ gtk_table_attach(GTK_TABLE(p2->top_table),hbox,0,5,0,1,GTK_EXPAND|GTK_FILL,0,4,0);
+ gtk_box_pack_end(GTK_BOX(hbox),GTK_WIDGET(p->private->spinner),0,0,0);
+ }
+
+ /* dims */
p2->dim_table = gtk_table_new(p->dimensions,4,0);
- gtk_table_attach(GTK_TABLE(p2->top_table),p2->dim_table,0,5,1+p->objectives,2+p->objectives,
- GTK_EXPAND|GTK_FILL,0,0,5);
+ gtk_table_attach(GTK_TABLE(p2->top_table),p2->dim_table,0,5,2+p->objectives,3+p->objectives,
+ GTK_EXPAND|GTK_FILL,0,4,5);
/* graph */
p->private->graph = GTK_WIDGET(plot_new(recompute_callback_2d,p,
(void *)(void *)_sushiv_panel2d_crosshairs_callback,p,
box_callback,p,0));
- gtk_table_attach(GTK_TABLE(p2->top_table),p->private->graph,0,5,0,1,
- GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,0,5);
+ gtk_table_attach(GTK_TABLE(p2->top_table),p->private->graph,0,5,1,2,
+ GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,4,1);
+ gtk_table_set_row_spacing(GTK_TABLE(p2->top_table),1,4);
/* objective sliders */
p2->range_scales = calloc(p->objectives,sizeof(*p2->range_scales));
@@ -1489,7 +1506,7 @@
/* label */
GtkWidget *label = gtk_label_new(o->name);
gtk_misc_set_alignment(GTK_MISC(label),1.,.5);
- gtk_table_attach(GTK_TABLE(p2->top_table),label,0,1,i+1,i+2,
+ gtk_table_attach(GTK_TABLE(p2->top_table),label,0,1,i+2,i+3,
GTK_FILL,0,10,0);
/* mapping pulldown */
@@ -1501,8 +1518,8 @@
gtk_combo_box_set_active(GTK_COMBO_BOX(menu),0);
g_signal_connect (G_OBJECT (menu), "changed",
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);
+ gtk_table_attach(GTK_TABLE(p2->top_table),menu,4,5,i+2,i+3,
+ GTK_SHRINK,GTK_SHRINK,4,0);
p2->range_pulldowns[i] = menu;
}
@@ -1511,11 +1528,11 @@
sl[1] = slice_new(map_callback_2d,p->objective_list+i);
sl[2] = slice_new(map_callback_2d,p->objective_list+i);
- gtk_table_attach(GTK_TABLE(p2->top_table),sl[0],1,2,i+1,i+2,
+ gtk_table_attach(GTK_TABLE(p2->top_table),sl[0],1,2,i+2,i+3,
GTK_EXPAND|GTK_FILL,0,0,0);
- gtk_table_attach(GTK_TABLE(p2->top_table),sl[1],2,3,i+1,i+2,
+ gtk_table_attach(GTK_TABLE(p2->top_table),sl[1],2,3,i+2,i+3,
GTK_EXPAND|GTK_FILL,0,0,0);
- gtk_table_attach(GTK_TABLE(p2->top_table),sl[2],3,4,i+1,i+2,
+ gtk_table_attach(GTK_TABLE(p2->top_table),sl[2],3,4,i+2,i+3,
GTK_EXPAND|GTK_FILL,0,0,0);
p2->range_scales[i] = slider_new((Slice **)sl,3,o->scale->label_list,o->scale->val_list,
o->scale->vals,SLIDER_FLAG_INDEPENDENT_MIDDLE);
@@ -1606,6 +1623,7 @@
gtk_widget_realize(p->private->toplevel);
gtk_widget_realize(p->private->graph);
+ gtk_widget_realize(GTK_WIDGET(p->private->spinner));
gtk_widget_show_all(p->private->toplevel);
update_xy_availability(p); // yes, this was already done; however,
// gtk clobbered the event setup on the
Modified: trunk/sushivision/panel.c
===================================================================
--- trunk/sushivision/panel.c 2007-02-15 03:48:15 UTC (rev 12474)
+++ trunk/sushivision/panel.c 2007-02-15 23:07:39 UTC (rev 12475)
@@ -179,6 +179,7 @@
p->flags = flags;
p->sushi = s;
p->private = calloc(1, sizeof(*p->private));
+ p->private->spinner = spinner_new();
i=0;
while(objectives && objectives[i]>=0)i++;
Modified: trunk/sushivision/plot.c
===================================================================
--- trunk/sushivision/plot.c 2007-02-15 03:48:15 UTC (rev 12474)
+++ trunk/sushivision/plot.c 2007-02-15 23:07:39 UTC (rev 12475)
@@ -34,69 +34,6 @@
static GtkWidgetClass *parent_class = NULL;
-static void plot_draw_busy(Plot *p, cairo_t *c){
- cairo_surface_t *s = p->stage;
- int w = cairo_image_surface_get_width(s);
- int h = cairo_image_surface_get_height(s);
- int xv[8] = {-20,-13,-10,-13,-20,-27,-30,-27};
- int yv[8] = {-30,-27,-20,-13,-10,-13,-20,-27};
- int i;
- double alpha=1.;
-
- i = p->busy_count;
- do{
- double x = w+xv[i]+.5;
- double y = h+yv[i]+.5;
-
- cairo_set_source_rgba (c, 0,0,.5,1.);
- cairo_arc(c,x,y,3.5,0,M_PI*2.);
- cairo_fill(c);
-
- cairo_set_source_rgba (c, 1.,1.,1.,alpha);
- cairo_arc(c,x,y,3.5,0,M_PI*2.);
- cairo_fill(c);
-
- i--;
- alpha *=.8;
- if(i<0)i=7;
- }while(i!=p->busy_count);
-}
-
-void plot_expose_busy(Plot *p){
- cairo_surface_t *s = p->stage;
- int w = cairo_image_surface_get_width(s);
- int h = cairo_image_surface_get_height(s);
-
- plot_expose_request_partial(p,w - 40, h - 40, 40, 40);
-}
-
-void plot_set_busy(Plot *p){
- struct timeval now;
- long test;
-
- if(!p->busy){
- p->busy=1;
- plot_expose_busy(p);
- }else{
- gettimeofday(&now,NULL);
-
- test = now.tv_sec*1000 + now.tv_usec/1000;
- if(p->last_busy_throttle + 100 < test) {
- p->busy_count++;
- if(p->busy_count>7)
- p->busy_count=0;
- p->last_busy_throttle = test;
- plot_expose_busy(p);
- return;
- }
- }
-}
-
-void plot_set_idle(Plot *p){
- p->busy=0;
- plot_expose_busy(p);
-}
-
static void draw_scales_work(cairo_surface_t *s, scalespace xs, scalespace ys){
int w = cairo_image_surface_get_width(s);
int h = cairo_image_surface_get_height(s);
@@ -470,10 +407,6 @@
cairo_restore(c);
}
- // busy indicator
- if(p->busy)
- plot_draw_busy(p, c);
-
cairo_destroy(c);
// blit to window
Modified: trunk/sushivision/plot.h
===================================================================
--- trunk/sushivision/plot.h 2007-02-15 03:48:15 UTC (rev 12474)
+++ trunk/sushivision/plot.h 2007-02-15 23:07:39 UTC (rev 12475)
@@ -1,6 +1,6 @@
/*
*
- * sushivision copyright (C) 2005 Monty <monty at xiph.org>
+ * sushivision copyright (C) 2005-2007 Monty <monty at xiph.org>
*
* sushivision is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -57,9 +57,6 @@
double selx;
double sely;
int cross_active;
- int busy;
- int busy_count;
- time_t last_busy_throttle;
double box_x1;
double box_y1;
@@ -122,8 +119,5 @@
void plot_do_enter(Plot *p);
void plot_do_escape(Plot *p);
-void plot_set_busy(Plot *p);
-void plot_set_idle(Plot *p);
-
#define PLOT_NO_X_CROSS 1
#define PLOT_NO_Y_CROSS 2
Added: trunk/sushivision/spinner.c
===================================================================
--- trunk/sushivision/spinner.c 2007-02-15 03:48:15 UTC (rev 12474)
+++ trunk/sushivision/spinner.c 2007-02-15 23:07:39 UTC (rev 12475)
@@ -0,0 +1,256 @@
+/*
+ *
+ * sushivision copyright (C) 2006-2007 Monty <monty at xiph.org>
+ *
+ * sushivision is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * sushivision is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with sushivision; see the file COPYING. If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
+#include <gdk/gdk.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include "spinner.h"
+
+static GtkWidgetClass *parent_class = NULL;
+
+#define DIA 4
+#define SPA 6
+
+static void spinner_draw(GtkWidget *wg, cairo_surface_t *s,int n){
+ cairo_t *c = cairo_create(s);
+ int w = cairo_image_surface_get_width(s);
+ int h = cairo_image_surface_get_height(s);
+ int i = n;
+ double alpha = (n>=0?1.:0.);
+
+ if(n==-1)i=n=7;
+
+ GdkColor *bg = &wg->style->bg[GTK_STATE_NORMAL];
+ double shade_r=bg->red/65535.;
+ double shade_g=bg->green/65535.;
+ double shade_b=bg->blue/65535.;
+ cairo_set_source_rgb (c, shade_r,shade_g,shade_b);
+ cairo_paint(c);
+
+ do{
+ double x = w/2 - 7*SPA/2 + i*SPA +.5;
+ double y = h/2 + .5;
+
+ cairo_set_source_rgba (c, 0,0,.5,1.);
+ cairo_arc(c,x,y,DIA*.5,0,M_PI*2.);
+ cairo_fill(c);
+
+ cairo_set_source_rgba (c, 1.,1.,1.,alpha);
+ cairo_arc(c,x,y,DIA*.5,0,M_PI*2.);
+ cairo_fill(c);
+
+ i--;
+ alpha *=.8;
+ if(i<0)i=7;
+ }while(i!=n);
+}
+
+static void spinner_init (Spinner *p){
+ // instance initialization
+}
+
+static void spinner_destroy (GtkObject *object){
+ int i;
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+
+ GtkWidget *widget = GTK_WIDGET(object);
+ Spinner *p = SPINNER (widget);
+ // free local resources
+ if(p->wc){
+ cairo_destroy(p->wc);
+ p->wc=0;
+ }
+ if(p->b){
+ for(i=0;i<9;i++)
+ if(p->b[i]){
+ cairo_surface_destroy(p->b[i]);
+ p->b[i]=0;
+ }
+ }
+}
+
+static gint spinner_expose (GtkWidget *widget,
+ GdkEventExpose *event){
+ if (GTK_WIDGET_REALIZED (widget)){
+ Spinner *sp = SPINNER (widget);
+ int frame = (sp->busy?sp->busy_count+1:0);
+
+ // blit to window
+ if(sp->b && sp->b[frame]){
+ cairo_set_source_surface(sp->wc,
+ sp->b[frame],0,0);
+ cairo_paint(sp->wc);
+ gdk_flush();
+ }
+ }
+ return FALSE;
+}
+
+static void spinner_size_request (GtkWidget *widget,
+ GtkRequisition *requisition){
+ requisition->width = SPA*7 + DIA + 2;
+ requisition->height = DIA + 2;
+}
+
+static void spinner_realize (GtkWidget *widget){
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
+
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.event_mask =
+ gtk_widget_get_events (widget) |
+ GDK_EXPOSURE_MASK;
+
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ widget->window = gdk_window_new (widget->parent->window,
+ &attributes, attributes_mask);
+ gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+ gdk_window_set_user_data (widget->window, widget);
+ gtk_widget_set_double_buffered (widget, FALSE);
+}
+
+static void spinner_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation){
+ Spinner *p = SPINNER (widget);
+ int i;
+
+ if (GTK_WIDGET_REALIZED (widget)){
+
+ if(p->wc)
+ cairo_destroy(p->wc);
+
+ if(p->b){
+ for(i=0;i<9;i++)
+ if(p->b[i]){
+ cairo_surface_destroy(p->b[i]);
+ p->b[i]=0;
+ }
+ }
+
+ gdk_window_move_resize (widget->window, allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ p->wc = gdk_cairo_create(widget->window);
+
+ for(i=0;i<9;i++){
+ p->b[i] = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
+ allocation->width,
+ allocation->height);
+ spinner_draw(widget, p->b[i],i-1);
+ }
+ }
+
+ widget->allocation = *allocation;
+}
+
+static void spinner_class_init (SpinnerClass * class) {
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ object_class = (GtkObjectClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+ parent_class = gtk_type_class (GTK_TYPE_WIDGET);
+
+ object_class->destroy = spinner_destroy;
+ widget_class->realize = spinner_realize;
+ widget_class->expose_event = spinner_expose;
+ widget_class->size_request = spinner_size_request;
+ widget_class->size_allocate = spinner_size_allocate;
+
+}
+
+GType spinner_get_type (void){
+
+ static GType spinner_type = 0;
+
+ if (!spinner_type)
+ {
+ static const GTypeInfo spinner_info = {
+ sizeof (SpinnerClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) spinner_class_init,
+ NULL,
+ NULL,
+ sizeof (Spinner),
+ 0,
+ (GInstanceInitFunc) spinner_init,
+ 0
+ };
+
+ spinner_type = g_type_register_static (GTK_TYPE_WIDGET, "Spinner",
+ &spinner_info, 0);
+ }
+
+ return spinner_type;
+}
+
+Spinner *spinner_new (){
+ GtkWidget *g = GTK_WIDGET (g_object_new (SPINNER_TYPE, NULL));
+ Spinner *p = SPINNER (g);
+ return p;
+}
+
+void spinner_set_busy(Spinner *p){
+ struct timeval now;
+ long test;
+
+ if(!p)return;
+
+ if(!p->busy){
+ p->busy=1;
+ spinner_expose(GTK_WIDGET(p),NULL); // do it now
+ }else{
+ gettimeofday(&now,NULL);
+
+ test = now.tv_sec*1000 + now.tv_usec/1000;
+ if(p->last_busy_throttle + 100 < test) {
+ p->busy_count++;
+ if(p->busy_count>7)
+ p->busy_count=0;
+ p->last_busy_throttle = test;
+ spinner_expose(GTK_WIDGET(p),NULL); // do it now
+ }
+ }
+}
+
+void spinner_set_idle(Spinner *p){
+ if(!p)return;
+ p->busy=0;
+ spinner_expose(GTK_WIDGET(p),NULL); // do it now
+}
+
Added: trunk/sushivision/spinner.h
===================================================================
--- trunk/sushivision/spinner.h 2007-02-15 03:48:15 UTC (rev 12474)
+++ trunk/sushivision/spinner.h 2007-02-15 23:07:39 UTC (rev 12475)
@@ -0,0 +1,62 @@
+/*
+ *
+ * sushivision copyright (C) 2005-2007 Monty <monty at xiph.org>
+ *
+ * sushivision is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * sushivision is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with sushivision; see the file COPYING. If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+G_BEGIN_DECLS
+
+#define SPINNER_TYPE (spinner_get_type ())
+#define SPINNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPINNER_TYPE, Spinner))
+#define SPINNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPINNER_TYPE, SpinnerClass))
+#define IS_SPINNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPINNER_TYPE))
+#define IS_SPINNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPINNER_TYPE))
+
+typedef struct _Spinner Spinner;
+typedef struct _SpinnerClass SpinnerClass;
+
+struct _Spinner{
+ GtkWidget w;
+ cairo_t *wc;
+ cairo_surface_t *b[9];
+
+ int busy;
+ int busy_count;
+ time_t last_busy_throttle;
+};
+
+struct _SpinnerClass{
+ GtkWidgetClass parent_class;
+ void (*spinner) (Spinner *m);
+};
+
+GType spinner_get_type (void);
+Spinner *spinner_new (void);
+
+G_END_DECLS
+
+// the widget subclass half
+void spinner_set_busy(Spinner *p);
+void spinner_set_idle(Spinner *p);
More information about the commits
mailing list