2 * Copyright(c) 2019 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 using System.Collections.Generic;
19 using Tizen.NUI.BaseComponents;
20 using System.ComponentModel;
22 namespace Tizen.NUI.CommonUI
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.
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
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;
42 /// Creates a new instance of a Tab.
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)]
53 /// Creates a new instance of a Tab with style.
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)
65 /// Creates a new instance of a Tab with attributes.
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)
77 /// An event for the item changed signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
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;
85 /// Selected item's index in Tab.
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
98 if (value < itemList.Count)
100 UpdateSelectedItem(itemList[value]);
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.
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
116 return tabAttributes.IsNatureTextWidth;
120 tabAttributes.IsNatureTextWidth = value;
126 /// Gap between items.
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)]
135 return tabAttributes.ItemGap;
139 tabAttributes.ItemGap = value;
145 /// Left space in Tab.
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)]
154 return (int)tabAttributes.Space.X;
158 tabAttributes.Space.X = value;
164 /// Bottom space in Tab.
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
173 return (int)tabAttributes.Space.W;
177 tabAttributes.Space.W = value;
183 /// Right space in Tab.
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
192 return (int)tabAttributes.Space.Y;
196 tabAttributes.Space.Y = value;
202 /// Top space in Tab.
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)]
211 return (int)tabAttributes.Space.Z;
215 tabAttributes.Space.Z = value;
221 /// UnderLine view's size in Tab.
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
230 return tabAttributes.UnderLineAttributes?.Size2D;
236 CreateUnderLineAttributes();
237 tabAttributes.UnderLineAttributes.Size2D = value;
244 /// UnderLine view's background in Tab.
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
253 return tabAttributes.UnderLineAttributes?.BackgroundColor?.All;
259 CreateUnderLineAttributes();
260 if (tabAttributes.UnderLineAttributes.BackgroundColor == null)
262 tabAttributes.UnderLineAttributes.BackgroundColor = new ColorSelector();
264 tabAttributes.UnderLineAttributes.BackgroundColor.All = value;
271 /// Text point size in Tab.
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
280 return tabAttributes.TextAttributes?.PointSize?.All ?? 0;
284 CreateTextAttributes();
285 if (tabAttributes.TextAttributes.PointSize == null)
287 tabAttributes.TextAttributes.PointSize = new FloatSelector();
289 tabAttributes.TextAttributes.PointSize.All = value;
295 /// Text font family in Tab.
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
304 return tabAttributes.TextAttributes?.FontFamily;
308 CreateTextAttributes();
309 tabAttributes.TextAttributes.FontFamily = value;
315 /// Text color in Tab.
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
324 return tabAttributes.TextAttributes?.TextColor?.All;
328 CreateTextAttributes();
329 if (tabAttributes.TextAttributes.TextColor == null)
331 tabAttributes.TextAttributes.TextColor = new ColorSelector();
333 tabAttributes.TextAttributes.TextColor.All = value;
339 /// Text color selector in Tab.
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
348 return tabAttributes.TextAttributes.TextColor;
354 CreateTextAttributes();
355 tabAttributes.TextAttributes.TextColor = value.Clone() as ColorSelector;
362 /// Add tab item by item data. The added item will be added to end of all items automatically.
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)
370 AddItemByIndex(itemData, itemList.Count);
374 /// Insert tab item by item data. The inserted item will be added to the special position by index automatically.
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)
383 AddItemByIndex(itemData, index);
387 /// Delete tab item by index.
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)
395 if(itemList == null || itemIndex < 0 || itemIndex >= itemList.Count)
400 if (curIndex > itemIndex || (curIndex == itemIndex && itemIndex == itemList.Count - 1))
405 Remove(itemList[itemIndex]);
406 itemList[itemIndex].Dispose();
407 itemList.RemoveAt(itemIndex);
413 /// Dispose Tab and all children on it.
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)
426 if (type == DisposeTypes.Explicit)
428 if(underlineAni != null)
430 if(underlineAni.State == Animation.States.Playing)
434 underlineAni.Dispose();
437 Utility.Dispose(underline);
440 for(int i = 0; i < itemList.Count; i++)
443 itemList[i].Dispose();
455 /// Update Tab by attributes.
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()
462 if (tabAttributes.UnderLineAttributes != null)
464 if (underline == null)
466 underline = new View()
468 PositionUsesPivotPoint = true,
469 ParentOrigin = Tizen.NUI.ParentOrigin.BottomLeft,
470 PivotPoint = Tizen.NUI.PivotPoint.BottomLeft,
473 CreateUnderLineAnimation();
475 ApplyAttributes(underline, tabAttributes.UnderLineAttributes);
478 if (tabAttributes.TextAttributes != null)
480 if (curIndex >= 0 && curIndex < itemList.Count)
482 itemList[curIndex].UpdateItemText(tabAttributes.TextAttributes);
490 /// Get Tab attribues.
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()
497 return new TabAttributes();
501 /// Theme change callback when theme is changed, this callback will be trigger.
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)
508 TabAttributes tempAttributes = StyleManager.Instance.GetAttributes(style) as TabAttributes;
509 if (tempAttributes != null)
511 tempAttributes.IsNatureTextWidth = tabAttributes.IsNatureTextWidth; // keep IsNatureTextWidth as original
512 attributes = tabAttributes = tempAttributes;
518 /// Layout child in Tab and it can be override by user.
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()
525 if (tabAttributes == null || itemList == null)
529 int totalNum = itemList.Count;
535 int preX = (int)tabAttributes.Space.X;
537 int itemGap = tabAttributes.ItemGap;
539 if (LayoutDirection == ViewLayoutDirectionType.LTR)
541 if (tabAttributes.IsNatureTextWidth == true)
543 for (int i = 0; i < totalNum; i++)
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;
554 preW = (Size2D.Width - (int)tabAttributes.Space.X - (int)tabAttributes.Space.Y) / totalNum;
555 for (int i = 0; i < totalNum; i++)
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;
566 preX = (int)tabAttributes.Space.Y;
567 if (tabAttributes.IsNatureTextWidth == true)
569 int w = Size2D.Width;
570 for (int i = 0; i < totalNum; i++)
572 preW = itemList[i].TextItem.NaturalSize2D.Width;
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;
581 preW = (Size2D.Width - (int)tabAttributes.Space.X - (int)tabAttributes.Space.Y) / totalNum;
582 for (int i = totalNum - 1; i >= 0; i--)
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;
591 UpdateUnderLinePos();
594 private void Initialize()
596 tabAttributes = attributes as TabAttributes;
597 if (tabAttributes == null)
599 throw new Exception("Tab attribute parse error.");
602 ApplyAttributes(this, tabAttributes);
603 LayoutDirectionChanged += OnLayoutDirectionChanged;
606 private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
611 private void AddItemByIndex(TabItemData itemData, int index)
614 int topSpace = (int)tabAttributes.Space.Z;
615 if (tabAttributes.UnderLineAttributes != null && tabAttributes.UnderLineAttributes.Size2D != null)
617 h = tabAttributes.UnderLineAttributes.Size2D.Height;
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;
627 if(index >= itemList.Count)
633 itemList.Insert(index, item);
639 private void UpdateItems()
642 if (itemList != null && curIndex >= 0 && curIndex < itemList.Count)
644 itemList[curIndex].State = ControlStates.Selected;
645 itemList[curIndex].UpdateItemText(tabAttributes.TextAttributes);
646 UpdateUnderLinePos();
650 if (underline != null)
657 private void CreateUnderLineAttributes()
659 if (tabAttributes.UnderLineAttributes == null)
661 tabAttributes.UnderLineAttributes = new ViewAttributes()
663 PositionUsesPivotPoint = true,
664 ParentOrigin = Tizen.NUI.ParentOrigin.BottomLeft,
665 PivotPoint = Tizen.NUI.PivotPoint.BottomLeft,
670 private void CreateTextAttributes()
672 if (tabAttributes.TextAttributes == null)
674 tabAttributes.TextAttributes = new TextAttributes()
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
687 private void CreateUnderLineAnimation()
689 if (underlineAni == null)
691 underlineAni = new Animation(aniTime);
695 private void UpdateUnderLinePos()
697 if (underline == null || tabAttributes.UnderLineAttributes == null || tabAttributes.UnderLineAttributes.Size2D == null
698 || itemList == null || itemList.Count <= 0)
703 tabAttributes.UnderLineAttributes.Size2D.Width = itemList[curIndex].Size2D.Width;
705 underline.Size2D = new Size2D(itemList[curIndex].Size2D.Width, tabAttributes.UnderLineAttributes.Size2D.Height);
706 underline.BackgroundColor = tabAttributes.UnderLineAttributes.BackgroundColor.All;
709 CreateUnderLineAnimation();
710 if (underlineAni.State == Animation.States.Playing)
714 underlineAni.Clear();
715 underlineAni.AnimateTo(underline, "PositionX", itemList[curIndex].Position2D.X);
720 underline.Position2D.X = itemList[curIndex].Position2D.X;
721 isNeedAnimation = true;
727 private void UpdateSelectedItem(TabItem item)
729 if(item == null || curIndex == item.Index)
734 ItemChangeEventArgs e = new ItemChangeEventArgs
736 PreviousIndex = curIndex,
737 CurrentIndex = item.Index
739 ItemChangedEvent?.Invoke(this, e);
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);
747 UpdateUnderLinePos();
750 private bool ItemTouchEvent(object source, TouchEventArgs e)
752 TabItem item = source as TabItem;
757 PointStateType state = e.Touch.GetState(0);
758 if (state == PointStateType.Up)
760 UpdateSelectedItem(item);
766 internal class TabItem : Control
768 public TabItem() : base()
770 TextItem = new TextLabel()
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
787 return TextItem.Text;
791 TextItem.Text = value;
801 internal TextLabel TextItem
807 protected override void Dispose(DisposeTypes type)
814 if (type == DisposeTypes.Explicit)
816 if (TextItem != null)
827 protected override Attributes GetAttributes()
832 internal void UpdateItemText(TextAttributes attrs)
834 ApplyAttributes(TextItem, attrs);
839 /// TabItemData is a class to record all data which will be applied to Tab item.
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
847 /// Text string in tab item view.
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)]
860 /// ItemChangeEventArgs is a class to record item change event arguments which will sent to user.
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
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;