[NUI] Fix license year information for TabView classes
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / TabButton.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.ComponentModel;
18 using System.Diagnostics.CodeAnalysis;
19 using Tizen.NUI.BaseComponents;
20
21 namespace Tizen.NUI.Components
22 {
23     /// <summary>
24     /// TabButton is a class which is used for selecting one content in a TabView.
25     /// </summary>
26     [EditorBrowsable(EditorBrowsableState.Never)]
27     public class TabButton : SelectButton
28     {
29         private bool selectedAgain = false;
30
31         private TabButtonStyle tabButtonStyle = null;
32
33         private bool styleApplied = false;
34
35         private View topLine = null;
36         private View bottomLine = null; // Visible only if TabButton is selected or pressed.
37
38         /// <summary>
39         /// Creates a new instance of TabButton.
40         /// </summary>
41         [EditorBrowsable(EditorBrowsableState.Never)]
42         public TabButton()
43         {
44             Initialize();
45         }
46
47         /// <summary>
48         /// Creates a new instance of TabButton.
49         /// </summary>
50         /// <param name="style">Creates TabButton by special style defined in UX.</param>
51         [EditorBrowsable(EditorBrowsableState.Never)]
52         public TabButton(string style) : base(style)
53         {
54             Initialize();
55         }
56
57         /// <summary>
58         /// Creates a new instance of TabButton.
59         /// </summary>
60         /// <param name="tabButtonStyle">Creates TabButton by style customized by user.</param>
61         [EditorBrowsable(EditorBrowsableState.Never)]
62         public TabButton(TabButtonStyle tabButtonStyle) : base(tabButtonStyle)
63         {
64             Initialize();
65         }
66
67         /// <summary>
68         /// Applies style to TabButton.
69         /// </summary>
70         /// <param name="viewStyle">The style to apply.</param>
71         [EditorBrowsable(EditorBrowsableState.Never)]
72         public override void ApplyStyle(ViewStyle viewStyle)
73         {
74             styleApplied = false;
75
76             base.ApplyStyle(viewStyle);
77
78             tabButtonStyle = viewStyle as TabButtonStyle;
79
80             //Apply TopLine style.
81             if (tabButtonStyle?.TopLine != null)
82             {
83                 topLine?.ApplyStyle(tabButtonStyle.TopLine);
84             }
85
86             //Apply BottomLine style.
87             if (tabButtonStyle?.BottomLine != null)
88             {
89                 bottomLine?.ApplyStyle(tabButtonStyle.BottomLine);
90             }
91
92             styleApplied = true;
93
94             //Calculate children's sizes and positions based on padding sizes.
95             LayoutItems();
96         }
97
98         /// <inheritdoc/>
99         [EditorBrowsable(EditorBrowsableState.Never)]
100         public override bool OnKey(Key key)
101         {
102             if ((IsEnabled == false) || (key == null))
103             {
104                 return false;
105             }
106
107             if (key.State == Key.StateType.Up)
108             {
109                 if (key.KeyPressedName == "Return")
110                 {
111                     if (IsSelected == true)
112                     {
113                         selectedAgain = true;
114                     }
115                 }
116             }
117
118             bool ret = base.OnKey(key);
119
120             if (selectedAgain == true)
121             {
122                 IsSelected = true;
123                 selectedAgain = false;
124             }
125
126             return ret;
127         }
128
129         /// <summary>
130         /// Dispose TabButton and all children on it.
131         /// </summary>
132         /// <param name="type">Dispose type.</param>
133         [EditorBrowsable(EditorBrowsableState.Never)]
134         protected override void Dispose(DisposeTypes type)
135         {
136             if (disposed)
137             {
138                 return;
139             }
140
141             if (type == DisposeTypes.Explicit)
142             {
143                 if (topLine != null)
144                 {
145                     Utility.Dispose(topLine);
146                 }
147
148                 if (bottomLine != null)
149                 {
150                     Utility.Dispose(bottomLine);
151                 }
152             }
153
154             base.Dispose(type);
155         }
156
157         /// <summary>
158         /// Gets TabButton style.
159         /// </summary>
160         /// <returns>The default TabButton style.</returns>
161         [EditorBrowsable(EditorBrowsableState.Never)]
162         protected override ViewStyle CreateViewStyle()
163         {
164             return new TabButtonStyle();
165         }
166
167         /// <inheritdoc/>
168         [EditorBrowsable(EditorBrowsableState.Never)]
169         protected override bool HandleControlStateOnTouch(Touch touch)
170         {
171             if ((IsEnabled == false) || (touch == null))
172             {
173                 return false;
174             }
175
176             PointStateType state = touch.GetState(0);
177             switch (state)
178             {
179                 case PointStateType.Up:
180                     if (IsSelected == true)
181                     {
182                         selectedAgain = true;
183                     }
184                     break;
185                 default:
186                     break;
187             }
188
189             bool ret = base.HandleControlStateOnTouch(touch);
190
191             if (selectedAgain == true)
192             {
193                 IsSelected = true;
194                 selectedAgain = false;
195             }
196
197             return ret;
198         }
199
200         /// <inheritdoc/>
201         [SuppressMessage("Microsoft.Design",
202                          "CA1062: Validate arguments of public methods",
203                          MessageId = "controlStateChangedInfo",
204                          Justification = "OnControlStateChanged is called when controlState is changed so controlStateChangedInfo cannot be null.")]
205         [EditorBrowsable(EditorBrowsableState.Never)]
206         protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo)
207         {
208             if (controlStateChangedInfo.PreviousState.Contains(ControlState.Selected) != controlStateChangedInfo.CurrentState.Contains(ControlState.Selected))
209             {
210                 // TabButton does not invoke SelectedChanged if button or key is
211                 // unpressed while its state is selected.
212                 if (selectedAgain == true)
213                 {
214                     return;
215                 }
216
217                 base.OnControlStateChanged(controlStateChangedInfo);
218             }
219         }
220
221         /// <inheritdoc/>
222         [EditorBrowsable(EditorBrowsableState.Never)]
223         protected override void OnUpdate()
224         {
225             base.OnUpdate();
226             LayoutItems();
227         }
228
229         /// <inheritdoc/>
230         [EditorBrowsable(EditorBrowsableState.Never)]
231         protected override void LayoutItems()
232         {
233             if (styleApplied == false)
234             {
235                 return;
236             }
237
238             if ((Icon == null) && (TextLabel == null))
239             {
240                 return;
241             }
242
243             // Icon is added in Button.LayoutItems().
244             if ((Icon != null) && (Children.Contains(Icon) == false))
245             {
246                 Add(Icon);
247             }
248
249             // TextLabel is added in Button.LayoutItems().
250             if ((TextLabel != null) && (Children.Contains(TextLabel) == false))
251             {
252                 Add(TextLabel);
253             }
254
255             // FIXME: set Selector<Extents> to padding
256             var padding = new Extents(40, 40, 24, 24);
257             var iconPadding = IconPadding;
258             var textPadding = TextPadding;
259
260             // Calculate size of TextLabel.
261             if (TextLabel != null)
262             {
263                 // TODO: Other orientation cases are not implemented yet.
264                 if ((IconRelativeOrientation == IconOrientation.Left) || (IconRelativeOrientation == IconOrientation.Right))
265                 {
266                     var naturalWidthSum = (ushort)padding?.Start + (ushort)padding?.End + iconPadding.Start + iconPadding.End + (float)Icon?.SizeWidth + TextLabel.GetNaturalSize().Width;
267                     var naturalWidthDiff = SizeWidth - naturalWidthSum;
268
269                     if (naturalWidthDiff > 0)
270                     {
271                         TextLabel.SizeWidth = TextLabel.GetNaturalSize().Width;
272                     }
273                     else
274                     {
275                         TextLabel.SizeWidth = SizeWidth - (ushort)padding?.Start - (ushort)padding?.End - iconPadding.Start - iconPadding.End - textPadding.Start - textPadding.End - (float)Icon?.SizeWidth;
276                     }
277                 }
278             }
279
280             // Calculate positions of Icon and TextLabel.
281             switch (IconRelativeOrientation)
282             {
283                 // TODO: Other orientation cases are not implemented yet.
284                 case IconOrientation.Left:
285                     if (LayoutDirection == ViewLayoutDirectionType.LTR)
286                     {
287                         if (Icon != null)
288                         {
289                             float iconX = 0;
290                             float iconY = (ushort)padding?.Top + iconPadding.Top;
291
292                             if (string.IsNullOrEmpty(TextLabel?.Text))
293                             {
294                                 iconX = (SizeWidth - Icon.SizeWidth) / 2;
295                             }
296                             else
297                             {
298                                 var widthSum = (ushort)padding?.Start + (ushort)padding?.End + iconPadding.Start + iconPadding.End + textPadding.Start + textPadding.End + Icon.SizeWidth + (float)TextLabel?.SizeWidth;
299                                 var widthDiff = SizeWidth - widthSum;
300
301                                 if (widthDiff > 0)
302                                 {
303                                     iconX = (ushort)padding?.Start + iconPadding.Start + (widthDiff / 2);
304                                 }
305                                 else
306                                 {
307                                     iconX = (ushort)padding?.Start + iconPadding.Start;
308                                 }
309                             }
310
311                             Icon.Position = new Position(iconX, iconY);
312                         }
313
314                         if (TextLabel != null)
315                         {
316                             TextLabel.HorizontalAlignment = HorizontalAlignment.Begin;
317
318                             float textX = 0;
319                             float textY = 0;
320
321                             if (string.IsNullOrEmpty(Icon?.ResourceUrl))
322                             {
323                                 textX = (SizeWidth - TextLabel.SizeWidth) / 2;
324                                 textY = (ushort)padding?.Top + textPadding.Top;
325                             }
326                             else
327                             {
328                                 textX = (float)Icon?.PositionX + (float)Icon?.SizeWidth;
329                                 textY = (ushort)padding?.Top + textPadding.Top + (((float)Icon?.SizeHeight - TextLabel.SizeHeight) / 2);
330                             }
331
332                             TextLabel.Position = new Position(textX, textY);
333                         }
334                     }
335                     break;
336                 default:
337                     break;
338             }
339
340             padding?.Dispose();
341         }
342
343         private void Initialize()
344         {
345             Layout = new AbsoluteLayout();
346
347             topLine = new View(tabButtonStyle?.TopLine);
348             Add(topLine);
349
350             bottomLine = new View(tabButtonStyle?.BottomLine);
351             Add(bottomLine);
352         }
353     }
354 }