[NUI] Format all files
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Button.Internal.cs
1 using System;
2 using System.ComponentModel;
3 using Tizen.NUI.BaseComponents;
4 using Tizen.NUI.Components.Extension;
5 using Tizen.NUI.Accessibility; // To use AccessibilityManager
6
7 namespace Tizen.NUI.Components
8 {
9     public partial class Button
10     {
11         private ImageView overlayImage;
12         private TextLabel buttonText;
13         private ImageView buttonIcon;
14
15         private EventHandler<StateChangedEventArgs> stateChangeHandler;
16
17         private bool isPressed = false;
18         private bool styleApplied = false;
19
20         /// <summary>
21         /// Get accessibility name.
22         /// </summary>
23         [EditorBrowsable(EditorBrowsableState.Never)]
24         protected override string AccessibilityGetName()
25         {
26             return Text;
27         }
28
29         /// <summary>
30         /// Prevents from showing child widgets in AT-SPI tree.
31         /// </summary>
32         [EditorBrowsable(EditorBrowsableState.Never)]
33         protected override bool AccessibilityShouldReportZeroChildren()
34         {
35             return true;
36         }
37
38         /// <summary>
39         /// The ButtonExtension instance that is injected by ButtonStyle.
40         /// </summary>
41         [EditorBrowsable(EditorBrowsableState.Never)]
42         protected ButtonExtension Extension { get; set; }
43
44         /// <summary>
45         /// Creates Button's text part.
46         /// </summary>
47         /// <return>The created Button's text part.</return>
48         [EditorBrowsable(EditorBrowsableState.Never)]
49         protected virtual TextLabel CreateText()
50         {
51             return new TextLabel
52             {
53                 PositionUsesPivotPoint = true,
54                 ParentOrigin = NUI.ParentOrigin.Center,
55                 PivotPoint = NUI.PivotPoint.Center,
56                 WidthResizePolicy = ResizePolicyType.FillToParent,
57                 HeightResizePolicy = ResizePolicyType.FillToParent,
58                 HorizontalAlignment = HorizontalAlignment.Center,
59                 VerticalAlignment = VerticalAlignment.Center,
60                 AccessibilityHighlightable = false
61             };
62         }
63
64         /// <summary>
65         /// Creates Button's icon part.
66         /// </summary>
67         /// <return>The created Button's icon part.</return>
68         [EditorBrowsable(EditorBrowsableState.Never)]
69         protected virtual ImageView CreateIcon()
70         {
71             return new ImageView
72             {
73                 PositionUsesPivotPoint = true,
74                 ParentOrigin = NUI.ParentOrigin.Center,
75                 PivotPoint = NUI.PivotPoint.Center,
76                 AccessibilityHighlightable = false
77             };
78         }
79
80         /// <summary>
81         /// Creates Button's overlay image part.
82         /// </summary>
83         /// <return>The created Button's overlay image part.</return>
84         [EditorBrowsable(EditorBrowsableState.Never)]
85         protected virtual ImageView CreateOverlayImage()
86         {
87             return new ImageView
88             {
89                 PositionUsesPivotPoint = true,
90                 ParentOrigin = NUI.ParentOrigin.Center,
91                 PivotPoint = NUI.PivotPoint.Center,
92                 WidthResizePolicy = ResizePolicyType.FillToParent,
93                 HeightResizePolicy = ResizePolicyType.FillToParent,
94                 AccessibilityHighlightable = false
95             };
96         }
97
98         /// <summary>
99         /// Called when the Button is Clicked by a user
100         /// </summary>
101         /// <param name="eventArgs">The click information.</param>
102         [EditorBrowsable(EditorBrowsableState.Never)]
103         protected virtual void OnClicked(ClickedEventArgs eventArgs)
104         {
105         }
106
107         /// <summary>
108         /// Get Button style.
109         /// </summary>
110         /// <returns>The default button style.</returns>
111         /// <since_tizen> 8 </since_tizen>
112         protected override ViewStyle CreateViewStyle()
113         {
114             return new ButtonStyle();
115         }
116
117         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
118         [EditorBrowsable(EditorBrowsableState.Never)]
119         protected override void OnUpdate()
120         {
121             base.OnUpdate();
122             UpdateUIContent();
123
124             Extension?.OnRelayout(this);
125         }
126
127         /// <inheritdoc/>
128         [EditorBrowsable(EditorBrowsableState.Never)]
129         protected override bool HandleControlStateOnTouch(Touch touch)
130         {
131             if (!IsEnabled || null == touch)
132             {
133                 return false;
134             }
135
136             PointStateType state = touch.GetState(0);
137
138             switch (state)
139             {
140                 case PointStateType.Down:
141                     isPressed = true;
142                     Extension?.SetTouchInfo(touch);
143                     UpdateState();
144                     return true;
145                 case PointStateType.Interrupted:
146                     isPressed = false;
147                     UpdateState();
148                     return true;
149                 case PointStateType.Up:
150                     {
151                         bool clicked = isPressed && IsEnabled;
152
153                         isPressed = false;
154
155                         if (IsSelectable)
156                         {
157                             Extension?.SetTouchInfo(touch);
158                             IsSelected = !IsSelected;
159                         }
160                         else
161                         {
162                             Extension?.SetTouchInfo(touch);
163                             UpdateState();
164                         }
165
166                         if (clicked)
167                         {
168                             ClickedEventArgs eventArgs = new ClickedEventArgs();
169                             OnClickedInternal(eventArgs);
170                         }
171
172                         return true;
173                     }
174                 default:
175                     break;
176             }
177             return base.HandleControlStateOnTouch(touch);
178         }
179
180         /// <summary>
181         /// Update Button State.
182         /// </summary>
183         /// <since_tizen> 6 </since_tizen>
184         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
185         [EditorBrowsable(EditorBrowsableState.Never)]
186         protected void UpdateState()
187         {
188             if (!styleApplied) return;
189
190             ControlState sourceState = ControlState;
191             ControlState targetState;
192
193             // Normal, Disabled
194             targetState = IsEnabled ? ControlState.Normal : ControlState.Disabled;
195
196             // Selected, DisabledSelected
197             if (IsSelected) targetState += ControlState.Selected;
198
199             // Pressed, PressedSelected
200             if (isPressed) targetState += ControlState.Pressed;
201
202             // Focused, FocusedPressed, FocusedPressedSelected, DisabledFocused, DisabledSelectedFocused
203             if (IsFocused) targetState += ControlState.Focused;
204
205             if (sourceState != targetState)
206             {
207                 ControlState = targetState;
208                 OnUpdate();
209
210                 StateChangedEventArgs e = new StateChangedEventArgs
211                 {
212                     PreviousState = ControlStatesExtension.FromControlStateClass(sourceState),
213                     CurrentState = ControlStatesExtension.FromControlStateClass(targetState)
214                 };
215                 stateChangeHandler?.Invoke(this, e);
216
217                 Extension?.OnControlStateChanged(this, new ControlStateChangedEventArgs(sourceState, targetState));
218             }
219         }
220
221         /// <summary>
222         /// Measure text, it can be override.
223         /// </summary>
224         /// <since_tizen> 6 </since_tizen>
225         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
226         [EditorBrowsable(EditorBrowsableState.Never)]
227         protected virtual void MeasureText()
228         {
229             if (buttonIcon == null || buttonText == null)
230             {
231                 return;
232             }
233             buttonText.WidthResizePolicy = ResizePolicyType.Fixed;
234             buttonText.HeightResizePolicy = ResizePolicyType.Fixed;
235
236             var textPadding = TextPadding;
237             int textPaddingStart = textPadding.Start;
238             int textPaddingEnd = textPadding.End;
239             int textPaddingTop = textPadding.Top;
240             int textPaddingBottom = textPadding.Bottom;
241
242             var iconPadding = IconPadding;
243             int iconPaddingStart = iconPadding.Start;
244             int iconPaddingEnd = iconPadding.End;
245             int iconPaddingTop = iconPadding.Top;
246             int iconPaddingBottom = iconPadding.Bottom;
247
248             if (IconRelativeOrientation == IconOrientation.Top || IconRelativeOrientation == IconOrientation.Bottom)
249             {
250                 buttonText.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd;
251                 buttonText.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom - iconPaddingTop - iconPaddingBottom - buttonIcon.SizeHeight;
252             }
253             else
254             {
255                 buttonText.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd - iconPaddingStart - iconPaddingEnd - buttonIcon.SizeWidth;
256                 buttonText.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom;
257             }
258         }
259
260         /// <summary>
261         /// Layout child, it can be override.
262         /// </summary>
263         /// <since_tizen> 6 </since_tizen>
264         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
265         [EditorBrowsable(EditorBrowsableState.Never)]
266         protected virtual void LayoutChild()
267         {
268             if (buttonIcon == null || buttonText == null)
269             {
270                 return;
271             }
272
273             var textPadding = TextPadding;
274             int textPaddingStart = textPadding.Start;
275             int textPaddingEnd = textPadding.End;
276             int textPaddingTop = textPadding.Top;
277             int textPaddingBottom = textPadding.Bottom;
278
279             var iconPadding = IconPadding;
280             int iconPaddingStart = iconPadding.Start;
281             int iconPaddingEnd = iconPadding.End;
282             int iconPaddingTop = iconPadding.Top;
283             int iconPaddingBottom = iconPadding.Bottom;
284
285             switch (IconRelativeOrientation)
286             {
287                 case IconOrientation.Top:
288                     buttonIcon.PositionUsesPivotPoint = true;
289                     buttonIcon.ParentOrigin = NUI.ParentOrigin.TopCenter;
290                     buttonIcon.PivotPoint = NUI.PivotPoint.TopCenter;
291                     buttonIcon.Position2D = new Position2D(0, iconPaddingTop);
292
293                     buttonText.PositionUsesPivotPoint = true;
294                     buttonText.ParentOrigin = NUI.ParentOrigin.BottomCenter;
295                     buttonText.PivotPoint = NUI.PivotPoint.BottomCenter;
296                     buttonText.Position2D = new Position2D(0, -textPaddingBottom);
297                     break;
298                 case IconOrientation.Bottom:
299                     buttonIcon.PositionUsesPivotPoint = true;
300                     buttonIcon.ParentOrigin = NUI.ParentOrigin.BottomCenter;
301                     buttonIcon.PivotPoint = NUI.PivotPoint.BottomCenter;
302                     buttonIcon.Position2D = new Position2D(0, -iconPaddingBottom);
303
304                     buttonText.PositionUsesPivotPoint = true;
305                     buttonText.ParentOrigin = NUI.ParentOrigin.TopCenter;
306                     buttonText.PivotPoint = NUI.PivotPoint.TopCenter;
307                     buttonText.Position2D = new Position2D(0, textPaddingTop);
308                     break;
309                 case IconOrientation.Left:
310                     if (LayoutDirection == ViewLayoutDirectionType.LTR)
311                     {
312                         buttonIcon.PositionUsesPivotPoint = true;
313                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft;
314                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft;
315                         buttonIcon.Position2D = new Position2D(iconPaddingStart, 0);
316
317                         buttonText.PositionUsesPivotPoint = true;
318                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight;
319                         buttonText.PivotPoint = NUI.PivotPoint.CenterRight;
320                         buttonText.Position2D = new Position2D(-textPaddingEnd, 0);
321                     }
322                     else
323                     {
324                         buttonIcon.PositionUsesPivotPoint = true;
325                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight;
326                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight;
327                         buttonIcon.Position2D = new Position2D(-iconPaddingStart, 0);
328
329                         buttonText.PositionUsesPivotPoint = true;
330                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft;
331                         buttonText.PivotPoint = NUI.PivotPoint.CenterLeft;
332                         buttonText.Position2D = new Position2D(textPaddingEnd, 0);
333                     }
334
335                     break;
336                 case IconOrientation.Right:
337                     if (LayoutDirection == ViewLayoutDirectionType.RTL)
338                     {
339                         buttonIcon.PositionUsesPivotPoint = true;
340                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft;
341                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft;
342                         buttonIcon.Position2D = new Position2D(iconPaddingEnd, 0);
343
344                         buttonText.PositionUsesPivotPoint = true;
345                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight;
346                         buttonText.PivotPoint = NUI.PivotPoint.CenterRight;
347                         buttonText.Position2D = new Position2D(-textPaddingStart, 0);
348                     }
349                     else
350                     {
351                         buttonIcon.PositionUsesPivotPoint = true;
352                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight;
353                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight;
354                         buttonIcon.Position2D = new Position2D(-iconPaddingEnd, 0);
355
356                         buttonText.PositionUsesPivotPoint = true;
357                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft;
358                         buttonText.PivotPoint = NUI.PivotPoint.CenterLeft;
359                         buttonText.Position2D = new Position2D(textPaddingStart, 0);
360                     }
361                     break;
362                 default:
363                     break;
364             }
365             if (string.IsNullOrEmpty(buttonText.Text))
366             {
367                 buttonIcon.ParentOrigin = NUI.ParentOrigin.Center;
368                 buttonIcon.PivotPoint = NUI.PivotPoint.Center;
369             }
370         }
371
372         /// <summary>
373         /// Dispose Button and all children on it.
374         /// </summary>
375         /// <param name="type">Dispose type.</param>
376         /// <since_tizen> 6 </since_tizen>
377         protected override void Dispose(DisposeTypes type)
378         {
379             if (disposed)
380             {
381                 return;
382             }
383
384             if (type == DisposeTypes.Explicit)
385             {
386                 Extension?.OnDispose(this);
387
388                 if (buttonIcon != null)
389                 {
390                     Utility.Dispose(buttonIcon);
391                 }
392                 if (buttonText != null)
393                 {
394                     Utility.Dispose(buttonText);
395                 }
396                 if (overlayImage != null)
397                 {
398                     Utility.Dispose(overlayImage);
399                 }
400             }
401
402             base.Dispose(type);
403         }
404
405         /// <summary>
406         /// Initilizes AT-SPI object.
407         /// </summary>
408         [EditorBrowsable(EditorBrowsableState.Never)]
409         public override void OnInitialize()
410         {
411             base.OnInitialize();
412             SetAccessibilityConstructor(Role.PushButton);
413         }
414
415         /// <inheritdoc/>
416         [EditorBrowsable(EditorBrowsableState.Never)]
417         protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo)
418         {
419             base.OnControlStateChanged(controlStateChangedInfo);
420
421             var stateEnabled = !controlStateChangedInfo.CurrentState.Contains(ControlState.Disabled);
422
423             if (IsEnabled != stateEnabled)
424             {
425                 IsEnabled = stateEnabled;
426             }
427
428             var statePressed = controlStateChangedInfo.CurrentState.Contains(ControlState.Pressed);
429
430             if (isPressed != statePressed)
431             {
432                 isPressed = statePressed;
433             }
434         }
435
436         /// <summary>
437         /// It is hijack by using protected, style copy problem when class inherited from Button.
438         /// </summary>
439         /// <since_tizen> 6 </since_tizen>
440         private void Initialize()
441         {
442             AccessibilityHighlightable = true;
443             EnableControlStatePropagation = true;
444             UpdateState();
445             LayoutDirectionChanged += OnLayoutDirectionChanged;
446
447             AccessibilityManager.Instance.SetAccessibilityAttribute(this, AccessibilityManager.AccessibilityAttribute.Trait, "Button");
448
449 #if PROFILE_MOBILE
450                 Feedback = true;
451 #endif
452         }
453
454         private void UpdateUIContent()
455         {
456             MeasureText();
457             LayoutChild();
458
459             Sensitive = IsEnabled;
460         }
461
462         private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
463         {
464             MeasureText();
465             LayoutChild();
466         }
467
468         private void OnClickedInternal(ClickedEventArgs eventArgs)
469         {
470             Command?.Execute(CommandParameter);
471             OnClicked(eventArgs);
472             Extension?.OnClicked(this, eventArgs);
473
474             ClickEventArgs nestedEventArgs = new ClickEventArgs();
475             ClickEvent?.Invoke(this, nestedEventArgs);
476             Clicked?.Invoke(this, eventArgs);
477         }
478
479         private void OnIconRelayout(object sender, EventArgs e)
480         {
481             MeasureText();
482             LayoutChild();
483         }
484
485         internal override bool OnAccessibilityActivated()
486         {
487             using (var key = new Key())
488             {
489                 key.State = Key.StateType.Down;
490                 key.KeyPressedName = "Return";
491
492                 // Touch Down
493                 OnKey(key);
494
495                 // Touch Up
496                 key.State = Key.StateType.Up;
497                 OnKey(key);
498             }
499
500             return true;
501         }
502
503     }
504 }