1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include <math.h>
20 #include <stdio.h>
21 #include <gtk/gtkmain.h>
22 #include <gtk/gtksignal.h>
23 
24 #include "gtkdial.h"
25 
26 #define SCROLL_DELAY_LENGTH  300
27 #define DIAL_DEFAULT_SIZE 100
28 
29 /* Forward declarations */
30 
31 static void gtk_dial_class_init               ( GtkDialClass     *klass );
32 static void gtk_dial_init                     ( GtkDial          *dial );
33 static void gtk_dial_destroy                  ( GtkObject        *object );
34 static void gtk_dial_realize                  ( GtkWidget        *widget );
35 static void gtk_dial_size_request             ( GtkWidget        *widget,
36 		GtkRequisition   *requisition );
37 static void gtk_dial_size_allocate            ( GtkWidget        *widget,
38 		GtkAllocation    *allocation );
39 static gboolean gtk_dial_expose               ( GtkWidget        *widget,
40 		GdkEventExpose   *event );
41 static gboolean gtk_dial_button_press         ( GtkWidget        *widget,
42 		GdkEventButton   *event );
43 static gboolean gtk_dial_button_release       ( GtkWidget        *widget,
44 		GdkEventButton   *event );
45 static gboolean gtk_dial_motion_notify        ( GtkWidget        *widget,
46 		GdkEventMotion   *event );
47 static gboolean gtk_dial_timer                ( GtkDial          *dial );
48 
49 static void gtk_dial_update_mouse             ( GtkDial *dial, gint x, gint y );
50 static void gtk_dial_update                   ( GtkDial *dial );
51 static void gtk_dial_adjustment_changed       ( GtkAdjustment    *adjustment,
52 		gpointer          data );
53 static void gtk_dial_adjustment_value_changed ( GtkAdjustment    *adjustment,
54 		gpointer          data );
55 
56 /* Local data */
57 
58 static GtkWidgetClass *parent_class = NULL;
59 
60 GType
gtk_dial_get_type()61 gtk_dial_get_type ()
62 {
63 	static GType dial_type = 0;
64 
65 	if ( !dial_type )
66 	{
67 		const GTypeInfo dial_info =
68 		{
69 			sizeof ( GtkDialClass ),
70 			NULL,
71 			NULL,
72 			( GClassInitFunc ) gtk_dial_class_init,
73 			NULL,
74 			NULL,
75 			sizeof ( GtkDial ),
76 			0,
77 			( GInstanceInitFunc ) gtk_dial_init,
78 		};
79 
80 		dial_type = g_type_register_static ( GTK_TYPE_WIDGET, "GtkDial", &dial_info, 0 );
81 	}
82 
83 	return dial_type;
84 }
85 
86 static void
gtk_dial_class_init(GtkDialClass * class)87 gtk_dial_class_init ( GtkDialClass *class )
88 {
89 	GtkObjectClass *object_class;
90 	GtkWidgetClass *widget_class;
91 
92 	object_class = ( GtkObjectClass* ) class;
93 	widget_class = ( GtkWidgetClass* ) class;
94 
95 	parent_class = g_type_class_peek_parent ( class );
96 
97 	object_class->destroy = gtk_dial_destroy;
98 
99 	widget_class->realize = gtk_dial_realize;
100 	widget_class->expose_event = gtk_dial_expose;
101 	widget_class->size_request = gtk_dial_size_request;
102 	widget_class->size_allocate = gtk_dial_size_allocate;
103 	widget_class->button_press_event = gtk_dial_button_press;
104 	widget_class->button_release_event = gtk_dial_button_release;
105 	widget_class->motion_notify_event = gtk_dial_motion_notify;
106 }
107 
108 static void
gtk_dial_init(GtkDial * dial)109 gtk_dial_init ( GtkDial *dial )
110 {
111 	dial->button = 0;
112 	dial->policy = GTK_UPDATE_CONTINUOUS;
113 	dial->timer = 0;
114 	dial->radius = 0;
115 	dial->pointer_width = 0;
116 	dial->angle = 0.0;
117 	dial->old_value = 0.0;
118 	dial->old_lower = 0.0;
119 	dial->old_upper = 0.0;
120 	dial->adjustment = NULL;
121 }
122 
123 GtkWidget*
gtk_dial_new(GtkAdjustment * adjustment)124 gtk_dial_new ( GtkAdjustment *adjustment )
125 {
126 	GtkDial *dial;
127 
128 	dial = g_object_new ( gtk_dial_get_type (), NULL );
129 
130 	if ( !adjustment )
131 		adjustment = ( GtkAdjustment* ) gtk_adjustment_new ( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
132 
133 	gtk_dial_set_adjustment ( dial, adjustment );
134 
135 	return GTK_WIDGET ( dial );
136 }
137 
138 static void
gtk_dial_destroy(GtkObject * object)139 gtk_dial_destroy ( GtkObject *object )
140 {
141 	GtkDial *dial;
142 
143 	g_return_if_fail ( object != NULL );
144 	g_return_if_fail ( GTK_IS_DIAL ( object ) );
145 
146 	dial = GTK_DIAL ( object );
147 
148 	if ( dial->adjustment )
149 	{
150 		g_object_unref ( GTK_OBJECT ( dial->adjustment ) );
151 		dial->adjustment = NULL;
152 	}
153 
154 	GTK_OBJECT_CLASS ( parent_class )->destroy ( object );
155 }
156 
157 GtkAdjustment*
gtk_dial_get_adjustment(GtkDial * dial)158 gtk_dial_get_adjustment ( GtkDial *dial )
159 {
160 	g_return_val_if_fail ( dial != NULL, NULL );
161 	g_return_val_if_fail ( GTK_IS_DIAL ( dial ), NULL );
162 
163 	return dial->adjustment;
164 }
165 
gtk_dial_set_update_policy(GtkDial * dial,GtkUpdateType policy)166 void gtk_dial_set_update_policy ( GtkDial *dial, GtkUpdateType  policy )
167 {
168 	g_return_if_fail ( dial != NULL );
169 	g_return_if_fail ( GTK_IS_DIAL ( dial ) );
170 
171 	dial->policy = policy;
172 }
173 
gtk_dial_set_adjustment(GtkDial * dial,GtkAdjustment * adjustment)174 void gtk_dial_set_adjustment ( GtkDial *dial, GtkAdjustment *adjustment )
175 {
176 	g_return_if_fail ( dial != NULL );
177 	g_return_if_fail ( GTK_IS_DIAL ( dial ) );
178 
179 	if ( dial->adjustment )
180 	{
181 		g_signal_handlers_disconnect_by_func ( GTK_OBJECT ( dial->adjustment ), NULL, ( gpointer ) dial );
182 		g_object_unref ( GTK_OBJECT ( dial->adjustment ) );
183 	}
184 
185 	dial->adjustment = adjustment;
186 	g_object_ref ( GTK_OBJECT ( dial->adjustment ) );
187 
188 	g_signal_connect ( G_OBJECT ( adjustment ), "changed",
189 					   G_CALLBACK ( gtk_dial_adjustment_changed ),
190 					   ( gpointer ) dial );
191 	g_signal_connect ( G_OBJECT ( adjustment ), "value_changed",
192 					   G_CALLBACK ( gtk_dial_adjustment_value_changed ),
193 					   ( gpointer ) dial );
194 
195 	dial->old_value = adjustment->value;
196 	dial->old_lower = adjustment->lower;
197 	dial->old_upper = adjustment->upper;
198 
199 	gtk_dial_update ( dial );
200 }
201 
gtk_dial_realize(GtkWidget * widget)202 static void gtk_dial_realize ( GtkWidget *widget )
203 {
204 	GtkDial *dial;
205 	GdkWindowAttr attributes;
206 	gint attributes_mask;
207 
208 	g_return_if_fail ( widget != NULL );
209 	g_return_if_fail ( GTK_IS_DIAL ( widget ) );
210 
211 	gtk_widget_set_realized ( widget, TRUE );
212 	dial = GTK_DIAL ( widget );
213 
214 	attributes.x = widget->allocation.x;
215 	attributes.y = widget->allocation.y;
216 	attributes.width = widget->allocation.width;
217 	attributes.height = widget->allocation.height;
218 	attributes.wclass = GDK_INPUT_OUTPUT;
219 	attributes.window_type = GDK_WINDOW_CHILD;
220 	attributes.event_mask = gtk_widget_get_events ( widget ) |
221 							GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
222 							GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
223 							GDK_POINTER_MOTION_HINT_MASK;
224 	attributes.visual = gtk_widget_get_visual ( widget );
225 	attributes.colormap = gtk_widget_get_colormap ( widget );
226 
227 	attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
228 	widget->window = gdk_window_new ( widget->parent->window, &attributes, attributes_mask );
229 
230 	widget->style = gtk_style_attach ( widget->style, widget->window );
231 
232 	gdk_window_set_user_data ( widget->window, widget );
233 
234 	gtk_style_set_background ( widget->style, widget->window, GTK_STATE_ACTIVE );
235 }
236 
gtk_dial_size_request(GtkWidget * widget,GtkRequisition * requisition)237 static void gtk_dial_size_request ( GtkWidget *widget, GtkRequisition *requisition )
238 {
239 	requisition->width = DIAL_DEFAULT_SIZE;
240 	requisition->height = DIAL_DEFAULT_SIZE;
241 }
242 
gtk_dial_size_allocate(GtkWidget * widget,GtkAllocation * allocation)243 static void gtk_dial_size_allocate ( GtkWidget *widget, GtkAllocation *allocation )
244 {
245 	GtkDial *dial;
246 
247 	g_return_if_fail ( widget != NULL );
248 	g_return_if_fail ( GTK_IS_DIAL ( widget ) );
249 	g_return_if_fail ( allocation != NULL );
250 
251 	widget->allocation = *allocation;
252 	dial = GTK_DIAL ( widget );
253 
254 	if ( gtk_widget_get_realized ( widget ) )
255 	{
256 
257 		gdk_window_move_resize ( widget->window,
258 								 allocation->x, allocation->y,
259 								 allocation->width, allocation->height );
260 
261 	}
262 
263 	dial->radius = MIN ( allocation->width, allocation->height ) * 0.45;
264 	dial->pointer_width = dial->radius / 5;
265 }
266 
gtk_dial_expose(GtkWidget * widget,GdkEventExpose * event)267 static gboolean gtk_dial_expose ( GtkWidget *widget, GdkEventExpose *event )
268 {
269 	GtkDial *dial;
270 	GdkPoint points[6];
271 	gdouble s, c;
272 	gdouble theta, last, increment;
273 	GtkStyle      *blankstyle;
274 	gint xc, yc;
275 	gint upper, lower;
276 	gint tick_length;
277 	gint i, inc;
278 
279 	g_return_val_if_fail ( widget != NULL, FALSE );
280 	g_return_val_if_fail ( GTK_IS_DIAL ( widget ), FALSE );
281 	g_return_val_if_fail ( event != NULL, FALSE );
282 
283 	if ( event->count > 0 )
284 		return FALSE;
285 
286 	dial = GTK_DIAL ( widget );
287 
288 	/*  gdk_window_clear_area (widget->window,
289 				 0, 0,
290 				 widget->allocation.width,
291 				 widget->allocation.height);
292 	*/
293 	xc = widget->allocation.width / 2;
294 	yc = widget->allocation.height / 2;
295 
296 	upper = dial->adjustment->upper;
297 	lower = dial->adjustment->lower;
298 
299 	/* Erase old pointer */
300 
301 	s = sin ( dial->last_angle );
302 	c = cos ( dial->last_angle );
303 	dial->last_angle = dial->angle;
304 
305 	points[0].x = xc + s * dial->pointer_width / 2;
306 	points[0].y = yc + c * dial->pointer_width / 2;
307 	points[1].x = xc + c * dial->radius;
308 	points[1].y = yc - s * dial->radius;
309 	points[2].x = xc - s * dial->pointer_width / 2;
310 	points[2].y = yc - c * dial->pointer_width / 2;
311 	points[3].x = xc - c * dial->radius / 10;
312 	points[3].y = yc + s * dial->radius / 10;
313 	points[4].x = points[0].x;
314 	points[4].y = points[0].y;
315 
316 	blankstyle = gtk_style_new ();
317 	blankstyle->bg_gc[GTK_STATE_NORMAL] =
318 		widget->style->bg_gc[GTK_STATE_NORMAL];
319 	blankstyle->dark_gc[GTK_STATE_NORMAL] =
320 		widget->style->bg_gc[GTK_STATE_NORMAL];
321 	blankstyle->light_gc[GTK_STATE_NORMAL] =
322 		widget->style->bg_gc[GTK_STATE_NORMAL];
323 	blankstyle->black_gc =
324 		widget->style->bg_gc[GTK_STATE_NORMAL];
325 	blankstyle->depth =
326 		gdk_drawable_get_depth ( GDK_DRAWABLE ( widget->window ) );
327 
328 	gtk_paint_polygon ( blankstyle,
329 						widget->window,
330 						GTK_STATE_NORMAL,
331 						GTK_SHADOW_OUT,
332 						NULL,
333 						widget,
334 						NULL,
335 						points, 5,
336 						FALSE );
337 
338 	g_object_unref ( blankstyle );
339 
340 
341 	/* Draw ticks */
342 
343 	if ( ( upper - lower ) == 0 )
344 		return FALSE;
345 
346 	increment = ( 100 * M_PI ) / ( dial->radius * dial->radius );
347 
348 	inc = ( upper - lower );
349 
350 	while ( inc < 100 ) inc *= 10;
351 
352 	while ( inc >= 1000 ) inc /= 10;
353 
354 	last = -1;
355 
356 	for ( i = 0; i <= inc; i++ )
357 	{
358 		theta = ( ( gfloat ) i * M_PI / ( 18 * inc / 24. ) - M_PI / 6. );
359 
360 		if ( ( theta - last ) < ( increment ) )
361 			continue;
362 
363 		last = theta;
364 
365 		s = sin ( theta );
366 		c = cos ( theta );
367 
368 		tick_length = ( i % ( inc / 10 ) == 0 ) ? dial->pointer_width : dial->pointer_width / 2;
369 
370 		gdk_draw_line ( widget->window,
371 						widget->style->fg_gc[widget->state],
372 						xc + c* ( dial->radius - tick_length ),
373 						yc - s* ( dial->radius - tick_length ),
374 						xc + c * dial->radius,
375 						yc - s * dial->radius );
376 	}
377 
378 	/* Draw pointer */
379 
380 	s = sin ( dial->angle );
381 	c = cos ( dial->angle );
382 	dial->last_angle = dial->angle;
383 
384 	points[0].x = xc + s * dial->pointer_width / 2;
385 	points[0].y = yc + c * dial->pointer_width / 2;
386 	points[1].x = xc + c * dial->radius;
387 	points[1].y = yc - s * dial->radius;
388 	points[2].x = xc - s * dial->pointer_width / 2;
389 	points[2].y = yc - c * dial->pointer_width / 2;
390 	points[3].x = xc - c * dial->radius / 10;
391 	points[3].y = yc + s * dial->radius / 10;
392 	points[4].x = points[0].x;
393 	points[4].y = points[0].y;
394 
395 
396 	gtk_paint_polygon ( widget->style,
397 						widget->window,
398 						GTK_STATE_NORMAL,
399 						GTK_SHADOW_OUT,
400 						NULL,
401 						widget,
402 						NULL,
403 						points, 5,
404 						TRUE );
405 
406 	return FALSE;
407 }
408 
409 static gboolean
gtk_dial_button_press(GtkWidget * widget,GdkEventButton * event)410 gtk_dial_button_press ( GtkWidget      *widget,
411 						GdkEventButton *event )
412 {
413 	GtkDial *dial;
414 	gint dx, dy;
415 	double s, c;
416 	double d_parallel;
417 	double d_perpendicular;
418 
419 	g_return_val_if_fail ( widget != NULL, FALSE );
420 	g_return_val_if_fail ( GTK_IS_DIAL ( widget ), FALSE );
421 	g_return_val_if_fail ( event != NULL, FALSE );
422 
423 	dial = GTK_DIAL ( widget );
424 
425 	/* Determine if button press was within pointer region - we
426 	   do this by computing the parallel and perpendicular distance of
427 	   the point where the mouse was pressed from the line passing through
428 	   the pointer */
429 
430 	dx = event->x - widget->allocation.width / 2;
431 	dy = widget->allocation.height / 2 - event->y;
432 
433 	s = sin ( dial->angle );
434 	c = cos ( dial->angle );
435 
436 	d_parallel = s * dy + c * dx;
437 	d_perpendicular = fabs ( s * dx - c * dy );
438 
439 	if ( !dial->button &&
440 			( d_perpendicular < dial->pointer_width / 2 ) &&
441 			( d_parallel > - dial->pointer_width ) )
442 	{
443 		gtk_grab_add ( widget );
444 
445 		dial->button = event->button;
446 
447 		gtk_dial_update_mouse ( dial, event->x, event->y );
448 	}
449 
450 	return FALSE;
451 }
452 
453 static gboolean
gtk_dial_button_release(GtkWidget * widget,GdkEventButton * event)454 gtk_dial_button_release ( GtkWidget      *widget,
455 						  GdkEventButton *event )
456 {
457 	GtkDial *dial;
458 
459 	g_return_val_if_fail ( widget != NULL, FALSE );
460 	g_return_val_if_fail ( GTK_IS_DIAL ( widget ), FALSE );
461 	g_return_val_if_fail ( event != NULL, FALSE );
462 
463 	dial = GTK_DIAL ( widget );
464 
465 	if ( dial->button == event->button )
466 	{
467 		gtk_grab_remove ( widget );
468 
469 		dial->button = 0;
470 
471 		if ( dial->policy == GTK_UPDATE_DELAYED )
472 			g_source_remove ( dial->timer );
473 
474 		if ( ( dial->policy != GTK_UPDATE_CONTINUOUS ) &&
475 				( dial->old_value != dial->adjustment->value ) )
476 			g_signal_emit_by_name ( GTK_OBJECT ( dial->adjustment ), "value_changed" );
477 	}
478 
479 	return FALSE;
480 }
481 
482 static gboolean
gtk_dial_motion_notify(GtkWidget * widget,GdkEventMotion * event)483 gtk_dial_motion_notify ( GtkWidget      *widget,
484 						 GdkEventMotion *event )
485 {
486 	GtkDial *dial;
487 	GdkModifierType mods;
488 	gint x, y, mask;
489 
490 	g_return_val_if_fail ( widget != NULL, FALSE );
491 	g_return_val_if_fail ( GTK_IS_DIAL ( widget ), FALSE );
492 	g_return_val_if_fail ( event != NULL, FALSE );
493 
494 	dial = GTK_DIAL ( widget );
495 
496 	if ( dial->button != 0 )
497 	{
498 		x = event->x;
499 		y = event->y;
500 
501 		if ( event->is_hint || ( event->window != widget->window ) )
502 			gdk_window_get_pointer ( widget->window, &x, &y, &mods );
503 
504 		switch ( dial->button )
505 		{
506 			case 1:
507 				mask = GDK_BUTTON1_MASK;
508 				break;
509 			case 2:
510 				mask = GDK_BUTTON2_MASK;
511 				break;
512 			case 3:
513 				mask = GDK_BUTTON3_MASK;
514 				break;
515 			default:
516 				mask = 0;
517 				break;
518 		}
519 
520 		if ( mods & mask )
521 			gtk_dial_update_mouse ( dial, x, y );
522 	}
523 
524 	return FALSE;
525 }
526 
527 static gboolean
gtk_dial_timer(GtkDial * dial)528 gtk_dial_timer ( GtkDial *dial )
529 {
530 	g_return_val_if_fail ( dial != NULL, FALSE );
531 	g_return_val_if_fail ( GTK_IS_DIAL ( dial ), FALSE );
532 
533 	if ( dial->policy == GTK_UPDATE_DELAYED )
534 		g_signal_emit_by_name ( GTK_OBJECT ( dial->adjustment ), "value_changed" );
535 
536 	return FALSE;
537 }
538 
539 static void
gtk_dial_update_mouse(GtkDial * dial,gint x,gint y)540 gtk_dial_update_mouse ( GtkDial *dial, gint x, gint y )
541 {
542 	gint xc, yc;
543 	gfloat old_value;
544 
545 	g_return_if_fail ( dial != NULL );
546 	g_return_if_fail ( GTK_IS_DIAL ( dial ) );
547 
548 	xc = GTK_WIDGET ( dial )->allocation.width / 2;
549 	yc = GTK_WIDGET ( dial )->allocation.height / 2;
550 
551 	old_value = dial->adjustment->value;
552 	dial->angle = atan2 ( yc - y, x - xc );
553 
554 	if ( dial->angle < -M_PI / 2. )
555 		dial->angle += 2 * M_PI;
556 
557 	if ( dial->angle < -M_PI / 6 )
558 		dial->angle = -M_PI / 6;
559 
560 	if ( dial->angle > 7.*M_PI / 6. )
561 		dial->angle = 7.*M_PI / 6.;
562 
563 	dial->adjustment->value = dial->adjustment->lower + ( 7.*M_PI / 6 - dial->angle ) *
564 							  ( dial->adjustment->upper - dial->adjustment->lower ) / ( 4.*M_PI / 3. );
565 
566 	if ( dial->adjustment->value != old_value )
567 	{
568 		if ( dial->policy == GTK_UPDATE_CONTINUOUS )
569 		{
570 			g_signal_emit_by_name ( GTK_OBJECT ( dial->adjustment ), "value_changed" );
571 		}
572 
573 		else
574 		{
575 			gtk_widget_queue_draw ( GTK_WIDGET ( dial ) );
576 
577 			if ( dial->policy == GTK_UPDATE_DELAYED )
578 			{
579 				if ( dial->timer )
580 					g_source_remove ( dial->timer );
581 
582 				dial->timer = gdk_threads_add_timeout ( SCROLL_DELAY_LENGTH,
583 														( GSourceFunc ) gtk_dial_timer,
584 														( gpointer ) dial );
585 			}
586 		}
587 	}
588 }
589 
590 static void
gtk_dial_update(GtkDial * dial)591 gtk_dial_update ( GtkDial *dial )
592 {
593 	gfloat new_value;
594 
595 	g_return_if_fail ( dial != NULL );
596 	g_return_if_fail ( GTK_IS_DIAL ( dial ) );
597 
598 	new_value = dial->adjustment->value;
599 
600 	if ( new_value < dial->adjustment->lower )
601 		new_value = dial->adjustment->lower;
602 
603 	if ( new_value > dial->adjustment->upper )
604 		new_value = dial->adjustment->upper;
605 
606 	if ( new_value != dial->adjustment->value )
607 	{
608 		dial->adjustment->value = new_value;
609 		g_signal_emit_by_name ( GTK_OBJECT ( dial->adjustment ), "value_changed" );
610 	}
611 
612 	dial->angle = 7.*M_PI / 6. - ( new_value - dial->adjustment->lower ) * 4.*M_PI / 3. /
613 				  ( dial->adjustment->upper - dial->adjustment->lower );
614 
615 	gtk_widget_queue_draw ( GTK_WIDGET ( dial ) );
616 }
617 
618 static void
gtk_dial_adjustment_changed(GtkAdjustment * adjustment,gpointer data)619 gtk_dial_adjustment_changed ( GtkAdjustment *adjustment,
620 							  gpointer       data )
621 {
622 	GtkDial *dial;
623 
624 	g_return_if_fail ( adjustment != NULL );
625 	g_return_if_fail ( data != NULL );
626 
627 	dial = GTK_DIAL ( data );
628 
629 	if ( ( dial->old_value != adjustment->value ) ||
630 			( dial->old_lower != adjustment->lower ) ||
631 			( dial->old_upper != adjustment->upper ) )
632 	{
633 		gtk_dial_update ( dial );
634 
635 		dial->old_value = adjustment->value;
636 		dial->old_lower = adjustment->lower;
637 		dial->old_upper = adjustment->upper;
638 	}
639 }
640 
641 static void
gtk_dial_adjustment_value_changed(GtkAdjustment * adjustment,gpointer data)642 gtk_dial_adjustment_value_changed ( GtkAdjustment *adjustment,
643 									gpointer       data )
644 {
645 	GtkDial *dial;
646 
647 	g_return_if_fail ( adjustment != NULL );
648 	g_return_if_fail ( data != NULL );
649 
650 	dial = GTK_DIAL ( data );
651 
652 	if ( dial->old_value != adjustment->value )
653 	{
654 		gtk_dial_update ( dial );
655 
656 		dial->old_value = adjustment->value;
657 	}
658 }
659