[NUI] Fix Svace issue on TabButton by null check
[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;
18 using System.ComponentModel;
19 using System.Diagnostics.CodeAnalysis;
20 using Tizen.NUI.BaseComponents;
21
22 namespace Tizen.NUI.Components
23 {
24     /// <summary>
25     /// TabButton is a class which is used for selecting one content in a TabView.
26     /// </summary>
27     /// <since_tizen> 9 </since_tizen>
28     public class TabButton : SelectButton
29     {
30         private bool selectedAgain = false;
31
32         private TabButtonStyle tabButtonStyle = null;
33
34         private bool styleApplied = false;
35
36         /// <summary>
37         /// Creates a new instance of TabButton.
38         /// </summary>
39         /// <since_tizen> 9 </since_tizen>
40         public TabButton()
41         {
42             Initialize();
43         }
44
45         /// <summary>
46         /// Creates a new instance of TabButton.
47         /// </summary>
48         /// <param name="style">Creates TabButton by special style defined in UX.</param>
49         [EditorBrowsable(EditorBrowsableState.Never)]
50         public TabButton(string style) : base(style)
51         {
52             Initialize();
53         }
54
55         /// <summary>
56         /// Creates a new instance of TabButton.
57         /// </summary>
58         /// <param name="tabButtonStyle">Creates TabButton by style customized by user.</param>
59         [EditorBrowsable(EditorBrowsableState.Never)]
60         public TabButton(TabButtonStyle tabButtonStyle) : base(tabButtonStyle)
61         {
62             Initialize();
63         }
64
65         /// <inheritdoc/>
66         [EditorBrowsable(EditorBrowsableState.Never)]
67         public override void OnInitialize()
68         {
69             base.OnInitialize();
70
71             AccessibilityRole = Role.PageTab;
72         }
73
74         /// <inheritdoc/>
75         [EditorBrowsable(EditorBrowsableState.Never)]
76         public override void ApplyStyle(ViewStyle viewStyle)
77         {
78             styleApplied = false;
79
80             base.ApplyStyle(viewStyle);
81
82             tabButtonStyle = viewStyle as TabButtonStyle;
83
84             styleApplied = true;
85
86             //Calculate children's sizes and positions based on padding sizes.
87             LayoutItems();
88         }
89
90         /// <inheritdoc/>
91         [EditorBrowsable(EditorBrowsableState.Never)]
92         public override bool OnKey(Key key)
93         {
94             if ((IsEnabled == false) || (key == null))
95             {
96                 return false;
97             }
98
99             if (key.State == Key.StateType.Up)
100             {
101                 if (key.KeyPressedName == "Return")
102                 {
103                     if (IsSelected == true)
104                     {
105                         selectedAgain = true;
106                     }
107                 }
108             }
109
110             bool ret = base.OnKey(key);
111
112             if (selectedAgain == true)
113             {
114                 IsSelected = true;
115                 selectedAgain = false;
116             }
117
118             return ret;
119         }
120
121         /// <inheritdoc/>
122         [EditorBrowsable(EditorBrowsableState.Never)]
123         public override void OnRelayout(Vector2 size, RelayoutContainer container)
124         {
125             base.OnRelayout(size, container);
126             UpdateSizeAndSpacing();
127         }
128
129         /// <inheritdoc/>
130         [EditorBrowsable(EditorBrowsableState.Never)]
131         protected override void Dispose(DisposeTypes type)
132         {
133             if (disposed)
134             {
135                 return;
136             }
137
138             if (type == DisposeTypes.Explicit)
139             {
140                 // Dispose children explicitly
141             }
142
143             base.Dispose(type);
144         }
145
146         /// <summary>
147         /// Gets TabButton style.
148         /// </summary>
149         /// <returns>The default TabButton style.</returns>
150         [EditorBrowsable(EditorBrowsableState.Never)]
151         protected override ViewStyle CreateViewStyle()
152         {
153             return new TabButtonStyle();
154         }
155
156         /// <inheritdoc/>
157         [EditorBrowsable(EditorBrowsableState.Never)]
158         protected override bool HandleControlStateOnTouch(Touch touch)
159         {
160             if ((IsEnabled == false) || (touch == null))
161             {
162                 return false;
163             }
164
165             PointStateType state = touch.GetState(0);
166             switch (state)
167             {
168                 case PointStateType.Up:
169                     if (IsSelected == true)
170                     {
171                         selectedAgain = true;
172                     }
173                     break;
174                 default:
175                     break;
176             }
177
178             bool ret = base.HandleControlStateOnTouch(touch);
179
180             if (selectedAgain == true)
181             {
182                 IsSelected = true;
183                 selectedAgain = false;
184             }
185
186             return ret;
187         }
188
189         /// <inheritdoc/>
190         [SuppressMessage("Microsoft.Design",
191                          "CA1062: Validate arguments of public methods",
192                          MessageId = "controlStateChangedInfo",
193                          Justification = "OnControlStateChanged is called when controlState is changed so controlStateChangedInfo cannot be null.")]
194         [EditorBrowsable(EditorBrowsableState.Never)]
195         protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo)
196         {
197             if (controlStateChangedInfo.PreviousState.Contains(ControlState.Selected) != controlStateChangedInfo.CurrentState.Contains(ControlState.Selected))
198             {
199                 // TabButton does not invoke SelectedChanged if button or key is
200                 // unpressed while its state is selected.
201                 if (selectedAgain == true)
202                 {
203                     return;
204                 }
205
206                 base.OnControlStateChanged(controlStateChangedInfo);
207             }
208         }
209
210         /// <inheritdoc/>
211         [EditorBrowsable(EditorBrowsableState.Never)]
212         protected override void LayoutItems()
213         {
214             UpdateSizeAndSpacing();
215         }
216
217         private void Initialize()
218         {
219             Layout = new LinearLayout()
220             {
221                 LinearOrientation = LinearLayout.Orientation.Vertical,
222                 HorizontalAlignment = HorizontalAlignment.Center,
223                 VerticalAlignment = VerticalAlignment.Center,
224             };
225
226             WidthSpecification = LayoutParamPolicies.MatchParent;
227
228             AccessibilityHighlightable = true;
229         }
230
231         private void UpdateSizeAndSpacing()
232         {
233             if (styleApplied == false)
234             {
235                 return;
236             }
237
238             bool isEmptyIcon = false;
239             bool isEmptyText = false;
240
241             if (String.IsNullOrEmpty(Icon.ResourceUrl))
242             {
243                 isEmptyIcon = true;
244             }
245
246             if (String.IsNullOrEmpty(TextLabel.Text))
247             {
248                 isEmptyText = true;
249             }
250
251             if (isEmptyIcon)
252             {
253                 if (Children.Contains(Icon))
254                 {
255                     Remove(Icon);
256                 }
257             }
258             else if (Children.Contains(Icon) == false)
259             {
260                 Add(Icon);
261             }
262
263             if (isEmptyText)
264             {
265                 if (Children.Contains(TextLabel))
266                 {
267                     Remove(TextLabel);
268                 }
269             }
270             else if (Children.Contains(TextLabel) == false)
271             {
272                 Add(TextLabel);
273             }
274
275             if (tabButtonStyle != null)
276             {
277                 // Icon and Text
278                 if (!isEmptyIcon && !isEmptyText)
279                 {
280                     if (tabButtonStyle.Size != null)
281                     {
282                         WidthSpecification = (int)tabButtonStyle.Size.Width;
283                         HeightSpecification = (int)tabButtonStyle.Size.Height;
284                     }
285
286                     Padding = tabButtonStyle.Padding;
287                 }
288                 // Icon only
289                 else if (!isEmptyIcon && isEmptyText)
290                 {
291                     if (tabButtonStyle.SizeWithIconOnly != null)
292                     {
293                         WidthSpecification = (int)tabButtonStyle.SizeWithIconOnly.Width;
294                         HeightSpecification = (int)tabButtonStyle.SizeWithIconOnly.Height;
295                     }
296
297                     Padding = tabButtonStyle.PaddingWithIconOnly;
298
299                     if (tabButtonStyle.IconSizeWithIconOnly != null)
300                     {
301                         Icon.WidthSpecification = (int)tabButtonStyle.IconSizeWithIconOnly.Width;
302                         Icon.HeightSpecification = (int)tabButtonStyle.IconSizeWithIconOnly.Height;
303                     }
304                 }
305                 // Text only
306                 else if (isEmptyIcon && !isEmptyText)
307                 {
308                     if (tabButtonStyle.SizeWithTextOnly != null)
309                     {
310                         WidthSpecification = (int)tabButtonStyle.SizeWithTextOnly.Width;
311                         HeightSpecification = (int)tabButtonStyle.SizeWithTextOnly.Height;
312                     }
313
314                     Padding = tabButtonStyle.PaddingWithTextOnly;
315
316                     if ((tabButtonStyle.Icon != null) && (tabButtonStyle.Icon.Size != null))
317                     {
318                         Icon.WidthSpecification = (int)tabButtonStyle.Icon.Size.Width;
319                         Icon.HeightSpecification = (int)tabButtonStyle.Icon.Size.Height;
320                     }
321                 }
322                 // Nothing
323                 else
324                 {
325                     if (tabButtonStyle.Size != null)
326                     {
327                         WidthSpecification = (int)tabButtonStyle.Size.Width;
328                         HeightSpecification = (int)tabButtonStyle.Size.Height;
329                     }
330
331                     Padding = tabButtonStyle.Padding;
332                 }
333             }
334         }
335     }
336 }