[NUI] Change View.ControlState setter to protected. (#1727)
[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             ControlStates sourceState = ControlState;
108             ControlStates targetState;
109
110             if (isEnabled)
111             {
112                 if (isPressed)
113                 {
114                     // Pressed
115                     targetState = ControlStates.Pressed;
116                 }
117                 else
118                 {
119                     // Normal
120                     targetState = ControlStates.Normal;
121
122                     // Selected
123                     targetState |= (IsSelected ? ControlStates.Selected : 0);
124
125                     // Focused, SelectedFocused
126                     targetState |= (IsFocused ? ControlStates.Focused : 0);
127                 }
128             }
129             else
130             {
131                 // Disabled
132                 targetState = ControlStates.Disabled;
133
134                 // DisabledSelected, DisabledFocused
135                 targetState |= (IsSelected ? ControlStates.Selected : (IsFocused ? ControlStates.Focused : 0));
136             }
137
138             if (sourceState != targetState)
139             {
140                 ControlState = targetState;
141
142                 OnUpdate();
143
144                 StateChangedEventArgs e = new StateChangedEventArgs
145                 {
146                     PreviousState = sourceState,
147                     CurrentState = targetState
148                 };
149                 stateChangeHander?.Invoke(this, e);
150
151                 Extension?.OnControlStateChanged(this, new ControlStateChangedEventArgs(sourceState, targetState));
152             }
153         }
154
155         /// <summary>
156         /// Measure text, it can be override.
157         /// </summary>
158         /// <since_tizen> 6 </since_tizen>
159         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
160         [EditorBrowsable(EditorBrowsableState.Never)]
161         protected virtual void MeasureText()
162         {
163             if (Style.IconRelativeOrientation == null || Icon == null || TextLabel == null)
164             {
165                 return;
166             }
167             TextLabel.WidthResizePolicy = ResizePolicyType.Fixed;
168             TextLabel.HeightResizePolicy = ResizePolicyType.Fixed;
169             int textPaddingStart = Style.TextPadding.Start;
170             int textPaddingEnd = Style.TextPadding.End;
171             int textPaddingTop = Style.TextPadding.Top;
172             int textPaddingBottom = Style.TextPadding.Bottom;
173
174             int iconPaddingStart = Style.IconPadding.Start;
175             int iconPaddingEnd = Style.IconPadding.End;
176             int iconPaddingTop = Style.IconPadding.Top;
177             int iconPaddingBottom = Style.IconPadding.Bottom;
178
179             if (IconRelativeOrientation == IconOrientation.Top || IconRelativeOrientation == IconOrientation.Bottom)
180             {
181                 TextLabel.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd;
182                 TextLabel.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom - iconPaddingTop - iconPaddingBottom - Icon.SizeHeight;
183             }
184             else
185             {
186                 TextLabel.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd - iconPaddingStart - iconPaddingEnd - Icon.SizeWidth;
187                 TextLabel.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom;
188             }
189         }
190
191         /// <summary>
192         /// Layout child, it can be override.
193         /// </summary>
194         /// <since_tizen> 6 </since_tizen>
195         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
196         [EditorBrowsable(EditorBrowsableState.Never)]
197         protected virtual void LayoutChild()
198         {
199             if (Style.IconRelativeOrientation == null || Icon == null || TextLabel == null)
200             {
201                 return;
202             }
203
204             var buttonIcon = Icon;
205             var buttonText = TextLabel;
206
207             int textPaddingStart = Style.TextPadding.Start;
208             int textPaddingEnd = Style.TextPadding.End;
209             int textPaddingTop = Style.TextPadding.Top;
210             int textPaddingBottom = Style.TextPadding.Bottom;
211
212             int iconPaddingStart = Style.IconPadding.Start;
213             int iconPaddingEnd = Style.IconPadding.End;
214             int iconPaddingTop = Style.IconPadding.Top;
215             int iconPaddingBottom = Style.IconPadding.Bottom;
216
217             switch (IconRelativeOrientation)
218             {
219                 case IconOrientation.Top:
220                     buttonIcon.PositionUsesPivotPoint = true;
221                     buttonIcon.ParentOrigin = NUI.ParentOrigin.TopCenter;
222                     buttonIcon.PivotPoint = NUI.PivotPoint.TopCenter;
223                     buttonIcon.Position2D = new Position2D(0, iconPaddingTop);
224
225                     buttonText.PositionUsesPivotPoint = true;
226                     buttonText.ParentOrigin = NUI.ParentOrigin.BottomCenter;
227                     buttonText.PivotPoint = NUI.PivotPoint.BottomCenter;
228                     buttonText.Position2D = new Position2D(0, -textPaddingBottom);
229                     break;
230                 case IconOrientation.Bottom:
231                     buttonIcon.PositionUsesPivotPoint = true;
232                     buttonIcon.ParentOrigin = NUI.ParentOrigin.BottomCenter;
233                     buttonIcon.PivotPoint = NUI.PivotPoint.BottomCenter;
234                     buttonIcon.Position2D = new Position2D(0, -iconPaddingBottom);
235
236                     buttonText.PositionUsesPivotPoint = true;
237                     buttonText.ParentOrigin = NUI.ParentOrigin.TopCenter;
238                     buttonText.PivotPoint = NUI.PivotPoint.TopCenter;
239                     buttonText.Position2D = new Position2D(0, textPaddingTop);
240                     break;
241                 case IconOrientation.Left:
242                     if (LayoutDirection == ViewLayoutDirectionType.LTR)
243                     {
244                         buttonIcon.PositionUsesPivotPoint = true;
245                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft;
246                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft;
247                         buttonIcon.Position2D = new Position2D(iconPaddingStart, 0);
248
249                         buttonText.PositionUsesPivotPoint = true;
250                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight;
251                         buttonText.PivotPoint = NUI.PivotPoint.CenterRight;
252                         buttonText.Position2D = new Position2D(-textPaddingEnd, 0);
253                     }
254                     else
255                     {
256                         buttonIcon.PositionUsesPivotPoint = true;
257                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight;
258                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight;
259                         buttonIcon.Position2D = new Position2D(-iconPaddingStart, 0);
260
261                         buttonText.PositionUsesPivotPoint = true;
262                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft;
263                         buttonText.PivotPoint = NUI.PivotPoint.CenterLeft;
264                         buttonText.Position2D = new Position2D(textPaddingEnd, 0);
265                     }
266
267                     break;
268                 case IconOrientation.Right:
269                     if (LayoutDirection == ViewLayoutDirectionType.RTL)
270                     {
271                         buttonIcon.PositionUsesPivotPoint = true;
272                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft;
273                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft;
274                         buttonIcon.Position2D = new Position2D(iconPaddingEnd, 0);
275
276                         buttonText.PositionUsesPivotPoint = true;
277                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight;
278                         buttonText.PivotPoint = NUI.PivotPoint.CenterRight;
279                         buttonText.Position2D = new Position2D(-textPaddingStart, 0);
280                     }
281                     else
282                     {
283                         buttonIcon.PositionUsesPivotPoint = true;
284                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight;
285                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight;
286                         buttonIcon.Position2D = new Position2D(-iconPaddingEnd, 0);
287
288                         buttonText.PositionUsesPivotPoint = true;
289                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft;
290                         buttonText.PivotPoint = NUI.PivotPoint.CenterLeft;
291                         buttonText.Position2D = new Position2D(textPaddingStart, 0);
292                     }
293                     break;
294                 default:
295                     break;
296             }
297             if (string.IsNullOrEmpty(buttonText.Text))
298             {
299                 buttonIcon.ParentOrigin = NUI.ParentOrigin.Center;
300                 buttonIcon.PivotPoint = NUI.PivotPoint.Center;
301             }
302         }
303
304         /// <summary>
305         /// Theme change callback when theme is changed, this callback will be trigger.
306         /// </summary>
307         /// <param name="sender">The sender</param>
308         /// <param name="e">The event data</param>
309         /// <since_tizen> 8 </since_tizen>
310         protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
311         {
312             ButtonStyle buttonStyle = StyleManager.Instance.GetViewStyle(StyleName) as ButtonStyle;
313             if (buttonStyle != null)
314             {
315                 Style.CopyFrom(buttonStyle);
316                 UpdateUIContent();
317             }
318         }
319
320         /// <summary>
321         /// Dispose Button and all children on it.
322         /// </summary>
323         /// <param name="type">Dispose type.</param>
324         /// <since_tizen> 6 </since_tizen>
325         protected override void Dispose(DisposeTypes type)
326         {
327             if (disposed)
328             {
329                 return;
330             }
331
332             if (type == DisposeTypes.Explicit)
333             {
334                 Extension?.OnDispose(this);
335
336                 if (Icon != null)
337                 {
338                     Utility.Dispose(Icon);
339                 }
340                 if (TextLabel != null)
341                 {
342                     Utility.Dispose(TextLabel);
343                 }
344                 if (OverlayImage != null)
345                 {
346                     Utility.Dispose(OverlayImage);
347                 }
348             }
349
350             base.Dispose(type);
351         }
352
353         /// <inheritdoc/>
354         [EditorBrowsable(EditorBrowsableState.Never)]
355         protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo)
356         {
357             base.OnControlStateChanged(controlStateChangedInfo);
358
359             var stateEnabled = !((controlStateChangedInfo.CurrentState & ControlStates.Disabled) == ControlStates.Disabled);
360
361             if (isEnabled != stateEnabled)
362             {
363                 isEnabled = stateEnabled;
364             }
365
366             var stateSelected = (controlStateChangedInfo.CurrentState & ControlStates.Selected) == ControlStates.Selected;
367
368             if (isSelected != stateSelected)
369             {
370                 isSelected = stateSelected;
371             }
372
373             var statePressed = (controlStateChangedInfo.CurrentState & ControlStates.Pressed) == ControlStates.Pressed;
374
375             if (isPressed != statePressed)
376             {
377                 isPressed = statePressed;
378             }
379         }
380
381         /// <summary>
382         /// It is hijack by using protected, style copy problem when class inherited from Button.
383         /// </summary>
384         /// <since_tizen> 6 </since_tizen>
385         private void Initialize()
386         {
387             var style = (ButtonStyle)Style;
388             EnableControlStatePropagation = true;
389             UpdateState();
390             LayoutDirectionChanged += OnLayoutDirectionChanged;
391         }
392
393         private void UpdateUIContent()
394         {
395             MeasureText();
396             LayoutChild();
397
398             Sensitive = isEnabled;
399         }
400
401         private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
402         {
403             MeasureText();
404             LayoutChild();
405         }
406
407         private void OnClickInternal(ClickEventArgs eventArgs)
408         {
409             Command?.Execute(CommandParameter);
410             OnClick(eventArgs);
411             Extension?.OnClick(this, eventArgs);
412             ClickEvent?.Invoke(this, eventArgs);
413         }
414
415         private void OnIconRelayout(object sender, EventArgs e)
416         {
417             MeasureText();
418             LayoutChild();
419         }
420
421     }
422 }