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/widget/ags_scale.h>
21
22 #include <pango/pango.h>
23
24 #ifndef __APPLE__
25 #include <pango/pangofc-fontmap.h>
26 #endif
27
28 #include <atk/atk.h>
29
30 #include <gdk/gdkkeysyms.h>
31
32 #include <math.h>
33
34 static GType ags_accessible_scale_get_type(void);
35 void ags_scale_class_init(AgsScaleClass *scale);
36 void ags_scale_init(AgsScale *scale);
37 void ags_accessible_scale_class_init(AtkObject *object);
38 void ags_accessible_scale_value_interface_init(AtkValueIface *value);
39 void ags_accessible_scale_action_interface_init(AtkActionIface *action);
40 void ags_scale_set_property(GObject *gobject,
41 guint prop_id,
42 const GValue *value,
43 GParamSpec *param_spec);
44 void ags_scale_get_property(GObject *gobject,
45 guint prop_id,
46 GValue *value,
47 GParamSpec *param_spec);
48 void ags_scale_finalize(GObject *gobject);
49 AtkObject* ags_scale_get_accessible(GtkWidget *widget);
50 void ags_scale_show(GtkWidget *widget);
51
52 void ags_accessible_scale_get_value_and_text(AtkValue *value,
53 gdouble *current_value,
54 gchar **text);
55 #ifdef HAVE_ATK_2_12
56 AtkRange* ags_accessible_scale_get_range(AtkValue *value);
57 #endif
58 gdouble ags_accessible_scale_get_increment(AtkValue *value);
59 void ags_accessible_scale_set_value(AtkValue *value,
60 gdouble new_value);
61
62 gboolean ags_accessible_scale_do_action(AtkAction *action,
63 gint i);
64 gint ags_accessible_scale_get_n_actions(AtkAction *action);
65 const gchar* ags_accessible_scale_get_description(AtkAction *action,
66 gint i);
67 const gchar* ags_accessible_scale_get_name(AtkAction *action,
68 gint i);
69 const gchar* ags_accessible_scale_get_keybinding(AtkAction *action,
70 gint i);
71 gboolean ags_accessible_scale_set_description(AtkAction *action,
72 gint i);
73 gchar* ags_accessible_scale_get_localized_name(AtkAction *action,
74 gint i);
75
76 void ags_scale_map(GtkWidget *widget);
77 void ags_scale_realize(GtkWidget *widget);
78 void ags_scale_size_allocate(GtkWidget *widget,
79 GtkAllocation *allocation);
80 void ags_scale_get_preferred_width(GtkWidget *widget,
81 gint *minimal_width,
82 gint *natural_width);
83 void ags_scale_get_preferred_height(GtkWidget *widget,
84 gint *minimal_height,
85 gint *natural_height);
86 gboolean ags_scale_button_press(GtkWidget *widget,
87 GdkEventButton *event);
88 gboolean ags_scale_button_release(GtkWidget *widget,
89 GdkEventButton *event);
90 gboolean ags_scale_key_press(GtkWidget *widget,
91 GdkEventKey *event);
92 gboolean ags_scale_key_release(GtkWidget *widget,
93 GdkEventKey *event);
94 gboolean ags_scale_motion_notify(GtkWidget *widget,
95 GdkEventMotion *event);
96
97 void ags_scale_send_configure(AgsScale *scale);
98
99 gboolean ags_scale_draw(AgsScale *scale, cairo_t *cr);
100
101 /**
102 * SECTION:ags_scale
103 * @short_description: A scale widget
104 * @title: AgsScale
105 * @section_id:
106 * @include: ags/widget/ags_scale.h
107 *
108 * #AgsScale is a widget that shows you a meter.
109 */
110
111 enum{
112 VALUE_CHANGED,
113 LAST_SIGNAL,
114 };
115
116 enum{
117 PROP_0,
118 PROP_SCALE_WIDTH,
119 PROP_SCALE_HEIGHT,
120 PROP_CONTROL_NAME,
121 PROP_LOWER,
122 PROP_UPPER,
123 PROP_DEFAULT_VALUE,
124 };
125
126 static gpointer ags_scale_parent_class = NULL;
127 static guint scale_signals[LAST_SIGNAL];
128
129 static GQuark quark_accessible_object = 0;
130
131 GType
ags_scale_get_type(void)132 ags_scale_get_type(void)
133 {
134 static volatile gsize g_define_type_id__volatile = 0;
135
136 if(g_once_init_enter (&g_define_type_id__volatile)){
137 GType ags_type_scale = 0;
138
139 static const GTypeInfo ags_scale_info = {
140 sizeof(AgsScaleClass),
141 NULL, /* base_init */
142 NULL, /* base_finalize */
143 (GClassInitFunc) ags_scale_class_init,
144 NULL, /* class_finalize */
145 NULL, /* class_data */
146 sizeof(AgsScale),
147 0, /* n_preallocs */
148 (GInstanceInitFunc) ags_scale_init,
149 };
150
151 ags_type_scale = g_type_register_static(GTK_TYPE_WIDGET,
152 "AgsScale", &ags_scale_info,
153 0);
154
155 g_once_init_leave(&g_define_type_id__volatile, ags_type_scale);
156 }
157
158 return g_define_type_id__volatile;
159 }
160
161 static GType
ags_accessible_scale_get_type(void)162 ags_accessible_scale_get_type(void)
163 {
164 static GType ags_type_accessible_scale = 0;
165
166 if(!ags_type_accessible_scale){
167 const GTypeInfo ags_accesssible_scale_info = {
168 sizeof(GtkAccessibleClass),
169 NULL, /* base_init */
170 NULL, /* base_finalize */
171 (GClassInitFunc) ags_accessible_scale_class_init,
172 NULL, /* class_finalize */
173 NULL, /* class_data */
174 sizeof(GtkAccessible),
175 0, /* n_preallocs */
176 NULL, NULL
177 };
178
179 static const GInterfaceInfo atk_value_interface_info = {
180 (GInterfaceInitFunc) ags_accessible_scale_value_interface_init,
181 NULL, /* interface_finalize */
182 NULL, /* interface_data */
183 };
184
185 static const GInterfaceInfo atk_action_interface_info = {
186 (GInterfaceInitFunc) ags_accessible_scale_action_interface_init,
187 NULL, /* interface_finalize */
188 NULL, /* interface_data */
189 };
190
191 ags_type_accessible_scale = g_type_register_static(GTK_TYPE_ACCESSIBLE,
192 "AgsAccessibleScale", &ags_accesssible_scale_info,
193 0);
194
195 g_type_add_interface_static(ags_type_accessible_scale,
196 ATK_TYPE_VALUE,
197 &atk_value_interface_info);
198
199 g_type_add_interface_static(ags_type_accessible_scale,
200 ATK_TYPE_ACTION,
201 &atk_action_interface_info);
202 }
203
204 return(ags_type_accessible_scale);
205 }
206
207 void
ags_scale_class_init(AgsScaleClass * scale)208 ags_scale_class_init(AgsScaleClass *scale)
209 {
210 GObjectClass *gobject;
211 GtkWidgetClass *widget;
212 GParamSpec *param_spec;
213
214 ags_scale_parent_class = g_type_class_peek_parent(scale);
215
216 quark_accessible_object = g_quark_from_static_string("ags-accessible-object");
217
218 /* GObjectClass */
219 gobject = (GObjectClass *) scale;
220
221 gobject->set_property = ags_scale_set_property;
222 gobject->get_property = ags_scale_get_property;
223
224 gobject->finalize = ags_scale_finalize;
225
226 /* properties */
227 /**
228 * AgsScale:scale-width:
229 *
230 * The scale width to use for drawing a scale.
231 *
232 * Since: 3.0.0
233 */
234 param_spec = g_param_spec_uint("scale-width",
235 "scale width",
236 "The scale width to use for drawing",
237 0,
238 G_MAXUINT,
239 AGS_SCALE_DEFAULT_SCALE_WIDTH,
240 G_PARAM_READABLE | G_PARAM_WRITABLE);
241 g_object_class_install_property(gobject,
242 PROP_SCALE_WIDTH,
243 param_spec);
244
245 /**
246 * AgsScale:scale-height:
247 *
248 * The scale height to use for drawing a scale.
249 *
250 * Since: 3.0.0
251 */
252 param_spec = g_param_spec_uint("scale-height",
253 "scale height",
254 "The scale height to use for drawing",
255 0,
256 G_MAXUINT,
257 AGS_SCALE_DEFAULT_SCALE_HEIGHT,
258 G_PARAM_READABLE | G_PARAM_WRITABLE);
259 g_object_class_install_property(gobject,
260 PROP_SCALE_HEIGHT,
261 param_spec);
262
263 /**
264 * AgsScale:control-name:
265 *
266 * The scale's control name.
267 *
268 * Since: 3.0.0
269 */
270 param_spec = g_param_spec_string("control-name",
271 "control name",
272 "The control name of scale",
273 NULL,
274 G_PARAM_READABLE | G_PARAM_WRITABLE);
275 g_object_class_install_property(gobject,
276 PROP_CONTROL_NAME,
277 param_spec);
278
279 /**
280 * AgsScale:lower:
281 *
282 * The scale's lower range.
283 *
284 * Since: 3.0.0
285 */
286 param_spec = g_param_spec_double("lower",
287 "lower",
288 "The lower of scale",
289 -G_MAXDOUBLE,
290 G_MAXDOUBLE,
291 AGS_SCALE_DEFAULT_LOWER,
292 G_PARAM_READABLE | G_PARAM_WRITABLE);
293 g_object_class_install_property(gobject,
294 PROP_LOWER,
295 param_spec);
296
297 /**
298 * AgsScale:upper:
299 *
300 * The scale's upper range.
301 *
302 * Since: 3.0.0
303 */
304 param_spec = g_param_spec_double("upper",
305 "upper",
306 "The upper of scale",
307 -G_MAXDOUBLE,
308 G_MAXDOUBLE,
309 AGS_SCALE_DEFAULT_UPPER,
310 G_PARAM_READABLE | G_PARAM_WRITABLE);
311 g_object_class_install_property(gobject,
312 PROP_UPPER,
313 param_spec);
314
315 /**
316 * AgsScale:default-value:
317 *
318 * The scale's default value.
319 *
320 * Since: 3.0.0
321 */
322 param_spec = g_param_spec_double("default-value",
323 "default value",
324 "The default value of scale",
325 -G_MAXDOUBLE,
326 G_MAXDOUBLE,
327 AGS_SCALE_DEFAULT_VALUE,
328 G_PARAM_READABLE | G_PARAM_WRITABLE);
329 g_object_class_install_property(gobject,
330 PROP_DEFAULT_VALUE,
331 param_spec);
332
333 /* GtkWidgetClass */
334 widget = (GtkWidgetClass *) scale;
335
336 widget->get_accessible = ags_scale_get_accessible;
337 // widget->map = ags_scale_map;
338 widget->realize = ags_scale_realize;
339 widget->size_allocate = ags_scale_size_allocate;
340 widget->get_preferred_width = ags_scale_get_preferred_width;
341 widget->get_preferred_height = ags_scale_get_preferred_height;
342 widget->button_press_event = ags_scale_button_press;
343 widget->button_release_event = ags_scale_button_release;
344 widget->key_press_event = ags_scale_key_press;
345 widget->key_release_event = ags_scale_key_release;
346 widget->motion_notify_event = ags_scale_motion_notify;
347 widget->draw = ags_scale_draw;
348 widget->show = ags_scale_show;
349
350 /* AgsScaleClass */
351 scale->value_changed = NULL;
352
353 /* signals */
354 /**
355 * AgsScale::value-changed:
356 * @scale: the #AgsScale
357 * @default_value: the changed default value
358 *
359 * The ::value-changed signal notifies about modified default value.
360 *
361 * Since: 3.0.0
362 */
363 scale_signals[VALUE_CHANGED] =
364 g_signal_new("value-changed",
365 G_TYPE_FROM_CLASS(scale),
366 G_SIGNAL_RUN_LAST,
367 G_STRUCT_OFFSET(AgsScaleClass, value_changed),
368 NULL, NULL,
369 g_cclosure_marshal_VOID__DOUBLE,
370 G_TYPE_NONE, 1,
371 G_TYPE_DOUBLE);
372 }
373
374 void
ags_accessible_scale_class_init(AtkObject * object)375 ags_accessible_scale_class_init(AtkObject *object)
376 {
377 /* empty */
378 }
379
380 void
ags_accessible_scale_value_interface_init(AtkValueIface * value)381 ags_accessible_scale_value_interface_init(AtkValueIface *value)
382 {
383 value->get_current_value = NULL;
384 value->get_maximum_value = NULL;
385 value->get_minimum_value = NULL;
386 value->set_current_value = NULL;
387 value->get_minimum_increment = NULL;
388
389 #ifdef HAVE_ATK_2_12
390 value->get_value_and_text = ags_accessible_scale_get_value_and_text;
391 value->get_range = ags_accessible_scale_get_range;
392 value->get_increment = ags_accessible_scale_get_increment;
393 value->get_sub_ranges = NULL;
394 value->set_value = ags_accessible_scale_set_value;
395 #endif
396 }
397
398 void
ags_accessible_scale_action_interface_init(AtkActionIface * action)399 ags_accessible_scale_action_interface_init(AtkActionIface *action)
400 {
401 action->do_action = ags_accessible_scale_do_action;
402 action->get_n_actions = ags_accessible_scale_get_n_actions;
403 action->get_description = ags_accessible_scale_get_description;
404 action->get_name = ags_accessible_scale_get_name;
405 action->get_keybinding = ags_accessible_scale_get_keybinding;
406 action->set_description = ags_accessible_scale_set_description;
407 action->get_localized_name = ags_accessible_scale_get_localized_name;
408 }
409
410 void
ags_scale_init(AgsScale * scale)411 ags_scale_init(AgsScale *scale)
412 {
413 AtkObject *accessible;
414
415 g_object_set(G_OBJECT(scale),
416 "app-paintable", TRUE,
417 "can-focus", TRUE,
418 NULL);
419
420 accessible = gtk_widget_get_accessible((GtkWidget *) scale);
421
422 g_object_set(accessible,
423 "accessible-name", "scale",
424 "accessible-description", "Specify a default value",
425 NULL);
426
427 scale->flags = 0;
428
429 scale->key_mask = 0;
430 scale->button_state = 0;
431 scale->layout = AGS_SCALE_LAYOUT_VERTICAL;
432
433 scale->font_size = 11;
434
435 scale->scale_width = AGS_SCALE_DEFAULT_SCALE_WIDTH;
436 scale->scale_height = AGS_SCALE_DEFAULT_SCALE_HEIGHT;
437
438 scale->control_name = NULL;
439
440 scale->lower = AGS_SCALE_DEFAULT_LOWER;
441 scale->upper = AGS_SCALE_DEFAULT_UPPER;
442
443 scale->default_value = AGS_SCALE_DEFAULT_VALUE;
444
445 scale->step_count = AGS_SCALE_DEFAULT_STEP_COUNT;
446 scale->page_size = AGS_SCALE_DEFAULT_PAGE_SIZE;
447
448 scale->scale_step_count = -1;
449 scale->scale_point = NULL;
450 scale->scale_value = NULL;
451 }
452
453 void
ags_scale_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)454 ags_scale_set_property(GObject *gobject,
455 guint prop_id,
456 const GValue *value,
457 GParamSpec *param_spec)
458 {
459 AgsScale *scale;
460
461 scale = AGS_SCALE(gobject);
462
463 switch(prop_id){
464 case PROP_SCALE_WIDTH:
465 {
466 scale->scale_width = g_value_get_uint(value);
467 }
468 break;
469 case PROP_SCALE_HEIGHT:
470 {
471 scale->scale_height = g_value_get_uint(value);
472 }
473 break;
474 case PROP_CONTROL_NAME:
475 {
476 gchar *control_name;
477
478 control_name = g_value_get_string(value);
479
480 g_free(scale->control_name);
481
482 scale->control_name = g_strdup(control_name);
483 }
484 break;
485 case PROP_LOWER:
486 {
487 scale->lower = g_value_get_double(value);
488
489 gtk_widget_queue_draw((GtkWidget *) scale);
490 }
491 break;
492 case PROP_UPPER:
493 {
494 scale->upper = g_value_get_double(value);
495
496 gtk_widget_queue_draw((GtkWidget *) scale);
497 }
498 break;
499 case PROP_DEFAULT_VALUE:
500 {
501 scale->default_value = g_value_get_double(value);
502
503 gtk_widget_queue_draw((GtkWidget *) scale);
504 }
505 break;
506 default:
507 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
508 break;
509 }
510 }
511
512 void
ags_scale_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)513 ags_scale_get_property(GObject *gobject,
514 guint prop_id,
515 GValue *value,
516 GParamSpec *param_spec)
517 {
518 AgsScale *scale;
519
520 scale = AGS_SCALE(gobject);
521
522 switch(prop_id){
523 case PROP_SCALE_WIDTH:
524 {
525 g_value_set_uint(value,
526 scale->scale_width);
527 }
528 break;
529 case PROP_SCALE_HEIGHT:
530 {
531 g_value_set_uint(value,
532 scale->scale_height);
533 }
534 break;
535 case PROP_CONTROL_NAME:
536 {
537 g_value_set_string(value,
538 scale->control_name);
539 }
540 break;
541 case PROP_LOWER:
542 {
543 g_value_set_double(value,
544 scale->lower);
545 }
546 break;
547 case PROP_UPPER:
548 {
549 g_value_set_double(value,
550 scale->upper);
551 }
552 break;
553 case PROP_DEFAULT_VALUE:
554 {
555 g_value_set_double(value,
556 scale->default_value);
557 }
558 break;
559 default:
560 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
561 break;
562 }
563 }
564
565 void
ags_scale_finalize(GObject * gobject)566 ags_scale_finalize(GObject *gobject)
567 {
568 AgsScale *scale;
569
570 scale = AGS_SCALE(gobject);
571
572 g_free(scale->control_name);
573
574 /* call parent */
575 G_OBJECT_CLASS(ags_scale_parent_class)->finalize(gobject);
576 }
577
578 void
ags_accessible_scale_get_value_and_text(AtkValue * value,gdouble * current_value,gchar ** text)579 ags_accessible_scale_get_value_and_text(AtkValue *value,
580 gdouble *current_value,
581 gchar **text)
582 {
583 AgsScale *scale;
584
585 scale = (AgsScale *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
586
587 if(current_value != NULL){
588 *current_value = scale->default_value;
589 }
590
591 if(text != NULL){
592 *text = g_strdup_printf("%f",
593 scale->default_value);
594 }
595 }
596
597 #ifdef HAVE_ATK_2_12
598 AtkRange*
ags_accessible_scale_get_range(AtkValue * value)599 ags_accessible_scale_get_range(AtkValue *value)
600 {
601 AgsScale *scale;
602 AtkRange *range;
603
604 scale = (AgsScale *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
605
606 range = atk_range_new(scale->lower,
607 scale->upper,
608 "Valid lower and upper input range of this scale");
609
610 return(range);
611 }
612 #endif
613
614 gdouble
ags_accessible_scale_get_increment(AtkValue * value)615 ags_accessible_scale_get_increment(AtkValue *value)
616 {
617 AgsScale *scale;
618
619 scale = (AgsScale *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
620
621 return((scale->upper - scale->lower) / scale->step_count);
622 }
623
624 void
ags_accessible_scale_set_value(AtkValue * value,gdouble new_value)625 ags_accessible_scale_set_value(AtkValue *value,
626 gdouble new_value)
627 {
628 AgsScale *scale;
629
630 scale = (AgsScale *) gtk_accessible_get_widget(GTK_ACCESSIBLE(value));
631 scale->default_value = new_value;
632
633 gtk_widget_queue_draw((GtkWidget *) scale);
634 }
635
636 gboolean
ags_accessible_scale_do_action(AtkAction * action,gint i)637 ags_accessible_scale_do_action(AtkAction *action,
638 gint i)
639 {
640 AgsScale *scale;
641
642 GdkEventKey *key_press, *key_release;
643
644 if(!(i >= 0 && i < 4)){
645 return(FALSE);
646 }
647
648 scale = (AgsScale *) gtk_accessible_get_widget(GTK_ACCESSIBLE(action));
649
650 key_press = gdk_event_new(GDK_KEY_PRESS);
651 key_release = gdk_event_new(GDK_KEY_RELEASE);
652
653 switch(i){
654 case AGS_SCALE_STEP_UP:
655 {
656 key_press->keyval =
657 key_release->keyval = GDK_KEY_Up;
658
659 /* send event */
660 gtk_widget_event((GtkWidget *) scale,
661 (GdkEvent *) key_press);
662 gtk_widget_event((GtkWidget *) scale,
663 (GdkEvent *) key_release);
664 }
665 break;
666 case AGS_SCALE_STEP_DOWN:
667 {
668 key_press->keyval =
669 key_release->keyval = GDK_KEY_Down;
670
671 /* send event */
672 gtk_widget_event((GtkWidget *) scale,
673 (GdkEvent *) key_press);
674 gtk_widget_event((GtkWidget *) scale,
675 (GdkEvent *) key_release);
676 }
677 break;
678 case AGS_SCALE_PAGE_UP:
679 {
680 key_press->keyval =
681 key_release->keyval = GDK_KEY_Page_Up;
682
683 /* send event */
684 gtk_widget_event((GtkWidget *) scale,
685 (GdkEvent *) key_press);
686 gtk_widget_event((GtkWidget *) scale,
687 (GdkEvent *) key_release);
688 }
689 break;
690 case AGS_SCALE_PAGE_DOWN:
691 {
692 key_press->keyval =
693 key_release->keyval = GDK_KEY_Page_Down;
694
695 /* send event */
696 gtk_widget_event((GtkWidget *) scale,
697 (GdkEvent *) key_press);
698 gtk_widget_event((GtkWidget *) scale,
699 (GdkEvent *) key_release);
700 }
701 break;
702 }
703
704 return(TRUE);
705 }
706
707 gint
ags_accessible_scale_get_n_actions(AtkAction * action)708 ags_accessible_scale_get_n_actions(AtkAction *action)
709 {
710 return(4);
711 }
712
713 const gchar*
ags_accessible_scale_get_description(AtkAction * action,gint i)714 ags_accessible_scale_get_description(AtkAction *action,
715 gint i)
716 {
717 static const gchar *actions[] = {
718 "step up scale default value",
719 "step down scale default value",
720 "page up scale default value",
721 "page down scale default value",
722 };
723
724 if(i >= 0 && i < 4){
725 return(actions[i]);
726 }else{
727 return(NULL);
728 }
729 }
730
731 const gchar*
ags_accessible_scale_get_name(AtkAction * action,gint i)732 ags_accessible_scale_get_name(AtkAction *action,
733 gint i)
734 {
735 static const gchar *actions[] = {
736 "step-up",
737 "step-down",
738 "page-up",
739 "page-down",
740 };
741
742 if(i >= 0 && i < 4){
743 return(actions[i]);
744 }else{
745 return(NULL);
746 }
747 }
748
749 const gchar*
ags_accessible_scale_get_keybinding(AtkAction * action,gint i)750 ags_accessible_scale_get_keybinding(AtkAction *action,
751 gint i)
752 {
753 static const gchar *actions[] = {
754 "up",
755 "down",
756 "page-up",
757 "page-down",
758 };
759
760 if(i >= 0 && i < 4){
761 return(actions[i]);
762 }else{
763 return(NULL);
764 }
765 }
766
767 gboolean
ags_accessible_scale_set_description(AtkAction * action,gint i)768 ags_accessible_scale_set_description(AtkAction *action,
769 gint i)
770 {
771 //TODO:JK: implement me
772
773 return(FALSE);
774 }
775
776 gchar*
ags_accessible_scale_get_localized_name(AtkAction * action,gint i)777 ags_accessible_scale_get_localized_name(AtkAction *action,
778 gint i)
779 {
780 //TODO:JK: implement me
781
782 return(NULL);
783 }
784
785 void
ags_scale_map(GtkWidget * widget)786 ags_scale_map(GtkWidget *widget)
787 {
788 if(gtk_widget_get_realized (widget) && !gtk_widget_get_mapped(widget)){
789 GTK_WIDGET_CLASS(ags_scale_parent_class)->map(widget);
790
791 gdk_window_show(gtk_widget_get_window(widget));
792 }
793 }
794
795 void
ags_scale_realize(GtkWidget * widget)796 ags_scale_realize(GtkWidget *widget)
797 {
798 AgsScale *scale;
799
800 GtkWindow *window;
801
802 GtkAllocation allocation;
803 GdkWindowAttr attributes;
804
805 gint attributes_mask;
806
807 g_return_if_fail(widget != NULL);
808 g_return_if_fail(AGS_IS_SCALE(widget));
809
810 scale = AGS_SCALE(widget);
811
812 gtk_widget_set_realized(widget, TRUE);
813
814 gtk_widget_get_allocation(widget,
815 &allocation);
816
817 /* */
818 attributes.window_type = GDK_WINDOW_CHILD;
819
820 attributes.x = allocation.x;
821 attributes.y = allocation.y;
822 attributes.width = scale->scale_width;
823 attributes.height = scale->scale_height;
824
825 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
826
827 attributes.wclass = GDK_INPUT_OUTPUT;
828 attributes.visual = gtk_widget_get_visual (widget);
829 attributes.event_mask = gtk_widget_get_events (widget);
830 attributes.event_mask |= (GDK_EXPOSURE_MASK);
831
832 window = gdk_window_new(gtk_widget_get_parent_window(widget),
833 &attributes, attributes_mask);
834
835 gtk_widget_register_window(widget, window);
836 gtk_widget_set_window(widget, window);
837
838 ags_scale_send_configure(scale);
839 }
840
841 void
ags_scale_size_allocate(GtkWidget * widget,GtkAllocation * allocation)842 ags_scale_size_allocate(GtkWidget *widget,
843 GtkAllocation *allocation)
844 {
845 AgsScale *scale;
846
847 GdkWindow *window;
848
849 g_return_if_fail(AGS_IS_SCALE(widget));
850 g_return_if_fail(allocation != NULL);
851
852 scale = AGS_SCALE(widget);
853
854 if(scale->layout == AGS_SCALE_LAYOUT_VERTICAL){
855 allocation->width = scale->scale_width;
856 allocation->height = scale->scale_height;
857 }else if(scale->layout == AGS_SCALE_LAYOUT_HORIZONTAL){
858 allocation->width = scale->scale_height;
859 allocation->height = scale->scale_width;
860 }
861
862 gtk_widget_set_allocation(widget, allocation);
863
864 if(gtk_widget_get_realized(widget)){
865 gdk_window_move_resize(gtk_widget_get_window(widget),
866 allocation->x, allocation->y,
867 allocation->width, allocation->height);
868
869 ags_scale_send_configure(scale);
870 }
871 }
872
873 void
ags_scale_send_configure(AgsScale * scale)874 ags_scale_send_configure(AgsScale *scale)
875 {
876 GtkAllocation allocation;
877 GtkWidget *widget;
878 GdkEvent *event = gdk_event_new (GDK_CONFIGURE);
879
880 widget = GTK_WIDGET(scale);
881 gtk_widget_get_allocation(widget, &allocation);
882
883 event->configure.window = g_object_ref(gtk_widget_get_window (widget));
884 event->configure.send_event = TRUE;
885 event->configure.x = allocation.x;
886 event->configure.y = allocation.y;
887 event->configure.width = allocation.width;
888 event->configure.height = allocation.height;
889
890 gtk_widget_event(widget, event);
891 gdk_event_free(event);
892 }
893
894 void
ags_scale_get_preferred_width(GtkWidget * widget,gint * minimal_width,gint * natural_width)895 ags_scale_get_preferred_width(GtkWidget *widget,
896 gint *minimal_width,
897 gint *natural_width)
898 {
899 AgsScale *scale;
900
901 scale = AGS_SCALE(widget);
902
903 if(scale->layout == AGS_SCALE_LAYOUT_VERTICAL){
904 minimal_width[0] =
905 natural_width[0] = scale->scale_width;
906 }else if(scale->layout == AGS_SCALE_LAYOUT_HORIZONTAL){
907 minimal_width[0] =
908 natural_width[0] = scale->scale_height;
909 }
910 }
911
912 void
ags_scale_get_preferred_height(GtkWidget * widget,gint * minimal_height,gint * natural_height)913 ags_scale_get_preferred_height(GtkWidget *widget,
914 gint *minimal_height,
915 gint *natural_height)
916 {
917 AgsScale *scale;
918
919 scale = AGS_SCALE(widget);
920
921 if(scale->layout == AGS_SCALE_LAYOUT_VERTICAL){
922 minimal_height[0] =
923 natural_height[0] = scale->scale_height;
924 }else if(scale->layout == AGS_SCALE_LAYOUT_HORIZONTAL){
925 minimal_height[0] =
926 natural_height[0] = scale->scale_width;
927 }
928 }
929
930 AtkObject*
ags_scale_get_accessible(GtkWidget * widget)931 ags_scale_get_accessible(GtkWidget *widget)
932 {
933 AtkObject* accessible;
934
935 accessible = g_object_get_qdata(G_OBJECT(widget),
936 quark_accessible_object);
937
938 if(!accessible){
939 accessible = g_object_new(ags_accessible_scale_get_type(),
940 NULL);
941
942 g_object_set_qdata(G_OBJECT(widget),
943 quark_accessible_object,
944 accessible);
945 gtk_accessible_set_widget(GTK_ACCESSIBLE(accessible),
946 widget);
947 }
948
949 return(accessible);
950 }
951
952 void
ags_scale_show(GtkWidget * widget)953 ags_scale_show(GtkWidget *widget)
954 {
955 GTK_WIDGET_CLASS(ags_scale_parent_class)->show(widget);
956 }
957
958 gboolean
ags_scale_button_press(GtkWidget * widget,GdkEventButton * event)959 ags_scale_button_press(GtkWidget *widget,
960 GdkEventButton *event)
961 {
962 AgsScale *scale;
963
964 GtkAllocation allocation;
965
966 guint width, height;
967 guint x_start, y_start;
968
969 scale = AGS_SCALE(widget);
970
971 gtk_widget_get_allocation(widget,
972 &allocation);
973
974 width = allocation.width;
975 height = allocation.height;
976
977 x_start = 0;
978 y_start = 0;
979
980 if(event->x >= x_start &&
981 event->x < width &&
982 event->y >= y_start &&
983 event->y < height){
984 if(event->button == 1){
985 gdouble c_range;
986 gdouble default_value;
987
988 scale->button_state |= AGS_SCALE_BUTTON_1_PRESSED;
989
990 if((AGS_SCALE_LOGARITHMIC & (scale->flags)) != 0){
991 c_range = exp(scale->upper) - exp(scale->lower);
992 }else{
993 c_range = scale->upper - scale->lower;
994 }
995
996 default_value = 0.0;
997
998 if(scale->layout == AGS_SCALE_LAYOUT_VERTICAL){
999 default_value = event->y / c_range;
1000 }else if(scale->layout == AGS_SCALE_LAYOUT_HORIZONTAL){
1001 default_value = event->x / c_range;
1002 }
1003
1004 scale->default_value = default_value;
1005 gtk_widget_queue_draw((GtkWidget *) scale);
1006
1007 ags_scale_value_changed(scale,
1008 default_value);
1009 }
1010 }
1011
1012 return(FALSE);
1013 }
1014
1015 gboolean
ags_scale_button_release(GtkWidget * widget,GdkEventButton * event)1016 ags_scale_button_release(GtkWidget *widget,
1017 GdkEventButton *event)
1018 {
1019 AgsScale *scale;
1020
1021 gtk_widget_grab_focus(widget);
1022
1023 scale = AGS_SCALE(widget);
1024
1025 if(event->button == 1){
1026 if((AGS_SCALE_BUTTON_1_PRESSED & (scale->button_state)) != 0){
1027 gdouble c_range;
1028 gdouble default_value;
1029
1030 scale->button_state |= AGS_SCALE_BUTTON_1_PRESSED;
1031
1032 if((AGS_SCALE_LOGARITHMIC & (scale->flags)) != 0){
1033 c_range = exp(scale->upper) - exp(scale->lower);
1034 }else{
1035 c_range = scale->upper - scale->lower;
1036 }
1037
1038 default_value = 0.0;
1039
1040 if(scale->layout == AGS_SCALE_LAYOUT_VERTICAL){
1041 default_value = event->y / c_range;
1042 }else if(scale->layout == AGS_SCALE_LAYOUT_HORIZONTAL){
1043 default_value = event->x / c_range;
1044 }
1045
1046 scale->default_value = default_value;
1047 gtk_widget_queue_draw((GtkWidget *) scale);
1048
1049 ags_scale_value_changed(scale,
1050 default_value);
1051 }
1052
1053 scale->button_state &= (~AGS_SCALE_BUTTON_1_PRESSED);
1054 }
1055
1056 return(FALSE);
1057 }
1058
1059 gboolean
ags_scale_key_press(GtkWidget * widget,GdkEventKey * event)1060 ags_scale_key_press(GtkWidget *widget,
1061 GdkEventKey *event)
1062 {
1063 if(event->keyval == GDK_KEY_Tab ||
1064 event->keyval == GDK_KEY_ISO_Left_Tab ||
1065 event->keyval == GDK_KEY_Shift_L ||
1066 event->keyval == GDK_KEY_Shift_R ||
1067 event->keyval == GDK_KEY_Alt_L ||
1068 event->keyval == GDK_KEY_Alt_R ||
1069 event->keyval == GDK_KEY_Control_L ||
1070 event->keyval == GDK_KEY_Control_R ){
1071 return(GTK_WIDGET_CLASS(ags_scale_parent_class)->key_press_event(widget, event));
1072 }
1073
1074 return(TRUE);
1075 }
1076
1077 gboolean
ags_scale_key_release(GtkWidget * widget,GdkEventKey * event)1078 ags_scale_key_release(GtkWidget *widget,
1079 GdkEventKey *event)
1080 {
1081 AgsScale *scale;
1082
1083 //TODO:JK: implement me
1084
1085 if(event->keyval == GDK_KEY_Tab ||
1086 event->keyval == GDK_KEY_ISO_Left_Tab ||
1087 event->keyval == GDK_KEY_Shift_L ||
1088 event->keyval == GDK_KEY_Shift_R ||
1089 event->keyval == GDK_KEY_Alt_L ||
1090 event->keyval == GDK_KEY_Alt_R ||
1091 event->keyval == GDK_KEY_Control_L ||
1092 event->keyval == GDK_KEY_Control_R ){
1093 return(GTK_WIDGET_CLASS(ags_scale_parent_class)->key_release_event(widget, event));
1094 }
1095
1096 scale = AGS_SCALE(widget);
1097
1098 switch(event->keyval){
1099 case GDK_KEY_Up:
1100 case GDK_KEY_uparrow:
1101 {
1102 gdouble c_range;
1103 gdouble step;
1104
1105 if((AGS_SCALE_LOGARITHMIC & (scale->flags)) != 0){
1106 c_range = exp(scale->upper) - exp(scale->lower);
1107 }else{
1108 c_range = scale->upper - scale->lower;
1109 }
1110
1111 step = c_range / scale->step_count;
1112
1113 if(scale->default_value + log(step) > scale->upper){
1114 scale->default_value = scale->upper;
1115 }else{
1116 scale->default_value += log(step);
1117 }
1118
1119 gtk_widget_queue_draw(widget);
1120
1121 ags_scale_value_changed(scale,
1122 scale->default_value);
1123 }
1124 break;
1125 case GDK_KEY_Down:
1126 case GDK_KEY_downarrow:
1127 {
1128 gdouble c_range;
1129 gdouble step;
1130
1131 if((AGS_SCALE_LOGARITHMIC & (scale->flags)) != 0){
1132 c_range = exp(scale->upper) - exp(scale->lower);
1133 }else{
1134 c_range = scale->upper - scale->lower;
1135 }
1136
1137 step = c_range / scale->step_count;
1138
1139 if(scale->default_value - log(step) < scale->lower){
1140 scale->default_value = scale->lower;
1141 }else{
1142 scale->default_value -= log(step);
1143 }
1144
1145 gtk_widget_queue_draw(widget);
1146
1147 ags_scale_value_changed(scale,
1148 scale->default_value);
1149 }
1150 break;
1151 case GDK_KEY_Page_Up:
1152 case GDK_KEY_KP_Page_Up:
1153 {
1154 gdouble c_range;
1155 gdouble page;
1156
1157 if((AGS_SCALE_LOGARITHMIC & (scale->flags)) != 0){
1158 c_range = exp(scale->upper) - exp(scale->lower);
1159 }else{
1160 c_range = scale->upper - scale->lower;
1161 }
1162
1163 page = scale->page_size * (c_range / scale->step_count);
1164
1165 if(scale->default_value + log(page) > scale->upper){
1166 scale->default_value = scale->upper;
1167 }else{
1168 scale->default_value += log(page);
1169 }
1170
1171 gtk_widget_queue_draw(widget);
1172
1173 ags_scale_value_changed(scale,
1174 scale->default_value);
1175 }
1176 break;
1177 case GDK_KEY_Page_Down:
1178 case GDK_KEY_KP_Page_Down:
1179 {
1180 gdouble c_range;
1181 gdouble page;
1182
1183 if((AGS_SCALE_LOGARITHMIC & (scale->flags)) != 0){
1184 c_range = exp(scale->upper) - exp(scale->lower);
1185 }else{
1186 c_range = scale->upper - scale->lower;
1187 }
1188
1189 page = scale->page_size * (c_range / scale->step_count);
1190
1191 if(scale->default_value - log(page) < scale->lower){
1192 scale->default_value = scale->lower;
1193 }else{
1194 scale->default_value -= log(page);
1195 }
1196
1197 gtk_widget_queue_draw(widget);
1198
1199 ags_scale_value_changed(scale,
1200 scale->default_value);
1201 }
1202 break;
1203 }
1204
1205 return(TRUE);
1206 }
1207
1208 gboolean
ags_scale_motion_notify(GtkWidget * widget,GdkEventMotion * event)1209 ags_scale_motion_notify(GtkWidget *widget,
1210 GdkEventMotion *event)
1211 {
1212 AgsScale *scale;
1213
1214 GtkAllocation allocation;
1215
1216 guint width, height;
1217 guint x_start, y_start;
1218
1219 scale = AGS_SCALE(widget);
1220
1221 gtk_widget_get_allocation(widget,
1222 &allocation);
1223
1224 width = allocation.width;
1225 height = allocation.height;
1226
1227 x_start = 0;
1228 y_start = 0;
1229
1230 if((AGS_SCALE_BUTTON_1_PRESSED & (scale->button_state)) != 0){
1231 gdouble c_range;
1232 gdouble new_default_value;
1233
1234 scale->button_state |= AGS_SCALE_BUTTON_1_PRESSED;
1235
1236 if((AGS_SCALE_LOGARITHMIC & (scale->flags)) != 0){
1237 c_range = exp(scale->upper) - exp(scale->lower);
1238 }else{
1239 c_range = scale->upper - scale->lower;
1240 }
1241
1242 new_default_value = 0.0;
1243
1244 if(scale->layout == AGS_SCALE_LAYOUT_VERTICAL){
1245 new_default_value = event->y / c_range;
1246 }else if(scale->layout == AGS_SCALE_LAYOUT_HORIZONTAL){
1247 new_default_value = event->x / c_range;
1248 }
1249
1250 if(new_default_value != scale->default_value){
1251 scale->default_value = new_default_value;
1252 gtk_widget_queue_draw((GtkWidget *) scale);
1253
1254 ags_scale_value_changed(scale,
1255 new_default_value);
1256 }
1257 }
1258
1259 return(FALSE);
1260 }
1261
1262 gboolean
ags_scale_draw(AgsScale * scale,cairo_t * cr)1263 ags_scale_draw(AgsScale *scale, cairo_t *cr)
1264 {
1265 PangoLayout *layout;
1266 PangoFontDescription *desc;
1267
1268 PangoRectangle ink_rect, logical_rect;
1269
1270 GtkAllocation allocation;
1271
1272 gchar *font_name;
1273
1274 guint width, height;
1275 guint x_start, y_start;
1276
1277 g_object_get(gtk_settings_get_default(),
1278 "gtk-font-name", &font_name,
1279 NULL);
1280
1281 gtk_widget_get_allocation(scale,
1282 &allocation);
1283
1284 width = allocation.width;
1285 height = allocation.height;
1286
1287 x_start = 0;
1288 y_start = 0;
1289
1290 // cairo_surface_flush(cairo_get_target(cr));
1291 cairo_push_group(cr);
1292
1293 /* background */
1294 cairo_set_source_rgb(cr,
1295 0.0,
1296 0.0,
1297 0.0);
1298 cairo_rectangle(cr,
1299 (gdouble) x_start, (gdouble) y_start,
1300 (gdouble) width, (gdouble) height);
1301 cairo_fill(cr);
1302
1303 /* box */
1304 cairo_set_source_rgb(cr,
1305 0.5, 0.4, 0.0);
1306 cairo_set_line_width(cr,
1307 1.0);
1308 cairo_rectangle(cr,
1309 (gdouble) x_start, (gdouble) y_start,
1310 (gdouble) width, (gdouble) height);
1311 cairo_stroke(cr);
1312
1313 /* draw scale */
1314 //TODO:JK: implement me
1315
1316 /* show control name */
1317 layout = pango_cairo_create_layout(cr);
1318 pango_layout_set_text(layout,
1319 scale->control_name,
1320 -1);
1321 desc = pango_font_description_from_string(font_name);
1322 pango_font_description_set_size(desc,
1323 scale->font_size * PANGO_SCALE);
1324 pango_layout_set_font_description(layout,
1325 desc);
1326 pango_font_description_free(desc);
1327
1328 pango_layout_get_extents(layout,
1329 &ink_rect,
1330 &logical_rect);
1331
1332 cairo_set_source_rgb(cr,
1333 1.0,
1334 1.0,
1335 1.0);
1336
1337 if(scale->layout == AGS_SCALE_LAYOUT_VERTICAL){
1338 cairo_move_to(cr,
1339 x_start + scale->font_size, y_start + height - 1.0);
1340 cairo_rotate(cr,
1341 2 * M_PI * 0.75);
1342 }else{
1343 cairo_move_to(cr,
1344 x_start + scale->font_size, y_start + 1.0);
1345 }
1346
1347 pango_cairo_show_layout(cr,
1348 layout);
1349
1350 g_object_unref(layout);
1351
1352 g_free(font_name);
1353
1354 cairo_pop_group_to_source(cr);
1355 cairo_paint(cr);
1356
1357 // cairo_surface_mark_dirty(cairo_get_target(cr));
1358
1359 return(FALSE);
1360 }
1361
1362 /**
1363 * ags_scale_set_scale_width:
1364 * @scale: the #AgsScale
1365 * @scale_width: the scale width
1366 *
1367 * Set @scale_width of @scale.
1368 *
1369 * Since: 3.2.2
1370 */
1371 void
ags_scale_set_scale_width(AgsScale * scale,guint scale_width)1372 ags_scale_set_scale_width(AgsScale *scale,
1373 guint scale_width)
1374 {
1375 if(!AGS_IS_SCALE(scale)){
1376 return;
1377 }
1378
1379 g_object_set(scale,
1380 "scale-width", scale_width,
1381 NULL);
1382 }
1383
1384 /**
1385 * ags_scale_get_scale_width:
1386 * @scale: the #AgsScale
1387 *
1388 * Get scale width of @scale.
1389 *
1390 * Returns: the scale width
1391 *
1392 * Since: 3.2.2
1393 */
1394 guint
ags_scale_get_scale_width(AgsScale * scale)1395 ags_scale_get_scale_width(AgsScale *scale)
1396 {
1397 guint scale_width;
1398
1399 if(!AGS_IS_SCALE(scale)){
1400 return(0);
1401 }
1402
1403 g_object_get(scale,
1404 "scale-width", &scale_width,
1405 NULL);
1406
1407 return(scale_width);
1408 }
1409
1410 /**
1411 * ags_scale_set_scale_height:
1412 * @scale: the #AgsScale
1413 * @scale_height: the scale height
1414 *
1415 * Set @scale_height of @scale.
1416 *
1417 * Since: 3.2.2
1418 */
1419 void
ags_scale_set_scale_height(AgsScale * scale,guint scale_height)1420 ags_scale_set_scale_height(AgsScale *scale,
1421 guint scale_height)
1422 {
1423 if(!AGS_IS_SCALE(scale)){
1424 return;
1425 }
1426
1427 g_object_set(scale,
1428 "scale-height", scale_height,
1429 NULL);
1430 }
1431
1432 /**
1433 * ags_scale_get_scale_height:
1434 * @scale: the #AgsScale
1435 *
1436 * Get scale height of @scale.
1437 *
1438 * Returns: the scale height
1439 *
1440 * Since: 3.2.2
1441 */
1442 guint
ags_scale_get_scale_height(AgsScale * scale)1443 ags_scale_get_scale_height(AgsScale *scale)
1444 {
1445 guint scale_height;
1446
1447 if(!AGS_IS_SCALE(scale)){
1448 return(0);
1449 }
1450
1451 g_object_get(scale,
1452 "scale-height", &scale_height,
1453 NULL);
1454
1455 return(scale_height);
1456 }
1457
1458 /**
1459 * ags_scale_set_control_name:
1460 * @scale: the #AgsScale
1461 * @control_name: the scale height
1462 *
1463 * Set @control_name of @scale.
1464 *
1465 * Since: 3.2.2
1466 */
1467 void
ags_scale_set_control_name(AgsScale * scale,gchar * control_name)1468 ags_scale_set_control_name(AgsScale *scale,
1469 gchar *control_name)
1470 {
1471 if(!AGS_IS_SCALE(scale)){
1472 return;
1473 }
1474
1475 g_object_set(scale,
1476 "control-name", control_name,
1477 NULL);
1478 }
1479
1480 /**
1481 * ags_scale_get_control_name:
1482 * @scale: the #AgsScale
1483 *
1484 * Get scale height of @scale.
1485 *
1486 * Returns: the scale height
1487 *
1488 * Since: 3.2.2
1489 */
1490 gchar*
ags_scale_get_control_name(AgsScale * scale)1491 ags_scale_get_control_name(AgsScale *scale)
1492 {
1493 gchar *control_name;
1494
1495 if(!AGS_IS_SCALE(scale)){
1496 return(NULL);
1497 }
1498
1499 g_object_get(scale,
1500 "control-name", &control_name,
1501 NULL);
1502
1503 return(control_name);
1504 }
1505
1506 /**
1507 * ags_scale_set_upper:
1508 * @scale: the #AgsScale
1509 * @upper: the upper
1510 *
1511 * Set @upper of @scale.
1512 *
1513 * Since: 3.2.2
1514 */
1515 void
ags_scale_set_upper(AgsScale * scale,gdouble upper)1516 ags_scale_set_upper(AgsScale *scale,
1517 gdouble upper)
1518 {
1519 if(!AGS_IS_SCALE(scale)){
1520 return;
1521 }
1522
1523 g_object_set(scale,
1524 "upper", upper,
1525 NULL);
1526 }
1527
1528 /**
1529 * ags_scale_get_upper:
1530 * @scale: the #AgsScale
1531 *
1532 * Get upper of @scale.
1533 *
1534 * Returns: the upper
1535 *
1536 * Since: 3.2.2
1537 */
1538 gdouble
ags_scale_get_upper(AgsScale * scale)1539 ags_scale_get_upper(AgsScale *scale)
1540 {
1541 gdouble upper;
1542
1543 if(!AGS_IS_SCALE(scale)){
1544 return(0.0);
1545 }
1546
1547 g_object_get(scale,
1548 "upper", &upper,
1549 NULL);
1550
1551 return(upper);
1552 }
1553
1554 /**
1555 * ags_scale_set_lower:
1556 * @scale: the #AgsScale
1557 * @lower: the lower
1558 *
1559 * Set @lower of @scale.
1560 *
1561 * Since: 3.2.2
1562 */
1563 void
ags_scale_set_lower(AgsScale * scale,gdouble lower)1564 ags_scale_set_lower(AgsScale *scale,
1565 gdouble lower)
1566 {
1567 if(!AGS_IS_SCALE(scale)){
1568 return;
1569 }
1570
1571 g_object_set(scale,
1572 "lower", lower,
1573 NULL);
1574 }
1575
1576 /**
1577 * ags_scale_get_lower:
1578 * @scale: the #AgsScale
1579 *
1580 * Get lower of @scale.
1581 *
1582 * Returns: the lower
1583 *
1584 * Since: 3.2.2
1585 */
1586 gdouble
ags_scale_get_lower(AgsScale * scale)1587 ags_scale_get_lower(AgsScale *scale)
1588 {
1589 gdouble lower;
1590
1591 if(!AGS_IS_SCALE(scale)){
1592 return(0.0);
1593 }
1594
1595 g_object_get(scale,
1596 "lower", &lower,
1597 NULL);
1598
1599 return(lower);
1600 }
1601
1602 /**
1603 * ags_scale_set_default_value:
1604 * @scale: the #AgsScale
1605 * @default_value: the normalized volume
1606 *
1607 * Set @default_value of @scale.
1608 *
1609 * Since: 3.2.2
1610 */
1611 void
ags_scale_set_default_value(AgsScale * scale,gdouble default_value)1612 ags_scale_set_default_value(AgsScale *scale,
1613 gdouble default_value)
1614 {
1615 if(!AGS_IS_SCALE(scale)){
1616 return;
1617 }
1618
1619 g_object_set(scale,
1620 "default-value", default_value,
1621 NULL);
1622 }
1623
1624 /**
1625 * ags_scale_get_default_value:
1626 * @scale: the #AgsScale
1627 *
1628 * Get normalized volume of @scale.
1629 *
1630 * Returns: the normalized volume
1631 *
1632 * Since: 3.2.2
1633 */
1634 gdouble
ags_scale_get_default_value(AgsScale * scale)1635 ags_scale_get_default_value(AgsScale *scale)
1636 {
1637 gdouble default_value;
1638
1639 if(!AGS_IS_SCALE(scale)){
1640 return(0.0);
1641 }
1642
1643 g_object_get(scale,
1644 "default-value", &default_value,
1645 NULL);
1646
1647 return(default_value);
1648 }
1649
1650 /**
1651 * ags_scale_value_changed:
1652 * @scale: the #AgsScale
1653 * @default_value: the default value
1654 *
1655 * Emits ::value-changed event.
1656 *
1657 * Since: 3.0.0
1658 */
1659 void
ags_scale_value_changed(AgsScale * scale,gdouble default_value)1660 ags_scale_value_changed(AgsScale *scale,
1661 gdouble default_value)
1662 {
1663 g_return_if_fail(AGS_IS_SCALE(scale));
1664
1665 g_object_ref((GObject *) scale);
1666 g_signal_emit(G_OBJECT(scale),
1667 scale_signals[VALUE_CHANGED], 0,
1668 default_value);
1669 g_object_unref((GObject *) scale);
1670 }
1671
1672 /**
1673 * ags_scale_new:
1674 *
1675 * Create a new instance of #AgsScale.
1676 *
1677 * Returns: the new #AgsScale instance
1678 *
1679 * Since: 3.0.0
1680 */
1681 AgsScale*
ags_scale_new()1682 ags_scale_new()
1683 {
1684 AgsScale *scale;
1685
1686 scale = (AgsScale *) g_object_new(AGS_TYPE_SCALE,
1687 NULL);
1688
1689 return(scale);
1690 }
1691