fd8d21663d4e78219660d0a23784fe62191a534e
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / TabView.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.ComponentModel;
19 using Tizen.NUI.BaseComponents;
20
21 namespace Tizen.NUI.Components
22 {
23     /// <summary>
24     /// TabView is a class which contains a TabBar and TabContent.
25     /// TabView adds TabButtons and Views to TabBar and TabContent in TabView by <see cref="TabView.AddTab"/>.
26     /// TabView removes TabButtons and Views from TabBar and TabContent in TabView by <see cref="TabView.RemoveTab"/>.
27     /// TabView selects a view from the TabContent according to the selected TabButton in the TabBar.
28     ///
29     /// <example>
30     /// <code>
31     /// var tabView = new TabView()
32     /// {
33     ///     WidthSpecification = LayoutParamPolicies.MatchParent,
34     ///     HeightSpecification = LayoutParamPolicies.MatchParent,
35     /// };
36     ///
37     /// var tabButton = new TabButton()
38     /// {
39     ///     Text = "Tab#1"
40     /// };
41     ///
42     /// var content = new View()
43     /// {
44     ///     BackgroundColor = Color.Red,
45     ///     WidthSpecification = LayoutParamPolicies.MatchParent,
46     ///     HeightSpecification = LayoutParamPolicies.MatchParent,
47     /// };
48     ///
49     /// tabView.AddTab(tabButton, content);
50     ///
51     /// var tabButton2 = new TabButton()
52     /// {
53     ///     Text = "Tab#2"
54     /// };
55     ///
56     /// var content2 = new View()
57     /// {
58     ///     BackgroundColor = Color.Green,
59     ///     WidthSpecification = LayoutParamPolicies.MatchParent,
60     ///     HeightSpecification = LayoutParamPolicies.MatchParent,
61     /// };
62     ///
63     /// tabView.AddTab(tabButton2, content2);
64     ///
65     /// var tabButton3 = new TabButton()
66     /// {
67     ///     Text = "Tab#3"
68     /// };
69     ///
70     /// var content3 = new View()
71     /// {
72     ///     BackgroundColor = Color.Blue,
73     ///     WidthSpecification = LayoutParamPolicies.MatchParent,
74     ///     HeightSpecification = LayoutParamPolicies.MatchParent,
75     /// };
76     ///
77     /// tabView.AddTab(tabButton3, content3);
78     /// </code>
79     /// </example>
80     /// </summary>
81     /// <since_tizen> 9 </since_tizen>
82     public class TabView : Control
83     {
84         private TabBar tabBar = null;
85
86         private TabContent content = null;
87
88         /// <summary>
89         /// Creates a new instance of TabView.
90         /// </summary>
91         /// <since_tizen> 9 </since_tizen>
92         public TabView()
93         {
94             // FIXME: Now, WidthSpecification/HeightSpecification are updated internally.
95             //        When this is resolved, LinearLayout can be used.
96             Layout = new AbsoluteLayout();
97             WidthSpecification = LayoutParamPolicies.MatchParent;
98             HeightSpecification = LayoutParamPolicies.MatchParent;
99
100             InitContent();
101             InitTabBar();
102
103             CalculatePosition();
104         }
105
106         private void InitTabBar()
107         {
108             if (tabBar != null)
109             {
110                 return;
111             }
112
113             tabBar = new TabBar();
114             tabBar.TabButtonSelected += tabButtonSelectedHandler;
115
116             Add(tabBar);
117         }
118
119         private void InitContent()
120         {
121             if (content != null)
122             {
123                 return;
124             }
125
126             content = new TabContent();
127             content.WidthSpecification = LayoutParamPolicies.MatchParent;
128             content.HeightSpecification = LayoutParamPolicies.MatchParent;
129
130             Add(content);
131         }
132
133         private void tabButtonSelectedHandler(object sender, TabButtonSelectedEventArgs args)
134         {
135             if ((content != null) && (content.ViewCount > args.Index))
136             {
137                 content.Select(args.Index);
138             }
139         }
140
141         /// <summary>
142         /// Gets TabBar of TabView.
143         /// </summary>
144         /// <since_tizen> 9 </since_tizen>
145         public TabBar TabBar
146         {
147             get
148             {
149                 return tabBar;
150             }
151         }
152
153         /// <summary>
154         /// Gets TabContent of TabView.
155         /// </summary>
156         /// <since_tizen> 9 </since_tizen>
157         public TabContent Content
158         {
159             get
160             {
161                 return content;
162             }
163         }
164
165         /// <summary>
166         /// Adds a tab with tab button and content view.
167         /// </summary>
168         /// <param name="tabButton">A tab button to be added.</param>
169         /// <param name="view">A content view to be added.</param>
170         /// <since_tizen> 9 </since_tizen>
171         public void AddTab(TabButton tabButton, View view)
172         {
173             if (TabBar != null)
174             {
175                 TabBar.AddTabButton(tabButton);
176             }
177
178             if (Content != null)
179             {
180                 Content.AddView(view);
181             }
182         }
183
184         /// <summary>
185         /// Removes a tab at the specified index of TabView.
186         /// The indices of tabs(tab buttons and views) in TabView are basically the order of adding to TabView by <see cref="TabView.AddTab"/>.
187         /// So the index of a tab(tab button and view) in TabView can be changed whenever <see cref="TabView.AddTab"/> or <see cref="TabView.RemoveTab"/> is called.
188         /// </summary>
189         /// <param name="index">The index of a tab(tab button and view) in TabView where the tab will be removed.</param>
190         /// <exception cref="ArgumentOutOfRangeException">Thrown when the index is less than 0, or greater than or equal to the number of tabs.</exception>
191         /// <since_tizen> 9 </since_tizen>
192         public void RemoveTab(int index)
193         {
194             var tabButton = TabBar.GetTabButton(index);
195             if (tabButton != null)
196             {
197                 TabBar.RemoveTabButton(tabButton);
198             }
199
200             var view = Content.GetView(index);
201             if (view != null)
202             {
203                 Content.RemoveView(view);
204             }
205         }
206
207         /// <inheritdoc/>
208         [EditorBrowsable(EditorBrowsableState.Never)]
209         public override void OnRelayout(Vector2 size, RelayoutContainer container)
210         {
211             base.OnRelayout(size, container);
212
213             CalculatePosition();
214         }
215
216         /// <inheritdoc/>
217         [EditorBrowsable(EditorBrowsableState.Never)]
218         protected override void Dispose(DisposeTypes type)
219         {
220             if (disposed)
221             {
222                 return;
223             }
224
225             if (type == DisposeTypes.Explicit)
226             {
227                 if (tabBar != null)
228                 {
229                     tabBar.TabButtonSelected -= tabButtonSelectedHandler;
230                     Utility.Dispose(tabBar);
231                 }
232
233                 if (content != null)
234                 {
235                     Utility.Dispose(content);
236                 }
237             }
238
239             base.Dispose(type);
240         }
241
242         private void CalculatePosition()
243         {
244             // If TabView size has not been set yet, then content size cannot be calculated.
245             if ((Size2D.Width == 0) && (Size2D.Height == 0))
246             {
247                 return;
248             }
249
250             if (tabBar != null)
251             {
252                 // FIXME: Now, WidthSpecification/HeightSpecification are updated internally.
253                 //        When this is resolved, comparing Specification with Size is removed.
254                 if ((tabBar.WidthSpecification == LayoutParamPolicies.MatchParent) || (tabBar.HeightSpecification == LayoutParamPolicies.MatchParent) ||
255                     (tabBar.WidthSpecification > Size.Width) || (tabBar.HeightSpecification > Size.Height))
256                 {
257                     int tabBarSizeW = tabBar.Size2D.Width;
258                     int tabBarSizeH = tabBar.Size2D.Height;
259
260                     if ((tabBar.WidthSpecification == LayoutParamPolicies.MatchParent) || (tabBar.WidthSpecification > Size.Width))
261                     {
262                         tabBarSizeW = Size2D.Width - Padding.Start - Padding.End - tabBar.Margin.Start - tabBar.Margin.End;
263                     }
264
265                     if ((tabBar.HeightSpecification == LayoutParamPolicies.MatchParent) || (tabBar.HeightSpecification > Size.Height))
266                     {
267                         tabBarSizeH = Size2D.Height - Padding.Top - Padding.Bottom - tabBar.Margin.Top - tabBar.Margin.Bottom;
268                     }
269
270                     tabBar.Size2D = new Size2D(tabBarSizeW, tabBarSizeH);
271                 }
272             }
273
274             if (content != null)
275             {
276                 int contentPosX = Padding.Start + content.Margin.Start;
277                 int contentPosY = Padding.Top + content.Margin.Top;
278
279                 content.Position = new Position(contentPosX, contentPosY);
280
281                 // FIXME: Now, WidthSpecification/HeightSpecification are updated internally.
282                 //        When this is resolved, comparing Specification with Size is removed.
283                 if ((content.WidthSpecification == LayoutParamPolicies.MatchParent) || (content.HeightSpecification == LayoutParamPolicies.MatchParent) ||
284                     (content.WidthSpecification > Size.Width) || (content.HeightSpecification > Size.Height))
285                 {
286                     int contentSizeW = content.Size2D.Width;
287                     int contentSizeH = content.Size2D.Height;
288
289                     if ((content.WidthSpecification == LayoutParamPolicies.MatchParent) || (content.WidthSpecification > Size.Width))
290                     {
291                         contentSizeW = Size2D.Width - Padding.Start - Padding.End - content.Margin.Start - content.Margin.End;
292                     }
293
294                     if ((content.HeightSpecification == LayoutParamPolicies.MatchParent) || (content.HeightSpecification > Size.Height))
295                     {
296                         contentSizeH = Size2D.Height - Padding.Top - Padding.Bottom - content.Margin.Top - content.Margin.Bottom - (tabBar?.Size2D.Height ?? 0);
297                     }
298
299                     content.Size2D = new Size2D(contentSizeW, contentSizeH);
300                 }
301             }
302
303             if (tabBar != null)
304             {
305                 int tabBarPosX = Padding.Start + tabBar.Margin.Start;
306                 int tabBarPosY = /*Padding.Top +*/ tabBar.Margin.Top + (content?.Size2D.Height ?? 0);
307
308                 tabBar.Position = new Position(tabBarPosX, tabBarPosY);
309             }
310         }
311     }
312 }