[NUI] Change the name of Tizen.NUI.CommonUI as Tizen.NUI.Components (#958)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Scrollbar.cs
1 /*
2  * Copyright(c) 2019 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 using System;
18 using Tizen.NUI.BaseComponents;
19 using System.ComponentModel;
20
21 namespace Tizen.NUI.Components
22 {
23     /// <summary>
24     /// The ScrollBar class of nui component. It allows users to recognize the direction and the range of lists/content. .
25     /// </summary>
26     /// <since_tizen> 6 </since_tizen>
27     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
28     [EditorBrowsable(EditorBrowsableState.Never)]
29     public class ScrollBar : Control
30     {
31         private ScrollBarAttributes scrollBarAttrs;
32         private ImageView trackImage;
33         private ImageView thumbImage;
34         private Animation scrollAniPlayer = null;
35         private float thumbImagePosX;
36         private float thumbImagePosY;
37         private bool enableAni = false;
38         private int minValue;
39         private int maxValue;
40         private int curValue;
41
42         /// <summary>
43         /// The constructor of ScrollBar
44         /// </summary>
45         /// <since_tizen> 6 </since_tizen>
46         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
47         [EditorBrowsable(EditorBrowsableState.Never)]
48         public ScrollBar() : base()
49         {
50             Initialize();
51         }
52
53         /// <summary>
54         /// The constructor of ScrollBar with specific style.
55         /// </summary>
56         /// <param name="style">style name</param>
57         /// <since_tizen> 6 </since_tizen>
58         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
59         [EditorBrowsable(EditorBrowsableState.Never)]
60         public ScrollBar(string style) : base(style)
61         {
62             Initialize();
63         }
64
65         /// <summary>
66         /// The constructor of ScrollBar with specific Attributes.
67         /// </summary>
68         /// <param name="attributes">The Attributes object to initialize the ScrollBar.</param>
69         /// <since_tizen> 6 </since_tizen>
70         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
71         [EditorBrowsable(EditorBrowsableState.Never)]
72         public ScrollBar(ScrollBarAttributes attributes) : base(attributes)
73         {
74             Initialize();
75         }
76
77         /// <summary>
78         /// The direction type of the Scroll.
79         /// </summary>
80         /// <since_tizen> 6 </since_tizen>
81         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
82         [EditorBrowsable(EditorBrowsableState.Never)]
83         public enum DirectionType
84         {
85             /// <summary>
86             /// The Horizontal type.
87             /// </summary>
88             /// <since_tizen> 6 </since_tizen>
89             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
90             [EditorBrowsable(EditorBrowsableState.Never)]
91             Horizontal,
92
93             /// <summary>
94             /// The Vertical type.
95             /// </summary>
96             /// <since_tizen> 6 </since_tizen>
97             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
98             [EditorBrowsable(EditorBrowsableState.Never)]
99             Vertical
100         }
101
102         #region public property 
103
104         /// <summary>
105         /// The property to get/set the direction of the ScrollBar.
106         /// </summary>
107         /// <since_tizen> 6 </since_tizen>
108         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
109         [EditorBrowsable(EditorBrowsableState.Never)]
110         public DirectionType Direction
111         {
112             get
113             {
114                 return scrollBarAttrs.Direction.Value;
115             }
116             set
117             {
118                 scrollBarAttrs.Direction = value;
119                 RelayoutRequest();
120             }
121         }
122
123         /// <summary>
124         /// The property to get/set the size of the thumb object.
125         /// </summary>
126         /// <exception cref="InvalidOperationException">Throw when ThumbSize is null.</exception>
127         /// <example>
128         /// <code>
129         /// ScrollBar scroll;
130         /// try
131         /// {
132         ///     scroll.ThumbSize = new Size(500, 10, 0);
133         /// }
134         /// catch(InvalidOperationException e)
135         /// {
136         ///     Tizen.Log.Error(LogTag, "Failed to set ThumbSize value : " + e.Message);
137         /// }
138         /// </code>
139         /// </example>
140         /// <since_tizen> 6 </since_tizen>
141         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
142         [EditorBrowsable(EditorBrowsableState.Never)]
143         public Size2D ThumbSize
144         {
145             get
146             {
147                 if (scrollBarAttrs.ThumbImageAttributes.Size2D == null)
148                 {
149                     scrollBarAttrs.ThumbImageAttributes.Size2D = new Size2D();
150                 }
151                 return scrollBarAttrs.ThumbImageAttributes.Size2D;
152             }
153             set
154             {
155                 if (scrollBarAttrs.ThumbImageAttributes.Size2D == null)
156                 {
157                     scrollBarAttrs.ThumbImageAttributes.Size2D = new Size2D();
158                 }
159                 if (thumbImage != null)
160                 {
161                     scrollBarAttrs.ThumbImageAttributes.Size2D.Width = value.Width;
162                     scrollBarAttrs.ThumbImageAttributes.Size2D.Height = value.Height;
163                     RelayoutRequest();
164                 }
165             }
166         }
167
168         /// <summary>
169         /// The property to get/set the image URL of the track object.
170         /// </summary>
171         /// <since_tizen> 6 </since_tizen>
172         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
173         [EditorBrowsable(EditorBrowsableState.Never)]
174         public string TrackImageURL
175         {
176             get
177             {
178                 return scrollBarAttrs.TrackImageAttributes.ResourceURL.All;
179             }
180             set
181             {
182                 if (trackImage != null)
183                 {
184                     if (scrollBarAttrs.TrackImageAttributes.ResourceURL == null)
185                     {
186                         scrollBarAttrs.TrackImageAttributes.ResourceURL = new StringSelector();
187                     }
188                     scrollBarAttrs.TrackImageAttributes.ResourceURL.All = value;
189                 }
190                 RelayoutRequest();
191             }
192         }
193
194         /// <summary>
195         /// The property to get/set the color of the track object.
196         /// </summary>
197         /// <since_tizen> 6 </since_tizen>
198         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
199         [EditorBrowsable(EditorBrowsableState.Never)]
200         public Color TrackColor
201         {
202             get
203             {
204                 return scrollBarAttrs.TrackImageAttributes.BackgroundColor?.All;
205             }
206             set
207             {
208                 if (scrollBarAttrs.TrackImageAttributes.BackgroundColor == null)
209                 {
210                     scrollBarAttrs.TrackImageAttributes.BackgroundColor = new ColorSelector { All = value };
211                 }
212                 else
213                 {
214                     scrollBarAttrs.TrackImageAttributes.BackgroundColor.All = value;
215                 }
216                 RelayoutRequest();
217             }
218         }
219
220         /// <summary>
221         /// The property to get/set the color of the thumb object.
222         /// </summary>
223         /// <since_tizen> 6 </since_tizen>
224         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
225         [EditorBrowsable(EditorBrowsableState.Never)]
226         public Color ThumbColor
227         {
228             get
229             {
230                 return scrollBarAttrs.ThumbImageAttributes.BackgroundColor?.All;
231             }
232             set
233             {
234                 if(scrollBarAttrs.ThumbImageAttributes.BackgroundColor == null)
235                 {
236                     scrollBarAttrs.ThumbImageAttributes.BackgroundColor = new ColorSelector { All = value };
237                 }
238                 else
239                 {
240                     scrollBarAttrs.ThumbImageAttributes.BackgroundColor.All = value;
241                 }
242                 RelayoutRequest();
243             }
244         }
245
246         /// <summary>
247         /// The property to get/set the max value of the ScrollBar.
248         /// </summary>
249         /// <since_tizen> 6 </since_tizen>
250         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
251         [EditorBrowsable(EditorBrowsableState.Never)]
252         public int MaxValue
253         {
254             get
255             {
256                 return maxValue;
257             }
258             set
259             {
260                 if(value >= 0)
261                 {
262                     maxValue = value;
263                     RelayoutRequest();
264                 }
265             }
266         }
267
268         /// <summary>
269         /// The property to get/set the min value of the ScrollBar.
270         /// </summary>
271         /// <since_tizen> 6 </since_tizen>
272         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
273         [EditorBrowsable(EditorBrowsableState.Never)]
274         public int MinValue
275         {
276             get
277             {
278                 return minValue;
279             }
280             set
281             {
282                 if(value >= 0)
283                 {
284                     minValue = value;
285                     RelayoutRequest();
286                 }
287             }
288         }
289
290         /// <summary>
291         /// The property to get/set the current value of the ScrollBar.
292         /// </summary>
293         /// <exception cref="ArgumentOutOfRangeException">Throw when Current value is less than Min value, or greater than Max value.</exception>
294         /// <example>
295         /// <code>
296         /// ScrollBar scroll;
297         /// scroll.MaxValue = 100;
298         /// scroll.MinValue = 0;
299         /// try
300         /// {
301         ///     scroll.CurrentValue = 50;
302         /// }
303         /// catch(ArgumentOutOfRangeException e)
304         /// {
305         ///     Tizen.Log.Error(LogTag, "Failed to set Current value : " + e.Message);
306         /// }
307         /// </code>
308         /// </example>
309         /// <since_tizen> 6 </since_tizen>
310         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
311         [EditorBrowsable(EditorBrowsableState.Never)]
312         public int CurrentValue
313         {
314             get
315             {
316                 return curValue;
317             }
318             set
319             {
320                 if(value >= 0)
321                 {
322                     curValue = value;
323                     RelayoutRequest();
324                 }
325             }
326         }
327
328         /// <summary>
329         /// Property to set/get animation duration.
330         /// </summary>
331         /// <since_tizen> 6 </since_tizen>
332         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
333         [EditorBrowsable(EditorBrowsableState.Never)]
334         public uint Duration
335         {
336             get
337             {
338                 return scrollBarAttrs.Duration;
339             }
340             set
341             {
342                 scrollBarAttrs.Duration = value;
343                 if (scrollAniPlayer != null)
344                 {
345                     scrollAniPlayer.Duration = (int)value;
346                 }
347             }
348         }
349         #endregion
350
351         /// <summary>
352         /// Method to set current value. The thumb object would move to the corresponding position with animation or not.
353         /// </summary>
354         /// <param name="currentValue">The special current value.</param>
355         /// <param name="isEnableAni">Enable move with animation or not, the default value is true.</param>
356         /// <exception cref="ArgumentOutOfRangeException">Throw when current size is less than the min value, or greater than the max value.</exception>
357         /// <example>
358         /// <code>
359         /// ScrollBar scroll;
360         /// scroll.MinValue = 0;
361         /// scroll.MaxValue = 100;
362         /// try
363         /// {
364         ///     scroll.SetCurrentValue(50);
365         /// }
366         /// catch(ArgumentOutOfRangeException e)
367         /// {
368         ///     Tizen.Log.Error(LogTag, "Failed to set current value : " + e.Message);
369         /// }
370         /// </code>
371         /// </example>
372         /// <since_tizen> 6 </since_tizen>
373         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
374         [EditorBrowsable(EditorBrowsableState.Never)]
375         public void SetCurrentValue(int currentValue, bool isEnableAni = true)
376         {
377             if (currentValue < minValue || currentValue > maxValue)
378             {
379                 //TNLog.E("Current value is less than the Min value, or greater than the Max value. currentValue = " + currentValue + ";");
380                 throw new ArgumentOutOfRangeException("Wrong Current value. It shoud be greater than the Min value, and less than the Max value!");
381             }
382
383             enableAni = isEnableAni;
384             CurrentValue = currentValue;
385         }
386
387         /// <summary>
388         /// Dispose ScrollBar.
389         /// </summary>
390         /// <param name="type">The DisposeTypes value.</param>
391         /// <since_tizen> 6 </since_tizen>
392         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
393         [EditorBrowsable(EditorBrowsableState.Never)]
394         protected override void Dispose(DisposeTypes type)
395         {
396             if (disposed)
397             {
398                 return;
399             }
400
401             if (type == DisposeTypes.Explicit)
402             {
403                 //Called by User
404                 //Release your own managed resources here.
405                 //You should release all of your own disposable objects here.
406
407                 if (trackImage != null)
408                 {
409                     Utility.Dispose(trackImage);
410                 }
411
412                 if (thumbImage != null)
413                 {
414                     Utility.Dispose(thumbImage);
415                 }
416
417                 if (scrollAniPlayer != null)
418                 {
419                     scrollAniPlayer.Stop();
420                     scrollAniPlayer.Clear();
421                     scrollAniPlayer.Dispose();
422                     scrollAniPlayer = null;
423                 }
424                 // UIDirectionChangedEvent -= OnUIDirectionChangedEvent;
425             }
426
427             //Release your own unmanaged resources here.
428             //You should not access any managed member here except static instance.
429             //because the execution order of Finalizes is non-deterministic.
430             //Unreference this from if a static instance refer to this. 
431
432             //You must call base.Dispose(type) just before exit.
433             base.Dispose(type);
434         }
435
436         /// <summary>
437         /// The method to update Attributes.
438         /// </summary>
439         /// <since_tizen> 6 </since_tizen>
440         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
441         [EditorBrowsable(EditorBrowsableState.Never)]
442         protected override void OnUpdate()
443         {
444             ApplyAttributes(this, scrollBarAttrs);
445             ApplyAttributes(trackImage, scrollBarAttrs.TrackImageAttributes);
446             ApplyAttributes(thumbImage, scrollBarAttrs.ThumbImageAttributes);
447             if (enableAni)
448             {
449                 UpdateValue(true);
450                 enableAni = false;
451             }
452             else
453             {
454                 UpdateValue();
455             }
456         }
457
458         /// <summary>
459         /// Get Scrollbar attribues.
460         /// </summary>
461         /// <since_tizen> 6 </since_tizen>
462         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
463         [EditorBrowsable(EditorBrowsableState.Never)]
464         protected override Attributes GetAttributes()
465         {
466             return new ScrollBarAttributes()
467             {
468                 ThumbImageAttributes = new ImageAttributes
469                 {
470                     WidthResizePolicy = ResizePolicyType.Fixed,
471                     HeightResizePolicy = ResizePolicyType.Fixed,
472                     PositionUsesPivotPoint = true,
473                     ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft,
474                     PivotPoint = Tizen.NUI.PivotPoint.TopLeft
475                 },
476                 TrackImageAttributes = new ImageAttributes
477                 {
478                     WidthResizePolicy = ResizePolicyType.FillToParent,
479                     HeightResizePolicy = ResizePolicyType.FillToParent,
480                     PositionUsesPivotPoint = true,
481                     ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft,
482                     PivotPoint = Tizen.NUI.PivotPoint.TopLeft
483                 }
484
485             };
486         }
487
488         /// <summary>
489         /// Theme change callback when theme is changed, this callback will be trigger.
490         /// </summary>
491         /// <since_tizen> 6 </since_tizen>
492         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
493         [EditorBrowsable(EditorBrowsableState.Never)]
494         protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
495         {
496             ScrollBarAttributes tempAttributes = StyleManager.Instance.GetAttributes(style) as ScrollBarAttributes;
497             if (tempAttributes != null)
498             {
499                 attributes = scrollBarAttrs = tempAttributes;
500                 RelayoutRequest();
501             }
502         }
503
504         private void Initialize()
505         {
506             scrollBarAttrs = this.attributes as ScrollBarAttributes;
507             if(scrollBarAttrs == null)
508             {
509                 throw new Exception("ScrollBar attribute parse error.");
510             }
511
512             this.Focusable = false;
513
514             trackImage = new ImageView
515             {
516                 Focusable = false,
517                 WidthResizePolicy = ResizePolicyType.FillToParent,
518                 HeightResizePolicy = ResizePolicyType.FillToParent,
519                 PositionUsesPivotPoint = true,
520                 ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft,
521                 PivotPoint = Tizen.NUI.PivotPoint.TopLeft
522
523             };
524             thumbImage = new ImageView
525             {
526                 Focusable = false,
527                 WidthResizePolicy = ResizePolicyType.Fixed,
528                 HeightResizePolicy = ResizePolicyType.Fixed,
529                 PositionUsesPivotPoint = true,
530                 ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft,
531                 PivotPoint = Tizen.NUI.PivotPoint.TopLeft
532             };
533
534             Add(trackImage);
535             Add(thumbImage);
536
537             scrollAniPlayer = new Animation(334);
538             scrollAniPlayer.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.Linear);
539
540             thumbImagePosX = 0;
541             thumbImagePosY = 0;
542             LayoutDirectionChanged += OnLayoutDirectionChanged;
543         }
544
545         private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
546         {
547             RelayoutRequest();
548         }
549
550         private void UpdateValue(bool enableAni = false)
551         {
552             if (trackImage == null || thumbImage == null || scrollBarAttrs.Direction == null)
553             {             
554                 return;
555             }
556
557             if (minValue >= maxValue || curValue < minValue || curValue > maxValue)
558             {
559                 return;
560             }
561             float width = (float)Size2D.Width;
562             float height = (float)Size2D.Height;
563             float thumbW = 0.0f;
564             float thumbH = 0.0f;
565             if (scrollBarAttrs.ThumbImageAttributes.Size2D == null)
566             {
567                 return;
568             }
569             else
570             {
571                 thumbW = scrollBarAttrs.ThumbImageAttributes.Size2D.Width;
572                 thumbH = scrollBarAttrs.ThumbImageAttributes.Size2D.Height;
573             }
574             float ratio = (float)(curValue - minValue) / (float)(maxValue - minValue);
575
576             if (scrollBarAttrs.Direction == DirectionType.Horizontal)
577             {
578                 if (LayoutDirection == ViewLayoutDirectionType.RTL)
579                 {
580                     ratio = 1.0f - ratio;
581                 }
582
583                 float posX = ratio * (width - thumbW);
584                 float posY = (height - thumbH) / 2.0f;
585
586                 thumbImagePosX = posX;
587                 if (scrollAniPlayer != null)
588                 {
589                     scrollAniPlayer.Stop();
590                 }
591
592                 if (!enableAni)
593                 {
594                     thumbImage.Position = new Position(posX, posY, 0);
595                 }
596                 else
597                 {
598                     if (scrollAniPlayer != null)
599                     {
600                         scrollAniPlayer.Clear();
601                         scrollAniPlayer.AnimateTo(thumbImage, "PositionX", posX);
602                         scrollAniPlayer.Play();
603                     }
604                 }
605             }
606             else
607             {
608                 float posX = (width - thumbW) / 2.0f;
609                 float posY = ratio * (height - thumbH);
610
611                 thumbImagePosY = posY;
612                 if (scrollAniPlayer != null)
613                 {
614                     scrollAniPlayer.Stop();
615                 }
616
617                 if (!enableAni)
618                 {
619                     thumbImage.Position = new Position(posX, posY, 0);
620                 }
621                 else
622                 {
623                     if (scrollAniPlayer != null)
624                     {
625                         scrollAniPlayer.Clear();
626                         scrollAniPlayer.AnimateTo(thumbImage, "PositionY", posY);
627                         scrollAniPlayer.Play();
628                     }
629                 }
630             }
631         }
632
633         private DirectionType CurrentDirection()
634         {
635             DirectionType dir = DirectionType.Horizontal;
636             if (scrollBarAttrs != null)
637             {
638                 if (scrollBarAttrs.Direction != null)
639                 {
640                     dir = scrollBarAttrs.Direction.Value;
641                 }
642             }
643             return dir;
644         }
645
646         private int CalculateCurrentValue(float offset, DirectionType dir)
647         {
648             if (dir == DirectionType.Horizontal)
649             {
650                 thumbImagePosX += offset;
651                 if (thumbImagePosX < 0)
652                 {
653                     thumbImage.PositionX = 0;
654                     curValue = minValue;
655                 }
656                 else if (thumbImagePosX > Size2D.Width - thumbImage.Size2D.Width)
657                 {
658                     thumbImage.PositionX = Size2D.Width - thumbImage.Size2D.Width;
659                     curValue = maxValue;
660                 }
661                 else
662                 {
663                     thumbImage.PositionX = thumbImagePosX;
664                     curValue = (int)((thumbImagePosX / (float)(Size2D.Width - thumbImage.Size2D.Width)) * (float)(maxValue - minValue) + 0.5f);
665                 }
666             }
667             else
668             {
669                 thumbImagePosY += offset;
670                 if (thumbImagePosY < 0)
671                 {
672                     thumbImage.PositionY = 0;
673                     curValue = minValue;
674                 }
675                 else if (thumbImagePosY > Size2D.Height - thumbImage.Size2D.Height)
676                 {
677                     thumbImage.PositionY = Size2D.Height - thumbImage.Size2D.Height;
678                     curValue = maxValue;
679                 }
680                 else
681                 {
682                     thumbImage.PositionY = thumbImagePosY;
683                     curValue = (int)((thumbImagePosY / (float)(Size2D.Height - thumbImage.Size2D.Height)) * (float)(maxValue - minValue) + 0.5f);
684                 }
685             }
686
687             return (int)curValue;
688         }
689     }
690 }