Fix Loading sizeproperty not work (#1797)
[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
6 namespace Tizen.NUI.Components
7 {
8     public partial class Button
9     {
10         private ImageView overlayImage;
11         private TextLabel buttonText;
12         private ImageView buttonIcon;
13
14         private EventHandler<StateChangedEventArgs> stateChangeHander;
15
16         private bool isSelected = false;
17         private bool isEnabled = true;
18         private bool isPressed = false;
19
20         private StringSelector textSelector = new StringSelector();
21         private StringSelector translatableTextSelector = new StringSelector();
22         private ColorSelector textColorSelector = new ColorSelector();
23         private FloatSelector pointSizeSelector = new FloatSelector();
24
25         private StringSelector iconURLSelector = new StringSelector();
26
27         /// <summary>
28         /// The last touch information triggering selected state change.
29         /// </summary>
30         [EditorBrowsable(EditorBrowsableState.Never)]
31         protected Touch SelectionChangedByTouch { get; set; }
32
33         /// <summary>
34         /// The ButtonExtension instance that is injected by ButtonStyle.
35         /// </summary>
36         [EditorBrowsable(EditorBrowsableState.Never)]
37         protected ButtonExtension Extension { get; set; }
38
39         /// <summary>
40         /// Creates Button's text part.
41         /// </summary>
42         /// <return>The created Button's text part.</return>
43         [EditorBrowsable(EditorBrowsableState.Never)]
44         protected virtual TextLabel CreateText()
45         {
46             return new TextLabel();
47         }
48
49         /// <summary>
50         /// Creates Button's icon part.
51         /// </summary>
52         /// <return>The created Button's icon part.</return>
53         [EditorBrowsable(EditorBrowsableState.Never)]
54         protected virtual ImageView CreateIcon()
55         {
56             return new ImageView();
57         }
58
59         /// <summary>
60         /// Creates Button's overlay image part.
61         /// </summary>
62         /// <return>The created Button's overlay image part.</return>
63         [EditorBrowsable(EditorBrowsableState.Never)]
64         protected virtual ImageView CreateOverlayImage()
65         {
66             return new ImageView();
67         }
68
69         /// <summary>
70         /// Called when the Button is Clicked by a user
71         /// </summary>
72         /// <param name="eventArgs">The click information.</param>
73         [EditorBrowsable(EditorBrowsableState.Never)]
74         protected virtual void OnClick(ClickEventArgs eventArgs)
75         {
76         }
77
78         /// <summary>
79         /// Get Button style.
80         /// </summary>
81         /// <returns>The default button style.</returns>
82         /// <since_tizen> 8 </since_tizen>
83         protected override ViewStyle CreateViewStyle()
84         {
85             return new ButtonStyle();
86         }
87
88         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
89         [EditorBrowsable(EditorBrowsableState.Never)]
90         protected override void OnUpdate()
91         {
92             base.OnUpdate();
93             UpdateUIContent();
94
95             Extension?.OnRelayout(this);
96         }
97
98         /// <summary>
99         /// Update Button State.
100         /// </summary>
101         /// <param name="touchInfo">The touch information in case the state has changed by touching.</param>
102         /// <since_tizen> 6 </since_tizen>
103         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
104         [EditorBrowsable(EditorBrowsableState.Never)]
105         protected void UpdateState()
106         {
107             ControlState sourceState = ControlState;
108             ControlState targetState;
109
110             if (isEnabled)
111             {
112                 if (isPressed)
113                 {
114                     // Pressed
115                     targetState = ControlState.Pressed;
116                 }
117                 else
118                 {
119                     // Normal
120                     targetState = ControlState.Normal;
121
122                     // Selected
123                     if (IsSelected) targetState += ControlState.Selected;
124
125                     // Focused, SelectedFocused
126                     if (IsFocused) targetState += ControlState.Focused;
127                 }
128             }
129             else
130             {
131                 // Disabled
132                 targetState = ControlState.Disabled;
133
134                 // DisabledSelected
135                 if (IsSelected) targetState += ControlState.Selected;
136                 // DisabledFocused
137                 else if (IsFocused) targetState += ControlState.Focused;
138             }
139
140             if (sourceState != targetState)
141             {
142                 ControlState = targetState;
143                 OnUpdate();
144
145                 StateChangedEventArgs e = new StateChangedEventArgs
146                 {
147                     PreviousState = ControlStatesExtension.FromControlStateClass(sourceState),
148                     CurrentState = ControlStatesExtension.FromControlStateClass(targetState)
149                 };
150                 stateChangeHander?.Invoke(this, e);
151
152                 Extension?.OnControlStateChanged(this, new ControlStateChangedEventArgs(sourceState, targetState));
153             }
154         }
155
156         /// <summary>
157         /// Measure text, it can be override.
158         /// </summary>
159         /// <since_tizen> 6 </since_tizen>
160         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
161         [EditorBrowsable(EditorBrowsableState.Never)]
162         protected virtual void MeasureText()
163         {
164             if (Style.IconRelativeOrientation == null || Icon == null || TextLabel == null)
165             {
166                 return;
167             }
168             TextLabel.WidthResizePolicy = ResizePolicyType.Fixed;
169             TextLabel.HeightResizePolicy = ResizePolicyType.Fixed;
170             int textPaddingStart = Style.TextPadding.Start;
171             int textPaddingEnd = Style.TextPadding.End;
172             int textPaddingTop = Style.TextPadding.Top;
173             int textPaddingBottom = Style.TextPadding.Bottom;
174
175             int iconPaddingStart = Style.IconPadding.Start;
176             int iconPaddingEnd = Style.IconPadding.End;
177             int iconPaddingTop = Style.IconPadding.Top;
178             int iconPaddingBottom = Style.IconPadding.Bottom;
179
180             if (IconRelativeOrientation == IconOrientation.Top || IconRelativeOrientation == IconOrientation.Bottom)
181             {
182                 TextLabel.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd;
183                 TextLabel.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom - iconPaddingTop - iconPaddingBottom - Icon.SizeHeight;
184             }
185             else
186             {
187                 TextLabel.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd - iconPaddingStart - iconPaddingEnd - Icon.SizeWidth;
188                 TextLabel.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom;
189             }
190         }
191
192         /// <summary>
193         /// Layout child, it can be override.
194         /// </summary>
195         /// <since_tizen> 6 </since_tizen>
196         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
197         [EditorBrowsable(EditorBrowsableState.Never)]
198         protected virtual void LayoutChild()
199         {
200             if (Style.IconRelativeOrientation == null || Icon == null || TextLabel == null)
201             {
202                 return;
203             }
204
205             var buttonIcon = Icon;
206             var buttonText = TextLabel;
207
208             int textPaddingStart = Style.TextPadding.Start;
209             int textPaddingEnd = Style.TextPadding.End;
210             int textPaddingTop = Style.TextPadding.Top;
211             int textPaddingBottom = Style.TextPadding.Bottom;
212
213             int iconPaddingStart = Style.IconPadding.Start;
214             int iconPaddingEnd = Style.IconPadding.End;
215             int iconPaddingTop = Style.IconPadding.Top;
216             int iconPaddingBottom = Style.IconPadding.Bottom;
217
218             switch (IconRelativeOrientation)
219             {
220                 case IconOrientation.Top:
221                     buttonIcon.PositionUsesPivotPoint = true;
222                     buttonIcon.ParentOrigin = NUI.ParentOrigin.TopCenter;
223                     buttonIcon.PivotPoint = NUI.PivotPoint.TopCenter;
224                     buttonIcon.Position2D = new Position2D(0, iconPaddingTop);
225
226                     buttonText.PositionUsesPivotPoint = true;
227                     buttonText.ParentOrigin = NUI.ParentOrigin.BottomCenter;
228                     buttonText.PivotPoint = NUI.PivotPoint.BottomCenter;
229                     buttonText.Position2D = new Position2D(0, -textPaddingBottom);
230                     break;
231                 case IconOrientation.Bottom:
232                     buttonIcon.PositionUsesPivotPoint = true;
233                     buttonIcon.ParentOrigin = NUI.ParentOrigin.BottomCenter;
234                     buttonIcon.PivotPoint = NUI.PivotPoint.BottomCenter;
235                     buttonIcon.Position2D = new Position2D(0, -iconPaddingBottom);
236
237                     buttonText.PositionUsesPivotPoint = true;
238                     buttonText.ParentOrigin = NUI.ParentOrigin.TopCenter;
239                     buttonText.PivotPoint = NUI.PivotPoint.TopCenter;
240                     buttonText.Position2D = new Position2D(0, textPaddingTop);
241                     break;
242                 case IconOrientation.Left:
243                     if (LayoutDirection == ViewLayoutDirectionType.LTR)
244                     {
245                         buttonIcon.PositionUsesPivotPoint = true;
246                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft;
247                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft;
248                         buttonIcon.Position2D = new Position2D(iconPaddingStart, 0);
249
250                         buttonText.PositionUsesPivotPoint = true;
251                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight;
252                         buttonText.PivotPoint = NUI.PivotPoint.CenterRight;
253                         buttonText.Position2D = new Position2D(-textPaddingEnd, 0);
254                     }
255                     else
256                     {
257                         buttonIcon.PositionUsesPivotPoint = true;
258                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight;
259                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight;
260                         buttonIcon.Position2D = new Position2D(-iconPaddingStart, 0);
261
262                         buttonText.PositionUsesPivotPoint = true;
263                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft;
264                         buttonText.PivotPoint = NUI.PivotPoint.CenterLeft;
265                         buttonText.Position2D = new Position2D(textPaddingEnd, 0);
266                     }
267
268                     break;
269                 case IconOrientation.Right:
270                     if (LayoutDirection == ViewLayoutDirectionType.RTL)
271                     {
272                         buttonIcon.PositionUsesPivotPoint = true;
273                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft;
274                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft;
275                         buttonIcon.Position2D = new Position2D(iconPaddingEnd, 0);
276
277                         buttonText.PositionUsesPivotPoint = true;
278                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight;
279                         buttonText.PivotPoint = NUI.PivotPoint.CenterRight;
280                         buttonText.Position2D = new Position2D(-textPaddingStart, 0);
281                     }
282                     else
283                     {
284                         buttonIcon.PositionUsesPivotPoint = true;
285                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight;
286                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight;
287                         buttonIcon.Position2D = new Position2D(-iconPaddingEnd, 0);
288
289                         buttonText.PositionUsesPivotPoint = true;
290                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft;
291                         buttonText.PivotPoint = NUI.PivotPoint.CenterLeft;
292                         buttonText.Position2D = new Position2D(textPaddingStart, 0);
293                     }
294                     break;
295                 default:
296                     break;
297             }
298             if (string.IsNullOrEmpty(buttonText.Text))
299             {
300                 buttonIcon.ParentOrigin = NUI.ParentOrigin.Center;
301                 buttonIcon.PivotPoint = NUI.PivotPoint.Center;
302             }
303         }
304
305         /// <summary>
306         /// Theme change callback when theme is changed, this callback will be trigger.
307         /// </summary>
308         /// <param name="sender">The sender</param>
309         /// <param name="e">The event data</param>
310         [EditorBrowsable(EditorBrowsableState.Never)]
311         protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
312         {
313             ButtonStyle buttonStyle = StyleManager.Instance.GetViewStyle(StyleName) as ButtonStyle;
314             if (buttonStyle != null)
315             {
316                 Style.CopyFrom(buttonStyle);
317                 UpdateUIContent();
318             }
319         }
320
321         /// <summary>
322         /// Dispose Button and all children on it.
323         /// </summary>
324         /// <param name="type">Dispose type.</param>
325         /// <since_tizen> 6 </since_tizen>
326         protected override void Dispose(DisposeTypes type)
327         {
328             if (disposed)
329             {
330                 return;
331             }
332
333             if (type == DisposeTypes.Explicit)
334             {
335                 Extension?.OnDispose(this);
336
337                 if (Icon != null)
338                 {
339                     Utility.Dispose(Icon);
340                 }
341                 if (TextLabel != null)
342                 {
343                     Utility.Dispose(TextLabel);
344                 }
345                 if (OverlayImage != null)
346                 {
347                     Utility.Dispose(OverlayImage);
348                 }
349             }
350
351             base.Dispose(type);
352         }
353
354         /// <inheritdoc/>
355         [EditorBrowsable(EditorBrowsableState.Never)]
356         protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo)
357         {
358             base.OnControlStateChanged(controlStateChangedInfo);
359
360             var stateEnabled = !controlStateChangedInfo.CurrentState.Contains(ControlState.Disabled);
361
362             if (isEnabled != stateEnabled)
363             {
364                 isEnabled = stateEnabled;
365             }
366
367             var statePressed = controlStateChangedInfo.CurrentState.Contains(ControlState.Pressed);
368
369             if (isPressed != statePressed)
370             {
371                 isPressed = statePressed;
372             }
373         }
374
375         /// <summary>
376         /// It is hijack by using protected, style copy problem when class inherited from Button.
377         /// </summary>
378         /// <since_tizen> 6 </since_tizen>
379         private void Initialize()
380         {
381             var style = (ButtonStyle)Style;
382             EnableControlStatePropagation = true;
383             UpdateState();
384             LayoutDirectionChanged += OnLayoutDirectionChanged;
385         }
386
387         private void UpdateUIContent()
388         {
389             MeasureText();
390             LayoutChild();
391
392             Sensitive = isEnabled;
393         }
394
395         private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
396         {
397             MeasureText();
398             LayoutChild();
399         }
400
401         private void OnClickInternal(ClickEventArgs eventArgs)
402         {
403             Command?.Execute(CommandParameter);
404             OnClick(eventArgs);
405             Extension?.OnClick(this, eventArgs);
406             ClickEvent?.Invoke(this, eventArgs);
407         }
408
409         private void OnIconRelayout(object sender, EventArgs e)
410         {
411             MeasureText();
412             LayoutChild();
413         }
414
415     }
416 }