Make mv's use signed chars explicitly.
[xiph/unicode.git] / sushivision / spinner.c
blob6a15b3993acb38e6fce2a0f33435d243a0d95446
1 /*
3 * sushivision copyright (C) 2006-2007 Monty <monty@xiph.org>
5 * sushivision is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * sushivision is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with sushivision; see the file COPYING. If not, write to the
17 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define _GNU_SOURCE
23 #include <gtk/gtk.h>
24 #include <gtk/gtkmain.h>
25 #include <gdk/gdk.h>
26 #include <stdlib.h>
27 #include <math.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include "spinner.h"
32 static GtkWidgetClass *parent_class = NULL;
34 #define DIA 4
35 #define SPA 6
37 static void _sv_spinner_draw(GtkWidget *wg, cairo_surface_t *s,int n){
38 cairo_t *c = cairo_create(s);
39 int w = cairo_image_surface_get_width(s);
40 int h = cairo_image_surface_get_height(s);
41 int i = n;
42 double alpha = (n>=0?1.:0.);
44 if(n==-1)i=n=7;
46 GdkColor *bg = &wg->style->bg[GTK_STATE_NORMAL];
47 double shade_r=bg->red/65535.;
48 double shade_g=bg->green/65535.;
49 double shade_b=bg->blue/65535.;
50 cairo_set_source_rgb (c, shade_r,shade_g,shade_b);
51 cairo_paint(c);
53 do{
54 double x = w/2 - 7*SPA/2 + i*SPA +.5;
55 double y = h/2 + .5;
57 cairo_set_source_rgba (c, 0,0,.5,1.);
58 cairo_arc(c,x,y,DIA*.5,0,M_PI*2.);
59 cairo_fill(c);
61 cairo_set_source_rgba (c, 1.,1.,1.,alpha);
62 cairo_arc(c,x,y,DIA*.5,0,M_PI*2.);
63 cairo_fill(c);
65 i--;
66 alpha *=.8;
67 if(i<0)i=7;
68 }while(i!=n);
71 static void _sv_spinner_init (_sv_spinner_t *p){
72 // instance initialization
75 static void _sv_spinner_destroy (GtkObject *object){
76 int i;
77 if (GTK_OBJECT_CLASS (parent_class)->destroy)
78 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
80 GtkWidget *widget = GTK_WIDGET(object);
81 _sv_spinner_t *p = SPINNER (widget);
82 // free local resources
83 if(p->wc){
84 cairo_destroy(p->wc);
85 p->wc=0;
87 if(p->b){
88 for(i=0;i<9;i++)
89 if(p->b[i]){
90 cairo_surface_destroy(p->b[i]);
91 p->b[i]=0;
96 static gint _sv_spinner_expose (GtkWidget *widget,
97 GdkEventExpose *event){
98 if (GTK_WIDGET_REALIZED (widget)){
99 _sv_spinner_t *sp = SPINNER (widget);
100 int frame = (sp->busy?sp->busy_count+1:0);
102 // blit to window
103 if(sp->b && sp->b[frame]){
104 cairo_set_source_surface(sp->wc,
105 sp->b[frame],0,0);
106 cairo_paint(sp->wc);
107 gdk_flush();
110 return FALSE;
113 static void _sv_spinner_size_request (GtkWidget *widget,
114 GtkRequisition *requisition){
115 requisition->width = SPA*7 + DIA + 2;
116 requisition->height = DIA + 2;
119 static void _sv_spinner_realize (GtkWidget *widget){
120 GdkWindowAttr attributes;
121 gint attributes_mask;
123 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
124 GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
126 attributes.x = widget->allocation.x;
127 attributes.y = widget->allocation.y;
128 attributes.width = widget->allocation.width;
129 attributes.height = widget->allocation.height;
130 attributes.wclass = GDK_INPUT_OUTPUT;
131 attributes.window_type = GDK_WINDOW_CHILD;
132 attributes.event_mask =
133 gtk_widget_get_events (widget) |
134 GDK_EXPOSURE_MASK;
136 attributes.visual = gtk_widget_get_visual (widget);
137 attributes.colormap = gtk_widget_get_colormap (widget);
138 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
139 widget->window = gdk_window_new (widget->parent->window,
140 &attributes, attributes_mask);
141 gtk_style_attach (widget->style, widget->window);
142 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
143 gdk_window_set_user_data (widget->window, widget);
144 gtk_widget_set_double_buffered (widget, FALSE);
147 static void _sv_spinner_size_allocate (GtkWidget *widget,
148 GtkAllocation *allocation){
149 _sv_spinner_t *p = SPINNER (widget);
150 int i;
152 if (GTK_WIDGET_REALIZED (widget)){
154 if(p->wc)
155 cairo_destroy(p->wc);
157 if(p->b){
158 for(i=0;i<9;i++)
159 if(p->b[i]){
160 cairo_surface_destroy(p->b[i]);
161 p->b[i]=0;
165 gdk_window_move_resize (widget->window, allocation->x, allocation->y,
166 allocation->width, allocation->height);
168 p->wc = gdk_cairo_create(widget->window);
170 for(i=0;i<9;i++){
171 p->b[i] = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
172 allocation->width,
173 allocation->height);
174 _sv_spinner_draw(widget, p->b[i],i-1);
178 widget->allocation = *allocation;
181 static void _sv_spinner_class_init (_sv_spinner_class_t * class) {
182 GtkObjectClass *object_class;
183 GtkWidgetClass *widget_class;
184 object_class = (GtkObjectClass *) class;
185 widget_class = (GtkWidgetClass *) class;
186 parent_class = gtk_type_class (GTK_TYPE_WIDGET);
188 object_class->destroy = _sv_spinner_destroy;
189 widget_class->realize = _sv_spinner_realize;
190 widget_class->expose_event = _sv_spinner_expose;
191 widget_class->size_request = _sv_spinner_size_request;
192 widget_class->size_allocate = _sv_spinner_size_allocate;
196 GType _sv_spinner_get_type (void){
198 static GType spinner_type = 0;
200 if (!spinner_type)
202 static const GTypeInfo spinner_info = {
203 sizeof (_sv_spinner_class_t),
204 NULL,
205 NULL,
206 (GClassInitFunc) _sv_spinner_class_init,
207 NULL,
208 NULL,
209 sizeof (_sv_spinner_t),
211 (GInstanceInitFunc) _sv_spinner_init,
215 spinner_type = g_type_register_static (GTK_TYPE_WIDGET, "Spinner",
216 &spinner_info, 0);
219 return spinner_type;
222 _sv_spinner_t *_sv_spinner_new (){
223 GtkWidget *g = GTK_WIDGET (g_object_new (SPINNER_TYPE, NULL));
224 _sv_spinner_t *p = SPINNER (g);
225 return p;
228 void _sv_spinner_set_busy(_sv_spinner_t *p){
229 struct timeval now;
230 int test;
232 if(!p)return;
234 gettimeofday(&now,NULL);
236 if(!p->busy){
237 p->busy=1;
238 p->last = now;
239 _sv_spinner_expose(GTK_WIDGET(p),NULL); // do it now
240 }else{
242 test = (now.tv_sec - p->last.tv_sec)*1000 + (now.tv_usec - p->last.tv_usec)/1000;
243 if(test>100) {
245 p->busy_count++;
247 if(p->busy_count>7)
248 p->busy_count=0;
249 p->last = now;
250 _sv_spinner_expose(GTK_WIDGET(p),NULL); // do it now
255 void _sv_spinner_set_idle(_sv_spinner_t *p){
256 if(!p)return;
257 p->busy=0;
258 _sv_spinner_expose(GTK_WIDGET(p),NULL); // do it now