ee33c5747882bcccb77500f3a91220ad40d24521
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Slider.cs
1 /*
2  * Copyright(c) 2022 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
18 using System;
19 using System.ComponentModel;
20 using Tizen.NUI.Accessibility;
21 using Tizen.NUI.BaseComponents;
22 using Tizen.NUI.Binding;
23
24 namespace Tizen.NUI.Components
25 {
26     /// <summary>
27     /// Slider value changed event data.
28     /// </summary>
29     /// <since_tizen> 8 </since_tizen>
30     public class SliderValueChangedEventArgs : EventArgs
31     {
32         /// <summary>
33         /// Current Slider value
34         /// </summary>
35         /// <since_tizen> 8 </since_tizen>
36         public float CurrentValue { get; set; }
37     }
38
39     /// <summary>
40     /// Slider sliding started event data.
41     /// </summary>
42     /// <since_tizen> 8 </since_tizen>
43     public class SliderSlidingStartedEventArgs : EventArgs
44     {
45         /// <summary>
46         /// Current Slider value
47         /// </summary>
48         /// <since_tizen> 8 </since_tizen>
49         public float CurrentValue { get; set; }
50     }
51
52     /// <summary>
53     /// Slider sliding finished event data.
54     /// </summary>
55     /// <since_tizen> 8 </since_tizen>
56     public class SliderSlidingFinishedEventArgs : EventArgs
57     {
58         /// <summary>
59         /// Current Slider value
60         /// </summary>
61         /// <since_tizen> 8 </since_tizen>
62         public float CurrentValue { get; set; }
63     }
64
65     /// <summary>
66     /// A slider lets users select a value from a continuous or discrete range of values by moving the slider thumb.
67     /// </summary>
68     /// <since_tizen> 6 </since_tizen>
69     public partial class Slider : Control, IAtspiValue
70     {
71         /// <summary>
72         /// SpaceBetweenTrackAndIndicatorProperty
73         /// </summary>
74         [EditorBrowsable(EditorBrowsableState.Never)]
75         public static readonly BindableProperty IndicatorProperty = BindableProperty.Create(nameof(Indicator), typeof(IndicatorType), typeof(Slider), IndicatorType.None, propertyChanged: (bindable, oldValue, newValue) =>
76         {
77             var instance = (Slider)bindable;
78             if (newValue != null)
79             {
80                 instance.privateIndicatorType = (IndicatorType)newValue;
81             }
82         },
83         defaultValueCreator: (bindable) =>
84         {
85             var instance = (Slider)bindable;
86             return instance.privateIndicatorType;
87         });
88
89         /// <summary>
90         /// SpaceBetweenTrackAndIndicatorProperty
91         /// </summary>
92         [EditorBrowsable(EditorBrowsableState.Never)]
93         public static readonly BindableProperty SpaceBetweenTrackAndIndicatorProperty = BindableProperty.Create(nameof(SpaceBetweenTrackAndIndicator), typeof(uint), typeof(Slider), (uint)0, propertyChanged: (bindable, oldValue, newValue) =>
94         {
95             var instance = (Slider)bindable;
96             if (newValue != null)
97             {
98                 instance.privateSpaceBetweenTrackAndIndicator = (uint)newValue;
99             }
100         },
101         defaultValueCreator: (bindable) =>
102         {
103             var instance = (Slider)bindable;
104             return instance.privateSpaceBetweenTrackAndIndicator;
105         });
106
107         /// <summary>
108         /// TrackThicknessProperty
109         /// </summary>
110         [EditorBrowsable(EditorBrowsableState.Never)]
111         public static readonly BindableProperty TrackThicknessProperty = BindableProperty.Create(nameof(TrackThickness), typeof(uint), typeof(Slider), (uint)0, propertyChanged: (bindable, oldValue, newValue) =>
112         {
113             var instance = (Slider)bindable;
114             if (newValue != null)
115             {
116                 instance.privateTrackThickness = (uint)newValue;
117             }
118         },
119         defaultValueCreator: (bindable) =>
120         {
121             var instance = (Slider)bindable;
122             return instance.privateTrackThickness;
123         });
124
125         /// <summary>
126         /// IsValueShownProperty
127         /// </summary>
128         [EditorBrowsable(EditorBrowsableState.Never)]
129         public static readonly BindableProperty IsValueShownProperty = BindableProperty.Create(nameof(IsValueShown), typeof(bool), typeof(Slider), true, propertyChanged: (bindable, oldValue, newValue) =>
130         {
131             var instance = (Slider)bindable;
132             if (newValue != null)
133             {
134                 bool newValueShown = (bool)newValue;
135                 if (instance.isValueShown != newValueShown)
136                 {
137                     instance.isValueShown = newValueShown;
138                 }
139             }
140         },
141         defaultValueCreator: (bindable) =>
142         {
143             var instance = (Slider)bindable;
144             return instance.isValueShown;
145         });
146
147         /// <summary>
148         /// ValueIndicatorTextProperty
149         /// </summary>
150         [EditorBrowsable(EditorBrowsableState.Never)]
151         public static readonly BindableProperty ValueIndicatorTextProperty = BindableProperty.Create(nameof(ValueIndicatorText), typeof(string), typeof(Slider), string.Empty, propertyChanged: (bindable, oldValue, newValue) =>
152         {
153             var instance = (Slider)bindable;
154             if (newValue != null)
155             {
156                 string newText = (string)newValue;
157                 instance.valueIndicatorText.Text = newText;
158             }
159         },
160         defaultValueCreator: (bindable) =>
161         {
162             var instance = (Slider)bindable;
163             return instance.valueIndicatorText.Text;
164         });
165
166         /// <summary>
167         /// Bindable property of CurrentValue
168         /// <remark>
169         /// Hidden API, used for NUI XAML data binding
170         /// </remark>
171         /// </summary>
172         [EditorBrowsable(EditorBrowsableState.Never)]
173         public static readonly BindableProperty CurrentValueProperty = BindableProperty.Create(nameof(CurrentValue), typeof(float), typeof(Slider), 0.0f, BindingMode.TwoWay,
174             propertyChanged: (bindable, oldValue, newValue) =>
175             {
176                 var instance = (Slider)bindable;
177
178                 if (newValue != null)
179                 {
180                     float value = (float)newValue;
181                     if (value < instance.minValue)
182                     {
183                         instance.curValue = instance.minValue;
184                     }
185                     else if (value > instance.maxValue)
186                     {
187                         instance.curValue = instance.maxValue;
188                     }
189                     else
190                     {
191                         instance.curValue = value;
192                     }
193
194                     instance.sliderValueChangedHandler?.Invoke(instance, new SliderValueChangedEventArgs {
195                         CurrentValue = instance.curValue
196                         });
197                     if (Accessibility.Accessibility.IsEnabled && instance.IsHighlighted)
198                     {
199                         instance.EmitAccessibilityEvent(AccessibilityPropertyChangeEvent.Value);
200                     }
201                     instance.UpdateValue();
202                 }
203             },
204             defaultValueCreator: (bindable) =>
205             {
206                 var instance = (Slider)bindable;
207                 return instance.curValue;
208             }
209         );
210
211         static Slider() { }
212
213         /// <summary>
214         /// The constructor of the Slider class.
215         /// </summary>
216         /// <since_tizen> 6 </since_tizen>
217         public Slider()
218         {
219             Focusable = true;
220             Initialize();
221         }
222
223         /// <summary>
224         /// The constructor of the Slider class with specific style.
225         /// </summary>
226         /// <param name="style">The string to initialize the Slider</param>
227         /// <since_tizen> 8 </since_tizen>
228         public Slider(string style) : base(style)
229         {
230             Focusable = true;
231             Initialize();
232         }
233
234         /// <summary>
235         /// The constructor of the Slider class with specific style.
236         /// </summary>
237         /// <param name="sliderStyle">The style object to initialize the Slider</param>
238         /// <since_tizen> 8 </since_tizen>
239         public Slider(SliderStyle sliderStyle) : base(sliderStyle)
240         {
241             Focusable = true;
242             Initialize();
243         }
244
245         /// <summary>
246         /// The value changed event handler.
247         /// </summary>
248         /// <since_tizen> 8 </since_tizen>
249         public event EventHandler<SliderValueChangedEventArgs> ValueChanged
250         {
251             add
252             {
253                 sliderValueChangedHandler += value;
254             }
255             remove
256             {
257                 sliderValueChangedHandler -= value;
258             }
259         }
260
261         /// <summary>
262         /// The sliding started event handler.
263         /// </summary>
264         /// <since_tizen> 8 </since_tizen>
265         public event EventHandler<SliderSlidingStartedEventArgs> SlidingStarted
266         {
267             add
268             {
269                 sliderSlidingStartedHandler += value;
270             }
271             remove
272             {
273                 sliderSlidingStartedHandler -= value;
274             }
275         }
276
277         /// <summary>
278         /// The sliding finished event handler.
279         /// </summary>
280         /// <since_tizen> 8 </since_tizen>
281         public event EventHandler<SliderSlidingFinishedEventArgs> SlidingFinished
282         {
283             add
284             {
285                 sliderSlidingFinishedHandler += value;
286             }
287             remove
288             {
289                 sliderSlidingFinishedHandler -= value;
290             }
291         }
292
293         /// <summary>
294         /// The direction type of slider.
295         /// </summary>
296         /// <since_tizen> 6 </since_tizen>
297         public enum DirectionType
298         {
299             /// <summary>
300             /// The Horizontal type.
301             /// </summary>
302             /// <since_tizen> 6 </since_tizen>
303             Horizontal,
304
305             /// <summary>
306             /// The Vertical type.
307             /// </summary>
308             /// <since_tizen> 6 </since_tizen>
309             Vertical
310         }
311
312         /// <summary>
313         /// The indicator type of slider.
314         /// </summary>
315         /// <since_tizen> 6 </since_tizen>
316         public enum IndicatorType
317         {
318             /// <summary> Only contains slider bar.</summary>
319             /// <since_tizen> 6 </since_tizen>
320             None,
321
322             /// <summary> Contains slider bar, IndicatorImage.</summary>
323             /// <since_tizen> 6 </since_tizen>
324             Image,
325
326             /// <summary> Contains slider bar, IndicatorText.</summary>
327             /// <since_tizen> 6 </since_tizen>
328             Text
329         }
330
331         /// <summary>
332         /// Return currently applied style.
333         /// </summary>
334         /// <remarks>
335         /// Modifying contents in style may cause unexpected behaviour.
336         /// </remarks>
337         /// <since_tizen> 8 </since_tizen>
338         public SliderStyle Style => (SliderStyle)(ViewStyle as SliderStyle)?.Clone();
339
340         /// <summary>
341         /// Gets or sets the direction type of slider.
342         /// </summary>
343         /// <since_tizen> 6 </since_tizen>
344         public DirectionType Direction
345         {
346             get
347             {
348                 return (DirectionType)GetValue(DirectionProperty);
349             }
350             set
351             {
352                 SetValue(DirectionProperty, value);
353                 NotifyPropertyChanged();
354             }
355         }
356         private DirectionType InternalDirection
357         {
358             get
359             {
360                 return direction;
361             }
362             set
363             {
364                 if (direction == value)
365                 {
366                     return;
367                 }
368                 direction = value;
369                 RelayoutBaseComponent(false);
370                 UpdateBgTrackSize();
371                 UpdateBgTrackPosition();
372                 UpdateWarningTrackSize();
373                 UpdateValue();
374             }
375         }
376
377         /// <summary>
378         /// Gets or sets the indicator type, arrow or sign.
379         /// </summary>
380         /// <since_tizen> 6 </since_tizen>
381         public IndicatorType Indicator
382         {
383             get
384             {
385                 return (IndicatorType)GetValue(IndicatorProperty);
386             }
387             set
388             {
389                 SetValue(IndicatorProperty, value);
390             }
391         }
392
393         /// <summary>
394         /// Gets or sets the minimum value of slider.
395         /// </summary>
396         /// <since_tizen> 6 </since_tizen>
397         public float MinValue
398         {
399             get
400             {
401                 return (float)GetValue(MinValueProperty);
402             }
403             set
404             {
405                 SetValue(MinValueProperty, value);
406                 NotifyPropertyChanged();
407             }
408         }
409         private float InternalMinValue
410         {
411             get
412             {
413                 return minValue;
414             }
415             set
416             {
417                 minValue = value;
418                 UpdateValue();
419             }
420         }
421
422         /// <summary>
423         /// Gets or sets the maximum value of slider.
424         /// </summary>
425         /// <since_tizen> 6 </since_tizen>
426         public float MaxValue
427         {
428             get
429             {
430                 return (float)GetValue(MaxValueProperty);
431             }
432             set
433             {
434                 SetValue(MaxValueProperty, value);
435                 NotifyPropertyChanged();
436             }
437         }
438         private float InternalMaxValue
439         {
440             get
441             {
442                 return maxValue;
443             }
444             set
445             {
446                 maxValue = value;
447                 UpdateValue();
448             }
449         }
450
451         /// <summary>
452         /// Gets or sets the current value of slider.
453         /// </summary>
454         /// <since_tizen> 6 </since_tizen>
455         public float CurrentValue
456         {
457             get
458             {
459                 return (float)GetValue(CurrentValueProperty);
460             }
461             set
462             {
463                 SetValue(CurrentValueProperty, value);
464             }
465         }
466
467         /// <summary>
468         /// Gets or sets the size of the thumb image object.
469         /// </summary>
470         /// <since_tizen> 6 </since_tizen>
471         public Size ThumbSize
472         {
473             get
474             {
475                 return GetValue(ThumbSizeProperty) as Size;
476             }
477             set
478             {
479                 SetValue(ThumbSizeProperty, value);
480                 NotifyPropertyChanged();
481             }
482         }
483         private Size InternalThumbSize
484         {
485             get
486             {
487                 return thumbImage?.Size;
488             }
489             set
490             {
491                 if (null != thumbImage)
492                 {
493                     thumbImage.Size = value;
494                     thumbSize = value;
495                 }
496             }
497         }
498
499         /// <summary>
500         /// Gets or sets the resource url of the thumb image object.
501         ///
502         /// Please use ThumbImageUrl property.
503         /// </summary>
504         /// <since_tizen> 6 </since_tizen>
505         public string ThumbImageURL
506         {
507             get
508             {
509                 return GetValue(ThumbImageURLProperty) as string;
510             }
511             set
512             {
513                 SetValue(ThumbImageURLProperty, value);
514                 NotifyPropertyChanged();
515             }
516         }
517         private string InternalThumbImageURL
518         {
519             get
520             {
521                 return thumbImage?.ResourceUrl;
522             }
523             set
524             {
525                 if (null != thumbImage)
526                 {
527                     thumbImage.ResourceUrl = value;
528                     thumbImageUrl = value;
529                 }
530             }
531         }
532
533         /// <summary>
534         /// Gets or sets the resource url selector of the thumb image object.
535         /// Getter returns copied selector value if exist, null otherwise.
536         ///
537         /// Please use ThumbImageUrl property.
538         /// </summary>
539         /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
540         /// <since_tizen> 6 </since_tizen>
541         public StringSelector ThumbImageURLSelector
542         {
543             get
544             {
545                 return GetValue(ThumbImageURLSelectorProperty) as StringSelector;
546             }
547             set
548             {
549                 SetValue(ThumbImageURLSelectorProperty, value);
550                 NotifyPropertyChanged();
551             }
552         }
553         private StringSelector InternalThumbImageURLSelector
554         {
555             get => thumbImage?.ResourceUrlSelector == null ? null : new StringSelector(thumbImage.ResourceUrlSelector);
556             set
557             {
558                 if (value == null || thumbImage == null)
559                 {
560                     throw new NullReferenceException("Slider.ThumbImageURLSelector is null");
561                 }
562                 else
563                 {
564                     thumbImage.ResourceUrlSelector = value;
565                 }
566             }
567         }
568
569         /// <summary>
570         /// Gets or sets the Url of the thumb image.
571         /// </summary>
572         /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
573         /// <since_tizen> 9 </since_tizen>
574         public Selector<string> ThumbImageUrl
575         {
576             get
577             {
578                 return GetValue(ThumbImageUrlProperty) as Selector<string>;
579             }
580             set
581             {
582                 SetValue(ThumbImageUrlProperty, value);
583                 NotifyPropertyChanged();
584             }
585         }
586         private Selector<string> InternalThumbImageUrl
587         {
588             get
589             {
590                 if (thumbImage == null)
591                 {
592                     return null;
593                 }
594                 else
595                 {
596                     return thumbImage.ResourceUrlSelector;
597                 }
598             }
599             set
600             {
601                 if (value == null || thumbImage == null)
602                 {
603                     throw new NullReferenceException("Slider.ThumbImageUrl is null");
604                 }
605                 else
606                 {
607                     thumbImage.ResourceUrlSelector = value;
608                 }
609             }
610         }
611
612         /// <summary>
613         /// Gets or sets the color of the thumb image object.
614         /// </summary>
615         /// <since_tizen> 8 </since_tizen>
616         public Color ThumbColor
617         {
618             get
619             {
620                 return GetValue(ThumbColorProperty) as Color;
621             }
622             set
623             {
624                 SetValue(ThumbColorProperty, value);
625                 NotifyPropertyChanged();
626             }
627         }
628         private Color InternalThumbColor
629         {
630             get
631             {
632                 return thumbColor;
633             }
634             set
635             {
636                 if (null != thumbImage)
637                 {
638                     thumbColor = value;
639
640                     if (thumbImage.ResourceUrl != null)
641                     {
642                         thumbImage.ResourceUrl = null;
643                     }
644
645                     using (PropertyMap map = new PropertyMap())
646                     {
647                         // To remove CA2000 warning messages, use `using` statement.
648                         using (PropertyValue type = new PropertyValue((int)Visual.Type.Color))
649                         {
650                             map.Insert((int)Visual.Property.Type, type);
651                         }
652                         using (PropertyValue color = new PropertyValue(thumbColor))
653                         {
654                             map.Insert((int)ColorVisualProperty.MixColor, color);
655                         }
656                         using (PropertyValue radius = new PropertyValue(0.5f))
657                         {
658                             map.Insert((int)Visual.Property.CornerRadius, radius);
659                         }
660                         using (PropertyValue policyType = new PropertyValue((int)VisualTransformPolicyType.Relative))
661                         {
662                             map.Insert((int)Visual.Property.CornerRadiusPolicy, policyType);
663                         }
664                         thumbImage.Image = map;
665                     }
666                 }
667             }
668         }
669
670         /// <summary>
671         /// Gets or sets the color of the background track image object.
672         /// </summary>
673         /// <since_tizen> 6 </since_tizen>
674         public Color BgTrackColor
675         {
676             get
677             {
678                 return GetValue(BgTrackColorProperty) as Color;
679             }
680             set
681             {
682                 SetValue(BgTrackColorProperty, value);
683                 NotifyPropertyChanged();
684             }
685         }
686         private Color InternalBgTrackColor
687         {
688             get
689             {
690                 return bgTrackImage?.BackgroundColor;
691             }
692             set
693             {
694                 if (null != bgTrackImage)
695                 {
696                     bgTrackImage.BackgroundColor = value;
697                 }
698             }
699         }
700
701         /// <summary>
702         /// Gets or sets the color of the slided track image object.
703         /// </summary>
704         /// <since_tizen> 6 </since_tizen>
705         public Color SlidedTrackColor
706         {
707             get
708             {
709                 return GetValue(SlidedTrackColorProperty) as Color;
710             }
711             set
712             {
713                 SetValue(SlidedTrackColorProperty, value);
714                 NotifyPropertyChanged();
715             }
716         }
717         private Color InternalSlidedTrackColor
718         {
719             get
720             {
721                 return slidedTrackImage?.BackgroundColor;
722             }
723             set
724             {
725                 if (null != slidedTrackImage)
726                 {
727                     slidedTrackImage.BackgroundColor = value;
728                 }
729             }
730         }
731
732         /// <summary>
733         /// Gets or sets the thickness value of the track.
734         /// </summary>
735         /// <since_tizen> 6 </since_tizen>
736         public uint TrackThickness
737         {
738             get
739             {
740                 return (uint)GetValue(TrackThicknessProperty);
741             }
742             set
743             {
744                 SetValue(TrackThicknessProperty, value);
745             }
746         }
747
748         /// <summary>
749         /// Gets or sets the warning start value between minimum value and maximum value of slider.
750         /// </summary>
751         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
752         [EditorBrowsable(EditorBrowsableState.Never)]
753         public float WarningStartValue
754         {
755             get
756             {
757                 return (float)GetValue(WarningStartValueProperty);
758             }
759             set
760             {
761                 SetValue(WarningStartValueProperty, value);
762                 NotifyPropertyChanged();
763             }
764         }
765         private float InternalWarningStartValue
766         {
767             get
768             {
769                 return warningStartValue;
770             }
771             set
772             {
773                 warningStartValue = value;
774                 UpdateValue();
775             }
776         }
777
778         /// <summary>
779         /// Gets or sets the color of the warning track image object.
780         /// </summary>
781         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
782         [EditorBrowsable(EditorBrowsableState.Never)]
783         public Color WarningTrackColor
784         {
785             get
786             {
787                 return GetValue(WarningTrackColorProperty) as Color;
788             }
789             set
790             {
791                 SetValue(WarningTrackColorProperty, value);
792                 NotifyPropertyChanged();
793             }
794         }
795         private Color InternalWarningTrackColor
796         {
797             get
798             {
799                 return warningTrackImage?.BackgroundColor;
800             }
801             set
802             {
803                 if (null != warningTrackImage)
804                 {
805                     warningTrackImage.BackgroundColor = value;
806                 }
807             }
808         }
809
810         /// <summary>
811         /// Gets or sets the color of the warning slided track image object.
812         /// </summary>
813         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
814         [EditorBrowsable(EditorBrowsableState.Never)]
815         public Color WarningSlidedTrackColor
816         {
817             get
818             {
819                 return GetValue(WarningSlidedTrackColorProperty) as Color;
820             }
821             set
822             {
823                 SetValue(WarningSlidedTrackColorProperty, value);
824                 NotifyPropertyChanged();
825             }
826         }
827         private Color InternalWarningSlidedTrackColor
828         {
829             get
830             {
831                 return warningSlidedTrackImage?.BackgroundColor;
832             }
833             set
834             {
835                 if (null != warningSlidedTrackImage)
836                 {
837                     warningSlidedTrackImage.BackgroundColor = value;
838                 }
839             }
840         }
841
842         /// <summary>
843         /// Gets or sets the Url of the warning thumb image.
844         /// </summary>
845         /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
846         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
847         [EditorBrowsable(EditorBrowsableState.Never)]
848         public Selector<string> WarningThumbImageUrl
849         {
850             get
851             {
852                 return GetValue(WarningThumbImageUrlProperty) as Selector<string>;
853             }
854             set
855             {
856                 SetValue(WarningThumbImageUrlProperty, value);
857                 NotifyPropertyChanged();
858             }
859         }
860         private Selector<string> InternalWarningThumbImageUrl
861         {
862             get
863             {
864                 return warningThumbImageUrlSelector;
865             }
866             set
867             {
868                 if (value == null || thumbImage == null)
869                 {
870                     throw new NullReferenceException("Slider.WarningThumbImageUrl is null");
871                 }
872                 else
873                 {
874                     warningThumbImageUrlSelector = value;
875                 }
876             }
877         }
878
879         /// <summary>
880         /// Gets or sets the color of the warning thumb image object.
881         /// </summary>
882         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
883         [EditorBrowsable(EditorBrowsableState.Never)]
884         public Color WarningThumbColor
885         {
886             get
887             {
888                 return GetValue(WarningThumbColorProperty) as Color;
889             }
890             set
891             {
892                 SetValue(WarningThumbColorProperty, value);
893                 NotifyPropertyChanged();
894             }
895         }
896         private Color InternalWarningThumbColor
897         {
898             get
899             {
900                 return warningThumbColor;
901             }
902             set
903             {
904                 warningThumbColor = value;
905             }
906         }
907
908         /// <summary>
909         /// Gets or sets the resource url of the low indicator image object.
910         /// </summary>
911         /// <since_tizen> 6 </since_tizen>
912         public string LowIndicatorImageURL
913         {
914             get
915             {
916                 return GetValue(LowIndicatorImageURLProperty) as string;
917             }
918             set
919             {
920                 SetValue(LowIndicatorImageURLProperty, value);
921                 NotifyPropertyChanged();
922             }
923         }
924         private string InternalLowIndicatorImageURL
925         {
926             get
927             {
928                 return lowIndicatorImage?.ResourceUrl;
929             }
930             set
931             {
932                 if (null == lowIndicatorImage)
933                 {
934                     lowIndicatorImage = new ImageView
935                     {
936                         AccessibilityHidden = true,
937                     };
938                 }
939
940                 lowIndicatorImage.ResourceUrl = value;
941             }
942         }
943
944         /// <summary>
945         /// Gets or sets the resource url of the high indicator image object.
946         /// </summary>
947         /// <since_tizen> 6 </since_tizen>
948         public string HighIndicatorImageURL
949         {
950             get
951             {
952                 return GetValue(HighIndicatorImageURLProperty) as string;
953             }
954             set
955             {
956                 SetValue(HighIndicatorImageURLProperty, value);
957                 NotifyPropertyChanged();
958             }
959         }
960         private string InternalHighIndicatorImageURL
961         {
962             get
963             {
964                 return highIndicatorImage?.ResourceUrl;
965             }
966             set
967             {
968                 if (null == highIndicatorImage)
969                 {
970                     highIndicatorImage = new ImageView
971                     {
972                         AccessibilityHidden = true,
973                     };
974                 }
975
976                 highIndicatorImage.ResourceUrl = value;
977             }
978         }
979
980         /// <summary>
981         /// Gets or sets the text content of the low indicator text object.
982         /// </summary>
983         /// <since_tizen> 6 </since_tizen>
984         public string LowIndicatorTextContent
985         {
986             get
987             {
988                 return GetValue(LowIndicatorTextContentProperty) as string;
989             }
990             set
991             {
992                 SetValue(LowIndicatorTextContentProperty, value);
993                 NotifyPropertyChanged();
994             }
995         }
996         private string InternalLowIndicatorTextContent
997         {
998             get
999             {
1000                 return lowIndicatorText?.Text;
1001             }
1002             set
1003             {
1004                 if (null != lowIndicatorText)
1005                 {
1006                     lowIndicatorText.Text = value;
1007                 }
1008             }
1009         }
1010
1011         /// <summary>
1012         /// Gets or sets the text content of the high indicator text object.
1013         /// </summary>
1014         /// <since_tizen> 6 </since_tizen>
1015         public string HighIndicatorTextContent
1016         {
1017             get
1018             {
1019                 return GetValue(HighIndicatorTextContentProperty) as string;
1020             }
1021             set
1022             {
1023                 SetValue(HighIndicatorTextContentProperty, value);
1024                 NotifyPropertyChanged();
1025             }
1026         }
1027         private string InternalHighIndicatorTextContent
1028         {
1029             get
1030             {
1031                 return highIndicatorText?.Text;
1032             }
1033             set
1034             {
1035                 if (null != highIndicatorText)
1036                 {
1037                     highIndicatorText.Text = value;
1038                 }
1039             }
1040         }
1041
1042         /// <summary>
1043         /// Gets or sets the size of the low indicator object(image or text).
1044         /// </summary>
1045         /// <since_tizen> 6 </since_tizen>
1046         public Size LowIndicatorSize
1047         {
1048             get
1049             {
1050                 return GetValue(LowIndicatorSizeProperty) as Size;
1051             }
1052             set
1053             {
1054                 SetValue(LowIndicatorSizeProperty, value);
1055                 NotifyPropertyChanged();
1056             }
1057         }
1058         private Size InternalLowIndicatorSize
1059         {
1060             get
1061             {
1062                 return lowIndicatorSize;
1063             }
1064             set
1065             {
1066                 lowIndicatorSize = value;
1067                 UpdateLowIndicatorSize();
1068                 UpdateBgTrackSize();
1069                 UpdateBgTrackPosition();
1070                 UpdateValue();
1071             }
1072         }
1073
1074         /// <summary>
1075         /// Gets or sets the size of the high indicator object(image or text).
1076         /// </summary>
1077         /// <since_tizen> 6 </since_tizen>
1078         public Size HighIndicatorSize
1079         {
1080             get
1081             {
1082                 return GetValue(HighIndicatorSizeProperty) as Size;
1083             }
1084             set
1085             {
1086                 SetValue(HighIndicatorSizeProperty, value);
1087                 NotifyPropertyChanged();
1088             }
1089         }
1090         private Size InternalHighIndicatorSize
1091         {
1092             get
1093             {
1094                 return highIndicatorSize;
1095             }
1096             set
1097             {
1098                 highIndicatorSize = value;
1099                 UpdateHighIndicatorSize();
1100                 UpdateBgTrackSize();
1101                 UpdateBgTrackPosition();
1102                 UpdateValue();
1103             }
1104         }
1105
1106         /// <summary>
1107         /// Gets or sets the value of the space between track and indicator.
1108         /// </summary>
1109         /// <since_tizen> 6 </since_tizen>
1110         public uint SpaceBetweenTrackAndIndicator
1111         {
1112             get
1113             {
1114                 return (uint)GetValue(SpaceBetweenTrackAndIndicatorProperty);
1115             }
1116             set
1117             {
1118                 SetValue(SpaceBetweenTrackAndIndicatorProperty, value);
1119             }
1120         }
1121
1122         /// <summary>
1123         /// Flag to decide whether the value indicator is shown
1124         /// </summary>
1125         /// <since_tizen> 9 </since_tizen>
1126         public bool IsValueShown
1127         {
1128             get
1129             {
1130                 return (bool)GetValue(IsValueShownProperty);
1131             }
1132             set
1133             {
1134                 SetValue(IsValueShownProperty, value);
1135             }
1136         }
1137
1138         /// <summary>
1139         /// Gets or sets the text of value indicator.
1140         /// </summary>
1141         /// <since_tizen> 9 </since_tizen>
1142         public string ValueIndicatorText
1143         {
1144             get
1145             {
1146                 return (string)GetValue(ValueIndicatorTextProperty);
1147             }
1148             set
1149             {
1150                 SetValue(ValueIndicatorTextProperty, value);
1151             }
1152         }
1153
1154         /// <summary>
1155         /// Gets or sets the size of the value indicator image object.
1156         /// </summary>
1157         /// <since_tizen> 9 </since_tizen>
1158         public Size ValueIndicatorSize
1159         {
1160             get
1161             {
1162                 return GetValue(ValueIndicatorSizeProperty) as Size;
1163             }
1164             set
1165             {
1166                 SetValue(ValueIndicatorSizeProperty, value);
1167                 NotifyPropertyChanged();
1168             }
1169         }
1170         private Size InternalValueIndicatorSize
1171         {
1172             get
1173             {
1174                 return valueIndicatorImage?.Size;
1175             }
1176             set
1177             {
1178                 if (null != valueIndicatorImage)
1179                 {
1180                     valueIndicatorImage.Size = value;
1181                 }
1182             }
1183         }
1184
1185         /// <summary>
1186         /// Gets or sets the resource url of the value indicator image object.
1187         /// </summary>
1188         /// <since_tizen> 9 </since_tizen>
1189         public string ValueIndicatorUrl
1190         {
1191             get
1192             {
1193                 return GetValue(ValueIndicatorUrlProperty) as string;
1194             }
1195             set
1196             {
1197                 SetValue(ValueIndicatorUrlProperty, value);
1198                 NotifyPropertyChanged();
1199             }
1200         }
1201         private string InternalValueIndicatorUrl
1202         {
1203             get
1204             {
1205                 return valueIndicatorImage?.ResourceUrl;
1206             }
1207             set
1208             {
1209                 if (null != valueIndicatorImage)
1210                 {
1211                     valueIndicatorImage.ResourceUrl = value;
1212                 }
1213             }
1214         }
1215
1216         /// <summary>
1217         /// Flag to decide whether the thumb snaps to the nearest discrete value when the user drags the thumb or taps.
1218         ///
1219         /// The default value is false.
1220         /// </summary>
1221         /// <since_tizen> 9 </since_tizen>
1222         public bool IsDiscrete
1223         {
1224             get
1225             {
1226                 return (bool)GetValue(IsDiscreteProperty);
1227             }
1228             set
1229             {
1230                 SetValue(IsDiscreteProperty, value);
1231                 NotifyPropertyChanged();
1232             }
1233         }
1234         private bool InternalIsDiscrete { get; set; } = false;
1235
1236         /// <summary>
1237         /// Gets or sets the discrete value of slider.
1238         /// </summary>
1239         /// <remarks>
1240         /// The discrete value is evenly spaced between MinValue and MaxValue.
1241         /// For example, MinValue is 0, MaxValue is 100, and DiscreteValue is 20.
1242         /// Then, the thumb can only go to 0, 20, 40, 60, 80, and 100.
1243         /// The default is 0.
1244         /// </remarks>
1245         /// <since_tizen> 9 </since_tizen>
1246         public float DiscreteValue
1247         {
1248             get
1249             {
1250                 return (float)GetValue(DiscreteValueProperty);
1251             }
1252             set
1253             {
1254                 SetValue(DiscreteValueProperty, value);
1255                 NotifyPropertyChanged();
1256             }
1257         }
1258         private float InternalDiscreteValue
1259         {
1260             get
1261             {
1262                 return discreteValue;
1263             }
1264             set
1265             {
1266                 discreteValue = value;
1267                 UpdateValue();
1268             }
1269         }
1270
1271         private Extents spaceBetweenTrackAndIndicator
1272         {
1273             get
1274             {
1275                 if (null == spaceTrackIndicator)
1276                 {
1277                     spaceTrackIndicator = new Extents((ushort start, ushort end, ushort top, ushort bottom) =>
1278                     {
1279                         Extents extents = new Extents(start, end, top, bottom);
1280                         spaceTrackIndicator.CopyFrom(extents);
1281                     }, 0, 0, 0, 0);
1282                 }
1283
1284                 return spaceTrackIndicator;
1285             }
1286         }
1287
1288         private IndicatorType privateIndicatorType
1289         {
1290             get
1291             {
1292                 return indicatorType;
1293             }
1294             set
1295             {
1296                 if (indicatorType == value)
1297                 {
1298                     return;
1299                 }
1300                 indicatorType = value;
1301                 RelayoutBaseComponent(false);
1302                 UpdateBgTrackSize();
1303                 UpdateBgTrackPosition();
1304                 UpdateValue();
1305             }
1306         }
1307
1308         private uint privateTrackThickness
1309         {
1310             get
1311             {
1312                 return trackThickness ?? 0;
1313             }
1314             set
1315             {
1316                 trackThickness = value;
1317                 if (bgTrackImage != null)
1318                 {
1319                     if (direction == DirectionType.Horizontal)
1320                     {
1321                         bgTrackImage.SizeHeight = (float)trackThickness.Value;
1322                     }
1323                     else if (direction == DirectionType.Vertical)
1324                     {
1325                         bgTrackImage.SizeWidth = (float)trackThickness.Value;
1326                     }
1327                 }
1328                 if (slidedTrackImage != null)
1329                 {
1330                     if (direction == DirectionType.Horizontal)
1331                     {
1332                         slidedTrackImage.SizeHeight = (float)trackThickness.Value;
1333                     }
1334                     else if (direction == DirectionType.Vertical)
1335                     {
1336                         slidedTrackImage.SizeWidth = (float)trackThickness.Value;
1337                     }
1338                 }
1339                 if (warningTrackImage != null)
1340                 {
1341                     if (direction == DirectionType.Horizontal)
1342                     {
1343                         warningTrackImage.SizeHeight = (float)trackThickness.Value;
1344                     }
1345                     else if (direction == DirectionType.Vertical)
1346                     {
1347                         warningTrackImage.SizeWidth = (float)trackThickness.Value;
1348                     }
1349                 }
1350                 if (warningSlidedTrackImage != null)
1351                 {
1352                     if (direction == DirectionType.Horizontal)
1353                     {
1354                         warningSlidedTrackImage.SizeHeight = (float)trackThickness.Value;
1355                     }
1356                     else if (direction == DirectionType.Vertical)
1357                     {
1358                         warningSlidedTrackImage.SizeWidth = (float)trackThickness.Value;
1359                     }
1360                 }
1361             }
1362         }
1363
1364         private uint privateSpaceBetweenTrackAndIndicator
1365         {
1366             get
1367             {
1368                 return privateTrackPadding.Start;
1369             }
1370             set
1371             {
1372                 ushort val = (ushort)value;
1373                 privateTrackPadding = new Extents(val, val, val, val);
1374             }
1375         }
1376
1377         private Extents privateTrackPadding
1378         {
1379             get
1380             {
1381                 return spaceBetweenTrackAndIndicator;
1382             }
1383             set
1384             {
1385                 spaceBetweenTrackAndIndicator.CopyFrom(value);
1386                 UpdateComponentByIndicatorTypeChanged();
1387                 UpdateBgTrackSize();
1388                 UpdateBgTrackPosition();
1389                 UpdateValue();
1390             }
1391         }
1392
1393         /// <summary>
1394         /// Focus gained callback.
1395         /// </summary>
1396         /// <since_tizen> 8 </since_tizen>
1397         public override void OnFocusGained()
1398         {
1399             //State = ControlStates.Focused;
1400             UpdateState(true, isPressed);
1401             base.OnFocusGained();
1402         }
1403
1404         /// <summary>
1405         /// Focus Lost callback.
1406         /// </summary>
1407         /// <since_tizen> 8 </since_tizen>
1408         public override void OnFocusLost()
1409         {
1410             //State = ControlStates.Normal;
1411             UpdateState(false, isPressed);
1412             base.OnFocusLost();
1413         }
1414
1415         private bool editMode = false;
1416         private View recoverIndicator;
1417         private View editModeIndicator;
1418
1419         /// <inheritdoc/>
1420         [EditorBrowsable(EditorBrowsableState.Never)]
1421         public override bool OnKeyboardEnter()
1422         {
1423             if (!IsEnabled)
1424             {
1425                 return false;
1426             }
1427             if (editMode)
1428             {
1429                 //set editMode false (toggle the mode)
1430                 editMode = false;
1431                 FocusManager.Instance.FocusIndicator = recoverIndicator;
1432             }
1433             else
1434             {
1435                 //set editMode true (toggle the mode)
1436                 editMode = true;
1437                 if (editModeIndicator == null)
1438                 {
1439                     editModeIndicator = new View()
1440                     {
1441                         PositionUsesPivotPoint = true,
1442                         PivotPoint = new Position(0, 0, 0),
1443                         WidthResizePolicy = ResizePolicyType.FillToParent,
1444                         HeightResizePolicy = ResizePolicyType.FillToParent,
1445                         BorderlineColor = Color.Red,
1446                         BorderlineWidth = 6.0f,
1447                         BorderlineOffset = -1f,
1448                         BackgroundColor = new Color(0.2f, 0.2f, 0.2f, 0.4f),
1449                         AccessibilityHidden = true,
1450                     };
1451                 }
1452                 recoverIndicator = FocusManager.Instance.FocusIndicator;
1453                 FocusManager.Instance.FocusIndicator = editModeIndicator;
1454             }
1455             UpdateState(true, isPressed);
1456             return true;
1457         }
1458
1459         /// <inheritdoc/>
1460         [EditorBrowsable(EditorBrowsableState.Never)]
1461         public override bool OnKey(Key key)
1462         {
1463             if (!IsEnabled || null == key)
1464             {
1465                 return false;
1466             }
1467
1468             if (key.State == Key.StateType.Down)
1469             {
1470                 if ((direction == DirectionType.Horizontal && key.KeyPressedName == "Left") ||
1471                     (direction == DirectionType.Vertical && key.KeyPressedName == "Down"))
1472                 {
1473                     if (editMode)
1474                     {
1475                         if (MinValue < CurrentValue)
1476                         {
1477                             isPressed = true;
1478                             if (IsDiscrete)
1479                             {
1480                                 float value = curValue - discreteValue;
1481                                 CurrentValue = value;
1482                             }
1483                             else
1484                             {
1485                                 CurrentValue -= 1;
1486                             }
1487                         }
1488                         return true; // Consumed
1489                     }
1490                 }
1491                 else if ((direction == DirectionType.Horizontal && key.KeyPressedName == "Right") ||
1492                          (direction == DirectionType.Vertical && key.KeyPressedName == "Up"))
1493                 {
1494                     if (editMode)
1495                     {
1496                         if (MaxValue > CurrentValue)
1497                         {
1498                             isPressed = true;
1499                             if (IsDiscrete)
1500                             {
1501                                 float value = curValue + discreteValue;
1502                                 CurrentValue = value;
1503                             }
1504                             else
1505                             {
1506                                 CurrentValue += 1;
1507                             }
1508                         }
1509                         return true; // Consumed
1510                     }
1511                 }
1512             }
1513             else if (key.State == Key.StateType.Up)
1514             {
1515                 isPressed = false;
1516             }
1517
1518             if (key.KeyPressedName == "Up" || key.KeyPressedName == "Right" || key.KeyPressedName == "Down" || key.KeyPressedName == "Left")
1519             {
1520                 if (editMode)
1521                 {
1522                     return true;
1523                 }
1524             }
1525             return false;
1526         }
1527
1528         /// <summary>
1529         /// Apply style to scrollbar.
1530         /// </summary>
1531         /// <param name="viewStyle">The style to apply.</param>
1532         /// <since_tizen> 8 </since_tizen>
1533         public override void ApplyStyle(ViewStyle viewStyle)
1534         {
1535             base.ApplyStyle(viewStyle);
1536
1537             SliderStyle sliderStyle = viewStyle as SliderStyle;
1538
1539             if (null != sliderStyle?.Progress)
1540             {
1541                 CreateSlidedTrack().ApplyStyle(sliderStyle.Progress);
1542             }
1543
1544             if (null != sliderStyle?.LowIndicator)
1545             {
1546                 CreateLowIndicatorText().ApplyStyle(sliderStyle.LowIndicator);
1547             }
1548
1549             if (null != sliderStyle?.HighIndicator)
1550             {
1551                 CreateHighIndicatorText().ApplyStyle(sliderStyle.HighIndicator);
1552             }
1553
1554             if (null != sliderStyle?.LowIndicatorImage)
1555             {
1556                 CreateLowIndicatorImage().ApplyStyle(sliderStyle.LowIndicatorImage);
1557             }
1558
1559             if (null != sliderStyle?.HighIndicatorImage)
1560             {
1561                 CreateHighIndicatorImage().ApplyStyle(sliderStyle.HighIndicatorImage);
1562             }
1563
1564             if (null != sliderStyle?.Track)
1565             {
1566                 CreateBackgroundTrack().ApplyStyle(sliderStyle.Track);
1567             }
1568
1569             if (null != sliderStyle?.Thumb)
1570             {
1571                 CreateThumb().ApplyStyle(sliderStyle.Thumb);
1572             }
1573
1574             if (null != sliderStyle?.ValueIndicatorText)
1575             {
1576                 CreateValueIndicatorText().ApplyStyle(sliderStyle.ValueIndicatorText);
1577             }
1578
1579             if (null != sliderStyle?.ValueIndicatorImage)
1580             {
1581                 CreateValueIndicatorImage().ApplyStyle(sliderStyle.ValueIndicatorImage);
1582             }
1583
1584             if (null != sliderStyle?.WarningTrack)
1585             {
1586                 CreateWarningTrack().ApplyStyle(sliderStyle.WarningTrack);
1587             }
1588
1589             if (null != sliderStyle?.WarningProgress)
1590             {
1591                 CreateWarningSlidedTrack().ApplyStyle(sliderStyle.WarningProgress);
1592             }
1593
1594             EnableControlStatePropagation = true;
1595         }
1596
1597         /// <summary>
1598         /// Gets minimum value for Accessibility.
1599         /// </summary>
1600         [EditorBrowsable(EditorBrowsableState.Never)]
1601         double IAtspiValue.AccessibilityGetMinimum()
1602         {
1603             return (double)MinValue;
1604         }
1605
1606         /// <summary>
1607         /// Gets the current value for Accessibility.
1608         /// </summary>
1609         [EditorBrowsable(EditorBrowsableState.Never)]
1610         double IAtspiValue.AccessibilityGetCurrent()
1611         {
1612             return (double)CurrentValue;
1613         }
1614
1615         /// <summary>
1616         /// Gets maximum value for Accessibility.
1617         /// </summary>
1618         [EditorBrowsable(EditorBrowsableState.Never)]
1619         double IAtspiValue.AccessibilityGetMaximum()
1620         {
1621             return (double)MaxValue;
1622         }
1623
1624         /// <summary>
1625         /// Sets the current value using Accessibility.
1626         /// </summary>
1627         [EditorBrowsable(EditorBrowsableState.Never)]
1628         bool IAtspiValue.AccessibilitySetCurrent(double value)
1629         {
1630             var current = (float)value;
1631
1632             if (current >= MinValue && current <= MaxValue)
1633             {
1634                 CurrentValue = current;
1635                 return true;
1636             }
1637
1638             return false;
1639         }
1640
1641         /// <summary>
1642         /// Gets minimum increment for Accessibility.
1643         /// </summary>
1644         [EditorBrowsable(EditorBrowsableState.Never)]
1645         double IAtspiValue.AccessibilityGetMinimumIncrement()
1646         {
1647             // FIXME
1648             return (MaxValue - MinValue) / 20.0;
1649         }
1650
1651         /// <summary>
1652         /// Initialize AT-SPI object.
1653         /// </summary>
1654         [EditorBrowsable(EditorBrowsableState.Never)]
1655         public override void OnInitialize()
1656         {
1657             base.OnInitialize();
1658             AccessibilityRole = Role.Slider;
1659         }
1660
1661         /// <summary>
1662         /// Get Slider style.
1663         /// </summary>
1664         /// <returns>The default slider style.</returns>
1665         /// <since_tizen> 8 </since_tizen>
1666         protected override ViewStyle CreateViewStyle()
1667         {
1668             return new SliderStyle();
1669         }
1670
1671         /// <summary>
1672         /// Dispose Slider.
1673         /// </summary>
1674         /// <param name="type">Dispose type.</param>
1675         /// <since_tizen> 6 </since_tizen>
1676         protected override void Dispose(DisposeTypes type)
1677         {
1678             if (disposed)
1679             {
1680                 return;
1681             }
1682
1683             if (type == DisposeTypes.Explicit)
1684             {
1685                 if (null != panGestureDetector)
1686                 {
1687                     panGestureDetector.Detach(this);
1688                     panGestureDetector.Detected -= OnPanGestureDetected;
1689                     panGestureDetector.Dispose();
1690                     panGestureDetector = null;
1691                 }
1692
1693                 if (null != thumbImage)
1694                 {
1695                     thumbImage.TouchEvent -= OnTouchEventForThumb;
1696                     Utility.Dispose(thumbImage);
1697                 }
1698                 Utility.Dispose(warningSlidedTrackImage);
1699                 Utility.Dispose(warningTrackImage);
1700                 Utility.Dispose(slidedTrackImage);
1701                 Utility.Dispose(bgTrackImage);
1702                 Utility.Dispose(lowIndicatorImage);
1703                 Utility.Dispose(highIndicatorImage);
1704                 Utility.Dispose(lowIndicatorText);
1705                 Utility.Dispose(highIndicatorText);
1706                 Utility.Dispose(valueIndicatorImage);
1707                 Utility.Dispose(valueIndicatorText);
1708
1709                 this.TouchEvent -= OnTouchEventForTrack;
1710
1711                 recoverIndicator = null;
1712                 if (editModeIndicator != null)
1713                 {
1714                     editModeIndicator.Dispose();
1715                     editModeIndicator = null;
1716                 }
1717             }
1718
1719             base.Dispose(type);
1720         }
1721
1722         /// <summary>
1723         /// Update Slider by style.
1724         /// </summary>
1725         /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
1726         [EditorBrowsable(EditorBrowsableState.Never)]
1727         protected override void OnUpdate()
1728         {
1729             RelayoutBaseComponent();
1730
1731             UpdateComponentByIndicatorTypeChanged();
1732             UpdateBgTrackSize();
1733             UpdateBgTrackPosition();
1734             UpdateWarningTrackSize();
1735             UpdateLowIndicatorSize();
1736             UpdateHighIndicatorSize();
1737             UpdateValue();
1738         }
1739
1740         /// <inheritdoc/>
1741         [EditorBrowsable(EditorBrowsableState.Never)]
1742         protected override void OnEnabled(bool enabled)
1743         {
1744             base.OnEnabled(enabled);
1745             UpdateValue();
1746         }
1747
1748         private void CalculateCurrentValueByGesture(float offset)
1749         {
1750             currentSlidedOffset += offset;
1751
1752             if (currentSlidedOffset <= 0)
1753             {
1754                 this.CurrentValue = minValue;
1755             }
1756             else if (currentSlidedOffset >= GetBgTrackLength())
1757             {
1758                 this.CurrentValue = maxValue;
1759             }
1760             else
1761             {
1762                 int bgTrackLength = GetBgTrackLength();
1763                 if (bgTrackLength != 0)
1764                 {
1765                     this.CurrentValue = ((currentSlidedOffset / (float)bgTrackLength) * (float)(maxValue - minValue)) + minValue;
1766                 }
1767             }
1768
1769             if (IsDiscrete)
1770             {
1771                 this.CurrentValue = CalculateDiscreteValue(this.CurrentValue);
1772             }
1773         }
1774
1775         private bool OnTouchEventForTrack(object source, TouchEventArgs e)
1776         {
1777             if (!IsEnabled)
1778             {
1779                 return false;
1780             }
1781
1782             if (this.FocusableInTouch == false && editMode == false)
1783             {
1784                 isFocused = false;
1785             }
1786
1787             PointStateType state = e.Touch.GetState(0);
1788             if (state == PointStateType.Down)
1789             {
1790                 if (isValueShown)
1791                 {
1792                     valueIndicatorImage.Show();
1793                 }
1794
1795                 UpdateState(isFocused, true);
1796
1797                 sliderSlidingStartedHandler?.Invoke(this, new SliderSlidingStartedEventArgs {
1798                     CurrentValue = curValue
1799                     });
1800
1801                 Vector2 pos = e.Touch.GetLocalPosition(0);
1802                 CalculateCurrentValueByTouch(pos);
1803                 UpdateValue();
1804             }
1805             else if (state == PointStateType.Up)
1806             {
1807                 if (isValueShown)
1808                 {
1809                     valueIndicatorImage.Hide();
1810                 }
1811
1812                 UpdateState(isFocused, false);
1813
1814                 sliderSlidingFinishedHandler?.Invoke(this, new SliderSlidingFinishedEventArgs {
1815                     CurrentValue = curValue
1816                     });
1817             }
1818             return false;
1819         }
1820
1821         private bool OnTouchEventForThumb(object source, TouchEventArgs e)
1822         {
1823             if (this.FocusableInTouch == false && editMode == false)
1824             {
1825                 isFocused = false;   
1826             }
1827
1828             PointStateType state = e.Touch.GetState(0);
1829             if (state == PointStateType.Down)
1830             {
1831                 UpdateState(isFocused, true);
1832             }
1833             else if (state == PointStateType.Up)
1834             {
1835                 UpdateState(isFocused, false);
1836             }
1837             return true;
1838         }
1839
1840         private void CalculateCurrentValueByTouch(Vector2 pos)
1841         {
1842             int bgTrackLength = GetBgTrackLength();
1843             if (direction == DirectionType.Horizontal)
1844             {
1845                 currentSlidedOffset = pos.X - GetBgTrackLowIndicatorOffset();
1846             }
1847             else if (direction == DirectionType.Vertical)
1848             {
1849                 currentSlidedOffset = this.Size2D.Height - pos.Y - GetBgTrackLowIndicatorOffset();
1850             }
1851
1852             if (bgTrackLength != 0)
1853             {
1854                 this.CurrentValue = ((currentSlidedOffset / (float)bgTrackLength) * (maxValue - minValue)) + minValue;
1855
1856                 if (IsDiscrete)
1857                 {
1858                     this.CurrentValue = CalculateDiscreteValue(this.CurrentValue);
1859                 }
1860             }
1861         }
1862
1863         private float CalculateDiscreteValue(float value)
1864         {
1865             return ((float)Math.Round((value / discreteValue)) * discreteValue);
1866         }
1867
1868         private void UpdateState(bool isFocusedNew, bool isPressedNew)
1869         {
1870             if (isFocused == isFocusedNew && isPressed == isPressedNew)
1871             {
1872                 return;
1873             }
1874             if (thumbImage == null || Style == null)
1875             {
1876                 return;
1877             }
1878             isFocused = isFocusedNew;
1879             isPressed = isPressedNew;
1880
1881             if (!IsEnabled) // Disabled
1882             {
1883                 ControlState = ControlState.Disabled;
1884             }
1885             else if (!isFocused && !isPressed)
1886             {
1887                 ControlState = ControlState.Normal;
1888             }
1889             else if (isPressed)
1890             {
1891                 ControlState = ControlState.Pressed;
1892             }
1893             else if (!isPressed && isFocused)
1894             {
1895                 ControlState = ControlState.Focused;
1896             }
1897         }
1898
1899         private void UpdateComponentByIndicatorTypeChanged()
1900         {
1901             IndicatorType type = CurrentIndicatorType();
1902             if (type == IndicatorType.None)
1903             {
1904                 if (lowIndicatorImage != null)
1905                 {
1906                     lowIndicatorImage.Hide();
1907                 }
1908                 if (highIndicatorImage != null)
1909                 {
1910                     highIndicatorImage.Hide();
1911                 }
1912                 if (lowIndicatorText != null)
1913                 {
1914                     lowIndicatorText.Hide();
1915                 }
1916                 if (highIndicatorText != null)
1917                 {
1918                     highIndicatorText.Hide();
1919                 }
1920             }
1921             else if (type == IndicatorType.Image)
1922             {
1923                 if (lowIndicatorImage != null)
1924                 {
1925                     lowIndicatorImage.Show();
1926                 }
1927                 if (highIndicatorImage != null)
1928                 {
1929                     highIndicatorImage.Show();
1930                 }
1931                 if (lowIndicatorText != null)
1932                 {
1933                     lowIndicatorText.Hide();
1934                 }
1935                 if (highIndicatorText != null)
1936                 {
1937                     highIndicatorText.Hide();
1938                 }
1939             }
1940             else if (type == IndicatorType.Text)
1941             {
1942                 if (lowIndicatorText != null)
1943                 {
1944                     lowIndicatorText.Show();
1945                 }
1946                 if (highIndicatorText != null)
1947                 {
1948                     highIndicatorText.Show();
1949                 }
1950                 if (lowIndicatorImage != null)
1951                 {
1952                     lowIndicatorImage.Hide();
1953                 }
1954                 if (highIndicatorImage != null)
1955                 {
1956                     highIndicatorImage.Hide();
1957                 }
1958             }
1959         }
1960     }
1961 }