b2696f50f0c2e4fa1a851c94a41ca7378540cd67
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Slider.cs
1 /*
2  * Copyright(c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 using System;
18 using Tizen.NUI.BaseComponents;
19 using System.ComponentModel;
20 using Tizen.NUI.Binding;
21
22 namespace Tizen.NUI.Components
23 {
24     /// <summary>
25     /// Slider value changed event data.
26     /// </summary>
27     /// <since_tizen> 8 </since_tizen>
28     public class SliderValueChangedEventArgs : EventArgs
29     {
30         /// <summary>
31         /// Current Slider value
32         /// </summary>
33         /// <since_tizen> 8 </since_tizen>
34         public float CurrentValue { get; set; }
35     }
36
37     /// <summary>
38     /// Slider sliding started event data.
39     /// </summary>
40     /// <since_tizen> 8 </since_tizen>
41     public class SliderSlidingStartedEventArgs : EventArgs
42     {
43         /// <summary>
44         /// Current Slider value
45         /// </summary>
46         /// <since_tizen> 8 </since_tizen>
47         public float CurrentValue { get; set; }
48     }
49
50     /// <summary>
51     /// Slider sliding finished event data.
52     /// </summary>
53     /// <since_tizen> 8 </since_tizen>
54     public class SliderSlidingFinishedEventArgs : EventArgs
55     {
56         /// <summary>
57         /// Current Slider value
58         /// </summary>
59         /// <since_tizen> 8 </since_tizen>
60         public float CurrentValue { get; set; }
61     }
62
63     /// <summary>
64     /// A slider lets users select a value from a continuous or discrete range of values by moving the slider thumb.
65     /// </summary>
66     /// <since_tizen> 6 </since_tizen>
67     public partial class Slider : Control
68     {
69         /// <summary>
70         /// IndicatorTypeProperty
71         /// </summary>
72         [EditorBrowsable(EditorBrowsableState.Never)]
73         public static readonly BindableProperty IndicatorTypeProperty = BindableProperty.Create("IndicatorType", typeof(IndicatorType), typeof(Slider), IndicatorType.None, propertyChanged: (bindable, oldValue, newValue) =>
74         {
75             var instance = (Slider)bindable;
76             if (newValue != null)
77             {
78                 instance.privateIndicatorType = (IndicatorType)newValue;
79             }
80         },
81         defaultValueCreator: (bindable) =>
82         {
83             var instance = (Slider)bindable;
84             return instance.privateIndicatorType;
85         });
86
87         /// <summary>
88         /// SpaceBetweenTrackAndIndicatorProperty
89         /// </summary>
90         [EditorBrowsable(EditorBrowsableState.Never)]
91         public static readonly BindableProperty SpaceBetweenTrackAndIndicatorProperty = BindableProperty.Create(nameof(SpaceBetweenTrackAndIndicator), typeof(uint), typeof(Slider), (uint)0, propertyChanged: (bindable, oldValue, newValue) =>
92         {
93             var instance = (Slider)bindable;
94             if (newValue != null)
95             {
96                 instance.privateSpaceBetweenTrackAndIndicator = (uint)newValue;
97             }
98         },
99         defaultValueCreator: (bindable) =>
100         {
101             var instance = (Slider)bindable;
102             return instance.privateSpaceBetweenTrackAndIndicator;
103         });
104
105         /// <summary>
106         /// TrackThicknessProperty
107         /// </summary>
108         [EditorBrowsable(EditorBrowsableState.Never)]
109         public static readonly BindableProperty TrackThicknessProperty = BindableProperty.Create(nameof(TrackThickness), typeof(uint), typeof(Slider), (uint)0, propertyChanged: (bindable, oldValue, newValue) =>
110         {
111             var instance = (Slider)bindable;
112             if (newValue != null)
113             {
114                 instance.privateTrackThickness = (uint)newValue;
115             }
116         },
117         defaultValueCreator: (bindable) =>
118         {
119             var instance = (Slider)bindable;
120             return instance.privateTrackThickness;
121         });
122
123         /// <summary>
124         /// IsValueShownProperty
125         /// </summary>
126         [EditorBrowsable(EditorBrowsableState.Never)]
127         public static readonly BindableProperty IsValueShownProperty = BindableProperty.Create(nameof(IsValueShown), typeof(bool), typeof(Slider), true, propertyChanged: (bindable, oldValue, newValue) =>
128         {
129             var instance = (Slider)bindable;
130             if (newValue != null)
131             {
132                 bool newValueShown = (bool)newValue;
133                 if (instance.isValueShown != newValueShown)
134                 {
135                     instance.isValueShown = newValueShown;
136                 }
137             }
138         },
139         defaultValueCreator: (bindable) =>
140         {
141             var instance = (Slider)bindable;
142             return instance.isValueShown;
143         });
144
145         /// <summary>
146         /// ValueIndicatorTextProperty
147         /// </summary>
148         [EditorBrowsable(EditorBrowsableState.Never)]
149         public static readonly BindableProperty ValueIndicatorTextProperty = BindableProperty.Create(nameof(ValueIndicatorText), typeof(string), typeof(Slider), string.Empty, propertyChanged: (bindable, oldValue, newValue) =>
150         {
151             var instance = (Slider)bindable;
152             if (newValue != null)
153             {
154                 string newText = (string)newValue;
155                 instance.valueIndicatorText.Text = newText;
156             }
157         },
158         defaultValueCreator: (bindable) =>
159         {
160             var instance = (Slider)bindable;
161             return instance.valueIndicatorText.Text;
162         });
163
164         /// <summary>
165         /// Bindable property of CurrentValue
166         /// <remark>
167         /// Hidden API, used for NUI XAML data binding
168         /// </remark>
169         /// </summary>
170         [EditorBrowsable(EditorBrowsableState.Never)]
171         public static readonly BindableProperty CurrentValueProperty = BindableProperty.Create(nameof(CurrentValue), typeof(float), typeof(Slider), 0.0f, BindingMode.TwoWay,
172             propertyChanged: (bindable, oldValue, newValue) =>
173             {
174                 var instance = (Slider)bindable;
175
176                 if (newValue != null)
177                 {
178                     instance.curValue = (float)newValue;
179                     if (instance.IsHighlighted)
180                     {
181                         instance.EmitAccessibilityEvent(ObjectPropertyChangeEvent.Value);
182                     }
183                     instance.UpdateValue();
184                 }
185             },
186             defaultValueCreator: (bindable) =>
187             {
188                 var instance = (Slider)bindable;
189                 return instance.curValue;
190             }
191         );
192
193         static Slider() { }
194
195         /// <summary>
196         /// The constructor of the Slider class.
197         /// </summary>
198         /// <since_tizen> 6 </since_tizen>
199         public Slider()
200         {
201             Initialize();
202         }
203
204         /// <summary>
205         /// The constructor of the Slider class with specific style.
206         /// </summary>
207         /// <param name="style">The string to initialize the Slider</param>
208         /// <since_tizen> 8 </since_tizen>
209         public Slider(string style) : base(style)
210         {
211             Initialize();
212         }
213
214         /// <summary>
215         /// The constructor of the Slider class with specific style.
216         /// </summary>
217         /// <param name="sliderStyle">The style object to initialize the Slider</param>
218         /// <since_tizen> 8 </since_tizen>
219         public Slider(SliderStyle sliderStyle) : base(sliderStyle)
220         {
221             Initialize();
222         }
223
224         /// <summary>
225         /// The value changed event handler.
226         /// </summary>
227         /// <since_tizen> 6 </since_tizen>
228         [Obsolete("Deprecated in API8; Will be removed in API10. Please use ValueChanged event instead.")]
229         public event EventHandler<ValueChangedArgs> ValueChangedEvent
230         {
231             add
232             {
233                 valueChangedHandler += value;
234             }
235             remove
236             {
237                 valueChangedHandler -= value;
238             }
239         }
240
241         /// <summary>
242         /// The sliding finished event handler.
243         /// </summary>
244         /// <since_tizen> 6 </since_tizen>
245         [Obsolete("Deprecated in API8; Will be removed in API10. Please use SlidingFinished event instead.")]
246         public event EventHandler<SlidingFinishedArgs> SlidingFinishedEvent
247         {
248             add
249             {
250                 slidingFinishedHandler += value;
251             }
252             remove
253             {
254                 slidingFinishedHandler -= value;
255             }
256         }
257
258         /// <summary>
259         /// The value changed event handler.
260         /// </summary>
261         /// <since_tizen> 8 </since_tizen>
262         public event EventHandler<SliderValueChangedEventArgs> ValueChanged
263         {
264             add
265             {
266                 sliderValueChangedHandler += value;
267             }
268             remove
269             {
270                 sliderValueChangedHandler -= value;
271             }
272         }
273
274         /// <summary>
275         /// The sliding started event handler.
276         /// </summary>
277         /// <since_tizen> 8 </since_tizen>
278         public event EventHandler<SliderSlidingStartedEventArgs> SlidingStarted
279         {
280             add
281             {
282                 sliderSlidingStartedHandler += value;
283             }
284             remove
285             {
286                 sliderSlidingStartedHandler -= value;
287             }
288         }
289
290         /// <summary>
291         /// The sliding finished event handler.
292         /// </summary>
293         /// <since_tizen> 8 </since_tizen>
294         public event EventHandler<SliderSlidingFinishedEventArgs> SlidingFinished
295         {
296             add
297             {
298                 sliderSlidingFinishedHandler += value;
299             }
300             remove
301             {
302                 sliderSlidingFinishedHandler -= value;
303             }
304         }
305
306         /// <summary>
307         /// The state changed event handler.
308         /// </summary>
309         /// <since_tizen> 6 </since_tizen>
310         [Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEvent")]
311         public event EventHandler<StateChangedArgs> StateChangedEvent
312         {
313             add
314             {
315                 stateChangedHandler += value;
316             }
317             remove
318             {
319                 stateChangedHandler -= value;
320             }
321         }
322
323         /// <summary>
324         /// The direction type of slider.
325         /// </summary>
326         /// <since_tizen> 6 </since_tizen>
327         public enum DirectionType
328         {
329             /// <summary>
330             /// The Horizontal type.
331             /// </summary>
332             /// <since_tizen> 6 </since_tizen>
333             Horizontal,
334
335             /// <summary>
336             /// The Vertical type.
337             /// </summary>
338             /// <since_tizen> 6 </since_tizen>
339             Vertical
340         }
341
342         /// <summary>
343         /// The indicator type of slider.
344         /// </summary>
345         /// <since_tizen> 6 </since_tizen>
346         public enum IndicatorType
347         {
348             /// <summary> Only contains slider bar.</summary>
349             /// <since_tizen> 6 </since_tizen>
350             None,
351
352             /// <summary> Contains slider bar, IndicatorImage.</summary>
353             /// <since_tizen> 6 </since_tizen>
354             Image,
355
356             /// <summary> Contains slider bar, IndicatorText.</summary>
357             /// <since_tizen> 6 </since_tizen>
358             Text
359         }
360
361         /// <summary>
362         /// Return currently applied style.
363         /// </summary>
364         /// <remarks>
365         /// Modifying contents in style may cause unexpected behaviour.
366         /// </remarks>
367         /// <since_tizen> 8 </since_tizen>
368         public SliderStyle Style => (SliderStyle)(ViewStyle as SliderStyle)?.Clone();
369
370         /// <summary>
371         /// Gets or sets the direction type of slider.
372         /// </summary>
373         /// <since_tizen> 6 </since_tizen>
374         public DirectionType Direction
375         {
376             get
377             {
378                 return direction;
379             }
380             set
381             {
382                 if (direction == value)
383                 {
384                     return;
385                 }
386                 direction = value;
387                 RelayoutBaseComponent(false);
388                 UpdateBgTrackSize();
389                 UpdateBgTrackPosition();
390                 UpdateWarningTrackSize();
391                 UpdateValue();
392             }
393         }
394
395         /// <summary>
396         /// Gets or sets the indicator type, arrow or sign.
397         /// </summary>
398         /// <since_tizen> 6 </since_tizen>
399         public IndicatorType Indicator
400         {
401             get
402             {
403                 return (IndicatorType)GetValue(IndicatorTypeProperty);
404             }
405             set
406             {
407                 SetValue(IndicatorTypeProperty, value);
408             }
409         }
410
411         /// <summary>
412         /// Gets or sets the minimum value of slider.
413         /// </summary>
414         /// <since_tizen> 6 </since_tizen>
415         public float MinValue
416         {
417             get
418             {
419                 return minValue;
420             }
421             set
422             {
423                 minValue = value;
424                 UpdateValue();
425             }
426         }
427
428         /// <summary>
429         /// Gets or sets the maximum value of slider.
430         /// </summary>
431         /// <since_tizen> 6 </since_tizen>
432         public float MaxValue
433         {
434             get
435             {
436                 return maxValue;
437             }
438             set
439             {
440                 maxValue = value;
441                 UpdateValue();
442             }
443         }
444
445         /// <summary>
446         /// Gets or sets the current value of slider.
447         /// </summary>
448         /// <since_tizen> 6 </since_tizen>
449         public float CurrentValue
450         {
451             get
452             {
453                 return (float)GetValue(CurrentValueProperty);
454             }
455             set
456             {
457                 SetValue(CurrentValueProperty, value);
458             }
459         }
460
461         /// <summary>
462         /// Gets or sets the size of the thumb image object.
463         /// </summary>
464         /// <since_tizen> 6 </since_tizen>
465         public Size ThumbSize
466         {
467             get
468             {
469                 return thumbImage?.Size;
470             }
471             set
472             {
473                 if (null != thumbImage)
474                 {
475                     thumbImage.Size = value;
476                     thumbSize = value;
477                 }
478             }
479         }
480
481         /// <summary>
482         /// Gets or sets the resource url of the thumb image object.
483         ///
484         /// Please use ThumbImageUrl property.
485         /// </summary>
486         /// <since_tizen> 6 </since_tizen>
487         public string ThumbImageURL
488         {
489             get
490             {
491                 return thumbImage?.ResourceUrl;
492             }
493             set
494             {
495                 if (null != thumbImage)
496                 {
497                     thumbImage.ResourceUrl = value;
498                     thumbImageUrl = value;
499                 }
500             }
501         }
502
503         /// <summary>
504         /// Gets or sets the resource url selector of the thumb image object.
505         /// Getter returns copied selector value if exist, null otherwise.
506         ///
507         /// Please use ThumbImageUrl property.
508         /// </summary>
509         /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
510         /// <since_tizen> 6 </since_tizen>
511         public StringSelector ThumbImageURLSelector
512         {
513             get => thumbImage == null ? null : new StringSelector(thumbImage.ResourceUrlSelector);
514             set
515             {
516                 if (value == null || thumbImage == null)
517                 {
518                     throw new NullReferenceException("Slider.ThumbImageURLSelector is null");
519                 }
520                 else
521                 {
522                     thumbImage.ResourceUrlSelector = value;
523                     thumbImageUrlSelector = value;
524                 }
525             }
526         }
527
528         /// <summary>
529         /// Gets or sets the Url of the thumb image.
530         /// </summary>
531         /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
532         /// <since_tizen> 9 </since_tizen>
533         public Selector<string> ThumbImageUrl
534         {
535             get
536             {
537                 if (thumbImage == null)
538                 {
539                     return null;
540                 }
541                 else
542                 {
543                     return thumbImage.ResourceUrlSelector;
544                 }
545             }
546             set
547             {
548                 if (value == null || thumbImage == null)
549                 {
550                     throw new NullReferenceException("Slider.ThumbImageUrl is null");
551                 }
552                 else
553                 {
554                     thumbImage.ResourceUrlSelector = value;
555                     thumbImageUrlSelector = value;
556                 }
557             }
558         }
559
560         /// <summary>
561         /// Gets or sets the color of the thumb image object.
562         /// </summary>
563         /// <since_tizen> 8 </since_tizen>
564         public Color ThumbColor
565         {
566             get
567             {
568                 return thumbImage?.Color;
569             }
570             set
571             {
572                 if (null != thumbImage)
573                 {
574                     thumbImage.BackgroundColor = value;
575                     thumbColor = value;
576                 }
577             }
578         }
579
580         /// <summary>
581         /// Gets or sets the color of the background track image object.
582         /// </summary>
583         /// <since_tizen> 6 </since_tizen>
584         public Color BgTrackColor
585         {
586             get
587             {
588                 return bgTrackImage?.BackgroundColor;
589             }
590             set
591             {
592                 if (null != bgTrackImage)
593                 {
594                     bgTrackImage.BackgroundColor = value;
595                 }
596             }
597         }
598
599         /// <summary>
600         /// Gets or sets the color of the slided track image object.
601         /// </summary>
602         /// <since_tizen> 6 </since_tizen>
603         public Color SlidedTrackColor
604         {
605             get
606             {
607                 return slidedTrackImage?.BackgroundColor;
608             }
609             set
610             {
611                 if (null != slidedTrackImage)
612                 {
613                     slidedTrackImage.BackgroundColor = value;
614                 }
615             }
616         }
617
618         /// <summary>
619         /// Gets or sets the thickness value of the track.
620         /// </summary>
621         /// <since_tizen> 6 </since_tizen>
622         public uint TrackThickness
623         {
624             get
625             {
626                 return (uint)GetValue(TrackThicknessProperty);
627             }
628             set
629             {
630                 SetValue(TrackThicknessProperty, value);
631             }
632         }
633
634         /// <summary>
635         /// Gets or sets the warning start value between minimum value and maximum value of slider.
636         /// </summary>
637         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
638         [EditorBrowsable(EditorBrowsableState.Never)]
639         public float WarningStartValue
640         {
641             get
642             {
643                 return warningStartValue;
644             }
645             set
646             {
647                 warningStartValue = value;
648                 UpdateValue();
649             }
650         }
651
652         /// <summary>
653         /// Gets or sets the color of the warning track image object.
654         /// </summary>
655         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
656         [EditorBrowsable(EditorBrowsableState.Never)]
657         public Color WarningTrackColor
658         {
659             get
660             {
661                 return warningTrackImage?.BackgroundColor;
662             }
663             set
664             {
665                 if (null != warningTrackImage)
666                 {
667                     warningTrackImage.BackgroundColor = value;
668                 }
669             }
670         }
671
672         /// <summary>
673         /// Gets or sets the color of the warning slided track image object.
674         /// </summary>
675         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
676         [EditorBrowsable(EditorBrowsableState.Never)]
677         public Color WarningSlidedTrackColor
678         {
679             get
680             {
681                 return warningSlidedTrackImage?.BackgroundColor;
682             }
683             set
684             {
685                 if (null != warningSlidedTrackImage)
686                 {
687                     warningSlidedTrackImage.BackgroundColor = value;
688                 }
689             }
690         }
691
692         /// <summary>
693         /// Gets or sets the Url of the warning thumb image.
694         /// </summary>
695         /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
696         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
697         [EditorBrowsable(EditorBrowsableState.Never)]
698         public Selector<string> WarningThumbImageUrl
699         {
700             get
701             {
702                 return warningThumbImageUrlSelector;
703             }
704             set
705             {
706                 if (value == null || thumbImage == null)
707                 {
708                     throw new NullReferenceException("Slider.WarningThumbImageUrl is null");
709                 }
710                 else
711                 {
712                     warningThumbImageUrlSelector = value;
713                 }
714             }
715         }
716
717         /// <summary>
718         /// Gets or sets the color of the warning thumb image object.
719         /// </summary>
720         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
721         [EditorBrowsable(EditorBrowsableState.Never)]
722         public Color WarningThumbColor
723         {
724             get
725             {
726                 return warningThumbColor;
727             }
728             set
729             {
730                 warningThumbColor = value;
731             }
732         }
733
734         /// <summary>
735         /// Gets or sets the resource url of the low indicator image object.
736         /// </summary>
737         /// <since_tizen> 6 </since_tizen>
738         public string LowIndicatorImageURL
739         {
740             get
741             {
742                 return lowIndicatorImage?.ResourceUrl;
743             }
744             set
745             {
746                 if (null == lowIndicatorImage) lowIndicatorImage = new ImageView();
747                 lowIndicatorImage.ResourceUrl = value;
748             }
749         }
750
751         /// <summary>
752         /// Gets or sets the resource url of the high indicator image object.
753         /// </summary>
754         /// <since_tizen> 6 </since_tizen>
755         public string HighIndicatorImageURL
756         {
757             get
758             {
759                 return highIndicatorImage?.ResourceUrl;
760             }
761             set
762             {
763                 if (null == highIndicatorImage) highIndicatorImage = new ImageView();
764                 highIndicatorImage.ResourceUrl = value;
765             }
766         }
767
768         /// <summary>
769         /// Gets or sets the text content of the low indicator text object.
770         /// </summary>
771         /// <since_tizen> 6 </since_tizen>
772         public string LowIndicatorTextContent
773         {
774             get
775             {
776                 return lowIndicatorText?.Text;
777             }
778             set
779             {
780                 if (null != lowIndicatorText)
781                 {
782                     lowIndicatorText.Text = value;
783                 }
784             }
785         }
786
787         /// <summary>
788         /// Gets or sets the text content of the high indicator text object.
789         /// </summary>
790         /// <since_tizen> 6 </since_tizen>
791         public string HighIndicatorTextContent
792         {
793             get
794             {
795                 return highIndicatorText?.Text;
796             }
797             set
798             {
799                 if (null != highIndicatorText)
800                 {
801                     highIndicatorText.Text = value;
802                 }
803             }
804         }
805
806         /// <summary>
807         /// Gets or sets the size of the low indicator object(image or text).
808         /// </summary>
809         /// <since_tizen> 6 </since_tizen>
810         public Size LowIndicatorSize
811         {
812             get
813             {
814                 return lowIndicatorSize;
815             }
816             set
817             {
818                 lowIndicatorSize = value;
819                 UpdateLowIndicatorSize();
820                 UpdateBgTrackSize();
821                 UpdateBgTrackPosition();
822                 UpdateValue();
823             }
824         }
825
826         /// <summary>
827         /// Gets or sets the size of the high indicator object(image or text).
828         /// </summary>
829         /// <since_tizen> 6 </since_tizen>
830         public Size HighIndicatorSize
831         {
832             get
833             {
834                 return highIndicatorText?.Size;
835             }
836             set
837             {
838                 if (null != highIndicatorText)
839                 {
840                     highIndicatorText.Size = value;
841                 }
842             }
843         }
844
845         /// <summary>
846         /// Gets or sets the value of the space between track and indicator.
847         /// </summary>
848         /// <since_tizen> 6 </since_tizen>
849         public uint SpaceBetweenTrackAndIndicator
850         {
851             get
852             {
853                 return (uint)GetValue(SpaceBetweenTrackAndIndicatorProperty);
854             }
855             set
856             {
857                 SetValue(SpaceBetweenTrackAndIndicatorProperty, value);
858             }
859         }
860
861         /// <summary>
862         /// Flag to decide whether the value indicator is shown
863         /// </summary>
864         /// <since_tizen> 9 </since_tizen>
865         public bool IsValueShown
866         {
867             get
868             {
869                 return (bool)GetValue(IsValueShownProperty);
870             }
871             set
872             {
873                 SetValue(IsValueShownProperty, value);
874             }
875         }
876
877         /// <summary>
878         /// Gets or sets the text of value indicator.
879         /// </summary>
880         /// <since_tizen> 9 </since_tizen>
881         public string ValueIndicatorText
882         {
883             get
884             {
885                 return (string)GetValue(ValueIndicatorTextProperty);
886             }
887             set
888             {
889                 SetValue(ValueIndicatorTextProperty, value);
890             }
891         }
892
893         /// <summary>
894         /// Gets or sets the size of the value indicator image object.
895         /// </summary>
896         /// <since_tizen> 9 </since_tizen>
897         public Size ValueIndicatorSize
898         {
899             get
900             {
901                 return valueIndicatorImage?.Size;
902             }
903             set
904             {
905                 if (null != valueIndicatorImage)
906                 {
907                     valueIndicatorImage.Size = value;
908                 }
909             }
910         }
911
912         /// <summary>
913         /// Gets or sets the resource url of the value indicator image object.
914         /// </summary>
915         /// <since_tizen> 9 </since_tizen>
916         public string ValueIndicatorUrl
917         {
918             get
919             {
920                 return valueIndicatorImage?.ResourceUrl;
921             }
922             set
923             {
924                 if (null != valueIndicatorImage)
925                 {
926                     valueIndicatorImage.ResourceUrl = value;
927                 }
928             }
929         }
930
931         /// <summary>
932         /// Flag to decide whether the thumb snap to the nearest discrete value when the user drags the thumb or taps.
933         ///
934         /// The default value is false.
935         /// </summary>
936         /// <since_tizen> 9 </since_tizen>
937         public bool IsDiscrete { get; set; } = false;
938
939         /// <summary>
940         /// Gets or sets the discrete value of slider.
941         ///
942         /// The discrete value is evenly spaced between MinValue and MaxValue.
943         /// For example, MinValue is 0, MaxValue is 100, and DiscreteValue is 20.
944         /// Then, the thumb can only go to 0, 20, 40, 60, 80, and 100.
945         /// The default is 0.
946         /// </summary>
947         /// <since_tizen> 9 </since_tizen>
948         public float DiscreteValue
949         {
950             get
951             {
952                 return discreteValue;
953             }
954             set
955             {
956                 discreteValue = value;
957                 UpdateValue();
958             }
959         }
960
961         private Extents spaceBetweenTrackAndIndicator
962         {
963             get
964             {
965                 if (null == spaceTrackIndicator)
966                 {
967                     spaceTrackIndicator = new Extents((ushort start, ushort end, ushort top, ushort bottom) =>
968                     {
969                         Extents extents = new Extents(start, end, top, bottom);
970                         spaceTrackIndicator.CopyFrom(extents);
971                     }, 0, 0, 0, 0);
972                 }
973
974                 return spaceTrackIndicator;
975             }
976         }
977
978         private IndicatorType privateIndicatorType
979         {
980             get
981             {
982                 return indicatorType;
983             }
984             set
985             {
986                 if (indicatorType == value)
987                 {
988                     return;
989                 }
990                 indicatorType = value;
991                 RelayoutBaseComponent(false);
992                 UpdateBgTrackSize();
993                 UpdateBgTrackPosition();
994                 UpdateValue();
995             }
996         }
997
998         private uint privateTrackThickness
999         {
1000             get
1001             {
1002                 return trackThickness ?? 0;
1003             }
1004             set
1005             {
1006                 trackThickness = value;
1007                 if (bgTrackImage != null)
1008                 {
1009                     if (direction == DirectionType.Horizontal)
1010                     {
1011                         bgTrackImage.SizeHeight = (float)trackThickness.Value;
1012                     }
1013                     else if (direction == DirectionType.Vertical)
1014                     {
1015                         bgTrackImage.SizeWidth = (float)trackThickness.Value;
1016                     }
1017                 }
1018                 if (slidedTrackImage != null)
1019                 {
1020                     if (direction == DirectionType.Horizontal)
1021                     {
1022                         slidedTrackImage.SizeHeight = (float)trackThickness.Value;
1023                     }
1024                     else if (direction == DirectionType.Vertical)
1025                     {
1026                         slidedTrackImage.SizeWidth = (float)trackThickness.Value;
1027                     }
1028                 }
1029                 if (warningTrackImage != null)
1030                 {
1031                     if (direction == DirectionType.Horizontal)
1032                     {
1033                         warningTrackImage.SizeHeight = (float)trackThickness.Value;
1034                     }
1035                     else if (direction == DirectionType.Vertical)
1036                     {
1037                         warningTrackImage.SizeWidth = (float)trackThickness.Value;
1038                     }
1039                 }
1040                 if (warningSlidedTrackImage != null)
1041                 {
1042                     if (direction == DirectionType.Horizontal)
1043                     {
1044                         warningSlidedTrackImage.SizeHeight = (float)trackThickness.Value;
1045                     }
1046                     else if (direction == DirectionType.Vertical)
1047                     {
1048                         warningSlidedTrackImage.SizeWidth = (float)trackThickness.Value;
1049                     }
1050                 }
1051             }
1052         }
1053
1054         private uint privateSpaceBetweenTrackAndIndicator
1055         {
1056             get
1057             {
1058                 return privateTrackPadding.Start;
1059             }
1060             set
1061             {
1062                 ushort val = (ushort)value;
1063                 privateTrackPadding = new Extents(val, val, val, val);
1064             }
1065         }
1066
1067         private Extents privateTrackPadding
1068         {
1069             get
1070             {
1071                 return spaceBetweenTrackAndIndicator;
1072             }
1073             set
1074             {
1075                 spaceBetweenTrackAndIndicator.CopyFrom(value);
1076                 UpdateComponentByIndicatorTypeChanged();
1077                 UpdateBgTrackSize();
1078                 UpdateBgTrackPosition();
1079                 UpdateValue();
1080             }
1081         }
1082
1083         /// <summary>
1084         /// Focus gained callback.
1085         /// </summary>
1086         /// <since_tizen> 8 </since_tizen>
1087         public override void OnFocusGained()
1088         {
1089             //State = ControlStates.Focused;
1090             UpdateState(true, isPressed);
1091             base.OnFocusGained();
1092         }
1093
1094         /// <summary>
1095         /// Focus Lost callback.
1096         /// </summary>
1097         /// <since_tizen> 8 </since_tizen>
1098         public override void OnFocusLost()
1099         {
1100             //State = ControlStates.Normal;
1101             UpdateState(false, isPressed);
1102             base.OnFocusLost();
1103         }
1104
1105         /// <summary>
1106         /// Apply style to scrollbar.
1107         /// </summary>
1108         /// <param name="viewStyle">The style to apply.</param>
1109         /// <since_tizen> 8 </since_tizen>
1110         public override void ApplyStyle(ViewStyle viewStyle)
1111         {
1112             base.ApplyStyle(viewStyle);
1113
1114             SliderStyle sliderStyle = viewStyle as SliderStyle;
1115
1116             if (null != sliderStyle?.Progress)
1117             {
1118                 CreateSlidedTrack().ApplyStyle(sliderStyle.Progress);
1119             }
1120
1121             if (null != sliderStyle?.LowIndicator)
1122             {
1123                 CreateLowIndicatorText().ApplyStyle(sliderStyle.LowIndicator);
1124             }
1125
1126             if (null != sliderStyle?.HighIndicator)
1127             {
1128                 CreateHighIndicatorText().ApplyStyle(sliderStyle.HighIndicator);
1129             }
1130
1131             if (null != sliderStyle?.Track)
1132             {
1133                 CreateBackgroundTrack().ApplyStyle(sliderStyle.Track);
1134             }
1135
1136             if (null != sliderStyle?.Thumb)
1137             {
1138                 CreateThumb().ApplyStyle(sliderStyle.Thumb);
1139             }
1140
1141             if (null != sliderStyle?.ValueIndicatorText)
1142             {
1143                 CreateValueIndicatorText().ApplyStyle(sliderStyle.ValueIndicatorText);
1144             }
1145
1146             if (null != sliderStyle?.ValueIndicatorImage)
1147             {
1148                 CreateValueIndicator().ApplyStyle(sliderStyle.ValueIndicatorImage);
1149             }
1150
1151             if (null != sliderStyle?.WarningTrack)
1152             {
1153                 CreateWarningTrack().ApplyStyle(sliderStyle.WarningTrack);
1154             }
1155
1156             if (null != sliderStyle?.WarningProgress)
1157             {
1158                 CreateWarningSlidedTrack().ApplyStyle(sliderStyle.WarningProgress);
1159             }
1160
1161             EnableControlStatePropagation = true;
1162         }
1163
1164         /// <summary>
1165         /// Prevents from showing child widgets in AT-SPI tree.
1166         /// </summary>
1167         [EditorBrowsable(EditorBrowsableState.Never)]
1168         protected override bool AccessibilityShouldReportZeroChildren()
1169         {
1170             return true;
1171         }
1172
1173         /// <summary>
1174         /// Minimum value.
1175         /// </summary>
1176         [EditorBrowsable(EditorBrowsableState.Never)]
1177         protected override double AccessibilityGetMinimum()
1178         {
1179             return (double)MinValue;
1180         }
1181
1182         /// <summary>
1183         /// Current value.
1184         /// </summary>
1185         [EditorBrowsable(EditorBrowsableState.Never)]
1186         protected override double AccessibilityGetCurrent()
1187         {
1188             return (double)CurrentValue;
1189         }
1190
1191         /// <summary>
1192         /// Maximum value.
1193         /// </summary>
1194         [EditorBrowsable(EditorBrowsableState.Never)]
1195         protected override double AccessibilityGetMaximum()
1196         {
1197             return (double)MaxValue;
1198         }
1199
1200         /// <summary>
1201         /// Current value.
1202         /// </summary>
1203         [EditorBrowsable(EditorBrowsableState.Never)]
1204         protected override bool AccessibilitySetCurrent(double value)
1205         {
1206             var f = (float)value;
1207
1208             if (f >= MinValue && f <= MaxValue)
1209             {
1210                 CurrentValue = f;
1211                 if (sliderValueChangedHandler != null)
1212                 {
1213                     sliderValueChangedHandler(this, new SliderValueChangedEventArgs { CurrentValue = f });
1214                 }
1215                 return true;
1216             }
1217
1218             return false;
1219         }
1220
1221         /// <summary>
1222         /// Minimum increment.
1223         /// </summary>
1224         [EditorBrowsable(EditorBrowsableState.Never)]
1225         protected override double AccessibilityGetMinimumIncrement()
1226         {
1227             // FIXME
1228             return (MaxValue - MinValue) / 20.0;
1229         }
1230
1231         /// <summary>
1232         /// Initialize AT-SPI object.
1233         /// </summary>
1234         [EditorBrowsable(EditorBrowsableState.Never)]
1235         public override void OnInitialize()
1236         {
1237             base.OnInitialize();
1238             SetAccessibilityConstructor(Role.Slider, AccessibilityInterface.Value);
1239         }
1240
1241         /// <summary>
1242         /// Get Slider style.
1243         /// </summary>
1244         /// <returns>The default slider style.</returns>
1245         /// <since_tizen> 8 </since_tizen>
1246         protected override ViewStyle CreateViewStyle()
1247         {
1248             return new SliderStyle();
1249         }
1250
1251         /// <summary>
1252         /// Dispose Slider.
1253         /// </summary>
1254         /// <param name="type">Dispose type.</param>
1255         /// <since_tizen> 6 </since_tizen>
1256         protected override void Dispose(DisposeTypes type)
1257         {
1258             if (disposed)
1259             {
1260                 return;
1261             }
1262
1263             if (type == DisposeTypes.Explicit)
1264             {
1265                 if (null != panGestureDetector)
1266                 {
1267                     panGestureDetector.Detach(this);
1268                     panGestureDetector.Detected -= OnPanGestureDetected;
1269                     panGestureDetector.Dispose();
1270                     panGestureDetector = null;
1271                 }
1272
1273                 if (null != thumbImage)
1274                 {
1275                     thumbImage.TouchEvent -= OnTouchEventForThumb;
1276                     Utility.Dispose(thumbImage);
1277                 }
1278                 Utility.Dispose(warningSlidedTrackImage);
1279                 Utility.Dispose(warningTrackImage);
1280                 Utility.Dispose(slidedTrackImage);
1281                 if (null != bgTrackImage)
1282                 {
1283                     bgTrackImage.TouchEvent -= OnTouchEventForBgTrack;
1284                     Utility.Dispose(bgTrackImage);
1285                 }
1286                 Utility.Dispose(lowIndicatorImage);
1287                 Utility.Dispose(highIndicatorImage);
1288                 Utility.Dispose(lowIndicatorText);
1289                 Utility.Dispose(highIndicatorText);
1290                 Utility.Dispose(valueIndicatorImage);
1291                 Utility.Dispose(valueIndicatorText);
1292             }
1293
1294             base.Dispose(type);
1295         }
1296
1297         /// <summary>
1298         /// Update Slider by style.
1299         /// </summary>
1300         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
1301         [EditorBrowsable(EditorBrowsableState.Never)]
1302         protected override void OnUpdate()
1303         {
1304             RelayoutBaseComponent();
1305
1306             UpdateComponentByIndicatorTypeChanged();
1307             UpdateBgTrackSize();
1308             UpdateBgTrackPosition();
1309             UpdateWarningTrackSize();
1310             UpdateLowIndicatorSize();
1311             UpdateValue();
1312         }
1313
1314         private void CalculateCurrentValueByGesture(float offset)
1315         {
1316             currentSlidedOffset += offset;
1317
1318             if (currentSlidedOffset <= 0)
1319             {
1320                 this.CurrentValue = minValue;
1321             }
1322             else if (currentSlidedOffset >= BgTrackLength())
1323             {
1324                 this.CurrentValue = maxValue;
1325             }
1326             else
1327             {
1328                 int bgTrackLength = BgTrackLength();
1329                 if (bgTrackLength != 0)
1330                 {
1331                     this.CurrentValue = ((currentSlidedOffset / (float)bgTrackLength) * (float)(maxValue - minValue)) + minValue;
1332                 }
1333             }
1334
1335             if (IsDiscrete)
1336             {
1337                 this.CurrentValue = CalculateDiscreteValue(this.CurrentValue);
1338             }
1339
1340             if (valueChangedHandler != null)
1341             {
1342                 ValueChangedArgs args = new ValueChangedArgs();
1343                 args.CurrentValue = this.CurrentValue;
1344                 valueChangedHandler(this, args);
1345             }
1346
1347             if (sliderValueChangedHandler != null)
1348             {
1349                 SliderValueChangedEventArgs args = new SliderValueChangedEventArgs();
1350                 args.CurrentValue = this.CurrentValue;
1351                 sliderValueChangedHandler(this, args);
1352             }
1353         }
1354
1355         private bool OnTouchEventForBgTrack(object source, TouchEventArgs e)
1356         {
1357             PointStateType state = e.Touch.GetState(0);
1358             if (state == PointStateType.Down)
1359             {
1360                 if (isValueShown)
1361                 {
1362                     valueIndicatorImage.Show();
1363                 }
1364
1365                 Vector2 pos = e.Touch.GetLocalPosition(0);
1366                 CalculateCurrentValueByTouch(pos);
1367                 UpdateValue();
1368                 if (null != slidingFinishedHandler)
1369                 {
1370                     SlidingFinishedArgs args = new SlidingFinishedArgs();
1371                     args.CurrentValue = curValue;
1372                     slidingFinishedHandler(this, args);
1373                 }
1374
1375                 if (null != sliderSlidingFinishedHandler)
1376                 {
1377                     SliderSlidingFinishedEventArgs args = new SliderSlidingFinishedEventArgs();
1378                     args.CurrentValue = curValue;
1379                     sliderSlidingFinishedHandler(this, args);
1380                 }
1381             }
1382             else if (state == PointStateType.Up)
1383             {
1384                 if (isValueShown)
1385                 {
1386                     valueIndicatorImage.Hide();
1387                 }
1388             }
1389             return false;
1390         }
1391
1392         private bool OnTouchEventForThumb(object source, TouchEventArgs e)
1393         {
1394             PointStateType state = e.Touch.GetState(0);
1395             if (state == PointStateType.Down)
1396             {
1397                 UpdateState(isFocused, true);
1398             }
1399             else if (state == PointStateType.Up)
1400             {
1401                 UpdateState(isFocused, false);
1402             }
1403             return true;
1404         }
1405
1406         private void CalculateCurrentValueByTouch(Vector2 pos)
1407         {
1408             int bgTrackLength = BgTrackLength();
1409             if (direction == DirectionType.Horizontal)
1410             {
1411                 currentSlidedOffset = pos.X;
1412             }
1413             else if (direction == DirectionType.Vertical)
1414             {
1415                 currentSlidedOffset = bgTrackLength - pos.Y;
1416             }
1417
1418             if (bgTrackLength != 0)
1419             {
1420                 this.CurrentValue = ((currentSlidedOffset / (float)bgTrackLength) * (maxValue - minValue)) + minValue;
1421
1422                 if (IsDiscrete)
1423                 {
1424                     this.CurrentValue = CalculateDiscreteValue(this.CurrentValue);
1425                 }
1426
1427                 if (null != valueChangedHandler)
1428                 {
1429                     ValueChangedArgs args = new ValueChangedArgs();
1430                     args.CurrentValue = this.CurrentValue;
1431                     valueChangedHandler(this, args);
1432                 }
1433
1434                 if (null != sliderValueChangedHandler)
1435                 {
1436                     SliderValueChangedEventArgs args = new SliderValueChangedEventArgs();
1437                     args.CurrentValue = this.CurrentValue;
1438                     sliderValueChangedHandler(this, args);
1439                 }
1440             }
1441         }
1442
1443         private float CalculateDiscreteValue(float value)
1444         {
1445             return ((float)Math.Round((value / discreteValue)) * discreteValue);
1446         }
1447
1448         private void UpdateState(bool isFocusedNew, bool isPressedNew)
1449         {
1450             if (isFocused == isFocusedNew && isPressed == isPressedNew)
1451             {
1452                 return;
1453             }
1454             if (thumbImage == null || Style == null)
1455             {
1456                 return;
1457             }
1458             isFocused = isFocusedNew;
1459             isPressed = isPressedNew;
1460
1461             if (!isFocused && !isPressed)
1462             {
1463                 ControlState = ControlState.Normal;
1464                 thumbImage.ResourceUrl = thumbImageUrlSelector?.Normal;
1465
1466                 if (stateChangedHandler != null)
1467                 {
1468                     StateChangedArgs args = new StateChangedArgs();
1469                     args.CurrentState = (ControlStates)ControlStates.Normal;
1470                     stateChangedHandler(this, args);
1471                 }
1472             }
1473             else if (isPressed)
1474             {
1475                 ControlState = ControlState.Pressed;
1476                 thumbImage.ResourceUrl = thumbImageUrlSelector?.Pressed;
1477
1478                 if (stateChangedHandler != null)
1479                 {
1480                     StateChangedArgs args = new StateChangedArgs();
1481                     args.CurrentState = (ControlStates)ControlStates.Pressed;
1482                     stateChangedHandler(this, args);
1483                 }
1484             }
1485             else if (!isPressed && isFocused)
1486             {
1487                 ControlState = ControlState.Focused;
1488                 thumbImage.ResourceUrl = thumbImageUrlSelector?.Focused;
1489
1490                 if (stateChangedHandler != null)
1491                 {
1492                     StateChangedArgs args = new StateChangedArgs();
1493                     args.CurrentState = (ControlStates)ControlStates.Focused;
1494                     stateChangedHandler(this, args);
1495                 }
1496             }
1497         }
1498
1499         private void UpdateComponentByIndicatorTypeChanged()
1500         {
1501             IndicatorType type = CurrentIndicatorType();
1502             if (type == IndicatorType.None)
1503             {
1504                 if (lowIndicatorImage != null)
1505                 {
1506                     lowIndicatorImage.Hide();
1507                 }
1508                 if (highIndicatorImage != null)
1509                 {
1510                     highIndicatorImage.Hide();
1511                 }
1512                 if (lowIndicatorText != null)
1513                 {
1514                     lowIndicatorText.Hide();
1515                 }
1516                 if (highIndicatorText != null)
1517                 {
1518                     highIndicatorText.Hide();
1519                 }
1520             }
1521             else if (type == IndicatorType.Image)
1522             {
1523                 if (lowIndicatorImage != null)
1524                 {
1525                     lowIndicatorImage.Show();
1526                 }
1527                 if (highIndicatorImage != null)
1528                 {
1529                     highIndicatorImage.Show();
1530                 }
1531                 if (lowIndicatorText != null)
1532                 {
1533                     lowIndicatorText.Hide();
1534                 }
1535                 if (highIndicatorText != null)
1536                 {
1537                     highIndicatorText.Hide();
1538                 }
1539             }
1540             else if (type == IndicatorType.Text)
1541             {
1542                 if (lowIndicatorText != null)
1543                 {
1544                     lowIndicatorText.Show();
1545                 }
1546                 if (highIndicatorText != null)
1547                 {
1548                     highIndicatorText.Show();
1549                 }
1550                 if (lowIndicatorImage != null)
1551                 {
1552                     lowIndicatorImage.Hide();
1553                 }
1554                 if (highIndicatorImage != null)
1555                 {
1556                     highIndicatorImage.Hide();
1557                 }
1558             }
1559         }
1560
1561         /// <summary>
1562         /// Value Changed event data.
1563         /// </summary>
1564         /// <since_tizen> 6 </since_tizen>
1565         [Obsolete("Deprecated in API8; Will be removed in API10. Please use SliderValueChangedEventArgs instead.")]
1566         [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
1567         public class ValueChangedArgs : EventArgs
1568         {
1569             /// <summary>
1570             /// Current value
1571             /// </summary>
1572             /// <since_tizen> 6 </since_tizen>
1573             /// It will be removed in API10
1574             [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
1575             [Obsolete("Deprecated in API8; Will be removed in API10. Please use SliderValueChangedEventArgs.CurrentValue instead.")]
1576             public float CurrentValue;
1577         }
1578
1579         /// <summary>
1580         /// Value Changed event data.
1581         /// </summary>
1582         /// <since_tizen> 6 </since_tizen>
1583         [Obsolete("Deprecated in API8; Will be removed in API10. Please use SliderSlidingFinishedEventArgs instead.")]
1584         [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
1585         public class SlidingFinishedArgs : EventArgs
1586         {
1587             /// <summary>
1588             /// Current value
1589             /// </summary>
1590             /// <since_tizen> 6 </since_tizen>
1591             /// It will be removed in API10
1592             [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
1593             [Obsolete("Deprecated in API8; Will be removed in API10. Please use SliderSlidingFinishedEventArgs.CurrentValue instead.")]
1594             public float CurrentValue;
1595         }
1596
1597         /// <summary>
1598         /// State Changed event data.
1599         /// </summary>
1600         /// <since_tizen> 6 </since_tizen>
1601         [Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEventArgs")]
1602         [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
1603         public class StateChangedArgs : EventArgs
1604         {
1605             /// <summary>
1606             /// Current state
1607             /// </summary>
1608             /// <since_tizen> 6 </since_tizen>
1609             /// It will be removed in API10
1610             [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
1611             [Obsolete("Deprecated in API8; Will be removed in API10")]
1612             public ControlStates CurrentState;
1613         }
1614     }
1615 }