5daadd1ba0753f26178db6f7731a3d61f34ef74a
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / TabBar.cs
1 /*
2  * Copyright(c) 2021 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 System.ComponentModel;
20 using Tizen.NUI.BaseComponents;
21
22 namespace Tizen.NUI.Components
23 {
24     /// <summary>
25     /// TabButtonSelectedEventArgs is a class to record tab button selected event
26     /// arguments which will be sent to a user.
27     /// </summary>
28     [EditorBrowsable(EditorBrowsableState.Never)]
29     public class TabButtonSelectedEventArgs : EventArgs
30     {
31         /// <summary>
32         /// Creates a new instance of TabButtonSelectedEventArgs.
33         /// The indices of tab buttons in TabBar are basically the order of adding to TabBar by <see cref="TabView.AddTab"/>.
34         /// So a tab button's index in TabBar can be changed whenever <see cref="TabView.AddTab"/> or <see cref="TabView.RemoveTab"/> is called.
35         /// </summary>
36         /// <param name="index">The index of the selected tab button in TabBar.</param>
37         [EditorBrowsable(EditorBrowsableState.Never)]
38         public TabButtonSelectedEventArgs(int index)
39         {
40             Index = index;
41         }
42
43         /// <summary>
44         /// The index of the selected tab button.
45         /// </summary>
46         [EditorBrowsable(EditorBrowsableState.Never)]
47         public int Index { get; }
48     }
49
50     /// <summary>
51     /// TabBar is a class which contains a set of TabButtons and has one of them selected.
52     /// </summary>
53     /// <since_tizen> 9 </since_tizen>
54     public class TabBar : Control
55     {
56         private IList<TabButton> tabButtons;
57
58         private TabButtonGroup tabButtonGroup;
59
60         /// <summary>
61         /// Creates a new instance of TabBar.
62         /// </summary>
63         /// <since_tizen> 9 </since_tizen>
64         public TabBar()
65         {
66             Layout = new LinearLayout() { LinearOrientation = LinearLayout.Orientation.Horizontal };
67
68             WidthSpecification = LayoutParamPolicies.MatchParent;
69
70             tabButtons = new List<TabButton>();
71             tabButtonGroup = new TabButtonGroup();
72             SelectedIndex = -1;
73         }
74
75         /// <summary>
76         /// An event for the tab button selected signal which can be used to
77         /// subscribe or unsubscribe the event handler provided by a user.
78         /// </summary>
79         [EditorBrowsable(EditorBrowsableState.Never)]
80         public event EventHandler<TabButtonSelectedEventArgs> TabButtonSelected;
81
82         /// <summary>
83         /// The index of the selected tab button.
84         /// The indices of tab buttons in TabBar are basically the order of adding to TabBar by <see cref="TabView.AddTab"/>.
85         /// So a tab button's index in TabBar can be changed whenever <see cref="TabView.AddTab"/> or <see cref="TabView.RemoveTab"/> is called.
86         /// </summary>
87         [EditorBrowsable(EditorBrowsableState.Never)]
88         protected int SelectedIndex { get; set; }
89
90         /// <summary>
91         /// Gets the count of tab buttons.
92         /// </summary>
93         /// <since_tizen> 9 </since_tizen>
94         public int TabButtonCount => tabButtons.Count;
95
96         /// <inheritdoc/>
97         [EditorBrowsable(EditorBrowsableState.Never)]
98         public override void OnInitialize()
99         {
100             base.OnInitialize();
101
102             AccessibilityRole = Role.PageTabList;
103         }
104
105         /// <summary>
106         /// Adds a tab button to TabBar.
107         /// </summary>
108         /// <param name="tabButton">A tab button to be added to TabBar.</param>
109         /// <exception cref="ArgumentNullException">Thrown when the argument tabButton is null.</exception>
110         [EditorBrowsable(EditorBrowsableState.Never)]
111         protected internal void AddTabButton(TabButton tabButton)
112         {
113             if (tabButton == null)
114             {
115                 throw new ArgumentNullException(nameof(tabButton), "tabButton should not be null.");
116             }
117
118             tabButtons.Add(tabButton);
119             Add(tabButton);
120             tabButtonGroup.Add(tabButton);
121
122             tabButton.Clicked += (object sender, ClickedEventArgs e) =>
123             {
124                 int index = tabButtons.IndexOf(tabButton);
125
126                 if (SelectedIndex == index)
127                 {
128                     return;
129                 }
130
131                 SelectedIndex = index;
132
133                 if (TabButtonSelected != null)
134                 {
135                     TabButtonSelectedEventArgs args = new TabButtonSelectedEventArgs(SelectedIndex);
136                     TabButtonSelected(this, args);
137                 }
138             };
139
140             if (SelectedIndex == -1)
141             {
142                 tabButton.IsSelected = true;
143                 SelectedIndex = 0;
144
145                 if (TabButtonSelected != null)
146                 {
147                     TabButtonSelectedEventArgs args = new TabButtonSelectedEventArgs(SelectedIndex);
148                     TabButtonSelected(this, args);
149                 }
150             }
151         }
152
153         /// <summary>
154         /// Removes a tab button from TabBar.
155         /// </summary>
156         /// <param name="tabButton">A tab button to be removed from TabBar.</param>
157         /// <exception cref="ArgumentNullException">Thrown when the argument tabButton is null.</exception>
158         /// <exception cref="ArgumentException">Thrown when the argument tabButton does not exist in TabBar.</exception>
159         [EditorBrowsable(EditorBrowsableState.Never)]
160         protected internal void RemoveTabButton(TabButton tabButton)
161         {
162             if (tabButton == null)
163             {
164                 throw new ArgumentNullException(nameof(tabButton), "tabButton should not be null.");
165             }
166
167             if (tabButtons.Contains(tabButton) == false)
168             {
169                 throw new ArgumentException("tabButton does not exist in TabBar.", nameof(tabButton));
170             }
171
172             int index = tabButtons.IndexOf(tabButton);
173             TabButton selectedTabButton = tabButtons[SelectedIndex];
174
175             tabButtons.Remove(tabButton);
176             Remove(tabButton);
177             tabButtonGroup.Remove(tabButton);
178
179             if ((index < SelectedIndex) || (tabButtons.Count == SelectedIndex))
180             {
181                 SelectedIndex -= 1;
182
183                 if (TabButtonSelected != null)
184                 {
185                     TabButtonSelectedEventArgs args = new TabButtonSelectedEventArgs(SelectedIndex);
186                     TabButtonSelected(this, args);
187                 }
188             }
189
190             if ((SelectedIndex != -1) && (selectedTabButton != tabButtons[SelectedIndex]))
191             {
192                 tabButtons[SelectedIndex].IsSelected = true;
193             }
194         }
195
196         /// <summary>
197         /// Gets the tab button at the specified index of TabBar.
198         /// The indices of tab buttons in TabBar are basically the order of adding to TabBar by <see cref="TabView.AddTab"/>.
199         /// So a tab button's index in TabBar can be changed whenever <see cref="TabView.AddTab"/> or <see cref="TabView.RemoveTab"/> is called.
200         /// </summary>
201         /// <param name="index">The index of tab button in TabBar where the specified tab button exists.</param>
202         /// <exception cref="ArgumentOutOfRangeException">Thrown when the index is less than 0, or greater than or equal to the number of tab buttons.</exception>
203         /// <since_tizen> 9 </since_tizen>
204         public TabButton GetTabButton(int index)
205         {
206             if ((index < 0) || (index >= tabButtons.Count))
207             {
208                 throw new ArgumentOutOfRangeException(nameof(index), "index should not be greater than or equal to 0, and less than the number of tab buttons.");
209             }
210
211             return tabButtons[index];
212         }
213
214         /// <inheritdoc/>
215         [EditorBrowsable(EditorBrowsableState.Never)]
216         protected override void Dispose(DisposeTypes type)
217         {
218             if (disposed)
219             {
220                 return;
221             }
222
223             if (type == DisposeTypes.Explicit)
224             {
225                 if (tabButtons != null)
226                 {
227                     foreach (TabButton tabButton in tabButtons)
228                     {
229                         Utility.Dispose(tabButton);
230                     }
231
232                     tabButtons = null;
233                 }
234
235                 tabButtonGroup = null;
236             }
237
238             base.Dispose(type);
239         }
240     }
241 }