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