[NUI] Add maximum motion age of pan motion gesture
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Slider.Internal.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.BaseComponents;
21
22 namespace Tizen.NUI.Components
23 {
24     public partial class Slider
25     {
26         // the background track image object
27         private ImageView bgTrackImage = null;
28         // the slided track image object
29         private ImageView slidedTrackImage = null;
30         // the warning track image object
31         private ImageView warningTrackImage = null;
32         // the warning slided track image object
33         private ImageView warningSlidedTrackImage = null;
34         // the thumb image object
35         private ImageView thumbImage = null;
36         // the low indicator image object
37         private ImageView lowIndicatorImage = null;
38         // the high indicator image object
39         private ImageView highIndicatorImage = null;
40         // the low indicator text object
41         private TextLabel lowIndicatorText = null;
42         // the high indicator text object
43         private TextLabel highIndicatorText = null;
44         // the direction type
45         private DirectionType direction = DirectionType.Horizontal;
46         // the indicator type
47         private IndicatorType indicatorType = IndicatorType.None;
48         private const float round = 0.5f;
49         // the minimum value
50         private float minValue = 0;
51         // the maximum value
52         private float maxValue = 100;
53         // the current value
54         private float curValue = 0;
55         // the warning start value
56         private float warningStartValue = 100;
57         // the size of the low indicator
58         private Size lowIndicatorSize = null;
59         // the size of the high indicator
60         private Size highIndicatorSize = null;
61         // the track thickness value
62         private uint? trackThickness = null;
63         // the value of the space between track and indicator object
64         private Extents spaceTrackIndicator = null;
65         // Whether the value indicator is shown or not
66         private bool isValueShown = false;
67         // the value indicator text
68         private TextLabel valueIndicatorText = null;
69         // the value indicator image object
70         private ImageView valueIndicatorImage = null;
71
72         // To store the thumb size of normal state
73         private Size thumbSize = null;
74         // To store the thumb image url of normal state
75         private string thumbImageUrl = null;
76         // To store the thumb color of normal state
77         private Color thumbColor = Color.White;
78         // To store the thumb image url of warning state
79         private string warningThumbImageUrl = null;
80         // To store the thumb image url selector of warning state
81         private Selector<string> warningThumbImageUrlSelector = null;
82         // To store the thumb color of warning state
83         private Color warningThumbColor = null;
84         // the discrete value
85         private float discreteValue = 0;
86
87         private PanGestureDetector panGestureDetector = null;
88         private readonly uint panGestureMotionEventAge = 16; // TODO : Can't we get this value from system configure?
89         private float currentSlidedOffset;
90         private EventHandler<SliderValueChangedEventArgs> sliderValueChangedHandler;
91         private EventHandler<SliderSlidingStartedEventArgs> sliderSlidingStartedHandler;
92         private EventHandler<SliderSlidingFinishedEventArgs> sliderSlidingFinishedHandler;
93
94         bool isFocused = false;
95         bool isPressed = false;
96
97         private void Initialize()
98         {
99             AccessibilityHighlightable = true;
100
101             currentSlidedOffset = 0;
102             isFocused = false;
103             isPressed = false;
104             LayoutDirectionChanged += OnLayoutDirectionChanged;
105
106             this.TouchEvent += OnTouchEventForTrack;
107             this.GrabTouchAfterLeave = true;
108
109             panGestureDetector = new PanGestureDetector();
110             panGestureDetector.Attach(this);
111             panGestureDetector.SetMaximumMotionEventAge(panGestureMotionEventAge);
112             panGestureDetector.Detected += OnPanGestureDetected;
113
114             this.Layout = new LinearLayout()
115             {
116                 LinearOrientation = LinearLayout.Orientation.Horizontal,
117             };
118         }
119
120         private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
121         {
122             RelayoutRequest();
123         }
124
125         private ImageView CreateSlidedTrack()
126         {
127             if (null == slidedTrackImage)
128             {
129                 slidedTrackImage = new ImageView()
130                 {
131                     WidthResizePolicy = ResizePolicyType.Fixed,
132                     HeightResizePolicy = ResizePolicyType.Fixed,
133                     AccessibilityHidden = true,
134                 };
135
136                 if (bgTrackImage != null)
137                 {
138                     bgTrackImage.Add(slidedTrackImage);
139                 }
140             }
141
142             return slidedTrackImage;
143         }
144
145         private ImageView CreateWarningTrack()
146         {
147             if (null == warningTrackImage)
148             {
149                 warningTrackImage = new ImageView()
150                 {
151                     WidthResizePolicy = ResizePolicyType.Fixed,
152                     HeightResizePolicy = ResizePolicyType.Fixed,
153                     AccessibilityHidden = true,
154                 };
155
156                 if (bgTrackImage != null)
157                 {
158                     bgTrackImage.Add(warningTrackImage);
159                 }
160
161                 if (warningSlidedTrackImage != null)
162                 {
163                     warningTrackImage.Add(warningSlidedTrackImage);
164                 }
165
166                 if (slidedTrackImage != null)
167                 {
168                     warningTrackImage.RaiseAbove(slidedTrackImage);
169                 }
170             }
171
172             return warningTrackImage;
173         }
174
175         private ImageView CreateWarningSlidedTrack()
176         {
177             if (null == warningSlidedTrackImage)
178             {
179                 warningSlidedTrackImage = new ImageView()
180                 {
181                     WidthResizePolicy = ResizePolicyType.Fixed,
182                     HeightResizePolicy = ResizePolicyType.Fixed,
183                     AccessibilityHidden = true,
184                 };
185
186                 if (warningTrackImage != null)
187                 {
188                     warningTrackImage.Add(warningSlidedTrackImage);
189                 }
190             }
191
192             return warningSlidedTrackImage;
193         }
194
195         private TextLabel CreateLowIndicatorText()
196         {
197             if (null == lowIndicatorText)
198             {
199                 lowIndicatorText = new TextLabel()
200                 {
201                     WidthResizePolicy = ResizePolicyType.Fixed,
202                     HeightResizePolicy = ResizePolicyType.Fixed,
203                     AccessibilityHidden = true,
204                 };
205                 this.Add(lowIndicatorText);
206             }
207
208             return lowIndicatorText;
209         }
210
211         private TextLabel CreateHighIndicatorText()
212         {
213             if (null == highIndicatorText)
214             {
215                 highIndicatorText = new TextLabel()
216                 {
217                     WidthResizePolicy = ResizePolicyType.Fixed,
218                     HeightResizePolicy = ResizePolicyType.Fixed,
219                     AccessibilityHidden = true,
220                 };
221                 this.Add(highIndicatorText);
222             }
223
224             return highIndicatorText;
225         }
226
227         private ImageView CreateLowIndicatorImage()
228         {
229             if (lowIndicatorImage == null)
230             {
231                 lowIndicatorImage = new ImageView()
232                 {
233                     WidthResizePolicy = ResizePolicyType.Fixed,
234                     HeightResizePolicy = ResizePolicyType.Fixed,
235                     AccessibilityHidden = true,
236                 };
237                 this.Add(lowIndicatorImage);
238             }
239
240             return lowIndicatorImage;
241         }
242
243         private ImageView CreateHighIndicatorImage()
244         {
245             if (highIndicatorImage == null)
246             {
247                 highIndicatorImage = new ImageView()
248                 {
249                     WidthResizePolicy = ResizePolicyType.Fixed,
250                     HeightResizePolicy = ResizePolicyType.Fixed,
251                                         AccessibilityHidden = true,
252                 };
253                 this.Add(highIndicatorImage);
254             }
255
256             return highIndicatorImage;
257         }
258
259
260
261         private ImageView CreateBackgroundTrack()
262         {
263             if (null == bgTrackImage)
264             {
265                 bgTrackImage = new ImageView()
266                 {
267                     WidthResizePolicy = ResizePolicyType.Fixed,
268                     HeightResizePolicy = ResizePolicyType.Fixed,
269                     ParentOrigin = Tizen.NUI.ParentOrigin.Center,
270                     PivotPoint = Tizen.NUI.PivotPoint.Center,
271                     PositionUsesPivotPoint = true,
272                     GrabTouchAfterLeave = true,
273                     AccessibilityHidden = true,
274                 };
275                 this.Add(bgTrackImage);
276
277                 if (null != slidedTrackImage)
278                 {
279                     bgTrackImage.Add(slidedTrackImage);
280                 }
281                 if (null != warningTrackImage)
282                 {
283                     bgTrackImage.Add(warningTrackImage);
284                 }
285                 if (null != thumbImage)
286                 {
287                     bgTrackImage.Add(thumbImage);
288                     thumbImage.RaiseToTop();
289                 }
290             }
291
292             return bgTrackImage;
293         }
294
295         private ImageView CreateThumb()
296         {
297             if (null == thumbImage)
298             {
299                 thumbImage = new ImageView()
300                 {
301                     WidthResizePolicy = ResizePolicyType.Fixed,
302                     HeightResizePolicy = ResizePolicyType.Fixed,
303                     ParentOrigin = NUI.ParentOrigin.Center,
304                     PivotPoint = NUI.PivotPoint.Center,
305                     PositionUsesPivotPoint = true,
306                     EnableControlState = true,
307                     GrabTouchAfterLeave = true,
308                     AccessibilityHidden = true,
309                 };
310                 if (bgTrackImage != null)
311                 {
312                     bgTrackImage.Add(thumbImage);
313                 }
314                 thumbImage.RaiseToTop();
315                 thumbImage.TouchEvent += OnTouchEventForThumb;
316             }
317
318             return thumbImage;
319         }
320
321         private ImageView CreateValueIndicatorImage()
322         {
323             if (valueIndicatorImage == null)
324             {
325                 valueIndicatorImage = new ImageView()
326                 {
327                     PositionUsesPivotPoint = true,
328                     ParentOrigin = Tizen.NUI.ParentOrigin.Center,
329                     PivotPoint = Tizen.NUI.PivotPoint.Center,
330                     WidthResizePolicy = ResizePolicyType.Fixed,
331                     HeightResizePolicy = ResizePolicyType.Fixed,
332                     AccessibilityHidden = true,
333                 };
334                 if (valueIndicatorText != null)
335                 {
336                     valueIndicatorImage.Add(valueIndicatorText);
337                 }
338                 // TODO : ValueIndicator can be a child of Thumb
339                 this.Add(valueIndicatorImage);
340             }
341
342             valueIndicatorImage.Hide();
343             return valueIndicatorImage;
344         }
345
346         private TextLabel CreateValueIndicatorText()
347         {
348             if (null == valueIndicatorText)
349             {
350                 valueIndicatorText = new TextLabel()
351                 {
352                     WidthResizePolicy = ResizePolicyType.Fixed,
353                     HeightResizePolicy = ResizePolicyType.Fixed,
354                     AccessibilityHidden = true,
355                 };
356                 if (valueIndicatorImage != null)
357                 {
358                     valueIndicatorImage.Add(valueIndicatorText);
359                 }
360             }
361
362             return valueIndicatorText;
363         }
364
365         private void OnPanGestureDetected(object source, PanGestureDetector.DetectedEventArgs e)
366         {
367             if (e.PanGesture.State == Gesture.StateType.Started)
368             {
369                 if (direction == DirectionType.Horizontal)
370                 {
371                     currentSlidedOffset = slidedTrackImage.SizeWidth;
372                 }
373                 else if (direction == DirectionType.Vertical)
374                 {
375                     currentSlidedOffset = slidedTrackImage.SizeHeight;
376                 }
377
378                 if (isValueShown)
379                 {
380                     valueIndicatorImage.Show();
381                 }
382
383                 if (null != sliderSlidingStartedHandler)
384                 {
385                     SliderSlidingStartedEventArgs args = new SliderSlidingStartedEventArgs();
386                     args.CurrentValue = curValue;
387                     sliderSlidingStartedHandler(this, args);
388                 }
389                 UpdateState(isFocused, true);
390             }
391
392             if (e.PanGesture.State == Gesture.StateType.Continuing || e.PanGesture.State == Gesture.StateType.Started)
393             {
394                 if (direction == DirectionType.Horizontal)
395                 {
396                     CalculateCurrentValueByGesture(e.PanGesture.Displacement.X);
397                 }
398                 else if (direction == DirectionType.Vertical)
399                 {
400                     CalculateCurrentValueByGesture(-e.PanGesture.Displacement.Y);
401                 }
402                 UpdateState(isFocused, true);
403                 UpdateValue();
404             }
405
406             if (e.PanGesture.State == Gesture.StateType.Finished)
407             {
408                 // Update as finished position value
409                 if (direction == DirectionType.Horizontal)
410                 {
411                     CalculateCurrentValueByGesture(e.PanGesture.Displacement.X);
412                 }
413                 else if (direction == DirectionType.Vertical)
414                 {
415                     CalculateCurrentValueByGesture(-e.PanGesture.Displacement.Y);
416                 }
417                 UpdateValue();
418
419                 if (isValueShown)
420                 {
421                     valueIndicatorImage.Hide();
422                 }
423
424                 if (null != sliderSlidingFinishedHandler)
425                 {
426                     SliderSlidingFinishedEventArgs args = new SliderSlidingFinishedEventArgs();
427                     args.CurrentValue = curValue;
428                     sliderSlidingFinishedHandler(this, args);
429                 }
430
431                 UpdateState(isFocused, false);
432             }
433         }
434
435         // Relayout basic component: track, thumb and indicator
436         private void RelayoutBaseComponent(bool isInitial = true)
437         {
438             if (direction == DirectionType.Horizontal)
439             {
440                 if (slidedTrackImage != null)
441                 {
442                     slidedTrackImage.ParentOrigin = NUI.ParentOrigin.CenterLeft;
443                     slidedTrackImage.PivotPoint = NUI.PivotPoint.CenterLeft;
444                     slidedTrackImage.PositionUsesPivotPoint = true;
445                 }
446                 if (warningTrackImage != null)
447                 {
448                     warningTrackImage.ParentOrigin = NUI.ParentOrigin.CenterRight;
449                     warningTrackImage.PivotPoint = NUI.PivotPoint.CenterRight;
450                     warningTrackImage.PositionUsesPivotPoint = true;
451                 }
452                 if (warningSlidedTrackImage != null)
453                 {
454                     warningSlidedTrackImage.ParentOrigin = NUI.ParentOrigin.CenterLeft;
455                     warningSlidedTrackImage.PivotPoint = NUI.PivotPoint.CenterLeft;
456                     warningSlidedTrackImage.PositionUsesPivotPoint = true;
457                 }
458                 if (thumbImage != null)
459                 {
460                     thumbImage.ParentOrigin = NUI.ParentOrigin.CenterLeft;
461                     thumbImage.PivotPoint = NUI.PivotPoint.Center;
462                     thumbImage.PositionUsesPivotPoint = true;
463                 }
464                 if (lowIndicatorImage != null)
465                 {
466                     lowIndicatorImage.ParentOrigin = NUI.ParentOrigin.CenterLeft;
467                     lowIndicatorImage.PivotPoint = NUI.PivotPoint.CenterLeft;
468                     lowIndicatorImage.PositionUsesPivotPoint = true;
469                 }
470                 if (highIndicatorImage != null)
471                 {
472                     highIndicatorImage.ParentOrigin = NUI.ParentOrigin.CenterRight;
473                     highIndicatorImage.PivotPoint = NUI.PivotPoint.CenterRight;
474                     highIndicatorImage.PositionUsesPivotPoint = true;
475                 }
476                 if (lowIndicatorText != null)
477                 {
478                     lowIndicatorText.ParentOrigin = NUI.ParentOrigin.CenterLeft;
479                     lowIndicatorText.PivotPoint = NUI.PivotPoint.CenterLeft;
480                     lowIndicatorText.PositionUsesPivotPoint = true;
481                 }
482                 if (highIndicatorText != null)
483                 {
484                     highIndicatorText.ParentOrigin = NUI.ParentOrigin.CenterRight;
485                     highIndicatorText.PivotPoint = NUI.PivotPoint.CenterRight;
486                     highIndicatorText.PositionUsesPivotPoint = true;
487                 }
488                 if (valueIndicatorImage != null)
489                 {
490                     valueIndicatorImage.ParentOrigin = NUI.ParentOrigin.TopLeft;
491                     valueIndicatorImage.PivotPoint = NUI.PivotPoint.BottomCenter;
492                     valueIndicatorImage.PositionUsesPivotPoint = true;
493                 }
494                 if (valueIndicatorText != null)
495                 {
496                     valueIndicatorText.ParentOrigin = NUI.ParentOrigin.TopCenter;
497                     valueIndicatorText.PivotPoint = NUI.PivotPoint.TopCenter;
498                     valueIndicatorText.PositionUsesPivotPoint = true;
499                     valueIndicatorText.Padding = new Extents(0, 0, 5, 0); // TODO : How to set the text as center
500                 }
501                 if (panGestureDetector != null)
502                 {
503                     if (!isInitial)
504                     {
505                         panGestureDetector.RemoveDirection(PanGestureDetector.DirectionVertical);
506                     }
507                     panGestureDetector.AddDirection(PanGestureDetector.DirectionHorizontal);
508                 }
509             }
510             else if (direction == DirectionType.Vertical)
511             {
512                 if (slidedTrackImage != null)
513                 {
514                     slidedTrackImage.ParentOrigin = NUI.ParentOrigin.BottomCenter;
515                     slidedTrackImage.PivotPoint = NUI.PivotPoint.BottomCenter;
516                     slidedTrackImage.PositionUsesPivotPoint = true;
517                 }
518                 if (warningTrackImage != null)
519                 {
520                     warningTrackImage.ParentOrigin = NUI.ParentOrigin.TopCenter;
521                     warningTrackImage.PivotPoint = NUI.PivotPoint.TopCenter;
522                     warningTrackImage.PositionUsesPivotPoint = true;
523                 }
524                 if (warningSlidedTrackImage != null)
525                 {
526                     warningSlidedTrackImage.ParentOrigin = NUI.ParentOrigin.BottomCenter;
527                     warningSlidedTrackImage.PivotPoint = NUI.PivotPoint.BottomCenter;
528                     warningSlidedTrackImage.PositionUsesPivotPoint = true;
529                 }
530                 if (thumbImage != null)
531                 {
532                     thumbImage.ParentOrigin = NUI.ParentOrigin.BottomCenter;
533                     thumbImage.PivotPoint = NUI.PivotPoint.Center;
534                     thumbImage.PositionUsesPivotPoint = true;
535                 }
536                 if (lowIndicatorImage != null)
537                 {
538                     lowIndicatorImage.ParentOrigin = NUI.ParentOrigin.BottomCenter;
539                     lowIndicatorImage.PivotPoint = NUI.PivotPoint.BottomCenter;
540                     lowIndicatorImage.PositionUsesPivotPoint = true;
541                 }
542                 if (highIndicatorImage != null)
543                 {
544                     highIndicatorImage.ParentOrigin = NUI.ParentOrigin.TopCenter;
545                     highIndicatorImage.PivotPoint = NUI.PivotPoint.TopCenter;
546                     highIndicatorImage.PositionUsesPivotPoint = true;
547                 }
548                 if (lowIndicatorText != null)
549                 {
550                     lowIndicatorText.ParentOrigin = NUI.ParentOrigin.BottomCenter;
551                     lowIndicatorText.PivotPoint = NUI.PivotPoint.BottomCenter;
552                     lowIndicatorText.PositionUsesPivotPoint = true;
553                 }
554                 if (highIndicatorText != null)
555                 {
556                     highIndicatorText.ParentOrigin = NUI.ParentOrigin.TopCenter;
557                     highIndicatorText.PivotPoint = NUI.PivotPoint.TopCenter;
558                     highIndicatorText.PositionUsesPivotPoint = true;
559                 }
560                 if (valueIndicatorImage != null)
561                 {
562                     valueIndicatorImage.ParentOrigin = NUI.ParentOrigin.BottomCenter;
563                     valueIndicatorImage.PivotPoint = NUI.PivotPoint.BottomCenter;
564                     valueIndicatorImage.PositionUsesPivotPoint = true;
565                 }
566                 if (valueIndicatorText != null)
567                 {
568                     valueIndicatorText.ParentOrigin = NUI.ParentOrigin.TopCenter;
569                     valueIndicatorText.PivotPoint = NUI.PivotPoint.TopCenter;
570                     valueIndicatorText.PositionUsesPivotPoint = true;
571                     valueIndicatorText.Padding = new Extents(0, 0, 5, 0); // TODO : How to set the text as center
572                 }
573                 if (panGestureDetector != null)
574                 {
575                     if (!isInitial)
576                     {
577                         panGestureDetector.RemoveDirection(PanGestureDetector.DirectionHorizontal);
578                     }
579                     panGestureDetector.AddDirection(PanGestureDetector.DirectionVertical);
580                 }
581             }
582         }
583
584         private int GetBgTrackLength()
585         {
586             int bgTrackLength = 0;
587
588             int lowIndicatorOffset = GetBgTrackLowIndicatorOffset();
589             int highIndicatorOffet = GetBgTrackHighIndicatorOffset();
590
591             if (direction == DirectionType.Horizontal)
592             {
593                 bgTrackLength = this.Size2D.Width - lowIndicatorOffset - highIndicatorOffet;
594             }
595             else if (direction == DirectionType.Vertical)
596             {
597                 bgTrackLength = this.Size2D.Height - lowIndicatorOffset - highIndicatorOffet;
598             }
599
600             return bgTrackLength;
601         }
602
603         /// <summary>
604         /// Get offset value of bgtrack's low indicator side.
605         /// </summary>
606         private int GetBgTrackLowIndicatorOffset()
607         {
608             int bgTrackLowIndicatorOffset = 0;
609             IndicatorType type = CurrentIndicatorType();
610
611             if (type == IndicatorType.None)
612             {
613                 if (direction == DirectionType.Horizontal)
614                 {
615                     bgTrackLowIndicatorOffset = (int)(thumbImage.Size.Width * 0.5f);
616                 }
617                 else if (direction == DirectionType.Vertical)
618                 {
619                     bgTrackLowIndicatorOffset = (int)(thumbImage.Size.Height * 0.5f);
620                 }
621             }
622             else if (type == IndicatorType.Image || type == IndicatorType.Text)
623             {// <lowIndicatorImage or Text> <spaceBetweenTrackAndIndicator> <bgTrack>
624                 Size lowIndicatorSize = (type == IndicatorType.Image) ? LowIndicatorImageSize() : LowIndicatorTextSize();
625                 int curSpace = (int)CurrentSpaceBetweenTrackAndIndicator();
626                 if (direction == DirectionType.Horizontal)
627                 {
628                     bgTrackLowIndicatorOffset = ((lowIndicatorSize.Width == 0) ? (0) : ((int)(curSpace + lowIndicatorSize.Width)));
629                 }
630                 else if (direction == DirectionType.Vertical)
631                 {
632                     bgTrackLowIndicatorOffset = ((lowIndicatorSize.Height == 0) ? (0) : ((int)(curSpace + lowIndicatorSize.Height)));
633                 }
634             }
635             return bgTrackLowIndicatorOffset;
636         }
637
638         /// <summary>
639         /// Get offset value of bgtrack's high indicator side.
640         /// </summary>
641         private int GetBgTrackHighIndicatorOffset()
642         {
643             int bgTrackHighIndicatorOffset = 0;
644             IndicatorType type = CurrentIndicatorType();
645
646             if (type == IndicatorType.None)
647             {
648                 if (direction == DirectionType.Horizontal)
649                 {
650                     bgTrackHighIndicatorOffset = (int)(thumbImage.Size.Width * 0.5f);
651                 }
652                 else if (direction == DirectionType.Vertical)
653                 {
654                     bgTrackHighIndicatorOffset = (int)(thumbImage.Size.Height * 0.5f);
655                 }
656             }
657             else if (type == IndicatorType.Image || type == IndicatorType.Text)
658             {// <bgTrack> <spaceBetweenTrackAndIndicator> <highIndicatorImage or Text>
659                 Size highIndicatorSize = (type == IndicatorType.Image) ? HighIndicatorImageSize() : HighIndicatorTextSize();
660                 int curSpace = (int)CurrentSpaceBetweenTrackAndIndicator();
661                 if (direction == DirectionType.Horizontal)
662                 {
663                     bgTrackHighIndicatorOffset = ((highIndicatorSize.Width == 0) ? (0) : ((int)(curSpace + highIndicatorSize.Width)));
664                 }
665                 else if (direction == DirectionType.Vertical)
666                 {
667                     bgTrackHighIndicatorOffset = ((highIndicatorSize.Height == 0) ? (0) : ((int)(curSpace + highIndicatorSize.Height)));
668                 }
669             }
670             return bgTrackHighIndicatorOffset;
671         }
672
673         private void UpdateLowIndicatorSize()
674         {
675             if (lowIndicatorSize != null)
676             {
677                 if (lowIndicatorImage != null)
678                 {
679                     lowIndicatorImage.Size = lowIndicatorSize;
680                 }
681                 if (lowIndicatorText != null)
682                 {
683                     lowIndicatorText.Size = lowIndicatorSize;
684                 }
685             }
686             else
687             {
688                 if (lowIndicatorImage != null && lowIndicatorImage.Size != null)
689                 {
690                     lowIndicatorImage.Size = lowIndicatorSize ?? (ViewStyle as SliderStyle)?.LowIndicatorImage.Size;
691                 }
692                 if (lowIndicatorText != null && lowIndicatorText.Size != null)
693                 {
694                     lowIndicatorText.Size = lowIndicatorSize ?? (ViewStyle as SliderStyle)?.LowIndicator.Size;
695                 }
696             }
697         }
698
699         private void UpdateHighIndicatorSize()
700         {
701             if (highIndicatorSize != null)
702             {
703                 if (highIndicatorImage != null)
704                 {
705                     highIndicatorImage.Size = highIndicatorSize;
706                 }
707                 if (highIndicatorText != null)
708                 {
709                     highIndicatorText.Size = highIndicatorSize;
710                 }
711             }
712             else
713             {
714                 if (highIndicatorImage != null && highIndicatorImage.Size != null)
715                 {
716                     highIndicatorImage.Size = highIndicatorSize ?? (ViewStyle as SliderStyle)?.HighIndicatorImage.Size;
717                 }
718                 if (highIndicatorText != null && highIndicatorText.Size != null)
719                 {
720                     highIndicatorText.Size = highIndicatorSize ?? (ViewStyle as SliderStyle)?.HighIndicator.Size;
721                 }
722             }
723         }
724
725         private void UpdateBgTrackSize()
726         {
727             if (bgTrackImage == null)
728             {
729                 return;
730             }
731             int curTrackThickness = (int)CurrentTrackThickness();
732             int bgTrackLength = GetBgTrackLength();
733             if (direction == DirectionType.Horizontal)
734             {
735                 bgTrackImage.Size2D = new Size2D(bgTrackLength, curTrackThickness);
736             }
737             else if (direction == DirectionType.Vertical)
738             {
739                 bgTrackImage.Size2D = new Size2D(curTrackThickness, bgTrackLength);
740             }
741         }
742
743         private void UpdateBgTrackPosition()
744         {
745             if (bgTrackImage == null)
746             {
747                 return;
748             }
749
750             int lowIndicatorOffset = GetBgTrackLowIndicatorOffset();
751             int highIndicatorOffet = GetBgTrackHighIndicatorOffset();
752
753             if (direction == DirectionType.Horizontal)
754             {
755                 bgTrackImage.Position2D = new Position2D((lowIndicatorOffset - highIndicatorOffet) / 2, 0);
756             }
757             else if (direction == DirectionType.Vertical)
758             {
759                 bgTrackImage.Position2D = new Position2D(0, (highIndicatorOffet - lowIndicatorOffset) / 2);
760             }
761         }
762
763         private void UpdateValue()
764         {
765             if (slidedTrackImage == null)
766             {
767                 return;
768             }
769             if (curValue < minValue || curValue > maxValue || minValue >= maxValue)
770             {
771                 return;
772             }
773
774             float ratio = 0;
775             ratio = (float)(curValue - minValue) / (float)(maxValue - minValue);
776
777             uint curTrackThickness = CurrentTrackThickness();
778
779             if (direction == DirectionType.Horizontal)
780             {
781                 if (LayoutDirection == ViewLayoutDirectionType.RTL)
782                 {
783                     ratio = 1.0f - ratio;
784                 }
785                 float slidedTrackLength = (float)GetBgTrackLength() * ratio;
786                 slidedTrackImage.Size2D = new Size2D((int)(slidedTrackLength + round), (int)curTrackThickness); //Add const round to reach Math.Round function.
787                 thumbImage.Position = new Position(slidedTrackImage.Size2D.Width, 0);
788                 thumbImage.RaiseToTop();
789
790                 if (isValueShown)
791                 {
792                     valueIndicatorImage.Position = new Position(slidedTrackImage.Size2D.Width, 0);
793                 }
794             }
795             else if (direction == DirectionType.Vertical)
796             {
797                 float slidedTrackLength = (float)GetBgTrackLength() * ratio;
798                 slidedTrackImage.Size2D = new Size2D((int)curTrackThickness, (int)(slidedTrackLength + round)); //Add const round to reach Math.Round function.
799                 thumbImage.Position = new Position(0, -slidedTrackImage.Size2D.Height);
800                 thumbImage.RaiseToTop();
801
802                 if (isValueShown)
803                 {
804                     valueIndicatorImage.Position = new Position(0, -(slidedTrackImage.Size2D.Height + thumbImage.Size.Height / 2));
805                 }
806             }
807
808             // Update the track and thumb when the value is over warning value.
809             if (curValue >= warningStartValue)
810             {
811                 if (direction == DirectionType.Horizontal)
812                 {
813                     warningSlidedTrackImage.Size2D = new Size2D((int)(((curValue - warningStartValue) / 100) * this.Size2D.Width), (int)curTrackThickness);
814                 }
815                 else if (direction == DirectionType.Vertical)
816                 {
817                     warningSlidedTrackImage.Size2D = new Size2D((int)curTrackThickness, (int)(((curValue - warningStartValue) / 100) * this.Size2D.Height));
818                 }
819
820                 if (warningThumbColor != null && thumbImage.Color.NotEqualTo(warningThumbColor))
821                 {
822                     thumbImage.Color = warningThumbColor;
823                 }
824                 if (warningThumbImageUrl != null && !thumbImage.ResourceUrl.Equals(warningThumbImageUrl))
825                 {
826                     thumbImage.ResourceUrl = warningThumbImageUrl;
827                 }
828             }
829             else
830             {
831                 warningSlidedTrackImage.Size2D = new Size2D(0, 0);
832                 if (warningThumbColor != null && thumbImage.Color.EqualTo(warningThumbColor))
833                 {
834                     thumbImage.Color = thumbColor;
835                 }
836                 if (warningThumbImageUrl != null && thumbImage.ResourceUrl.Equals(warningThumbImageUrl))
837                 {
838                     thumbImage.ResourceUrl = thumbImageUrl;
839                 }
840             }
841         }
842
843         private uint CurrentTrackThickness()
844         {
845             uint curTrackThickness = 0;
846             if (trackThickness != null)
847             {
848                 curTrackThickness = trackThickness.Value;
849             }
850             else
851             {
852                 if (ViewStyle is SliderStyle sliderStyle && sliderStyle.TrackThickness != null)
853                 {
854                     curTrackThickness = sliderStyle.TrackThickness.Value;
855                 }
856             }
857             return curTrackThickness;
858         }
859
860         private uint CurrentSpaceBetweenTrackAndIndicator()
861         {
862             uint curSpace = 0;
863             if (spaceBetweenTrackAndIndicator != null)
864             {
865                 curSpace = spaceBetweenTrackAndIndicator.Start;
866             }
867             else
868             {
869                 if (ViewStyle is SliderStyle sliderStyle && sliderStyle.TrackPadding != null)
870                 {
871                     curSpace = sliderStyle.TrackPadding.Start;
872                 }
873             }
874             return curSpace;
875         }
876
877         private void UpdateWarningTrackSize()
878         {
879             if (warningTrackImage == null)
880             {
881                 return;
882             }
883
884             int curTrackThickness = (int)CurrentTrackThickness();
885             float warningTrackLength = maxValue - warningStartValue;
886             if (direction == DirectionType.Horizontal)
887             {
888                 warningTrackLength = (warningTrackLength / 100) * this.Size2D.Width;
889                 warningTrackImage.Size2D = new Size2D((int)warningTrackLength, curTrackThickness);
890             }
891             else if (direction == DirectionType.Vertical)
892             {
893                 warningTrackLength = (warningTrackLength / 100) * this.Size2D.Height;
894                 warningTrackImage.Size2D = new Size2D(curTrackThickness, (int)warningTrackLength);
895             }
896         }
897
898         private IndicatorType CurrentIndicatorType()
899         {
900             IndicatorType type = IndicatorType.None;
901             if (ViewStyle is SliderStyle sliderStyle)
902             {
903                 type = (IndicatorType)sliderStyle.IndicatorType;
904             }
905             return type;
906         }
907
908         private Size LowIndicatorImageSize()
909         {
910             Size size = new Size(0, 0);
911             if (lowIndicatorSize != null)
912             {
913                 size = lowIndicatorSize;
914             }
915             else
916             {
917                 if (ViewStyle is SliderStyle sliderStyle && sliderStyle.LowIndicatorImage != null && sliderStyle.LowIndicatorImage.Size != null)
918                 {
919                     size = sliderStyle.LowIndicatorImage.Size;
920                 }
921             }
922             return size;
923         }
924
925         private Size HighIndicatorImageSize()
926         {
927             Size size = new Size(0, 0);
928             if (highIndicatorSize != null)
929             {
930                 size = highIndicatorSize;
931             }
932             else
933             {
934                 if (ViewStyle is SliderStyle sliderStyle && sliderStyle.HighIndicatorImage != null && sliderStyle.HighIndicatorImage.Size != null)
935                 {
936                     size = sliderStyle.HighIndicatorImage.Size;
937                 }
938             }
939             return size;
940         }
941
942         private Size LowIndicatorTextSize()
943         {
944             Size size = new Size(0, 0);
945             if (lowIndicatorSize != null)
946             {
947                 size = lowIndicatorSize;
948             }
949             else
950             {
951                 if (ViewStyle is SliderStyle sliderStyle && sliderStyle.LowIndicator != null && sliderStyle.LowIndicator.Size != null)
952                 {
953                     size = sliderStyle.LowIndicator.Size;
954                 }
955             }
956             return size;
957         }
958
959         private Size HighIndicatorTextSize()
960         {
961             Size size = new Size(0, 0);
962             if (highIndicatorSize != null)
963             {
964                 size = highIndicatorSize;
965             }
966             else
967             {
968                 if (ViewStyle is SliderStyle sliderStyle && sliderStyle.HighIndicator != null && sliderStyle.HighIndicator.Size != null)
969                 {
970                     size = sliderStyle.HighIndicator.Size;
971                 }
972             }
973             return size;
974         }
975     }
976 }