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