6e6e49fc639768b76504cd5802651a4e0ac9ea20
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.CommonUI / Controls / Tab.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 System.Collections.Generic;
19 using Tizen.NUI.BaseComponents;
20 using System.ComponentModel;
21
22 namespace Tizen.NUI.CommonUI
23 {
24     /// <summary>
25     /// Tab is one kind of common component, it can be used as menu label.
26     /// User can handle Tab by adding/inserting/deleting TabItem.
27     /// </summary>
28     /// <since_tizen> 6 </since_tizen>
29     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
30     [EditorBrowsable(EditorBrowsableState.Never)]
31     public class Tab : Control
32     {
33         private const int aniTime = 100; // will be defined in const file later
34         private List<TabItem> itemList = new List<TabItem>();
35         private int curIndex = 0;
36         private View underline = null;
37         private TabAttributes tabAttributes = null;
38         private Animation underlineAni = null;
39         private bool isNeedAnimation = false;
40
41         /// <summary>
42         /// Creates a new instance of a Tab.
43         /// </summary>
44         /// <since_tizen> 6 </since_tizen>
45         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
46         [EditorBrowsable(EditorBrowsableState.Never)]
47         public Tab() : base()
48         {
49             Initialize();
50         }
51
52         /// <summary>
53         /// Creates a new instance of a Tab with style.
54         /// </summary>
55         /// <param name="style">Create Tab by special style defined in UX.</param>
56         /// <since_tizen> 6 </since_tizen>
57         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
58         [EditorBrowsable(EditorBrowsableState.Never)]
59         public Tab(string style) : base(style)
60         {
61             Initialize();
62         }
63
64         /// <summary>
65         /// Creates a new instance of a Tab with attributes.
66         /// </summary>
67         /// <param name="attributes">Create Tab by attributes customized by user.</param>
68         /// <since_tizen> 6 </since_tizen>
69         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
70         [EditorBrowsable(EditorBrowsableState.Never)]
71         public Tab(TabAttributes attributes) : base(attributes)
72         {
73             Initialize();
74         }
75
76         /// <summary>
77         /// An event for the item changed signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
78         /// </summary>
79         /// <since_tizen> 6 </since_tizen>
80         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
81         [EditorBrowsable(EditorBrowsableState.Never)]
82         public event EventHandler<ItemChangeEventArgs> ItemChangedEvent;
83
84         /// <summary>
85         /// Selected item's index in Tab.
86         /// </summary>
87         /// <since_tizen> 6 </since_tizen>
88         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
89         [EditorBrowsable(EditorBrowsableState.Never)]
90         public int SelectedItemIndex
91         {
92             get
93             {
94                 return curIndex;
95             }
96             set
97             {
98                 if (value < itemList.Count)
99                 {
100                     UpdateSelectedItem(itemList[value]);
101                 }
102             }
103         }
104
105         /// <summary>
106         /// Flag to decide if TabItem is adjusted by text's natural width.
107         /// If true, TabItem's width will be equal as text's natural width, if false, it will be decided by Tab's width and tab item count.
108         /// </summary>
109         /// <since_tizen> 6 </since_tizen>
110         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
111         [EditorBrowsable(EditorBrowsableState.Never)]
112         public bool IsNatureTextWidth
113         {
114             get
115             {
116                 return tabAttributes.IsNatureTextWidth;
117             }
118             set
119             {
120                 tabAttributes.IsNatureTextWidth = value;
121                 RelayoutRequest();
122             }
123         }
124
125         /// <summary>
126         /// Gap between items.
127         /// </summary>
128         /// <since_tizen> 6 </since_tizen>
129         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
130         [EditorBrowsable(EditorBrowsableState.Never)]
131         public int ItemGap
132         {
133             get
134             {
135                 return tabAttributes.ItemGap;
136             }
137             set
138             {
139                 tabAttributes.ItemGap = value;
140                 RelayoutRequest();
141             }
142         }
143
144         /// <summary>
145         /// Left space in Tab.
146         /// </summary>
147         /// <since_tizen> 6 </since_tizen>
148         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
149         [EditorBrowsable(EditorBrowsableState.Never)]
150         public int LeftSpace
151         {
152             get
153             {
154                 return (int)tabAttributes.Space.X;
155             }
156             set
157             {
158                 tabAttributes.Space.X = value;
159                 RelayoutRequest();
160             }
161         }
162
163         /// <summary>
164         /// Bottom space in Tab.
165         /// </summary>
166         /// <since_tizen> 6 </since_tizen>
167         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
168         [EditorBrowsable(EditorBrowsableState.Never)]
169         public int BottomSpace
170         {
171             get
172             {
173                 return (int)tabAttributes.Space.W;
174             }
175             set
176             {
177                 tabAttributes.Space.W = value;
178                 RelayoutRequest();
179             }
180         }
181
182         /// <summary>
183         /// Right space in Tab.
184         /// </summary>
185         /// <since_tizen> 6 </since_tizen>
186         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
187         [EditorBrowsable(EditorBrowsableState.Never)]
188         public int RightSpace
189         {
190             get
191             {
192                 return (int)tabAttributes.Space.Y;
193             }
194             set
195             {
196                 tabAttributes.Space.Y = value;
197                 RelayoutRequest();
198             }
199         }
200
201         /// <summary>
202         /// Top space in Tab.
203         /// </summary>
204         /// <since_tizen> 6 </since_tizen>
205         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
206         [EditorBrowsable(EditorBrowsableState.Never)]
207         public int TopSpace
208         {
209             get
210             {
211                 return (int)tabAttributes.Space.Z;
212             }
213             set
214             {
215                 tabAttributes.Space.Z = value;
216                 RelayoutRequest();
217             }
218         }
219
220         /// <summary>
221         /// UnderLine view's size in Tab.
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 Size2D UnderLineSize2D
227         {
228             get
229             {
230                 return tabAttributes.UnderLineAttributes?.Size2D;
231             }
232             set
233             {
234                 if (value != null)
235                 {
236                     CreateUnderLineAttributes();
237                     tabAttributes.UnderLineAttributes.Size2D = value;
238                     RelayoutRequest();
239                 }
240             }
241         }
242
243         /// <summary>
244         /// UnderLine view's background in Tab.
245         /// </summary>
246         /// <since_tizen> 6 </since_tizen>
247         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
248         [EditorBrowsable(EditorBrowsableState.Never)]
249         public Color UnderLineBackgroundColor
250         {
251             get
252             {
253                 return tabAttributes.UnderLineAttributes?.BackgroundColor?.All;
254             }
255             set
256             {
257                 if (value != null)
258                 {
259                     CreateUnderLineAttributes();
260                     if (tabAttributes.UnderLineAttributes.BackgroundColor == null)
261                     {
262                         tabAttributes.UnderLineAttributes.BackgroundColor = new ColorSelector();
263                     }
264                     tabAttributes.UnderLineAttributes.BackgroundColor.All = value;
265                     RelayoutRequest();
266                 }
267             }
268         }
269
270         /// <summary>
271         /// Text point size in Tab.
272         /// </summary>
273         /// <since_tizen> 6 </since_tizen>
274         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
275         [EditorBrowsable(EditorBrowsableState.Never)]
276         public float PointSize
277         {
278             get
279             {
280                 return tabAttributes.TextAttributes?.PointSize?.All ?? 0;
281             }
282             set
283             {
284                 CreateTextAttributes();
285                 if (tabAttributes.TextAttributes.PointSize == null)
286                 {
287                     tabAttributes.TextAttributes.PointSize = new FloatSelector();
288                 }
289                 tabAttributes.TextAttributes.PointSize.All = value;
290                 RelayoutRequest();
291             }
292         }
293
294         /// <summary>
295         /// Text font family in Tab.
296         /// </summary>
297         /// <since_tizen> 6 </since_tizen>
298         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
299         [EditorBrowsable(EditorBrowsableState.Never)]
300         public string FontFamily
301         {
302             get
303             {
304                 return tabAttributes.TextAttributes?.FontFamily;
305             }
306             set
307             {
308                 CreateTextAttributes();
309                 tabAttributes.TextAttributes.FontFamily = value;
310                 RelayoutRequest();
311             }
312         }
313
314         /// <summary>
315         /// Text color in Tab.
316         /// </summary>
317         /// <since_tizen> 6 </since_tizen>
318         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
319         [EditorBrowsable(EditorBrowsableState.Never)]
320         public Color TextColor
321         {
322             get
323             {
324                 return tabAttributes.TextAttributes?.TextColor?.All;
325             }
326             set
327             {
328                 CreateTextAttributes();
329                 if (tabAttributes.TextAttributes.TextColor == null)
330                 {
331                     tabAttributes.TextAttributes.TextColor = new ColorSelector();
332                 }
333                 tabAttributes.TextAttributes.TextColor.All = value;
334                 RelayoutRequest();
335             }
336         }
337
338         /// <summary>
339         /// Text color selector in Tab.
340         /// </summary>
341         /// <since_tizen> 6 </since_tizen>
342         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
343         [EditorBrowsable(EditorBrowsableState.Never)]
344         public ColorSelector TextColorSelector
345         {
346             get
347             {
348                 return tabAttributes.TextAttributes.TextColor;
349             }
350             set
351             {
352                 if (value != null)
353                 {
354                     CreateTextAttributes();
355                     tabAttributes.TextAttributes.TextColor = value.Clone() as ColorSelector;
356                     RelayoutRequest();
357                 }
358             }
359         }
360
361         /// <summary>
362         /// Add tab item by item data. The added item will be added to end of all items automatically.
363         /// </summary>
364         /// <param name="itemData">Item data which will apply to tab item view.</param>
365         /// <since_tizen> 6 </since_tizen>
366         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
367         [EditorBrowsable(EditorBrowsableState.Never)]
368         public void AddItem(TabItemData itemData)
369         {
370             AddItemByIndex(itemData, itemList.Count);
371         }
372
373         /// <summary>
374         /// Insert tab item by item data. The inserted item will be added to the special position by index automatically.
375         /// </summary>
376         /// <param name="itemData">Item data which will apply to tab item view.</param>
377         /// <param name="index">Position index where will be inserted.</param>
378         /// <since_tizen> 6 </since_tizen>
379         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
380         [EditorBrowsable(EditorBrowsableState.Never)]
381         public void InsertItem(TabItemData itemData, int index)
382         {
383             AddItemByIndex(itemData, index);
384         }
385
386         /// <summary>
387         /// Delete tab item by index.
388         /// </summary>
389         /// <param name="itemIndex">Position index where will be deleted.</param>
390         /// <since_tizen> 6 </since_tizen>
391         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
392         [EditorBrowsable(EditorBrowsableState.Never)]
393         public void DeleteItem(int itemIndex)
394         {
395             if(itemList == null || itemIndex < 0 || itemIndex >= itemList.Count)
396             {
397                 return;
398             }
399
400             if (curIndex > itemIndex || (curIndex == itemIndex && itemIndex == itemList.Count - 1))
401             {
402                 curIndex--;
403             }
404
405             Remove(itemList[itemIndex]);
406             itemList[itemIndex].Dispose();
407             itemList.RemoveAt(itemIndex);
408
409             UpdateItems();
410         }
411
412         /// <summary>
413         /// Dispose Tab and all children on it.
414         /// </summary>
415         /// <param name="type">Dispose type.</param>
416         /// <since_tizen> 6 </since_tizen>
417         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
418         [EditorBrowsable(EditorBrowsableState.Never)]
419         protected override void Dispose(DisposeTypes type)
420         {
421             if (disposed)
422             {
423                 return;
424             }
425
426             if (type == DisposeTypes.Explicit)
427             {
428                 if(underlineAni != null)
429                 {
430                     if(underlineAni.State == Animation.States.Playing)
431                     {
432                         underlineAni.Stop();
433                     }
434                     underlineAni.Dispose();
435                     underlineAni = null;
436                 }
437                 Utility.Dispose(underline);
438                 if(itemList != null)
439                 {
440                     for(int i = 0; i < itemList.Count; i++)
441                     {
442                         Remove(itemList[i]);
443                         itemList[i].Dispose();
444                         itemList[i] = null;
445                     }
446                     itemList.Clear();
447                     itemList = null;
448                 }
449             }
450
451             base.Dispose(type);
452         }
453
454         /// <summary>
455         /// Update Tab by attributes.
456         /// </summary>
457         /// <since_tizen> 6 </since_tizen>
458         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
459         [EditorBrowsable(EditorBrowsableState.Never)]
460         protected override void OnUpdate()
461         {
462             if (tabAttributes.UnderLineAttributes != null)
463             {
464                 if (underline == null)
465                 {
466                     underline = new View()
467                     {
468                         PositionUsesPivotPoint = true,
469                         ParentOrigin = Tizen.NUI.ParentOrigin.BottomLeft,
470                         PivotPoint = Tizen.NUI.PivotPoint.BottomLeft,
471                     };
472                     Add(underline);
473                     CreateUnderLineAnimation();
474                 }
475                 ApplyAttributes(underline, tabAttributes.UnderLineAttributes);
476             }
477
478             if (tabAttributes.TextAttributes != null)
479             {
480                 if (curIndex >= 0 && curIndex < itemList.Count)
481                 {
482                     itemList[curIndex].UpdateItemText(tabAttributes.TextAttributes);
483                 }
484             }
485
486             LayoutChild();
487         }
488
489         /// <summary>
490         /// Get Tab attribues.
491         /// </summary>
492         /// <since_tizen> 6 </since_tizen>
493         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
494         [EditorBrowsable(EditorBrowsableState.Never)]
495         protected override Attributes GetAttributes()
496         {
497             return new TabAttributes();
498         }
499
500         /// <summary>
501         /// Theme change callback when theme is changed, this callback will be trigger.
502         /// </summary>
503         /// <since_tizen> 6 </since_tizen>
504         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
505         [EditorBrowsable(EditorBrowsableState.Never)]
506         protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
507         {
508             TabAttributes tempAttributes = StyleManager.Instance.GetAttributes(style) as TabAttributes;
509             if (tempAttributes != null)
510             {
511                 tempAttributes.IsNatureTextWidth = tabAttributes.IsNatureTextWidth; // keep IsNatureTextWidth as original
512                 attributes = tabAttributes = tempAttributes;
513                 RelayoutRequest();
514             }
515         }
516
517         /// <summary>
518         /// Layout child in Tab and it can be override by user.
519         /// </summary>
520         /// <since_tizen> 6 </since_tizen>
521         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
522         [EditorBrowsable(EditorBrowsableState.Never)]
523         protected virtual void LayoutChild()
524         {
525             if (tabAttributes == null || itemList == null)
526             {
527                 return;
528             }
529             int totalNum = itemList.Count;
530             if (totalNum == 0)
531             {
532                 return;
533             }
534
535             int preX = (int)tabAttributes.Space.X;
536             int preW = 0;
537             int itemGap = tabAttributes.ItemGap;
538
539             if (LayoutDirection == ViewLayoutDirectionType.LTR)
540             {
541                 if (tabAttributes.IsNatureTextWidth == true)
542                 {
543                     for (int i = 0; i < totalNum; i++)
544                     {
545                         preW = itemList[i].TextItem.NaturalSize2D.Width;
546                         itemList[i].Position2D.X = preX;
547                         itemList[i].Size2D.Width = preW;
548                         preX = itemList[i].Position2D.X + preW + itemGap;
549                         itemList[i].Index = i;
550                     }
551                 }
552                 else
553                 {
554                     preW = (Size2D.Width - (int)tabAttributes.Space.X - (int)tabAttributes.Space.Y) / totalNum;
555                     for (int i = 0; i < totalNum; i++)
556                     {
557                         itemList[i].Position2D.X = preX;
558                         itemList[i].Size2D.Width = preW;
559                         preX = itemList[i].Position2D.X + preW + itemGap;
560                         itemList[i].Index = i;
561                     }
562                 }
563             }
564             else
565             {
566                 preX = (int)tabAttributes.Space.Y;
567                 if (tabAttributes.IsNatureTextWidth == true)
568                 {
569                     int w = Size2D.Width;
570                     for (int i = 0; i < totalNum; i++)
571                     {
572                         preW = (itemList[i].TextItem.NaturalSize2D != null ? itemList[i].TextItem.NaturalSize2D.Width : 0);
573                         itemList[i].Position2D.X = w - preW - preX;
574                         itemList[i].Size2D.Width = preW;
575                         preX = w - itemList[i].Position2D.X + itemGap;
576                         itemList[i].Index = i;
577                     }
578                 }
579                 else
580                 {
581                     preW = (Size2D.Width - (int)tabAttributes.Space.X - (int)tabAttributes.Space.Y) / totalNum;
582                     for (int i = totalNum - 1; i >= 0; i--)
583                     {
584                         itemList[i].Position2D.X = preX;
585                         itemList[i].Size2D.Width = preW;
586                         preX = itemList[i].Position2D.X + preW + itemGap;
587                         itemList[i].Index = i;
588                     }
589                 }
590             }
591             UpdateUnderLinePos();
592         }
593
594         private void Initialize()
595         {
596             tabAttributes = attributes as TabAttributes;
597             if (tabAttributes == null)
598             {
599                 throw new Exception("Tab attribute parse error.");
600             }
601
602             ApplyAttributes(this, tabAttributes);
603             LayoutDirectionChanged += OnLayoutDirectionChanged;
604         }
605
606         private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
607         {
608             LayoutChild();
609         }
610
611         private void AddItemByIndex(TabItemData itemData, int index)
612         {
613             int h = 0;
614             int topSpace = (int)tabAttributes.Space.Z;
615             if (tabAttributes.UnderLineAttributes != null && tabAttributes.UnderLineAttributes.Size2D != null)
616             {
617                 h = tabAttributes.UnderLineAttributes.Size2D.Height;
618             }
619             Tab.TabItem item = new TabItem();
620             ApplyAttributes(item.TextItem, tabAttributes.TextAttributes);
621             item.TextItem.Text = itemData.Text;
622             item.Size2D.Height = Size2D.Height - h - topSpace;
623             item.Position2D.Y = topSpace;
624             item.TouchEvent += ItemTouchEvent;
625             Add(item);
626
627             if(index >= itemList.Count)
628             {
629                 itemList.Add(item);
630             }
631             else
632             {
633                 itemList.Insert(index, item);
634             }
635
636             UpdateItems();
637         }
638
639         private void UpdateItems()
640         {
641             LayoutChild();
642             if (itemList != null && curIndex >= 0 && curIndex < itemList.Count)
643             {
644                 itemList[curIndex].State = ControlStates.Selected;
645                 itemList[curIndex].UpdateItemText(tabAttributes.TextAttributes);
646                 UpdateUnderLinePos();
647             }
648             else
649             {
650                 if (underline != null)
651                 {
652                     underline.Hide();
653                 }
654             }
655         }
656
657         private void CreateUnderLineAttributes()
658         {
659             if (tabAttributes.UnderLineAttributes == null)
660             {
661                 tabAttributes.UnderLineAttributes = new ViewAttributes()
662                 {
663                     PositionUsesPivotPoint = true,
664                     ParentOrigin = Tizen.NUI.ParentOrigin.BottomLeft,
665                     PivotPoint = Tizen.NUI.PivotPoint.BottomLeft,
666                 };
667             }
668         }
669
670         private void CreateTextAttributes()
671         {
672             if (tabAttributes.TextAttributes == null)
673             {
674                 tabAttributes.TextAttributes = new TextAttributes()
675                 {
676                     PositionUsesPivotPoint =  true,
677                     ParentOrigin = Tizen.NUI.ParentOrigin.Center,
678                     PivotPoint = Tizen.NUI.PivotPoint.Center,
679                     HorizontalAlignment = HorizontalAlignment.Center,
680                     VerticalAlignment = VerticalAlignment.Center,
681                     WidthResizePolicy =  ResizePolicyType.FillToParent,
682                     HeightResizePolicy = ResizePolicyType.FillToParent
683                 };
684             }
685         }
686
687         private void CreateUnderLineAnimation()
688         {
689             if (underlineAni == null)
690             {
691                 underlineAni = new Animation(aniTime);
692             }
693         }
694         
695         private void UpdateUnderLinePos()
696         {
697             if (underline == null || tabAttributes.UnderLineAttributes == null || tabAttributes.UnderLineAttributes.Size2D == null
698                 || itemList == null || itemList.Count <= 0)
699             {
700                 return;
701             }
702
703             tabAttributes.UnderLineAttributes.Size2D.Width = itemList[curIndex].Size2D.Width;
704
705             underline.Size2D = new Size2D(itemList[curIndex].Size2D.Width, tabAttributes.UnderLineAttributes.Size2D.Height);
706             underline.BackgroundColor = tabAttributes.UnderLineAttributes.BackgroundColor.All;
707             if (isNeedAnimation)
708             {
709                 CreateUnderLineAnimation();
710                 if (underlineAni.State == Animation.States.Playing)
711                 {
712                     underlineAni.Stop();
713                 }
714                 underlineAni.Clear();
715                 underlineAni.AnimateTo(underline, "PositionX", itemList[curIndex].Position2D.X);
716                 underlineAni.Play();
717             }
718             else
719             {
720                 underline.Position2D.X = itemList[curIndex].Position2D.X;
721                 isNeedAnimation = true;
722             }
723
724             underline.Show();
725         }
726
727         private void UpdateSelectedItem(TabItem item)
728         {
729             if(item == null || curIndex == item.Index)
730             {
731                 return;
732             }
733
734             ItemChangeEventArgs e = new ItemChangeEventArgs
735             {
736                 PreviousIndex = curIndex,
737                 CurrentIndex = item.Index
738             };
739             ItemChangedEvent?.Invoke(this, e);
740
741             itemList[curIndex].State = ControlStates.Normal;
742             itemList[curIndex].UpdateItemText(tabAttributes.TextAttributes);
743             curIndex = item.Index;
744             itemList[curIndex].State = ControlStates.Selected;
745             itemList[curIndex].UpdateItemText(tabAttributes.TextAttributes);
746
747             UpdateUnderLinePos();
748         }
749
750         private bool ItemTouchEvent(object source, TouchEventArgs e)
751         {
752             TabItem item = source as TabItem;
753             if(item == null)
754             {
755                 return false;
756             }
757             PointStateType state = e.Touch.GetState(0);
758             if (state == PointStateType.Up)
759             {
760                 UpdateSelectedItem(item);
761             }
762
763             return true;
764         }
765
766         internal class TabItem : Control
767         {
768             public TabItem() : base()
769             {
770                 TextItem = new TextLabel()
771                 {
772                     ParentOrigin = Tizen.NUI.ParentOrigin.Center,
773                     PivotPoint = Tizen.NUI.PivotPoint.Center,
774                     PositionUsesPivotPoint = true,
775                     WidthResizePolicy = ResizePolicyType.FillToParent,
776                     HeightResizePolicy = ResizePolicyType.FillToParent,
777                     HorizontalAlignment = HorizontalAlignment.Center,
778                     VerticalAlignment = VerticalAlignment.Center
779                 };
780                 Add(TextItem);
781             }
782
783             public string Text
784             {
785                 get
786                 {
787                     return TextItem.Text;
788                 }
789                 set
790                 {
791                     TextItem.Text = value;
792                 }
793             }
794
795             internal int Index
796             {
797                 get;
798                 set;
799             }
800
801             internal TextLabel TextItem
802             {
803                 get;
804                 set;
805             }
806
807             protected override void Dispose(DisposeTypes type)
808             {
809                 if (disposed)
810                 {
811                     return;
812                 }
813
814                 if (type == DisposeTypes.Explicit)
815                 {
816                     if (TextItem != null)
817                     {
818                         Remove(TextItem);
819                         TextItem.Dispose();
820                         TextItem = null;
821                     }
822                 }
823
824                 base.Dispose(type);
825             }
826
827             protected override Attributes GetAttributes()
828             {
829                 return null;
830             }
831
832             internal void UpdateItemText(TextAttributes attrs)
833             {
834                 ApplyAttributes(TextItem, attrs);
835             }
836         }
837
838         /// <summary>
839         /// TabItemData is a class to record all data which will be applied to Tab item.
840         /// </summary>
841         /// <since_tizen> 6 </since_tizen>
842         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
843         [EditorBrowsable(EditorBrowsableState.Never)]
844         public class TabItemData
845         {
846             /// <summary>
847             /// Text string in tab item view.
848             /// </summary>
849             /// <since_tizen> 6 </since_tizen>
850             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
851             [EditorBrowsable(EditorBrowsableState.Never)]
852             public string Text
853             {
854                 get;
855                 set;
856             }
857         }
858
859         /// <summary>
860         /// ItemChangeEventArgs is a class to record item change event arguments which will sent to user.
861         /// </summary>
862         /// <since_tizen> 6 </since_tizen>
863         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
864         [EditorBrowsable(EditorBrowsableState.Never)]
865         public class ItemChangeEventArgs : EventArgs
866         {
867             /// <summary> Previous selected index of Tab </summary>
868             /// <since_tizen> 6 </since_tizen>
869             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
870             [EditorBrowsable(EditorBrowsableState.Never)]
871             public int PreviousIndex;
872             /// <summary> Current selected index of Tab </summary>
873             /// <since_tizen> 6 </since_tizen>
874             /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
875             [EditorBrowsable(EditorBrowsableState.Never)]
876             public int CurrentIndex;
877         }
878     }
879 }