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.Components
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 [Obsolete("Deprecated in API8; Will be removed in API10")]
30 public class Tab : Control
32 private const int aniTime = 100; // will be defined in const file later
33 private List<TabItem> itemList = new List<TabItem>();
34 private int curIndex = 0;
35 private View underline = null;
36 private Animation underlineAni = null;
37 private bool isNeedAnimation = false;
38 private Extents space;
39 private TabStyle tabStyle => ViewStyle as TabStyle;
44 /// Creates a new instance of a Tab.
46 /// <since_tizen> 6 </since_tizen>
47 [Obsolete("Deprecated in API8; Will be removed in API10")]
54 /// Creates a new instance of a Tab with style.
56 /// <param name="style">Create Tab by special style defined in UX.</param>
57 [EditorBrowsable(EditorBrowsableState.Never)]
58 public Tab(string style) : base(style)
64 /// Creates a new instance of a Tab with style.
66 /// <param name="tabStyle">Create Tab by style customized by user.</param>
67 [EditorBrowsable(EditorBrowsableState.Never)]
68 public Tab(TabStyle tabStyle) : base(tabStyle)
74 /// An event for the item changed signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
76 /// <since_tizen> 6 </since_tizen>
77 [Obsolete("Deprecated in API8; Will be removed in API10")]
78 public event EventHandler<ItemChangedEventArgs> ItemChangedEvent;
81 /// Return a copied Style instance of Tab
84 /// It returns copied Style instance and changing it does not effect to the Tab.
85 /// Style setting is possible by using constructor or the function of ApplyStyle(ViewStyle viewStyle)
87 /// <since_tizen> 8 </since_tizen>
88 public new TabStyle Style
92 var result = new TabStyle(tabStyle);
93 result.CopyPropertiesFromView(this);
94 result.UnderLine.CopyPropertiesFromView(underline);
99 [EditorBrowsable(EditorBrowsableState.Never)]
100 public View Underline
104 if (null == underline)
106 underline = new View()
108 PositionUsesPivotPoint = true,
109 ParentOrigin = Tizen.NUI.ParentOrigin.BottomLeft,
110 PivotPoint = Tizen.NUI.PivotPoint.BottomLeft,
123 /// Selected item's index in Tab.
125 /// <since_tizen> 6 </since_tizen>
126 [Obsolete("Deprecated in API8; Will be removed in API10")]
127 public int SelectedItemIndex
135 if (value < itemList.Count)
137 UpdateSelectedItem(itemList[value]);
143 /// Flag to decide if TabItem is adjusted by text's natural width.
144 /// 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.
146 /// <since_tizen> 6 </since_tizen>
147 [Obsolete("Deprecated in API8; Will be removed in API10")]
148 public bool UseTextNaturalSize
152 return tabStyle?.UseTextNaturalSize ?? false;
156 if (null != tabStyle)
158 tabStyle.UseTextNaturalSize = value;
165 /// Gap between items.
167 /// <since_tizen> 6 </since_tizen>
168 [Obsolete("Deprecated in API8; Will be removed in API10")]
173 return tabStyle?.ItemSpace ?? 0;
177 if (null != tabStyle)
179 tabStyle.ItemSpace = value;
186 /// Space in Tab. Sequence as Left, Right, Top, Bottom
188 /// <since_tizen> 6 </since_tizen>
189 [Obsolete("Deprecated in API8; Will be removed in API10")]
203 /// Item paddings in Tab. Sequence as Left, Right, Top, Bottom
205 /// <since_tizen> 6 </since_tizen>
206 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
207 [EditorBrowsable(EditorBrowsableState.Never)]
208 public Extents ItemPadding
216 if (null != value && null != tabStyle?.ItemPadding)
218 tabStyle.ItemPadding.CopyFrom(value);
222 space = new Extents((ushort start, ushort end, ushort top, ushort bottom) =>
224 tabStyle.ItemPadding.Start = start;
225 tabStyle.ItemPadding.End = end;
226 tabStyle.ItemPadding.Top = top;
227 tabStyle.ItemPadding.Bottom = bottom;
229 }, value.Start, value.End, value.Top, value.Bottom);
233 space.CopyFrom(value);
242 /// UnderLine view's size in Tab.
244 /// <since_tizen> 6 </since_tizen>
245 [Obsolete("Deprecated in API8; Will be removed in API10")]
246 public Size UnderLineSize
250 return Underline.Size;
254 if (null != tabStyle?.UnderLine)
256 tabStyle.UnderLine.Size = value;
258 Underline.Size = value;
263 /// UnderLine view's background in Tab.
265 /// <since_tizen> 6 </since_tizen>
266 [Obsolete("Deprecated in API8; Will be removed in API10")]
267 public Color UnderLineBackgroundColor
271 return Underline.BackgroundColor;
275 if (null != tabStyle?.BackgroundColor)
277 tabStyle.UnderLine.BackgroundColor = value;
279 Underline.BackgroundColor = value;
284 /// Text point size in Tab.
286 /// <since_tizen> 6 </since_tizen>
287 [Obsolete("Deprecated in API8; Will be removed in API10")]
288 public float PointSize
292 return tabStyle?.Text?.PointSize?.All ?? 0;
296 if (null != tabStyle?.Text)
298 tabStyle.Text.PointSize = value;
305 /// Text font family in Tab.
307 /// <since_tizen> 6 </since_tizen>
308 [Obsolete("Deprecated in API8; Will be removed in API10")]
309 public string FontFamily
313 return tabStyle?.Text?.FontFamily?.All;
317 if (null != tabStyle?.Text)
319 tabStyle.Text.FontFamily = value;
326 /// Text color in Tab.
328 /// <since_tizen> 6 </since_tizen>
329 [Obsolete("Deprecated in API8; Will be removed in API10")]
330 public Color TextColor
334 return tabStyle?.Text?.TextColor?.All;
338 if (null != tabStyle?.Text)
340 tabStyle.Text.TextColor = value;
346 private ColorSelector textColorSelector = new ColorSelector();
348 /// Text color selector in Tab.
350 /// <since_tizen> 6 </since_tizen>
351 [Obsolete("Deprecated in API8; Will be removed in API10")]
352 public ColorSelector TextColorSelector
356 return textColorSelector;
360 if (value == null || textColorSelector == null)
362 Tizen.Log.Fatal("NUI", "[Exception] Tab.TextColorSelector is null");
363 throw new NullReferenceException("Tab.TextColorSelector is null");
367 textColorSelector.Clone(value);
373 /// Add tab item by item data. The added item will be added to end of all items automatically.
375 /// <param name="itemData">Item data which will apply to tab item view.</param>
376 /// <since_tizen> 6 </since_tizen>
377 [Obsolete("Deprecated in API8; Will be removed in API10")]
378 public void AddItem(TabItemData itemData)
380 AddItemByIndex(itemData, itemList.Count);
384 /// Insert tab item by item data. The inserted item will be added to the special position by index automatically.
386 /// <param name="itemData">Item data which will apply to tab item view.</param>
387 /// <param name="index">Position index where will be inserted.</param>
388 /// <since_tizen> 6 </since_tizen>
389 [Obsolete("Deprecated in API8; Will be removed in API10")]
390 public void InsertItem(TabItemData itemData, int index)
392 AddItemByIndex(itemData, index);
396 /// Delete tab item by index.
398 /// <param name="itemIndex">Position index where will be deleted.</param>
399 /// <since_tizen> 6 </since_tizen>
400 [Obsolete("Deprecated in API8; Will be removed in API10")]
401 public void DeleteItem(int itemIndex)
403 if (itemList == null || itemIndex < 0 || itemIndex >= itemList.Count)
408 if (curIndex > itemIndex || (curIndex == itemIndex && itemIndex == itemList.Count - 1))
413 Remove(itemList[itemIndex]);
414 itemList[itemIndex].Dispose();
415 itemList.RemoveAt(itemIndex);
421 /// Apply style to tab.
423 /// <param name="viewStyle">The style to apply.</param>
424 [EditorBrowsable(EditorBrowsableState.Never)]
425 public override void ApplyStyle(ViewStyle viewStyle)
427 base.ApplyStyle(viewStyle);
429 TabStyle tabStyle = viewStyle as TabStyle;
431 if (null != tabStyle)
433 Underline.ApplyStyle(tabStyle.UnderLine);
434 CreateUnderLineAnimation();
439 /// Dispose Tab and all children on it.
441 /// <param name="type">Dispose type.</param>
442 /// <since_tizen> 6 </since_tizen>
443 [Obsolete("Deprecated in API8; Will be removed in API10")]
444 protected override void Dispose(DisposeTypes type)
451 if (type == DisposeTypes.Explicit)
453 if (underlineAni != null)
455 if (underlineAni.State == Animation.States.Playing)
459 underlineAni.Dispose();
462 Utility.Dispose(underline);
463 if (itemList != null)
465 for (int i = 0; i < itemList.Count; i++)
468 itemList[i].Dispose();
482 /// <since_tizen> 6 </since_tizen>
483 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
484 [EditorBrowsable(EditorBrowsableState.Never)]
485 protected override void OnUpdate()
493 /// <returns>The default tab style.</returns>
494 [EditorBrowsable(EditorBrowsableState.Never)]
495 protected override ViewStyle CreateViewStyle()
497 return new TabStyle();
501 /// Layout child in Tab and it can be override by user.
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 virtual void LayoutChild()
508 if (itemList == null)
513 int totalNum = itemList.Count;
519 int preX = (int)tabStyle?.ItemPadding.Start;
521 int itemSpace = (null != tabStyle) ? tabStyle.ItemSpace : 0;
523 if (LayoutDirection == ViewLayoutDirectionType.LTR)
525 if (tabStyle?.UseTextNaturalSize == true)
527 for (int i = 0; i < totalNum; i++)
529 preW = (itemList[i].TextItem.NaturalSize2D != null ? itemList[i].TextItem.NaturalSize2D.Width : 0);
530 itemList[i].Position2D.X = preX;
531 itemList[i].Size2D.Width = preW;
532 preX = itemList[i].Position2D.X + preW + itemSpace;
533 itemList[i].Index = i;
538 preW = (Size2D.Width - (int)tabStyle?.ItemPadding.Start - (int)tabStyle?.ItemPadding.End) / totalNum;
539 for (int i = 0; i < totalNum; i++)
541 itemList[i].Position2D.X = preX;
542 itemList[i].Size2D.Width = preW;
543 preX = itemList[i].Position2D.X + preW + itemSpace;
544 itemList[i].Index = i;
550 preX = (int)tabStyle?.ItemPadding.End;
551 if (tabStyle?.UseTextNaturalSize == true)
553 int w = Size2D.Width;
554 for (int i = 0; i < totalNum; i++)
556 preW = (itemList[i].NaturalSize2D != null ? itemList[i].NaturalSize2D.Width : 0);
557 itemList[i].Position2D.X = w - preW - preX;
558 itemList[i].Size2D.Width = preW;
559 preX = w - itemList[i].Position2D.X + itemSpace;
560 itemList[i].Index = i;
565 preW = (Size2D.Width - (int)tabStyle?.ItemPadding.Start - (int)tabStyle?.ItemPadding.End) / totalNum;
566 for (int i = totalNum - 1; i >= 0; i--)
568 itemList[i].Position2D.X = preX;
569 itemList[i].Size2D.Width = preW;
570 preX = itemList[i].Position2D.X + preW + itemSpace;
571 itemList[i].Index = i;
575 UpdateUnderLinePos();
578 private void Initialize()
580 LayoutDirectionChanged += OnLayoutDirectionChanged;
583 private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
588 private void AddItemByIndex(TabItemData itemData, int index)
590 if (null == itemData || null == tabStyle) return;
592 int topSpace = (int)tabStyle.ItemPadding.Top;
593 if (Underline.Size != null)
595 h = (int)Underline.Size.Height;
598 Tab.TabItem item = new TabItem();
599 item.TextItem.ApplyStyle(tabStyle.Text);
601 item.Text = itemData.Text;
602 item.Size2D.Height = Size2D.Height - h - topSpace;
603 item.Position2D.Y = topSpace;
604 item.TouchEvent += ItemTouchEvent;
607 if (index >= itemList.Count)
613 itemList.Insert(index, item);
619 private void UpdateItems()
622 if (itemList != null && curIndex >= 0 && curIndex < itemList.Count)
624 itemList[curIndex].IsSelected = true;
625 UpdateUnderLinePos();
629 if (underline != null)
636 private void CreateUnderLineAnimation()
638 if (underlineAni == null)
640 underlineAni = new Animation(aniTime);
644 private void UpdateUnderLinePos()
646 if (underline == null || Underline.Size == null || itemList == null || itemList.Count <= 0)
651 Underline.Size.Width = itemList[curIndex].Size2D.Width;
653 underline.Size2D = new Size2D(itemList[curIndex].Size2D.Width, (int)Underline.Size.Height);
654 underline.BackgroundColor = tabStyle.UnderLine.BackgroundColor.All;
657 CreateUnderLineAnimation();
658 if (underlineAni.State == Animation.States.Playing)
662 underlineAni.Clear();
663 underlineAni.AnimateTo(underline, "PositionX", itemList[curIndex].Position2D.X);
668 underline.Position2D.X = itemList[curIndex].Position2D.X;
669 isNeedAnimation = true;
675 private void UpdateSelectedItem(TabItem item)
677 if (item == null || curIndex == item.Index)
682 ItemChangedEventArgs e = new ItemChangedEventArgs
684 PreviousIndex = curIndex,
685 CurrentIndex = item.Index
687 ItemChangedEvent?.Invoke(this, e);
689 itemList[curIndex].IsSelected = false;
690 curIndex = item.Index;
691 itemList[curIndex].IsSelected = true;
693 UpdateUnderLinePos();
696 private bool ItemTouchEvent(object source, TouchEventArgs e)
698 TabItem item = source as TabItem;
703 PointStateType state = e.Touch.GetState(0);
704 if (state == PointStateType.Up)
706 UpdateSelectedItem(item);
712 internal class TabItem : View
714 private bool isSelected = false;
716 public TabItem() : base()
718 TextItem = new TextLabel()
720 ParentOrigin = Tizen.NUI.ParentOrigin.Center,
721 PivotPoint = Tizen.NUI.PivotPoint.Center,
722 PositionUsesPivotPoint = true,
723 WidthResizePolicy = ResizePolicyType.FillToParent,
724 HeightResizePolicy = ResizePolicyType.FillToParent,
725 HorizontalAlignment = HorizontalAlignment.Center,
726 VerticalAlignment = VerticalAlignment.Center
730 EnableControlStatePropagation = true;
743 return TextItem.Text;
747 TextItem.Text = value;
751 internal TextLabel TextItem
757 internal bool IsSelected
765 ControlState = value ? ControlState.Selected : ControlState.Normal;
772 /// TabItemData is a class to record all data which will be applied to Tab item.
774 /// <since_tizen> 6 </since_tizen>
775 [Obsolete("Deprecated in API8; Will be removed in API10")]
776 public class TabItemData
779 /// Text string in tab item view.
781 /// <since_tizen> 6 </since_tizen>
782 [Obsolete("Deprecated in API8; Will be removed in API10")]
791 /// ItemChangedEventArgs is a class to record item change event arguments which will sent to user.
793 /// <since_tizen> 6 </since_tizen>
794 [Obsolete("Deprecated in API8; Will be removed in API10")]
795 public class ItemChangedEventArgs : EventArgs
797 /// <summary> Previous selected index of Tab </summary>
798 /// <since_tizen> 6 </since_tizen>
799 [Obsolete("Deprecated in API8; Will be removed in API10")]
800 public int PreviousIndex;
801 /// <summary> Current selected index of Tab </summary>
802 /// <since_tizen> 6 </since_tizen>
803 [Obsolete("Deprecated in API8; Will be removed in API10")]
804 public int CurrentIndex;