1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2019 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GSequencer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "ags_dial.h"
21
22 #include <atk/atk.h>
23
24 #include <gdk/gdkkeysyms.h>
25
26 #include <stdlib.h>
27 #include <math.h>
28
29 static GType ags_accessible_dial_get_type(void);
30 void ags_dial_class_init(AgsDialClass *dial);
31 void ags_accessible_dial_class_init(AtkObject *object);
32 void ags_accessible_dial_value_interface_init(AtkValueIface *value);
33 void ags_accessible_dial_action_interface_init(AtkActionIface *action);
34 void ags_dial_init(AgsDial *dial);
35 void ags_dial_set_property(GObject *gobject,
36 guint prop_id,
37 const GValue *value,
38 GParamSpec *param_spec);
39 void ags_dial_get_property(GObject *gobject,
40 guint prop_id,
41 GValue *value,
42 GParamSpec *param_spec);
43 AtkObject* ags_dial_get_accessible(GtkWidget *widget);
44 void ags_dial_show(GtkWidget *widget);
45
46 void ags_accessible_dial_get_value_and_text(AtkValue *value,
47 gdouble *current_value,
48 gchar **text);
49 #ifdef HAVE_ATK_2_12
50 AtkRange* ags_accessible_dial_get_range(AtkValue *value);
51 #endif
52 gdouble ags_accessible_dial_get_increment(AtkValue *value);
53 void ags_accessible_dial_set_value(AtkValue *value,
54 gdouble new_value);
55
56 gboolean ags_accessible_dial_do_action(AtkAction *action,
57 gint i);
58 gint ags_accessible_dial_get_n_actions(AtkAction *action);
59 const gchar* ags_accessible_dial_get_description(AtkAction *action,
60 gint i);
61 const gchar* ags_accessible_dial_get_name(AtkAction *action,
62 gint i);
63 const gchar* ags_accessible_dial_get_keybinding(AtkAction *action,
64 gint i);
65 gboolean ags_accessible_dial_set_description(AtkAction *action,
66 gint i);
67 gchar* ags_accessible_dial_get_localized_name(AtkAction *action,
68 gint i);
69
70 void ags_dial_map(GtkWidget *widget);
71 void ags_dial_realize(GtkWidget *widget);
72 void ags_dial_get_preferred_width(GtkWidget *widget,
73 gint *minimal_width,
74 gint *natural_width);
75 void ags_dial_get_preferred_height(GtkWidget *widget,
76 gint *minimal_height,
77 gint *natural_height);
78 void ags_dial_size_allocate(GtkWidget *widget,
79 GtkAllocation *allocation);
80 gboolean ags_dial_button_press(GtkWidget *widget,
81 GdkEventButton *event);
82 gboolean ags_dial_button_release(GtkWidget *widget,
83 GdkEventButton *event);
84 gboolean ags_dial_key_press(GtkWidget *widget,
85 GdkEventKey *event);
86 gboolean ags_dial_key_release(GtkWidget *widget,
87 GdkEventKey *event);
88 gboolean ags_dial_motion_notify(GtkWidget *widget,
89 GdkEventMotion *event);
90
91 void ags_dial_send_configure(AgsDial *dial);
92
93 gboolean ags_dial_draw(AgsDial *dial, cairo_t *cr);
94
95 void ags_dial_adjustment_changed_callback(GtkAdjustment *adjustment,
96 AgsDial *dial);
97
98 gboolean ags_dial_button_press_is_down_event(AgsDial *dial,
99 GdkEventButton *event,
100 gint padding_left, guint padding_top);
101 gboolean ags_dial_button_press_is_up_event(AgsDial *dial,
102 GdkEventButton *event,
103 gint padding_left, guint padding_top);
104 gboolean ags_dial_button_press_is_dial_event(AgsDial *dial,
105 GdkEventButton *event,
106 gint padding_left, guint padding_top,
107 gint dial_left_position);
108
109 void ags_dial_motion_notify_do_dial(AgsDial *dial,
110 GdkEventMotion *event);
111 void ags_dial_motion_notify_do_seemless_dial(AgsDial *dial,
112 GdkEventMotion *event);
113
114 /**
115 * SECTION:ags_dial
116 * @short_description: A dial widget
117 * @title: AgsDial
118 * @section_id:
119 * @include: ags/widget/ags_dial.h
120 *
121 * #AgsDial is a widget representing a #GtkAdjustment.
122 */
123
124 enum{
125 VALUE_CHANGED,
126 LAST_SIGNAL,
127 };
128
129 enum{
130 PROP_0,
131 PROP_RADIUS,
132 PROP_OUTLINE_STRENGTH,
133 PROP_FONT_SIZE,
134 PROP_BUTTON_WIDTH,
135 PROP_BUTTON_HEIGHT,
136 PROP_MARGIN_LEFT,
137 PROP_MARGIN_RIGHT,
138 PROP_ADJUSTMENT,
139 PROP_SCALE_PRECISION,
140 };
141
142 static gpointer ags_dial_parent_class = NULL;
143 static guint dial_signals[LAST_SIGNAL];
144
145 static GQuark quark_accessible_object = 0;
146
147 GType
ags_dial_get_type(void)148 ags_dial_get_type(void)
149 {
150 static volatile gsize g_define_type_id__volatile = 0;
151
152 if(g_once_init_enter (&g_define_type_id__volatile)){
153 GType ags_type_dial = 0;
154
155 static const GTypeInfo ags_dial_info = {
156 sizeof(AgsDialClass),
157 NULL, /* base_init */
158 NULL, /* base_finalize */
159 (GClassInitFunc) ags_dial_class_init,
160 NULL, /* class_finalize */
161 NULL, /* class_data */
162 sizeof(AgsDial),
163 0, /* n_preallocs */
164 (GInstanceInitFunc) ags_dial_init,
165 };
166
167 ags_type_dial = g_type_register_static(GTK_TYPE_WIDGET,
168 "AgsDial", &ags_dial_info,
169 0);
170
171 g_once_init_leave(&g_define_type_id__volatile, ags_type_dial);
172 }
173
174 return g_define_type_id__volatile;
175 }
176
177 static GType
ags_accessible_dial_get_type(void)178 ags_accessible_dial_get_type(void)
179 {
180 static GType ags_type_accessible_dial = 0;
181
182 if(!ags_type_accessible_dial){
183 const GTypeInfo ags_accesssible_dial_info = {
184 sizeof(GtkAccessibleClass),
185 NULL, /* base_init */
186 NULL, /* base_finalize */
187 (GClassInitFunc) ags_accessible_dial_class_init,
188 NULL, /* class_finalize */
189 NULL, /* class_data */
190 sizeof(GtkAccessible),
191 0, /* n_preallocs */
192 NULL, NULL
193 };
194
195 static const GInterfaceInfo atk_value_interface_info = {
196 (GInterfaceInitFunc) ags_accessible_dial_value_interface_init,
197 NULL, /* interface_finalize */
198 NULL, /* interface_data */
199 };
200
201 static const GInterfaceInfo atk_action_interface_info = {
202 (GInterfaceInitFunc) ags_accessible_dial_action_interface_init,
203 NULL, /* interface_finalize */
204 NULL, /* interface_data */
205 };
206
207 ags_type_accessible_dial = g_type_register_static(GTK_TYPE_ACCESSIBLE,
208 "AgsAccessibleDial", &ags_accesssible_dial_info,
209 0);
210
211 g_type_add_interface_static(ags_type_accessible_dial,
212 ATK_TYPE_VALUE,
213 &atk_value_interface_info);
214
215 g_type_add_interface_static(ags_type_accessible_dial,
216 ATK_TYPE_ACTION,
217 &atk_action_interface_info);
218 }
219
220 return(ags_type_accessible_dial);
221 }
222
223 void
ags_dial_class_init(AgsDialClass * dial)224 ags_dial_class_init(AgsDialClass *dial)
225 {
226 GObjectClass *gobject;
227 GtkWidgetClass *widget;
228 GParamSpec *param_spec;
229
230 ags_dial_parent_class = g_type_class_peek_parent(dial);
231
232 quark_accessible_object = g_quark_from_static_string("ags-accessible-object");
233
234 /* GObjectClass */
235 gobject = (GObjectClass *) dial;
236
237 gobject->set_property = ags_dial_set_property;
238 gobject->get_property = ags_dial_get_property;
239
240 /* properties */
241 /**
242 * AgsDial:radius:
243 *
244 * The radius of the knob.
245 *
246 * Since: 3.0.0
247 */
248 param_spec = g_param_spec_uint("radius",
249 "radius",
250 "The knob's radius",
251 0,
252 G_MAXUINT,
253 AGS_DIAL_DEFAULT_RADIUS,
254 G_PARAM_READABLE | G_PARAM_WRITABLE);
255 g_object_class_install_property(gobject,
256 PROP_RADIUS,
257 param_spec);
258
259 /**
260 * AgsDial:outline-strength:
261 *
262 * The outline strength of the knob.
263 *
264 * Since: 3.0.0
265 */
266 param_spec = g_param_spec_uint("outline-strength",
267 "outline strength",
268 "The knob's outline strength",
269 0,
270 G_MAXUINT,
271 AGS_DIAL_DEFAULT_OUTLINE_STRENGTH,
272 G_PARAM_READABLE | G_PARAM_WRITABLE);
273 g_object_class_install_property(gobject,
274 PROP_OUTLINE_STRENGTH,
275 param_spec);
276
277 /**
278 * AgsDial:font-size:
279 *
280 * The font size of the buttons.
281 *
282 * Since: 3.0.0
283 */
284 param_spec = g_param_spec_uint("font-size",
285 "font size",
286 "The buttons font-size",
287 0,
288 G_MAXUINT,
289 AGS_DIAL_DEFAULT_FONT_SIZE,
290 G_PARAM_READABLE | G_PARAM_WRITABLE);
291 g_object_class_install_property(gobject,
292 PROP_FONT_SIZE,
293 param_spec);
294
295 /**
296 * AgsDial:button-width:
297 *
298 * The buttons width.
299 *
300 * Since: 3.0.0
301 */
302 param_spec = g_param_spec_int("button-width",
303 "buttons width",
304 "The buttons width",
305 -1,
306 G_MAXINT,
307 AGS_DIAL_DEFAULT_BUTTON_WIDTH,
308 G_PARAM_READABLE | G_PARAM_WRITABLE);
309 g_object_class_install_property(gobject,
310 PROP_BUTTON_WIDTH,
311 param_spec);
312
313 /**
314 * AgsDial:button-height:
315 *
316 * The buttons height.
317 *
318 * Since: 3.0.0
319 */
320 param_spec = g_param_spec_int("button-height",
321 "buttons height",
322 "The buttons height",
323 -1,
324 G_MAXINT,
325 AGS_DIAL_DEFAULT_BUTTON_HEIGHT,
326 G_PARAM_READABLE | G_PARAM_WRITABLE);
327 g_object_class_install_property(gobject,
328 PROP_BUTTON_HEIGHT,
329 param_spec);
330
331
332 /**
333 * AgsDial:margin-left:
334 *
335 * The button's margin left.
336 *
337 * Since: 3.0.0
338 */
339 param_spec = g_param_spec_int("margin-left",
340 "button's margin left",
341 "The button's margin left",
342 -1,
343 G_MAXINT,
344 AGS_DIAL_DEFAULT_MARGIN_LEFT,
345 G_PARAM_READABLE | G_PARAM_WRITABLE);
346 g_object_class_install_property(gobject,
347 PROP_MARGIN_LEFT,
348 param_spec);
349
350 /**
351 * AgsDial:margin-right:
352 *
353 * The button's margin right.
354 *
355 * Since: 3.0.0
356 */
357 param_spec = g_param_spec_int("margin-right",
358 "button's margin right",
359 "The button's margin right",
360 -1,
361 G_MAXINT,
362 AGS_DIAL_DEFAULT_MARGIN_RIGHT,
363 G_PARAM_READABLE | G_PARAM_WRITABLE);
364 g_object_class_install_property(gobject,
365 PROP_MARGIN_RIGHT,
366 param_spec);
367
368 /**
369 * AgsDial:adjustment:
370 *
371 * The adjustment storing current value and boundaries.
372 *
373 * Since: 3.0.0
374 */
375 param_spec = g_param_spec_object("adjustment",
376 "assigned adjustment",
377 "The adjustment it is assigned with",
378 G_TYPE_OBJECT,
379 G_PARAM_READABLE | G_PARAM_WRITABLE);
380 g_object_class_install_property(gobject,
381 PROP_ADJUSTMENT,
382 param_spec);
383
384 /**
385 * AgsDial:scale-precision:
386 *
387 * The precision of the scale.
388 *
389 * Since: 3.0.0
390 */
391 param_spec = g_param_spec_uint("scale-precision",
392 "scale precision",
393 "The precision of the scale",
394 0,
395 G_MAXUINT,
396 AGS_DIAL_DEFAULT_PRECISION,
397 G_PARAM_READABLE | G_PARAM_WRITABLE);
398 g_object_class_install_property(gobject,
399 PROP_SCALE_PRECISION,
400 param_spec);
401
402 /* GtkWidgetClass */
403 widget = (GtkWidgetClass *) dial;
404
405 widget->get_accessible = ags_dial_get_accessible;
406 // widget->map = ags_dial_map;
407 widget->realize = ags_dial_realize;
408 widget->size_allocate = ags_dial_size_allocate;
409 widget->get_preferred_width = ags_dial_get_preferred_width;
410 widget->get_preferred_height = ags_dial_get_preferred_height;
411 widget->button_press_event = ags_dial_button_press;
412 widget->button_release_event = ags_dial_button_release;
413 widget->key_press_event = ags_dial_key_press;
414 widget->key_release_event = ags_dial_key_release;
415 widget->motion_notify_event = ags_dial_motion_notify;
416 widget->show = ags_dial_show;
417 widget->draw = ags_dial_draw;
418
419 /* AgsDialClass */
420 dial->value_changed = NULL;
421
422 /* signals */
423 /**
424 * AgsDial::value-changed:
425 * @dial: the #AgsDial
426 *
427 * The ::value-changed signal notifies adjustment value changed.
428 *
429 * Since: 3.0.0
430 */
431 dial_signals[VALUE_CHANGED] =
432 g_signal_new("value-changed",
433 G_TYPE_FROM_CLASS(dial),
434 G_SIGNAL_RUN_LAST,
435 G_STRUCT_OFFSET(AgsDialClass, value_changed),
436 NULL, NULL,
437 g_cclosure_marshal_VOID__VOID,
438 G_TYPE_NONE, 0);
439 }
440
441 void
ags_accessible_dial_class_init(AtkObject * object)442 ags_accessible_dial_class_init(AtkObject *object)
443 {
444 /* empty */
445 }
446
447 void
ags_accessible_dial_value_interface_init(AtkValueIface * value)448 ags_accessible_dial_value_interface_init(AtkValueIface *value)
449 {
450 value->get_current_value = NULL;
451 value->get_maximum_value = NULL;
452 value->get_minimum_value = NULL;
453 value->set_current_value = NULL;
454 value->get_minimum_increment = NULL;
455
456 #ifdef HAVE_ATK_2_12
457 value->get_value_and_text = ags_accessible_dial_get_value_and_text;
458 value->get_range = ags_accessible_dial_get_range;
459 value->get_increment = ags_accessible_dial_get_increment;
460 value->get_sub_ranges = NULL;
461 value->set_value = ags_accessible_dial_set_value;
462 #endif
463 }
464
465 void
ags_accessible_dial_action_interface_init(AtkActionIface * action)466 ags_accessible_dial_action_interface_init(AtkActionIface *action)
467 {
468 action->do_action = ags_accessible_dial_do_action;
469 action->get_n_actions = ags_accessible_dial_get_n_actions;
470 action->get_description = ags_accessible_dial_get_description;
471 action->get_name = ags_accessible_dial_get_name;
472 action->get_keybinding = ags_accessible_dial_get_keybinding;
473 action->set_description = ags_accessible_dial_set_description;
474 action->get_localized_name = ags_accessible_dial_get_localized_name;
475 }
476
477 void
ags_dial_init(AgsDial * dial)478 ags_dial_init(AgsDial *dial)
479 {
480 AtkObject *accessible;
481
482 gtk_widget_set_can_focus((GtkWidget *) dial,
483 TRUE);
484
485 accessible = gtk_widget_get_accessible((GtkWidget *) dial);
486
487 g_object_set(accessible,
488 "accessible-name", "dial",
489 "accessible-description", "Adjust a value",
490 NULL);
491
492 g_object_set(G_OBJECT(dial),
493 "app-paintable", TRUE,
494 "can-focus", TRUE,
495 NULL);
496
497 dial->flags = (AGS_DIAL_WITH_BUTTONS |
498 AGS_DIAL_SEEMLESS_MODE |
499 AGS_DIAL_INVERSE_LIGHT);
500
501 dial->radius = AGS_DIAL_DEFAULT_RADIUS;
502 dial->scale_precision = AGS_DIAL_DEFAULT_PRECISION;
503 dial->scale_max_precision = AGS_DIAL_DEFAULT_PRECISION;
504 dial->outline_strength = AGS_DIAL_DEFAULT_OUTLINE_STRENGTH;
505
506 dial->font_size = AGS_DIAL_DEFAULT_FONT_SIZE;
507 dial->button_width = AGS_DIAL_DEFAULT_BUTTON_WIDTH;
508 dial->button_height = AGS_DIAL_DEFAULT_BUTTON_HEIGHT;
509 dial->margin_left = AGS_DIAL_DEFAULT_MARGIN_LEFT;
510 dial->margin_right = AGS_DIAL_DEFAULT_MARGIN_RIGHT;
511
512 dial->tolerance = 0.9;
513 dial->negated_tolerance = 1.1;
514
515 dial->adjustment = NULL;
516
517 dial->gravity_x = 0.0;
518 dial->gravity_y = 0.0;
519 dial->current_x = 0.0;
520 dial->current_y = 0.0;
521 }
522
523 void
ags_dial_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)524 ags_dial_set_property(GObject *gobject,
525 guint prop_id,
526 const GValue *value,
527 GParamSpec *param_spec)
528 {
529 AgsDial *dial;
530
531 dial = AGS_DIAL(gobject);
532
533 switch(prop_id){
534 case PROP_RADIUS:
535 {
536 dial->radius = g_value_get_uint(value);
537 }
538 break;
539 case PROP_OUTLINE_STRENGTH:
540 {
541 dial->outline_strength = g_value_get_uint(value);
542 }
543 break;
544 case PROP_FONT_SIZE:
545 {
546 dial->font_size = g_value_get_uint(value);
547 }
548 break;
549 case PROP_BUTTON_WIDTH:
550 {
551 dial->button_width = g_value_get_int(value);
552 }
553 break;
554 case PROP_BUTTON_HEIGHT:
555 {
556 dial->button_height = g_value_get_int(value);
557 }
558 break;
559 case PROP_MARGIN_LEFT:
560 {
561 dial->margin_left = g_value_get_int(value);
562 }
563 break;
564 case PROP_MARGIN_RIGHT:
565 {
566 dial->margin_right = g_value_get_int(value);
567 }
568 break;
569 case PROP_ADJUSTMENT:
570 {
571 GtkAdjustment *adjustment;
572
573 adjustment = (GtkAdjustment *) g_value_get_object(value);
574
575 if(dial->adjustment == adjustment){
576 return;
577 }
578
579 if(dial->adjustment != NULL){
580 g_object_unref(G_OBJECT(dial->adjustment));
581 }
582
583 if(adjustment != NULL){
584 g_object_ref(G_OBJECT(adjustment));
585 g_signal_connect(adjustment, "value-changed",
586 G_CALLBACK(ags_dial_adjustment_changed_callback), dial);
587 }
588
589 dial->adjustment = adjustment;
590 }
591 break;
592 case PROP_SCALE_PRECISION:
593 {
594 guint scale_precision;
595
596 scale_precision = g_value_get_uint(value);
597
598 if(scale_precision > dial->scale_max_precision){
599 dial->scale_precision = dial->scale_max_precision;
600 }else if(scale_precision == 0){
601 dial->scale_precision = 1;
602 }else{
603 dial->scale_precision = scale_precision;
604 }
605 }
606 break;
607 default:
608 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
609 break;
610 }
611 }
612
613 void
ags_dial_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)614 ags_dial_get_property(GObject *gobject,
615 guint prop_id,
616 GValue *value,
617 GParamSpec *param_spec)
618 {
619 AgsDial *dial;
620
621 dial = AGS_DIAL(gobject);
622
623 switch(prop_id){
624 case PROP_RADIUS:
625 {
626 g_value_set_uint(value, dial->radius);
627 }
628 break;
629 case PROP_OUTLINE_STRENGTH:
630 {
631 g_value_set_uint(value, dial->outline_strength);
632 }
633 break;
634 case PROP_FONT_SIZE:
635 {
636 g_value_set_uint(value, dial->font_size);
637 }
638 break;
639 case PROP_BUTTON_WIDTH:
640 {
641 g_value_set_int(value, dial->button_width);
642 }
643 break;
644 case PROP_BUTTON_HEIGHT:
645 {
646 g_value_set_int(value, dial->button_height);
647 }
648 break;
649 case PROP_MARGIN_LEFT:
650 {
651 g_value_set_int(value, dial->margin_left);
652 }
653 break;
654 case PROP_MARGIN_RIGHT:
655 {
656 g_value_set_int(value, dial->margin_right);
657 }
658 break;
659 case PROP_ADJUSTMENT:
660 {
661 g_value_set_object(value, dial->adjustment);
662 }
663 break;
664 case PROP_SCALE_PRECISION:
665 {
666 g_value_set_uint(value, dial->scale_precision);
667 }
668 break;
669 default:
670 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
671 break;
672 }
673 }
674
675 void
ags_accessible_dial_get_value_and_text(AtkValue * value,gdouble * current_value,gchar ** text)676 ags_accessible_dial_get_value_and_text(AtkValue *value,
677 gdouble *current_value,
678 gchar **text)
679 {
680 AgsDial *dial;
681
682 dial = (AgsDial *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
683
684 if(current_value != NULL){
685 *current_value = gtk_adjustment_get_value(dial->adjustment);
686 }
687
688 if(text != NULL){
689 *text = g_strdup_printf("%f",
690 gtk_adjustment_get_value(dial->adjustment));
691 }
692 }
693
694 #ifdef HAVE_ATK_2_12
695 AtkRange*
ags_accessible_dial_get_range(AtkValue * value)696 ags_accessible_dial_get_range(AtkValue *value)
697 {
698 AgsDial *dial;
699 AtkRange *range;
700
701 dial = (AgsDial *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
702
703 range = atk_range_new(gtk_adjustment_get_lower(dial->adjustment),
704 gtk_adjustment_get_upper(dial->adjustment),
705 "Valid lower and upper input range of this dial");
706
707 return(range);
708 }
709 #endif
710
711 gdouble
ags_accessible_dial_get_increment(AtkValue * value)712 ags_accessible_dial_get_increment(AtkValue *value)
713 {
714 AgsDial *dial;
715
716 dial = (AgsDial *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
717
718 return(gtk_adjustment_get_step_increment(dial->adjustment));
719 }
720
721 void
ags_accessible_dial_set_value(AtkValue * value,gdouble new_value)722 ags_accessible_dial_set_value(AtkValue *value,
723 gdouble new_value)
724 {
725 AgsDial *dial;
726
727 dial = (AgsDial *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
728 gtk_adjustment_set_value(dial->adjustment,
729 new_value);
730 gtk_widget_queue_draw((GtkWidget *) dial);
731 }
732
733 gboolean
ags_accessible_dial_do_action(AtkAction * action,gint i)734 ags_accessible_dial_do_action(AtkAction *action,
735 gint i)
736 {
737 AgsDial *dial;
738
739 GdkEventKey *key_press, *key_release;
740
741 if(!(i >= 0 && i < 2)){
742 return(FALSE);
743 }
744
745 dial = (AgsDial *) gtk_accessible_get_widget(GTK_ACCESSIBLE(action));
746
747 key_press = gdk_event_new(GDK_KEY_PRESS);
748 key_release = gdk_event_new(GDK_KEY_RELEASE);
749
750 switch(i){
751 case AGS_DIAL_INCREMENT:
752 {
753 key_press->keyval =
754 key_release->keyval = GDK_KEY_Page_Up;
755
756 /* send event */
757 gtk_widget_event((GtkWidget *) dial,
758 (GdkEvent *) key_press);
759 gtk_widget_event((GtkWidget *) dial,
760 (GdkEvent *) key_release);
761 }
762 break;
763 case AGS_DIAL_DECREMENT:
764 {
765 key_press->keyval =
766 key_release->keyval = GDK_KEY_Page_Down;
767
768 /* send event */
769 gtk_widget_event((GtkWidget *) dial,
770 (GdkEvent *) key_press);
771 gtk_widget_event((GtkWidget *) dial,
772 (GdkEvent *) key_release);
773 }
774 break;
775 }
776
777 return(TRUE);
778 }
779
780 gint
ags_accessible_dial_get_n_actions(AtkAction * action)781 ags_accessible_dial_get_n_actions(AtkAction *action)
782 {
783 return(2);
784 }
785
786 const gchar*
ags_accessible_dial_get_description(AtkAction * action,gint i)787 ags_accessible_dial_get_description(AtkAction *action,
788 gint i)
789 {
790 static const gchar *actions[] = {
791 "increment dial value",
792 "decrement dial value",
793 };
794
795 if(i >= 0 && i < 2){
796 return(actions[i]);
797 }else{
798 return(NULL);
799 }
800 }
801
802 const gchar*
ags_accessible_dial_get_name(AtkAction * action,gint i)803 ags_accessible_dial_get_name(AtkAction *action,
804 gint i)
805 {
806 static const gchar *actions[] = {
807 "increment",
808 "decrement",
809 };
810
811 if(i >= 0 && i < 2){
812 return(actions[i]);
813 }else{
814 return(NULL);
815 }
816 }
817
818 const gchar*
ags_accessible_dial_get_keybinding(AtkAction * action,gint i)819 ags_accessible_dial_get_keybinding(AtkAction *action,
820 gint i)
821 {
822 static const gchar *actions[] = {
823 "up",
824 "down",
825 };
826
827 if(i >= 0 && i < 2){
828 return(actions[i]);
829 }else{
830 return(NULL);
831 }
832 }
833
834 gboolean
ags_accessible_dial_set_description(AtkAction * action,gint i)835 ags_accessible_dial_set_description(AtkAction *action,
836 gint i)
837 {
838 //TODO:JK: implement me
839
840 return(FALSE);
841 }
842
843 gchar*
ags_accessible_dial_get_localized_name(AtkAction * action,gint i)844 ags_accessible_dial_get_localized_name(AtkAction *action,
845 gint i)
846 {
847 //TODO:JK: implement me
848
849 return(NULL);
850 }
851
852 void
ags_dial_map(GtkWidget * widget)853 ags_dial_map(GtkWidget *widget)
854 {
855 if (gtk_widget_get_realized (widget) && !gtk_widget_get_mapped (widget)) {
856 GTK_WIDGET_CLASS (ags_dial_parent_class)->map(widget);
857
858 gdk_window_show(gtk_widget_get_window(widget));
859 }
860 }
861
862 void
ags_dial_realize(GtkWidget * widget)863 ags_dial_realize(GtkWidget *widget)
864 {
865 AgsDial *dial;
866
867 GdkWindow *window;
868
869 GtkAllocation allocation;
870 GdkWindowAttr attributes;
871
872 gint attributes_mask;
873 gint buttons_width;
874 gint border_left, border_top;
875
876 g_return_if_fail(widget != NULL);
877 g_return_if_fail(AGS_IS_DIAL (widget));
878
879 dial = AGS_DIAL(widget);
880
881 gtk_widget_set_realized(widget, TRUE);
882
883 /* calculate some display dependend fields */
884 buttons_width = 0;
885
886 #if 0
887 if((AGS_DIAL_WITH_BUTTONS & (dial->flags)) != 0){
888 cairo_t *cr;
889 cairo_text_extents_t te_up, te_down;
890
891 cr = gdk_cairo_create(widget->parent->window);
892
893 if(cr == NULL){
894 return;
895 }
896
897 cairo_select_font_face (cr, "Georgia",
898 CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
899 cairo_set_font_size (cr, (gdouble) dial->font_size);
900 cairo_text_extents (cr, "-", &te_down);
901 cairo_text_extents (cr, "+", &te_up);
902
903 if(te_down.width < te_up.width){
904 dial->button_width = te_up.width * 3;
905 }else{
906 dial->button_width = te_down.width * 3;
907 }
908
909 buttons_width = 2 * dial->button_width;
910
911 if(te_down.height < te_up.height){
912 dial->button_height = te_up.height * 2;
913 }else{
914 dial->button_height = te_down.height * 2;
915 }
916
917 cairo_destroy(cr);
918 }
919 #endif
920
921 gtk_widget_get_allocation(widget,
922 &allocation);
923
924 /* */
925 attributes.window_type = GDK_WINDOW_CHILD;
926
927 attributes.x = allocation.x;
928 attributes.y = allocation.y;
929 attributes.width = allocation.width;
930 attributes.height = allocation.height;
931
932 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
933
934 attributes.wclass = GDK_INPUT_OUTPUT;
935 attributes.visual = gtk_widget_get_visual(widget);
936 attributes.event_mask = gtk_widget_get_events(widget);
937 attributes.event_mask |= (GDK_EXPOSURE_MASK |
938 GDK_BUTTON_PRESS_MASK |
939 GDK_BUTTON_RELEASE_MASK |
940 GDK_KEY_PRESS_MASK |
941 GDK_KEY_RELEASE_MASK |
942 GDK_BUTTON1_MOTION_MASK |
943 GDK_BUTTON3_MOTION_MASK |
944 GDK_POINTER_MOTION_HINT_MASK |
945 GDK_POINTER_MOTION_MASK |
946 GDK_ENTER_NOTIFY_MASK |
947 GDK_LEAVE_NOTIFY_MASK);
948
949 window = gdk_window_new(gtk_widget_get_parent_window(widget),
950 &attributes, attributes_mask);
951
952 gtk_widget_register_window(widget, window);
953 gtk_widget_set_window(widget, window);
954
955 ags_dial_send_configure(dial);
956 }
957
958 void
ags_dial_size_allocate(GtkWidget * widget,GtkAllocation * allocation)959 ags_dial_size_allocate(GtkWidget *widget,
960 GtkAllocation *allocation)
961 {
962 AgsDial *dial;
963
964 guint min_width;
965
966 g_return_if_fail(AGS_IS_DIAL(widget));
967 g_return_if_fail(allocation != NULL);
968
969 dial = AGS_DIAL(widget);
970
971 min_width = 2 * (dial->button_width + dial->radius + dial->outline_strength + 2) + (dial->margin_left + dial->margin_right);
972
973 if(allocation->width < min_width){
974 allocation->width = min_width;
975 }
976
977 allocation->height = 2 * (dial->radius + dial->outline_strength + 1);
978
979 //TODO:JK: improve me
980 gtk_widget_set_allocation(widget, allocation);
981
982 if(gtk_widget_get_realized(widget)){
983 gdk_window_move_resize(gtk_widget_get_window(widget),
984 allocation->x, allocation->y,
985 allocation->width, allocation->height);
986
987 ags_dial_send_configure(dial);
988 }
989 }
990
991 void
ags_dial_send_configure(AgsDial * dial)992 ags_dial_send_configure(AgsDial *dial)
993 {
994 GtkAllocation allocation;
995 GtkWidget *widget;
996 GdkEvent *event = gdk_event_new (GDK_CONFIGURE);
997
998 widget = GTK_WIDGET(dial);
999 gtk_widget_get_allocation(widget, &allocation);
1000
1001 event->configure.window = g_object_ref(gtk_widget_get_window (widget));
1002 event->configure.send_event = TRUE;
1003 event->configure.x = allocation.x;
1004 event->configure.y = allocation.y;
1005 event->configure.width = allocation.width;
1006 event->configure.height = allocation.height;
1007
1008 gtk_widget_event(widget, event);
1009 gdk_event_free(event);
1010 }
1011
1012 void
ags_dial_get_preferred_width(GtkWidget * widget,gint * minimal_width,gint * natural_width)1013 ags_dial_get_preferred_width(GtkWidget *widget,
1014 gint *minimal_width,
1015 gint *natural_width)
1016 {
1017 AgsDial *dial;
1018
1019 dial = AGS_DIAL(widget);
1020
1021 minimal_width[0] =
1022 natural_width[0] = 2 * (dial->button_width + dial->radius + dial->outline_strength + 2) + (dial->margin_left + dial->margin_right);
1023 }
1024
1025 void
ags_dial_get_preferred_height(GtkWidget * widget,gint * minimal_height,gint * natural_height)1026 ags_dial_get_preferred_height(GtkWidget *widget,
1027 gint *minimal_height,
1028 gint *natural_height)
1029 {
1030 AgsDial *dial;
1031
1032 dial = AGS_DIAL(widget);
1033
1034 minimal_height[0] =
1035 natural_height[0] = 2 * (dial->radius + dial->outline_strength + 1);
1036 }
1037
1038 AtkObject*
ags_dial_get_accessible(GtkWidget * widget)1039 ags_dial_get_accessible(GtkWidget *widget)
1040 {
1041 AtkObject* accessible;
1042
1043 accessible = g_object_get_qdata(G_OBJECT(widget),
1044 quark_accessible_object);
1045
1046 if(!accessible){
1047 accessible = g_object_new(ags_accessible_dial_get_type(),
1048 NULL);
1049
1050 g_object_set_qdata(G_OBJECT(widget),
1051 quark_accessible_object,
1052 accessible);
1053 gtk_accessible_set_widget(GTK_ACCESSIBLE(accessible),
1054 widget);
1055 }
1056
1057 return(accessible);
1058 }
1059
1060 void
ags_dial_show(GtkWidget * widget)1061 ags_dial_show(GtkWidget *widget)
1062 {
1063 GTK_WIDGET_CLASS(ags_dial_parent_class)->show(widget);
1064 }
1065
1066 gboolean
ags_dial_button_press_is_down_event(AgsDial * dial,GdkEventButton * event,gint padding_left,guint padding_top)1067 ags_dial_button_press_is_down_event(AgsDial *dial,
1068 GdkEventButton *event,
1069 gint padding_left, guint padding_top)
1070 {
1071 if(event->x >= padding_left &&
1072 event->x <= padding_left + dial->button_width &&
1073 event->y >= padding_top + 2 * dial->radius + 2 * dial->outline_strength - dial->button_height &&
1074 event->y <= padding_top + 2 * dial->radius + 2 * dial->outline_strength){
1075 return(TRUE);
1076 }else{
1077 return(FALSE);
1078 }
1079 }
1080
1081 gboolean
ags_dial_button_press_is_up_event(AgsDial * dial,GdkEventButton * event,gint padding_left,guint padding_top)1082 ags_dial_button_press_is_up_event(AgsDial *dial,
1083 GdkEventButton *event,
1084 gint padding_left, guint padding_top)
1085 {
1086 gint offset;
1087
1088 offset = padding_left + dial->button_width + 2 * dial->radius + dial->margin_left + dial->margin_right;
1089
1090 if(event->x >= offset &&
1091 event->x <= offset + dial->button_width &&
1092 event->y >= padding_top + 2 * dial->radius + 2 * dial->outline_strength - dial->button_height &&
1093 event->y <= padding_top + 2 * dial->radius + 2 * dial->outline_strength){
1094 return(TRUE);
1095 }else{
1096 return(FALSE);
1097 }
1098 }
1099
1100 gboolean
ags_dial_button_press_is_dial_event(AgsDial * dial,GdkEventButton * event,gint padding_left,guint padding_top,gint dial_left_position)1101 ags_dial_button_press_is_dial_event(AgsDial *dial,
1102 GdkEventButton *event,
1103 gint padding_left, guint padding_top,
1104 gint dial_left_position)
1105 {
1106 if(event->x >= dial_left_position &&
1107 event->x <= dial_left_position + 2 * dial->radius + 2 * dial->outline_strength){
1108 if((cos(event->y) < 0.0 && cos(event->y) >= -1.0) ||
1109 (sin(event->y) > 0.0 && sin(event->y) <= 1.0) ||
1110 (cos(event->y) < 0.0 && sin(event->y) >= -1.0) ||
1111 (sin(event->y) < 0.0 && cos(event->y) >= -1.0)){
1112 return(TRUE);
1113 }else{
1114 return(FALSE);
1115 }
1116 }else{
1117 return(FALSE);
1118 }
1119 }
1120
1121 gboolean
ags_dial_button_press(GtkWidget * widget,GdkEventButton * event)1122 ags_dial_button_press(GtkWidget *widget,
1123 GdkEventButton *event)
1124 {
1125 AgsDial *dial;
1126
1127 GtkAllocation allocation;
1128
1129 gdouble button_width, button_height, margin_left, margin_right;
1130 gdouble radius, outline_strength;
1131 guint width, height;
1132 gint padding_left, padding_top;
1133 gint dial_left_position;
1134
1135 // GTK_WIDGET_CLASS(ags_dial_parent_class)->button_press_event(widget, event);
1136
1137 dial = AGS_DIAL(widget);
1138 dial->flags |= AGS_DIAL_MOUSE_BUTTON_PRESSED;
1139
1140 gtk_widget_get_allocation(widget,
1141 &allocation);
1142
1143 button_width = dial->button_width;
1144 button_height = dial->button_height;
1145
1146 margin_left = (gdouble) dial->margin_left;
1147 margin_right = (gdouble) dial->margin_right;
1148
1149 radius = (gdouble) dial->radius;
1150 outline_strength = (gdouble) dial->outline_strength;
1151
1152 width = 2 * (button_height + radius + outline_strength + 2) + (margin_left + margin_right);
1153 height = 2 * (radius + outline_strength + 1);
1154
1155 padding_top = (allocation.height - height) / 2;
1156 padding_left = (allocation.width - width) / 2;
1157
1158 if((AGS_DIAL_WITH_BUTTONS & (dial->flags)) != 0){
1159 if(ags_dial_button_press_is_down_event(dial,
1160 event,
1161 padding_left, padding_top)){
1162 dial->flags |= AGS_DIAL_BUTTON_DOWN_PRESSED;
1163 }else if(ags_dial_button_press_is_up_event(dial,
1164 event,
1165 padding_left, padding_top)){
1166 dial->flags |= AGS_DIAL_BUTTON_UP_PRESSED;
1167 }else{
1168 dial_left_position = padding_left + dial->button_width;
1169
1170 if(ags_dial_button_press_is_dial_event(dial,
1171 event,
1172 padding_left, padding_top,
1173 dial_left_position)){
1174 dial->flags |= AGS_DIAL_MOTION_CAPTURING;
1175 }
1176 }
1177 }else{
1178 dial_left_position = padding_left;
1179
1180 if(ags_dial_button_press_is_dial_event(dial,
1181 event,
1182 padding_left, padding_top,
1183 dial_left_position)){
1184 dial->gravity_x = event->x;
1185 dial->gravity_y = event->y;
1186 dial->current_x = event->x;
1187 dial->current_y = event->y;
1188
1189 dial->flags |= AGS_DIAL_MOTION_CAPTURING_INIT;
1190 dial->flags |= AGS_DIAL_MOTION_CAPTURING;
1191 }
1192 }
1193
1194 return(FALSE);
1195 }
1196
1197 gboolean
ags_dial_button_release(GtkWidget * widget,GdkEventButton * event)1198 ags_dial_button_release(GtkWidget *widget,
1199 GdkEventButton *event)
1200 {
1201 AgsDial *dial;
1202
1203 // GTK_WIDGET_CLASS(ags_dial_parent_class)->button_release_event(widget, event);
1204
1205 gtk_widget_grab_focus(widget);
1206
1207 dial = AGS_DIAL(widget);
1208 dial->flags &= (~AGS_DIAL_MOUSE_BUTTON_PRESSED);
1209
1210 if((AGS_DIAL_BUTTON_DOWN_PRESSED & (dial->flags)) != 0){
1211 GtkAdjustment *adjustment;
1212
1213 adjustment = dial->adjustment;
1214
1215 if(gtk_adjustment_get_value(adjustment) > gtk_adjustment_get_lower(adjustment)){
1216 gtk_adjustment_set_value(adjustment,
1217 gtk_adjustment_get_value(adjustment) - gtk_adjustment_get_page_increment(adjustment));
1218
1219 gtk_widget_queue_draw(dial);
1220 }
1221
1222 dial->flags &= (~AGS_DIAL_BUTTON_DOWN_PRESSED);
1223 }else if((AGS_DIAL_BUTTON_UP_PRESSED & (dial->flags)) != 0){
1224 GtkAdjustment *adjustment;
1225
1226 adjustment = dial->adjustment;
1227
1228 if(gtk_adjustment_get_value(adjustment) < gtk_adjustment_get_upper(adjustment)){
1229 gtk_adjustment_set_value(adjustment,
1230 gtk_adjustment_get_value(adjustment) + gtk_adjustment_get_page_increment(adjustment));
1231
1232 gtk_widget_queue_draw(dial);
1233 }
1234
1235 dial->flags &= (~AGS_DIAL_BUTTON_UP_PRESSED);
1236 }else if((AGS_DIAL_MOTION_CAPTURING & (dial->flags)) != 0){
1237 dial->flags &= (~AGS_DIAL_MOTION_CAPTURING);
1238 }
1239
1240 return(FALSE);
1241 }
1242
1243 gboolean
ags_dial_key_press(GtkWidget * widget,GdkEventKey * event)1244 ags_dial_key_press(GtkWidget *widget,
1245 GdkEventKey *event)
1246 {
1247 if(event->keyval == GDK_KEY_Tab ||
1248 event->keyval == GDK_KEY_ISO_Left_Tab ||
1249 event->keyval == GDK_KEY_Shift_L ||
1250 event->keyval == GDK_KEY_Shift_R ||
1251 event->keyval == GDK_KEY_Alt_L ||
1252 event->keyval == GDK_KEY_Alt_R ||
1253 event->keyval == GDK_KEY_Control_L ||
1254 event->keyval == GDK_KEY_Control_R ){
1255 return(GTK_WIDGET_CLASS(ags_dial_parent_class)->key_press_event(widget, event));
1256 }
1257
1258 return(TRUE);
1259 }
1260
1261 gboolean
ags_dial_key_release(GtkWidget * widget,GdkEventKey * event)1262 ags_dial_key_release(GtkWidget *widget,
1263 GdkEventKey *event)
1264 {
1265 AgsDial *dial;
1266
1267 if(event->keyval == GDK_KEY_Tab ||
1268 event->keyval == GDK_KEY_ISO_Left_Tab ||
1269 event->keyval == GDK_KEY_Shift_L ||
1270 event->keyval == GDK_KEY_Shift_R ||
1271 event->keyval == GDK_KEY_Alt_L ||
1272 event->keyval == GDK_KEY_Alt_R ||
1273 event->keyval == GDK_KEY_Control_L ||
1274 event->keyval == GDK_KEY_Control_R ){
1275 return(GTK_WIDGET_CLASS(ags_dial_parent_class)->key_release_event(widget, event));
1276 }
1277
1278 dial = AGS_DIAL(widget);
1279
1280 switch(event->keyval){
1281 case GDK_KEY_Up:
1282 case GDK_KEY_uparrow:
1283 {
1284 gdouble value, step, upper;
1285
1286 value = gtk_adjustment_get_value(dial->adjustment);
1287 step = gtk_adjustment_get_step_increment(dial->adjustment);
1288 upper = gtk_adjustment_get_upper(dial->adjustment);
1289
1290 if(value + step > upper){
1291 gtk_adjustment_set_value(dial->adjustment,
1292 upper);
1293 }else{
1294 gtk_adjustment_set_value(dial->adjustment,
1295 value + step);
1296 }
1297
1298 gtk_widget_queue_draw(widget);
1299 }
1300 break;
1301 case GDK_KEY_Down:
1302 case GDK_KEY_downarrow:
1303 {
1304 gdouble value, step, lower;
1305
1306 value = gtk_adjustment_get_value(dial->adjustment);
1307 step = gtk_adjustment_get_step_increment(dial->adjustment);
1308 lower = gtk_adjustment_get_lower(dial->adjustment);
1309
1310 if(value - step < lower){
1311 gtk_adjustment_set_value(dial->adjustment,
1312 lower);
1313 }else{
1314 gtk_adjustment_set_value(dial->adjustment,
1315 value - step);
1316 }
1317
1318 gtk_widget_queue_draw(widget);
1319 }
1320 break;
1321 case GDK_KEY_Page_Up:
1322 case GDK_KEY_KP_Page_Up:
1323 {
1324 gdouble value, page, upper;
1325
1326 value = gtk_adjustment_get_value(dial->adjustment);
1327 page = gtk_adjustment_get_page_increment(dial->adjustment);
1328 upper = gtk_adjustment_get_upper(dial->adjustment);
1329
1330 if(value + page > upper){
1331 gtk_adjustment_set_value(dial->adjustment,
1332 upper);
1333 }else{
1334 gtk_adjustment_set_value(dial->adjustment,
1335 value + page);
1336 }
1337
1338 gtk_widget_queue_draw(widget);
1339 }
1340 break;
1341 case GDK_KEY_Page_Down:
1342 case GDK_KEY_KP_Page_Down:
1343 {
1344 gdouble value, page, lower;
1345
1346 value = gtk_adjustment_get_value(dial->adjustment);
1347 page = gtk_adjustment_get_page_increment(dial->adjustment);
1348 lower = gtk_adjustment_get_lower(dial->adjustment);
1349
1350 if(value - page < lower){
1351 gtk_adjustment_set_value(dial->adjustment,
1352 lower);
1353 }else{
1354 gtk_adjustment_set_value(dial->adjustment,
1355 value - page);
1356 }
1357
1358 gtk_widget_queue_draw(widget);
1359 }
1360 break;
1361 }
1362
1363 return(TRUE);
1364 }
1365
1366 void
ags_dial_motion_notify_do_dial(AgsDial * dial,GdkEventMotion * event)1367 ags_dial_motion_notify_do_dial(AgsDial *dial,
1368 GdkEventMotion *event)
1369 {
1370 GtkAdjustment *adjustment;
1371
1372 guint i;
1373 gint sign_one;
1374 gboolean gravity_up;
1375
1376 static const gboolean movement_matrix[] = {
1377 FALSE,
1378 TRUE,
1379 FALSE,
1380 FALSE,
1381 TRUE,
1382 FALSE,
1383 TRUE,
1384 TRUE,
1385 };
1386
1387 adjustment = dial->adjustment;
1388
1389 gravity_up = FALSE;
1390
1391 for(i = 0; i < 8 ; i++){
1392 if(!movement_matrix[i]){
1393 sign_one = -1;
1394 }else{
1395 sign_one = 1;
1396 }
1397
1398 if((movement_matrix[i] &&
1399 (sign_one * (dial->gravity_x - dial->current_x) < sign_one * (dial->gravity_y - dial->current_y))) ||
1400 (!movement_matrix[i] &&
1401 (sign_one * (dial->gravity_x - dial->current_x) > sign_one * (dial->gravity_y - dial->current_y)))){
1402 gravity_up = TRUE;
1403 break;
1404 }
1405 }
1406
1407 if(!gravity_up){
1408 if(gtk_adjustment_get_value(adjustment) > gtk_adjustment_get_lower(adjustment)){
1409 gtk_adjustment_set_value(adjustment,
1410 gtk_adjustment_get_value(adjustment) - gtk_adjustment_get_step_increment(adjustment));
1411
1412 gtk_widget_queue_draw(dial);
1413 }
1414 }else{
1415 if(gtk_adjustment_get_value(adjustment) < gtk_adjustment_get_lower(adjustment)){
1416 gtk_adjustment_set_value(adjustment,
1417 gtk_adjustment_get_value(adjustment) + gtk_adjustment_get_step_increment(adjustment));
1418
1419 gtk_widget_queue_draw(dial);
1420 }
1421 }
1422 }
1423
1424 void
ags_dial_motion_notify_do_seemless_dial(AgsDial * dial,GdkEventMotion * event)1425 ags_dial_motion_notify_do_seemless_dial(AgsDial *dial,
1426 GdkEventMotion *event)
1427 {
1428 GtkAdjustment *adjustment;
1429
1430 GtkAllocation allocation;
1431
1432 cairo_t *cr;
1433
1434 gdouble button_width, button_height, margin_left, margin_right;
1435 gdouble radius, outline_strength;
1436 guint width, height;
1437 gdouble padding_left, padding_top;
1438 gdouble range;
1439 gdouble a0, quarter;
1440 gdouble x0, y0, x1, y1;
1441 gdouble translated_x;
1442 gboolean x_toggled, y_toggled;
1443
1444 //TODO:JK: optimize me
1445 adjustment = dial->adjustment;
1446
1447 range = (gtk_adjustment_get_upper(dial->adjustment) - gtk_adjustment_get_lower(dial->adjustment));
1448
1449 if(range == 0.0){
1450 return;
1451 }
1452
1453 gtk_widget_get_allocation(dial,
1454 &allocation);
1455
1456 button_width = dial->button_width;
1457 button_height = dial->button_height;
1458
1459 margin_left = (gdouble) dial->margin_left;
1460 margin_right = (gdouble) dial->margin_right;
1461
1462 radius = (gdouble) dial->radius;
1463 outline_strength = (gdouble) dial->outline_strength;
1464
1465 width = 2 * (button_height + radius + outline_strength + 2) + (margin_left + margin_right);
1466 height = 2 * (radius + outline_strength + 1);
1467
1468 padding_top = (allocation.height - height) / 2;
1469 padding_left = (allocation.width - width) / 2;
1470
1471 x1 = event->x - (1.0 + dial->button_width + dial->margin_left + radius + padding_left);
1472 y1 = event->y - (dial->outline_strength + radius + padding_top);
1473 y1 *= -1.0;
1474
1475 x_toggled = FALSE;
1476 y_toggled = FALSE;
1477
1478 if(x1 < 0.0){
1479 x_toggled = TRUE;
1480 }
1481
1482 if(y1 < 0.0){
1483 y_toggled = TRUE;
1484 }
1485
1486 if(radius == 0.0){
1487 return;
1488 }
1489
1490 //FIXME:JK: ugly hack
1491 x1 = round(x1 + 1.0);
1492 y1 = round(y1 - 1.0);
1493
1494 if(x1 == 0.0 &&
1495 y1 == 0.0){
1496 return;
1497 }else if(x1 == 0.0){
1498 a0 = 1.0;
1499
1500 #if 0
1501 x0 = 0.0;
1502 y0 = 1.0 * radius;
1503 #endif
1504 }else if(y1 == 0.0){
1505 a0 = 0.0;
1506
1507 #if 0
1508 x0 = 1.0 * radius;
1509 y0 = 0.0;
1510 #endif
1511 }else{
1512 a0 = y1 / x1;
1513 #if 0
1514 x0 = cos(a0) * radius;
1515 y0 = sin(a0) * radius;
1516 #endif
1517 }
1518
1519 /* origin correction */
1520 #if 0
1521 if(x_toggled && y_toggled){
1522 if(x0 > 0.0){
1523 x0 *= -1.0;
1524 }
1525
1526 if(y0 > 0.0){
1527 y0 *= -1.0;
1528 }
1529 }else if(y_toggled){
1530 if(x0 < 0.0){
1531 x0 *= -1.0;
1532 }
1533
1534 if(y0 > 0.0){
1535 y0 *= -1.0;
1536 }
1537 }else if(x_toggled){
1538 if(y0 < 0.0){
1539 y0 *= -1.0;
1540 }
1541
1542 if(x0 > 0.0){
1543 x0 *= -1.0;
1544 }
1545 }else{
1546 if(x0 < 0.0){
1547 x0 *= -1.0;
1548 }
1549
1550 if(y0 < 0.0){
1551 y0 *= -1.0;
1552 }
1553 }
1554 #endif
1555
1556 if(a0 > 2.0 * M_PI / 4.0){
1557 a0 = (2.0 * M_PI / 4.0);
1558 }else if(a0 < -2.0 * M_PI / 4.0){
1559 a0 = (-2.0 * M_PI / 4.0);
1560 }
1561
1562 /* translated_x */
1563 translated_x = a0 * radius;
1564
1565 quarter = (2.0 * M_PI / 4.0) * radius;
1566
1567 if(x_toggled && y_toggled){
1568 if(translated_x < 0.0){
1569 translated_x = quarter + translated_x;
1570 }else{
1571 translated_x = quarter - translated_x;
1572 }
1573 }else if(y_toggled){
1574 if(translated_x < 0.0){
1575 translated_x *= -1.0;
1576 }
1577
1578 translated_x += 3.0 * quarter;
1579 }else if(x_toggled){
1580 if(translated_x < 0.0){
1581 translated_x *= -1.0;
1582 }
1583
1584 translated_x += quarter;
1585 }else{
1586 if(translated_x < 0.0){
1587 translated_x = quarter + translated_x;
1588 }else{
1589 translated_x = quarter - translated_x;
1590 }
1591
1592 translated_x += 2.0 * quarter;
1593 }
1594
1595 translated_x = ((4.0 / 3.0) * range) / (4.0 * quarter) * translated_x;
1596 translated_x -= (range / 3.0 / 2.0);
1597 translated_x = gtk_adjustment_get_lower(adjustment) + translated_x;
1598
1599 if(translated_x < gtk_adjustment_get_lower(adjustment)){
1600 translated_x = gtk_adjustment_get_lower(adjustment);
1601 }else if(translated_x > gtk_adjustment_get_upper(adjustment)){
1602 translated_x = gtk_adjustment_get_upper(adjustment);
1603 }
1604
1605 gtk_adjustment_set_value(adjustment,
1606 translated_x);
1607 gtk_widget_queue_draw(dial);
1608 }
1609
1610 gboolean
ags_dial_motion_notify(GtkWidget * widget,GdkEventMotion * event)1611 ags_dial_motion_notify(GtkWidget *widget,
1612 GdkEventMotion *event)
1613 {
1614 AgsDial *dial;
1615
1616 GtkAllocation allocation;
1617
1618 // GTK_WIDGET_CLASS(ags_dial_parent_class)->motion_notify_event(widget, event);
1619 dial = AGS_DIAL(widget);
1620
1621 gtk_widget_get_allocation(widget,
1622 &allocation);
1623
1624 if((AGS_DIAL_MOTION_CAPTURING & (dial->flags)) != 0){
1625 if((AGS_DIAL_SEEMLESS_MODE & (dial->flags)) != 0){
1626 if((AGS_DIAL_MOTION_CAPTURING_INIT & (dial->flags)) != 0){
1627 dial->current_x = event->x;
1628 dial->current_y = event->y;
1629 }else{
1630 dial->gravity_x = dial->current_x;
1631 dial->gravity_y = dial->current_y;
1632 dial->current_x = event->x;
1633 dial->current_y = event->y;
1634 }
1635
1636 ags_dial_motion_notify_do_seemless_dial(dial,
1637 event);
1638 }else{
1639 if((AGS_DIAL_MOTION_CAPTURING_INIT & (dial->flags)) != 0){
1640 dial->current_x = event->x;
1641 dial->current_y = event->y;
1642
1643 dial->flags &= (~AGS_DIAL_MOTION_CAPTURING_INIT);
1644
1645 ags_dial_motion_notify_do_dial(dial,
1646 event);
1647 }else{
1648 dial->gravity_x = dial->current_x;
1649 dial->gravity_y = dial->current_y;
1650 dial->current_x = event->x;
1651 dial->current_y = event->y;
1652
1653 ags_dial_motion_notify_do_dial(dial,
1654 event);
1655 }
1656 }
1657 }
1658
1659 return(FALSE);
1660 }
1661
1662 /**
1663 * ags_dial_draw:
1664 * @dial: an #AgsDial
1665 *
1666 * draws the widget
1667 *
1668 * Since: 3.0.0
1669 */
1670 gboolean
ags_dial_draw(AgsDial * dial,cairo_t * cr)1671 ags_dial_draw(AgsDial *dial, cairo_t *cr)
1672 {
1673 GtkWidget *widget;
1674
1675 GtkStyleContext *dial_style_context;
1676
1677 cairo_text_extents_t te_up, te_down;
1678
1679 GtkAllocation allocation;
1680
1681 GdkRGBA *fg_color;
1682 GdkRGBA *bg_color;
1683 GdkRGBA *border_color;
1684 GdkRGBA *font_color;
1685
1686 gdouble button_width, button_height, margin_left, margin_right;
1687 gdouble radius, outline_strength;
1688 guint width, height;
1689 guint padding_top, padding_left;
1690 gdouble unused;
1691 gdouble scale_area, scale_width, scale_inverted_width;
1692 gdouble starter_angle;
1693 gdouble translated_value;
1694 gdouble range;
1695 guint scale_precision;
1696 guint i;
1697
1698 GValue value = {0,};
1699
1700 widget = GTK_WIDGET(dial);
1701
1702 gtk_widget_get_allocation(GTK_WIDGET(dial),
1703 &allocation);
1704
1705 /* style context */
1706 dial_style_context = gtk_widget_get_style_context(GTK_WIDGET(dial));
1707
1708 gtk_style_context_get_property(dial_style_context,
1709 "color",
1710 GTK_STATE_FLAG_NORMAL,
1711 &value);
1712
1713 fg_color = g_value_dup_boxed(&value);
1714 g_value_unset(&value);
1715
1716 gtk_style_context_get_property(dial_style_context,
1717 "background-color",
1718 GTK_STATE_FLAG_NORMAL,
1719 &value);
1720
1721 bg_color = g_value_dup_boxed(&value);
1722 g_value_unset(&value);
1723
1724 gtk_style_context_get_property(dial_style_context,
1725 "border-color",
1726 GTK_STATE_FLAG_NORMAL,
1727 &value);
1728
1729 border_color = g_value_dup_boxed(&value);
1730 g_value_unset(&value);
1731
1732 gtk_style_context_get_property(dial_style_context,
1733 "font",
1734 GTK_STATE_FLAG_NORMAL,
1735 &value);
1736
1737 font_color = g_value_dup_boxed(&value);
1738 g_value_unset(&value);
1739
1740 /* dimension */
1741 button_width = dial->button_width;
1742 button_height = dial->button_height;
1743
1744 margin_left = (gdouble) dial->margin_left;
1745 margin_right = (gdouble) dial->margin_right;
1746
1747 radius = (gdouble) dial->radius;
1748 outline_strength = (gdouble) dial->outline_strength;
1749
1750 width = 2 * (button_width + radius + outline_strength + 1);
1751 height = 2 * (radius + outline_strength + 1);
1752
1753 padding_top = (allocation.height - height) / 2;
1754 padding_left = (allocation.width - width) / 2;
1755
1756 /* */
1757 // cairo_surface_flush(cairo_get_target(cr));
1758 cairo_push_group(cr);
1759
1760 /* clear bg */
1761 #if 0
1762 cairo_set_source_rgba(cr,
1763 bg_color->red,
1764 bg_color->green,
1765 bg_color->blue,
1766 bg_color->alpha);
1767
1768 cairo_rectangle(cr,
1769 0.0, 0.0,
1770 (gdouble) allocation.width, (gdouble) allocation.height);
1771 cairo_fill(cr);
1772 #else
1773 gtk_render_background(dial_style_context,
1774 cr,
1775 0.0, 0.0,
1776 (gdouble) allocation.width, (gdouble) allocation.height);
1777 #endif
1778
1779 if((AGS_DIAL_WITH_BUTTONS & (dial->flags)) != 0){
1780 PangoLayout *layout;
1781 PangoFontDescription *desc;
1782
1783 PangoRectangle ink_rect, logical_rect;
1784
1785 gchar *font_name;
1786
1787 static const gchar *text = "-";
1788
1789 g_object_get(gtk_settings_get_default(),
1790 "gtk-font-name", &font_name,
1791 NULL);
1792
1793 /* draw controller button down */
1794 cairo_set_source_rgba(cr,
1795 border_color->red,
1796 border_color->green,
1797 border_color->blue,
1798 border_color->alpha);
1799
1800 cairo_set_line_width(cr, 2.0);
1801
1802 cairo_rectangle(cr,
1803 (gdouble) padding_left + 1.0, (gdouble) padding_top + (2.0 * radius) - button_height + outline_strength,
1804 (gdouble) button_width, (gdouble) button_height);
1805 cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
1806 cairo_stroke(cr);
1807
1808 /* text */
1809 #if 0
1810 cairo_set_source_rgba(cr,
1811 font_color->red,
1812 font_color->green,
1813 font_color->blue,
1814 font_color->alpha);
1815 #else
1816 cairo_set_source_rgba(cr,
1817 fg_color->red,
1818 fg_color->green,
1819 fg_color->blue,
1820 fg_color->alpha);
1821 #endif
1822
1823 layout = pango_cairo_create_layout(cr);
1824 pango_layout_set_text(layout,
1825 text,
1826 -1);
1827 desc = pango_font_description_from_string(font_name);
1828 pango_font_description_set_size(desc,
1829 dial->font_size * PANGO_SCALE);
1830 pango_layout_set_font_description(layout,
1831 desc);
1832 pango_font_description_free(desc);
1833
1834 pango_layout_get_extents(layout,
1835 &ink_rect,
1836 &logical_rect);
1837
1838 cairo_move_to(cr,
1839 padding_left + 1.0 + 0.5 - (logical_rect.width / PANGO_SCALE) / 2.0 + button_width / 2.25,
1840 padding_top + 0.5 - (logical_rect.height / PANGO_SCALE) / 2.0 + (radius * 2.0) - button_height / 2.0 + outline_strength - 1.0);
1841
1842 pango_cairo_show_layout(cr,
1843 layout);
1844
1845 g_object_unref(layout);
1846
1847 g_free(font_name);
1848 }
1849
1850 if((AGS_DIAL_WITH_BUTTONS & (dial->flags)) != 0){
1851 PangoLayout *layout;
1852 PangoFontDescription *desc;
1853
1854 PangoRectangle ink_rect, logical_rect;
1855
1856 gchar *font_name;
1857
1858 static const gchar *text = "+";
1859
1860 g_object_get(gtk_settings_get_default(),
1861 "gtk-font-name", &font_name,
1862 NULL);
1863
1864 /* draw controller button up */
1865 cairo_set_source_rgba(cr,
1866 border_color->red,
1867 border_color->green,
1868 border_color->blue,
1869 border_color->alpha);
1870
1871 cairo_set_line_width(cr, 2.0);
1872
1873 cairo_rectangle(cr,
1874 padding_left + 1.0 + (2.0 * radius) + button_width + margin_left + margin_right, padding_top + (2.0 * radius) - button_height + outline_strength,
1875 button_width, button_height);
1876 cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER);
1877 cairo_stroke(cr);
1878
1879 /* text */
1880 #if 0
1881 cairo_set_source_rgba(cr,
1882 font_color->red,
1883 font_color->green,
1884 font_color->blue,
1885 font_color->alpha);
1886 #else
1887 cairo_set_source_rgba(cr,
1888 fg_color->red,
1889 fg_color->green,
1890 fg_color->blue,
1891 fg_color->alpha);
1892 #endif
1893
1894 layout = pango_cairo_create_layout(cr);
1895 pango_layout_set_text(layout,
1896 text,
1897 -1);
1898 desc = pango_font_description_from_string(font_name);
1899 pango_font_description_set_size(desc,
1900 dial->font_size * PANGO_SCALE);
1901 pango_layout_set_font_description(layout,
1902 desc);
1903 pango_font_description_free(desc);
1904
1905 pango_layout_get_extents(layout,
1906 &ink_rect,
1907 &logical_rect);
1908
1909 cairo_move_to(cr,
1910 padding_left + 1.0 + 0.5 - (logical_rect.width / PANGO_SCALE) / 2.0 + (radius * 2.0) + margin_left + margin_right + button_width + button_width / 2.25,
1911 padding_top + 0.5 - (logical_rect.height / PANGO_SCALE) / 2.0 + (radius * 2.0) - button_height / 2.0 + outline_strength - 1.0);
1912
1913 pango_cairo_show_layout(cr,
1914 layout);
1915
1916 g_object_unref(layout);
1917
1918 g_free(font_name);
1919 }
1920
1921 /* border fill * /
1922 cairo_set_source_rgb(cr,
1923 dial_style->fg[0].red / white_gc,
1924 dial_style->fg[0].green / white_gc,
1925 dial_style->fg[0].blue / white_gc);
1926 cairo_arc(cr,
1927 1.0 + button_width + margin_left + radius,
1928 radius + outline_strength,
1929 radius + 2.0,
1930 -1.0 * M_PI,
1931 1.0 * M_PI);
1932 cairo_stroke(cr);
1933 */
1934
1935 /* dial disk */
1936 cairo_set_source_rgba(cr,
1937 bg_color->red,
1938 bg_color->green,
1939 bg_color->blue,
1940 bg_color->alpha);
1941
1942 cairo_arc(cr,
1943 padding_left + 1.0 + button_width + margin_left + radius,
1944 padding_top + radius + outline_strength,
1945 radius + outline_strength - 1.25,
1946 -1.0 * M_PI,
1947 1.0 * M_PI);
1948 cairo_fill(cr);
1949
1950 /* dial disk border */
1951 cairo_set_source_rgba(cr,
1952 border_color->red,
1953 border_color->green,
1954 border_color->blue,
1955 border_color->alpha);
1956
1957 cairo_arc(cr,
1958 padding_left + 1.0 + button_width + margin_left + radius,
1959 padding_top + radius + outline_strength,
1960 radius,
1961 -1.0 * M_PI,
1962 1.0 * M_PI);
1963 cairo_stroke(cr);
1964
1965 /* light effect */
1966 if((AGS_DIAL_INVERSE_LIGHT & (dial->flags)) != 0){
1967 cairo_set_source_rgba(cr,
1968 0.0,
1969 0.0,
1970 0.0,
1971 1.0 / 3.0);
1972 }else{
1973 cairo_set_source_rgba(cr,
1974 1.0,
1975 1.0,
1976 1.0,
1977 1.0 / 3.0);
1978 }
1979
1980 cairo_line_to(cr,
1981 padding_left + 1.0 + button_width + margin_left + radius,
1982 padding_top + radius + 2.0 * outline_strength - 2.0 - outline_strength);
1983 cairo_line_to(cr,
1984 padding_left + 1.0 + sin(-1 * (0.35 * M_PI) / (0.65 * M_PI)) + button_width + margin_left + radius,
1985 padding_top + cos((0.65 * M_PI) / (0.35 * M_PI)) + radius + 2.0 * outline_strength - 1.0);
1986 cairo_line_to(cr,
1987 padding_left + 1.0 + sin((0.65 * M_PI) / (0.35 * M_PI)) + button_width + margin_left + radius,
1988 padding_top + -1 * cos((0.35 * M_PI) / (0.65 * M_PI)) + radius + 2.0 * outline_strength - 1.0);
1989 cairo_close_path(cr);
1990
1991 cairo_arc(cr,
1992 padding_left + 1.0 + button_width + margin_left + radius,
1993 padding_top + radius + outline_strength,
1994 radius,
1995 0.35 * M_PI,
1996 0.65 * M_PI);
1997 cairo_fill(cr);
1998
1999 cairo_line_to(cr,
2000 padding_left + 1.0 + cos((0.65 * M_PI) / (0.35 * M_PI)) + button_width + margin_left + radius,
2001 padding_top + -1 * sin((0.35 * M_PI) / (0.65 * M_PI)) + radius + 2.0 * outline_strength - 1.0);
2002 cairo_line_to(cr,
2003 padding_left + 1.0 + -1 * cos((0.35 * M_PI) / (0.65 * M_PI)) + button_width + margin_left + radius,
2004 padding_top + sin((0.65 * M_PI) / (0.35 * M_PI)) + radius + 2.0 * outline_strength - 1.0);
2005 cairo_line_to(cr,
2006 padding_left + 1.0 + button_width + margin_left + radius,
2007 padding_top + radius + 2.0 * outline_strength - 1.0);
2008 cairo_close_path(cr);
2009
2010 cairo_arc(cr,
2011 padding_left + 1.0 + button_width + margin_left + radius,
2012 padding_top + radius + outline_strength,
2013 radius,
2014 -0.65 * M_PI,
2015 -0.35 * M_PI);
2016 cairo_fill(cr);
2017
2018 /* outline */
2019 cairo_set_source_rgba(cr,
2020 0.0,
2021 0.0,
2022 0.0,
2023 1.0);
2024
2025 // cairo_set_line_width(cr, 1.0 - (2.0 / M_PI));
2026 cairo_set_line_width(cr, 1.0);
2027 cairo_arc(cr,
2028 padding_left + 1.0 + button_width + margin_left + radius,
2029 padding_top + radius + outline_strength,
2030 radius,
2031 -1.0 * M_PI,
2032 1.0 * M_PI);
2033 cairo_stroke(cr);
2034
2035 /* scale */
2036 cairo_set_source_rgba(cr,
2037 fg_color->red,
2038 fg_color->green,
2039 fg_color->blue,
2040 fg_color->alpha);
2041
2042 cairo_set_line_width(cr, 3.0);
2043
2044 unused = 0.25 * 2.0 * M_PI;
2045 starter_angle = (2.0 * M_PI - unused) * 0.5;
2046
2047 scale_precision = (gdouble) dial->scale_precision;
2048 scale_inverted_width = (2.0 * (radius + outline_strength) * M_PI - ((radius + outline_strength) * unused)) / scale_precision - 4.0;
2049 scale_width = (2.0 * (radius + outline_strength) * M_PI - ((radius + outline_strength) * unused)) / scale_precision - scale_inverted_width;
2050
2051 scale_inverted_width /= (radius + outline_strength);
2052 scale_width /= (radius + outline_strength);
2053
2054 for(i = 0; i <= scale_precision; i++){
2055 cairo_arc(cr,
2056 padding_left + 1.0 + button_width + margin_left + radius,
2057 padding_top + radius + outline_strength,
2058 radius + outline_strength / M_PI,
2059 starter_angle + ((gdouble) i * scale_inverted_width) + ((gdouble) i * scale_width),
2060 starter_angle + ((gdouble) i * scale_inverted_width) + ((gdouble) i * scale_width) + scale_width);
2061 cairo_stroke(cr);
2062 }
2063
2064 /* draw value */
2065 range = (gtk_adjustment_get_upper(dial->adjustment) - gtk_adjustment_get_lower(dial->adjustment));
2066
2067 if(range != 0.0 &&
2068 gtk_adjustment_get_upper(dial->adjustment) > gtk_adjustment_get_lower(dial->adjustment)){
2069 /* this is odd */
2070 translated_value = (gtk_adjustment_get_value(dial->adjustment) - gtk_adjustment_get_lower(dial->adjustment));
2071 translated_value = (gdouble) scale_precision * (translated_value / range);
2072
2073 // g_message("value: %f\nupper: %f\ntranslated_value: %f\n", GTK_RANGE(dial)->adjustment->value, GTK_RANGE(dial)->adjustment->upper, translated_value);
2074 cairo_set_line_width(cr, 4.0);
2075 cairo_set_source_rgba(cr,
2076 fg_color->red,
2077 fg_color->green,
2078 fg_color->blue,
2079 fg_color->alpha);
2080
2081 cairo_arc(cr,
2082 padding_left + 1.0 + button_width + margin_left + radius,
2083 padding_top + radius + outline_strength,
2084 radius - (outline_strength + 4.0) / M_PI,
2085 starter_angle + (translated_value * scale_inverted_width) + (translated_value * scale_width),
2086 starter_angle + (translated_value * scale_inverted_width) + (translated_value * scale_width) + scale_width);
2087 cairo_stroke(cr);
2088 }else{
2089 g_warning("ags_dial.c - invalid range");
2090 }
2091
2092 cairo_pop_group_to_source(cr);
2093 cairo_paint(cr);
2094
2095 g_boxed_free(GDK_TYPE_RGBA, fg_color);
2096 g_boxed_free(GDK_TYPE_RGBA, bg_color);
2097 g_boxed_free(GDK_TYPE_RGBA, border_color);
2098 g_boxed_free(GDK_TYPE_RGBA, font_color);
2099 // cairo_surface_mark_dirty(cairo_get_target(cr));
2100
2101 return(FALSE);
2102 }
2103
2104 /**
2105 * ags_dial_set_radius:
2106 * @dial: the #AgsDial
2107 * @radius: the radius
2108 *
2109 * Set radius of @dial.
2110 *
2111 * Since: 3.2.0
2112 */
2113 void
ags_dial_set_radius(AgsDial * dial,guint radius)2114 ags_dial_set_radius(AgsDial *dial,
2115 guint radius)
2116 {
2117 if(!AGS_IS_DIAL(dial)){
2118 return;
2119 }
2120
2121 g_object_set(dial,
2122 "radius", radius,
2123 NULL);
2124 }
2125
2126 /**
2127 * ags_dial_get_radius:
2128 * @dial: the #AgsDial
2129 *
2130 * Get radius of @dial.
2131 *
2132 * Returns: the radius
2133 *
2134 * Since: 3.2.0
2135 */
2136 guint
ags_dial_get_radius(AgsDial * dial)2137 ags_dial_get_radius(AgsDial *dial)
2138 {
2139 guint radius;
2140
2141 if(!AGS_IS_DIAL(dial)){
2142 return(0);
2143 }
2144
2145 g_object_get(dial,
2146 "radius", &radius,
2147 NULL);
2148
2149 return(radius);
2150 }
2151
2152 /**
2153 * ags_dial_set_outline_strength:
2154 * @dial: the #AgsDial
2155 * @outline_strength: the outline strength
2156 *
2157 * Set outline strength of @dial.
2158 *
2159 * Since: 3.2.0
2160 */
2161 void
ags_dial_set_outline_strength(AgsDial * dial,guint outline_strength)2162 ags_dial_set_outline_strength(AgsDial *dial,
2163 guint outline_strength)
2164 {
2165 if(!AGS_IS_DIAL(dial)){
2166 return;
2167 }
2168
2169 g_object_set(dial,
2170 "outline-strength", outline_strength,
2171 NULL);
2172 }
2173
2174 /**
2175 * ags_dial_get_outline_strength:
2176 * @dial: the #AgsDial
2177 *
2178 * Get outline strength of @dial.
2179 *
2180 * Returns: the outline _strength
2181 *
2182 * Since: 3.2.0
2183 */
2184 guint
ags_dial_get_outline_strength(AgsDial * dial)2185 ags_dial_get_outline_strength(AgsDial *dial)
2186 {
2187 guint outline_strength;
2188
2189 if(!AGS_IS_DIAL(dial)){
2190 return(0);
2191 }
2192
2193 g_object_get(dial,
2194 "outline-strength", &outline_strength,
2195 NULL);
2196
2197 return(outline_strength);
2198 }
2199
2200 /**
2201 * ags_dial_set_scale_precision:
2202 * @dial: the #AgsDial
2203 * @scale_precision: the scale precision
2204 *
2205 * Set scale precision of @dial.
2206 *
2207 * Since: 3.2.0
2208 */
2209 void
ags_dial_set_scale_precision(AgsDial * dial,guint scale_precision)2210 ags_dial_set_scale_precision(AgsDial *dial,
2211 guint scale_precision)
2212 {
2213 if(!AGS_IS_DIAL(dial)){
2214 return;
2215 }
2216
2217 g_object_set(dial,
2218 "scale-precision", scale_precision,
2219 NULL);
2220 }
2221
2222 /**
2223 * ags_dial_get_scale_precision:
2224 * @dial: the #AgsDial
2225 *
2226 * Get scale precision of @dial.
2227 *
2228 * Returns: the scale precision
2229 *
2230 * Since: 3.2.0
2231 */
2232 guint
ags_dial_get_scale_precision(AgsDial * dial)2233 ags_dial_get_scale_precision(AgsDial *dial)
2234 {
2235 guint scale_precision;
2236
2237 if(!AGS_IS_DIAL(dial)){
2238 return(0);
2239 }
2240
2241 g_object_get(dial,
2242 "scale-precision", &scale_precision,
2243 NULL);
2244
2245 return(scale_precision);
2246 }
2247
2248 /**
2249 * ags_dial_set_font_size:
2250 * @dial: the #AgsDial
2251 * @font_size: the font size
2252 *
2253 * Set font size of @dial.
2254 *
2255 * Since: 3.2.0
2256 */
2257 void
ags_dial_set_font_size(AgsDial * dial,guint font_size)2258 ags_dial_set_font_size(AgsDial *dial,
2259 guint font_size)
2260 {
2261 if(!AGS_IS_DIAL(dial)){
2262 return;
2263 }
2264
2265 g_object_set(dial,
2266 "font-size", font_size,
2267 NULL);
2268 }
2269
2270 /**
2271 * ags_dial_get_font_size:
2272 * @dial: the #AgsDial
2273 *
2274 * Get font size of @dial.
2275 *
2276 * Returns: the font size
2277 *
2278 * Since: 3.2.0
2279 */
2280 guint
ags_dial_get_font_size(AgsDial * dial)2281 ags_dial_get_font_size(AgsDial *dial)
2282 {
2283 guint font_size;
2284
2285 if(!AGS_IS_DIAL(dial)){
2286 return(0);
2287 }
2288
2289 g_object_get(dial,
2290 "font-size", &font_size,
2291 NULL);
2292
2293 return(font_size);
2294 }
2295
2296 /**
2297 * ags_dial_set_button_width:
2298 * @dial: the #AgsDial
2299 * @button_width: the button width
2300 *
2301 * Set button width of @dial.
2302 *
2303 * Since: 3.2.0
2304 */
2305 void
ags_dial_set_button_width(AgsDial * dial,gint button_width)2306 ags_dial_set_button_width(AgsDial *dial,
2307 gint button_width)
2308 {
2309 if(!AGS_IS_DIAL(dial)){
2310 return;
2311 }
2312
2313 g_object_set(dial,
2314 "button-width", button_width,
2315 NULL);
2316 }
2317
2318 /**
2319 * ags_dial_get_button_width:
2320 * @dial: the #AgsDial
2321 *
2322 * Get button width of @dial.
2323 *
2324 * Returns: the button width
2325 *
2326 * Since: 3.2.0
2327 */
2328 gint
ags_dial_get_button_width(AgsDial * dial)2329 ags_dial_get_button_width(AgsDial *dial)
2330 {
2331 gint button_width;
2332
2333 if(!AGS_IS_DIAL(dial)){
2334 return(-1);
2335 }
2336
2337 g_object_get(dial,
2338 "button-width", &button_width,
2339 NULL);
2340
2341 return(button_width);
2342 }
2343
2344 /**
2345 * ags_dial_set_button_height:
2346 * @dial: the #AgsDial
2347 * @button_height: the button height
2348 *
2349 * Set button height of @dial.
2350 *
2351 * Since: 3.2.0
2352 */
2353 void
ags_dial_set_button_height(AgsDial * dial,gint button_height)2354 ags_dial_set_button_height(AgsDial *dial,
2355 gint button_height)
2356 {
2357 if(!AGS_IS_DIAL(dial)){
2358 return;
2359 }
2360
2361 g_object_set(dial,
2362 "button-height", button_height,
2363 NULL);
2364 }
2365
2366 /**
2367 * ags_dial_get_button_height:
2368 * @dial: the #AgsDial
2369 *
2370 * Get button height of @dial.
2371 *
2372 * Returns: the button height
2373 *
2374 * Since: 3.2.0
2375 */
2376 gint
ags_dial_get_button_height(AgsDial * dial)2377 ags_dial_get_button_height(AgsDial *dial)
2378 {
2379 gint button_height;
2380
2381 if(!AGS_IS_DIAL(dial)){
2382 return(-1);
2383 }
2384
2385 g_object_get(dial,
2386 "button-height", &button_height,
2387 NULL);
2388
2389 return(button_height);
2390 }
2391
2392 /**
2393 * ags_dial_set_margin_left:
2394 * @dial: the #AgsDial
2395 * @margin_left: the margin left
2396 *
2397 * Set margin left of @dial.
2398 *
2399 * Since: 3.2.0
2400 */
2401 void
ags_dial_set_margin_left(AgsDial * dial,gint margin_left)2402 ags_dial_set_margin_left(AgsDial *dial,
2403 gint margin_left)
2404 {
2405 if(!AGS_IS_DIAL(dial)){
2406 return;
2407 }
2408
2409 g_object_set(dial,
2410 "margin-left", margin_left,
2411 NULL);
2412 }
2413
2414 /**
2415 * ags_dial_get_margin_left:
2416 * @dial: the #AgsDial
2417 *
2418 * Get margin_left of @dial.
2419 *
2420 * Returns: the margin left
2421 *
2422 * Since: 3.2.0
2423 */
2424 gint
ags_dial_get_margin_left(AgsDial * dial)2425 ags_dial_get_margin_left(AgsDial *dial)
2426 {
2427 gint margin_left;
2428
2429 if(!AGS_IS_DIAL(dial)){
2430 return(-1);
2431 }
2432
2433 g_object_set(dial,
2434 "margin-left", &margin_left,
2435 NULL);
2436
2437 return(margin_left);
2438 }
2439
2440 /**
2441 * ags_dial_set_margin_right:
2442 * @dial: the #AgsDial
2443 * @margin_right: the margin right
2444 *
2445 * Set margin right of @dial.
2446 *
2447 * Since: 3.2.0
2448 */
2449 void
ags_dial_set_margin_right(AgsDial * dial,gint margin_right)2450 ags_dial_set_margin_right(AgsDial *dial,
2451 gint margin_right)
2452 {
2453 if(!AGS_IS_DIAL(dial)){
2454 return;
2455 }
2456
2457 g_object_set(dial,
2458 "margin-right", margin_right,
2459 NULL);
2460 }
2461
2462 /**
2463 * ags_dial_get_margin_right:
2464 * @dial: the #AgsDial
2465 *
2466 * Get margin right of @dial.
2467 *
2468 * Returns: the margin right
2469 *
2470 * Since: 3.2.0
2471 */
2472 gint
ags_dial_get_margin_right(AgsDial * dial)2473 ags_dial_get_margin_right(AgsDial *dial)
2474 {
2475 gint margin_right;
2476
2477 if(!AGS_IS_DIAL(dial)){
2478 return(-1);
2479 }
2480
2481 g_object_get(dial,
2482 "margin-right", &margin_right,
2483 NULL);
2484
2485 return(margin_right);
2486 }
2487
2488 /**
2489 * ags_dial_set_adjustment:
2490 * @dial: the #AgsDial
2491 * @adjustment: (transfer none): the #GtkAdjustment
2492 *
2493 * Set adjustment of @dial.
2494 *
2495 * Since: 3.2.0
2496 */
2497 void
ags_dial_set_adjustment(AgsDial * dial,GtkAdjustment * adjustment)2498 ags_dial_set_adjustment(AgsDial *dial,
2499 GtkAdjustment *adjustment)
2500 {
2501 if(!AGS_IS_DIAL(dial)){
2502 return;
2503 }
2504
2505 g_object_set(dial,
2506 "adjustment", adjustment,
2507 NULL);
2508 }
2509
2510 /**
2511 * ags_dial_get_adjustment:
2512 * @dial: the #AgsDial
2513 *
2514 * Get adjustment of @dial.
2515 *
2516 * Returns: (transfer full): the #GtkAdjustment
2517 *
2518 * Since: 3.2.0
2519 */
2520 GtkAdjustment*
ags_dial_get_adjustment(AgsDial * dial)2521 ags_dial_get_adjustment(AgsDial *dial)
2522 {
2523 GtkAdjustment *adjustment;
2524
2525 if(!AGS_IS_DIAL(dial)){
2526 return(NULL);
2527 }
2528
2529 g_object_get(dial,
2530 "adjustment", &adjustment,
2531 NULL);
2532
2533 return(adjustment);
2534 }
2535
2536 /**
2537 * ags_dial_value_changed:
2538 * @dial: an #AgsDial
2539 *
2540 * draws the widget
2541 *
2542 * Since: 3.0.0
2543 */
2544 void
ags_dial_value_changed(AgsDial * dial)2545 ags_dial_value_changed(AgsDial *dial)
2546 {
2547 g_return_if_fail(AGS_IS_DIAL(dial));
2548
2549 g_object_ref((GObject *) dial);
2550 g_signal_emit(G_OBJECT(dial),
2551 dial_signals[VALUE_CHANGED], 0);
2552 g_object_unref((GObject *) dial);
2553 }
2554
2555 void
ags_dial_adjustment_changed_callback(GtkAdjustment * adjustment,AgsDial * dial)2556 ags_dial_adjustment_changed_callback(GtkAdjustment *adjustment,
2557 AgsDial *dial)
2558 {
2559 ags_dial_value_changed(dial);
2560 }
2561
2562 /**
2563 * ags_dial_set_value:
2564 * @dial: an #AgsDial
2565 * @value: the value to set
2566 *
2567 * Set value
2568 *
2569 * Since: 3.0.0
2570 */
2571 void
ags_dial_set_value(AgsDial * dial,gdouble value)2572 ags_dial_set_value(AgsDial *dial,
2573 gdouble value)
2574 {
2575 if(!AGS_IS_DIAL(dial)){
2576 return;
2577 }
2578
2579 gtk_adjustment_set_value(dial->adjustment,
2580 value);
2581 gtk_widget_queue_draw((GtkWidget *) dial);
2582 }
2583
2584 /**
2585 * ags_dial_new:
2586 *
2587 * Creates an #AgsDial
2588 *
2589 * Returns: a new #AgsDial
2590 *
2591 * Since: 3.0.0
2592 */
2593 AgsDial*
ags_dial_new()2594 ags_dial_new()
2595 {
2596 AgsDial *dial;
2597 GtkAdjustment *adjustment;
2598
2599 adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 1.0, 0.1, 0.1, 0.0);
2600
2601 dial = (AgsDial *) g_object_new(AGS_TYPE_DIAL,
2602 "adjustment", adjustment,
2603 NULL);
2604
2605 return(dial);
2606 }
2607