[NUI] Fixed TCT failed issues (#1176)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Button.cs
1 /*
2  * Copyright(c) 2019 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 Tizen.NUI.BaseComponents;
20 using Tizen.NUI.Binding;
21
22 namespace Tizen.NUI.Components
23 {
24     /// <summary>
25     /// Button is one kind of common component, a button clearly describes what action will occur when the user selects it.
26     /// Button may contain text or an icon.
27     /// </summary>
28     /// <since_tizen> 6 </since_tizen>
29     public class Button : Control
30     {
31         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
32         [EditorBrowsable(EditorBrowsableState.Never)]
33         public static readonly BindableProperty IconRelativeOrientationProperty = BindableProperty.Create("IconRelativeOrientation", typeof(IconOrientation?), typeof(Tizen.NUI.Components.Button), null, propertyChanged: (bindable, oldValue, newValue) =>
34         {
35             var instance = (Tizen.NUI.Components.Button)bindable;
36             if (newValue != null)
37             {
38                 instance.privateIconRelativeOrientation = (IconOrientation?)newValue;
39             }
40         },
41         defaultValueCreator: (bindable) =>
42         {
43             var instance = (Tizen.NUI.Components.Button)bindable;
44             return instance.privateIconRelativeOrientation;
45         });
46         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
47         [EditorBrowsable(EditorBrowsableState.Never)]
48         public static readonly BindableProperty IsEnabledProperty = BindableProperty.Create("IsEnabled", typeof(bool), typeof(Tizen.NUI.Components.Button), true, propertyChanged: (bindable, oldValue, newValue) =>
49         {
50             var instance = (Tizen.NUI.Components.Button)bindable;
51             if (newValue != null)
52             {
53                 instance.privateIsEnabled = (bool)newValue;
54             }
55         },
56         defaultValueCreator: (bindable) =>
57         {
58             var instance = (Tizen.NUI.Components.Button)bindable;
59             return instance.privateIsEnabled;
60         });
61         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
62         [EditorBrowsable(EditorBrowsableState.Never)]
63         public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create("IsSelected", typeof(bool), typeof(Tizen.NUI.Components.Button), true, propertyChanged: (bindable, oldValue, newValue) =>
64         {
65             var instance = (Tizen.NUI.Components.Button)bindable;
66             if (newValue != null)
67             {
68                 instance.privateIsSelected = (bool)newValue;
69             }
70         },
71         defaultValueCreator: (bindable) =>
72         {
73             var instance = (Tizen.NUI.Components.Button)bindable;
74             return instance.privateIsSelected;
75         });
76         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
77         [EditorBrowsable(EditorBrowsableState.Never)]
78         public static readonly BindableProperty IsSelectableProperty = BindableProperty.Create("IsSelectable", typeof(bool), typeof(Tizen.NUI.Components.Button), true, propertyChanged: (bindable, oldValue, newValue) =>
79         {
80             var instance = (Tizen.NUI.Components.Button)bindable;
81             if (newValue != null)
82             {
83                 instance.privateIsSelectable = (bool)newValue;
84             }
85         },
86         defaultValueCreator: (bindable) =>
87         {
88             var instance = (Tizen.NUI.Components.Button)bindable;
89             return instance.privateIsSelectable;
90         });
91
92         private ImageView overlayImage;
93
94         private TextLabel buttonText;
95         private ImageView buttonIcon;
96
97         private EventHandler<StateChangedEventArgs> stateChangeHander;
98
99         private bool isSelected = false;
100         private bool isEnabled = true;
101         private bool isPressed = false;
102
103         /// <summary>
104         /// Creates a new instance of a Button.
105         /// </summary>
106         /// <since_tizen> 6 </since_tizen>
107         public Button() : base()
108         {
109             Initialize();
110         }
111
112         /// <summary>
113         /// Creates a new instance of a Button with style.
114         /// </summary>
115         /// <param name="style">Create Button by special style defined in UX.</param>
116         /// <since_tizen> 6 </since_tizen>
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         public Button(string style) : base(style)
120         {
121             Initialize();
122         }
123
124         /// <summary>
125         /// Creates a new instance of a Button with attributes.
126         /// </summary>
127         /// <param name="controlStyle">Create Button by attributes customized by user.</param>
128         /// <since_tizen> 6 </since_tizen>
129         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
130         [EditorBrowsable(EditorBrowsableState.Never)]
131         public Button(ButtonStyle controlStyle) : base(controlStyle)
132         {
133             Initialize();
134         }
135
136         /// <summary>
137         /// An event for the button clicked signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
138         /// </summary>
139         /// <since_tizen> 6 </since_tizen>
140         public event EventHandler<ClickEventArgs> ClickEvent;
141         /// <summary>
142         /// An event for the button state changed signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
143         /// </summary>
144         /// <since_tizen> 6 </since_tizen>
145         public event EventHandler<StateChangedEventArgs> StateChangedEvent
146         {
147             add
148             {
149                 stateChangeHander += value;
150             }
151             remove
152             {
153                 stateChangeHander -= value;
154             }
155         }
156         /// <summary>
157         /// Icon orientation.
158         /// </summary>
159         /// <since_tizen> 6 </since_tizen>
160         public enum IconOrientation
161         {
162             /// <summary>
163             /// Top.
164             /// </summary>
165             /// <since_tizen> 6 </since_tizen>
166             Top,
167             /// <summary>
168             /// Bottom.
169             /// </summary>
170             /// <since_tizen> 6 </since_tizen>
171             Bottom,
172             /// <summary>
173             /// Left.
174             /// </summary>
175             /// <since_tizen> 6 </since_tizen>
176             Left,
177             /// <summary>
178             /// Right.
179             /// </summary>
180             /// <since_tizen> 6 </since_tizen>
181             Right,
182         }
183
184         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
185         [EditorBrowsable(EditorBrowsableState.Never)]
186         public new ButtonStyle Style => ViewStyle as ButtonStyle;
187
188         /// <summary>
189         /// The text of Button.
190         /// </summary>
191         /// <since_tizen> 6 </since_tizen>
192         public string Text
193         {
194             get
195             {
196                 return Style?.Text?.Text?.GetValue(ControlState);
197             }
198             set
199             {
200                 if (null != Style?.Text)
201                 {
202                     Style.Text.Text = value;
203                 }
204             }
205         }
206
207         /// <summary>
208         /// Flag to decide Button can be selected or not.
209         /// </summary>
210         /// <since_tizen> 6 </since_tizen>
211         public bool IsSelectable
212         {
213             get
214             {
215                 return (bool)GetValue(IsSelectableProperty);
216             }
217             set
218             {
219                 SetValue(IsSelectableProperty, value);
220             }
221         }
222
223         private bool privateIsSelectable
224         {
225             get
226             {
227                 return Style?.IsSelectable ?? false;
228             }
229             set
230             {
231                 Style.IsSelectable = value;
232             }
233         }
234
235         /// <summary>
236         /// Translate text string in Button.
237         /// </summary>
238         /// <since_tizen> 6 </since_tizen>
239         public string TranslatableText
240         {
241             get
242             {
243                 return Style?.Text?.TranslatableText?.All;
244             }
245             set
246             {
247                 if (null != Style?.Text)
248                 {
249                     Style.Text.TranslatableText = value;
250                 }
251             }
252         }
253
254         /// <summary>
255         /// Text point size in Button.
256         /// </summary>
257         /// <since_tizen> 6 </since_tizen>
258         public float PointSize
259         {
260             get
261             {
262                 return Style?.Text?.PointSize?.All ?? 0;
263             }
264             set
265             {
266                 if (null != Style?.Text)
267                 {
268                     Style.Text.PointSize = value;
269                 }
270             }
271         }
272
273         /// <summary>
274         /// Text font family in Button.
275         /// </summary>
276         /// <since_tizen> 6 </since_tizen>
277         public string FontFamily
278         {
279             get
280             {
281                 return Style?.Text?.FontFamily.All;
282             }
283             set
284             {
285                 if (null != Style?.Text)
286                 {
287                     Style.Text.FontFamily = value;
288                 }
289             }
290         }
291         /// <summary>
292         /// Text color in Button.
293         /// </summary>
294         /// <since_tizen> 6 </since_tizen>
295         public Color TextColor
296         {
297             get
298             {
299                 return Style?.Text?.TextColor?.All;
300             }
301             set
302             {
303                 if (null != Style?.Text)
304                 {
305                     Style.Text.TextColor = value;
306                 }
307             }
308         }
309         /// <summary>
310         /// Text horizontal alignment in Button.
311         /// </summary>
312         /// <since_tizen> 6 </since_tizen>
313         public HorizontalAlignment TextAlignment
314         {
315             get
316             {
317                 return Style?.Text?.HorizontalAlignment ?? HorizontalAlignment.Center;
318             }
319             set
320             {
321                 if (null != Style?.Text)
322                 {
323                     Style.Text.HorizontalAlignment = value;
324                 }
325             }
326         }
327         /// <summary>
328         /// Icon image's resource url in Button.
329         /// </summary>
330         /// <since_tizen> 6 </since_tizen>
331         public string IconURL
332         {
333             get
334             {
335                 return Style?.Icon?.ResourceUrl?.All;
336             }
337             set
338             {
339                 if (null != Style?.Icon)
340                 {
341                     Style.Icon.ResourceUrl = value;
342                 }
343             }
344         }
345
346         private StringSelector textSelector = new StringSelector();
347         /// <summary>
348         /// Text string selector in Button.
349         /// </summary>
350         /// <since_tizen> 6 </since_tizen>
351         public StringSelector TextSelector
352         {
353             get
354             {
355                 return textSelector;
356             }
357             set
358             {
359                 textSelector.Clone(value);
360             }
361         }
362
363         private StringSelector translatableTextSelector = new StringSelector();
364         /// <summary>
365         /// Translateable text string selector in Button.
366         /// </summary>
367         /// <since_tizen> 6 </since_tizen>
368         public StringSelector TranslatableTextSelector
369         {
370             get
371             {
372                 return translatableTextSelector;
373             }
374             set
375             {
376                 translatableTextSelector.Clone(value);
377             }
378         }
379
380         private ColorSelector textColorSelector = new ColorSelector();
381         /// <summary>
382         /// Text color selector in Button.
383         /// </summary>
384         /// <since_tizen> 6 </since_tizen>
385         public ColorSelector TextColorSelector
386         {
387             get
388             {
389                 return textColorSelector;
390             }
391             set
392             {
393                 textColorSelector.Clone(value);
394             }
395         }
396
397         private FloatSelector pointSizeSelector = new FloatSelector();
398         /// <summary>
399         /// Text font size selector in Button.
400         /// </summary>
401         /// <since_tizen> 6 </since_tizen>
402         public FloatSelector PointSizeSelector
403         {
404             get
405             {
406                 return pointSizeSelector;
407             }
408             set
409             {
410                 pointSizeSelector.Clone(value);
411             }
412         }
413
414         private StringSelector iconURLSelector = new StringSelector();
415         /// <summary>
416         /// Icon image's resource url selector in Button.
417         /// </summary>
418         /// <since_tizen> 6 </since_tizen>
419         public StringSelector IconURLSelector
420         {
421             get
422             {
423                 return iconURLSelector;
424             }
425             set
426             {
427                 iconURLSelector.Clone(value);
428             }
429         }
430
431         /// <summary>
432         /// Flag to decide selected state in Button.
433         /// </summary>
434         /// <since_tizen> 6 </since_tizen>
435         public bool IsSelected
436         {
437             get
438             {
439                 return (bool)GetValue(IsSelectedProperty);
440             }
441             set
442             {
443                 SetValue(IsSelectedProperty, value);
444             }
445         }
446         private bool privateIsSelected
447         {
448             get
449             {
450                 return isSelected;
451             }
452             set
453             {
454                 isSelected = value;
455                 UpdateState();
456             }
457         }
458         /// <summary>
459         /// Flag to decide enable or disable in Button.
460         /// </summary>
461         /// <since_tizen> 6 </since_tizen>
462         public bool IsEnabled
463         {
464             get
465             {
466                 return (bool)GetValue(IsEnabledProperty);
467             }
468             set
469             {
470                 SetValue(IsEnabledProperty, value);
471             }
472         }
473         private bool privateIsEnabled
474         {
475             get
476             {
477                 return isEnabled;
478             }
479             set
480             {
481                 isEnabled = value;
482                 UpdateState();
483             }
484         }
485
486         /// <summary>
487         /// Icon relative orientation in Button, work only when show icon and text.
488         /// </summary>
489         /// <since_tizen> 6 </since_tizen>
490         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
491         [EditorBrowsable(EditorBrowsableState.Never)]
492         public IconOrientation? IconRelativeOrientation
493         {
494             get
495             {
496                 return (IconOrientation?)GetValue(IconRelativeOrientationProperty);
497             }
498             set
499             {
500                 SetValue(IconRelativeOrientationProperty, value);
501             }
502         }
503         private IconOrientation? privateIconRelativeOrientation
504         {
505             get
506             {
507                 return Style?.IconRelativeOrientation;
508             }
509             set
510             {
511                 if(Style != null && Style.IconRelativeOrientation != value)
512                 {
513                     Style.IconRelativeOrientation = value;
514                     UpdateUIContent();
515                 }
516             }
517         }
518
519         /// <summary>
520         /// Icon padding in Button, work only when show icon and text.
521         /// </summary>
522         /// <since_tizen> 6 </since_tizen>
523         public Extents IconPadding
524         {
525             get
526             {
527                 return Style?.Icon?.Padding;
528             }
529             set
530             {
531                 if (null != value && null != Style?.Icon?.Padding)
532                 {
533                     Style.Icon.Padding.CopyFrom(value);
534                 }
535             }
536         }
537
538         /// <summary>
539         /// Text padding in Button, work only when show icon and text.
540         /// </summary>
541         /// <since_tizen> 6 </since_tizen>
542         public Extents TextPadding
543         {
544             get
545             {
546                 return Style?.Text?.Padding;
547             }
548             set
549             {
550                 if (null != value && null != Style?.Text?.Padding)
551                 {
552                     Style.Text.Padding.CopyFrom(value);
553                 }
554             }
555         }
556
557         /// <summary>
558         /// Dispose Button and all children on it.
559         /// </summary>
560         /// <param name="type">Dispose type.</param>
561         /// <since_tizen> 6 </since_tizen>
562         protected override void Dispose(DisposeTypes type)
563         {
564             if (disposed)
565             {
566                 return;
567             }
568
569             if (type == DisposeTypes.Explicit)
570             {
571                 if (buttonIcon != null)
572                 {
573                     buttonIcon.Relayout -= OnIconRelayout;
574                     Utility.Dispose(buttonIcon);
575                 }
576                 if (buttonText != null)
577                 {
578                     Utility.Dispose(buttonText);
579                 }
580                 if (overlayImage != null)
581                 {
582                     Utility.Dispose(overlayImage);
583                 }
584             }
585
586             base.Dispose(type);
587         }
588         /// <summary>
589         /// Called after a key event is received by the view that has had its focus set.
590         /// </summary>
591         /// <param name="key">The key event.</param>
592         /// <returns>True if the key event should be consumed.</returns>
593         /// <since_tizen> 6 </since_tizen>
594         public override bool OnKey(Key key)
595         {
596             if (key.State == Key.StateType.Down)
597             {
598                 if (key.KeyPressedName == "Return")
599                 {
600                     isPressed = true;
601                     UpdateState();
602                     if(isEnabled)
603                     {
604                         ClickEventArgs eventArgs = new ClickEventArgs();
605                         OnClick(eventArgs);
606                     }
607                 }
608             }
609             else if (key.State == Key.StateType.Up)
610             {
611                 if (key.KeyPressedName == "Return")
612                 {
613                     isPressed = false;
614                     if (Style.IsSelectable != null && Style.IsSelectable == true)
615                     {
616                         isSelected = !isSelected;
617                     }
618                     UpdateState();
619                 }
620             }
621             return base.OnKey(key);
622         }
623
624         /// <summary>
625         /// Called when the control gain key input focus. Should be overridden by derived classes if they need to customize what happens when the focus is gained.
626         /// </summary>
627         /// <since_tizen> 6 </since_tizen>
628         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
629         [EditorBrowsable(EditorBrowsableState.Never)]
630         public override void OnFocusGained()
631         {
632             base.OnFocusGained();
633             UpdateState();
634         }
635         /// <summary>
636         /// Called when the control loses key input focus. Should be overridden by derived classes if they need to customize what happens when the focus is lost.
637         /// </summary>
638         /// <since_tizen> 6 </since_tizen>
639         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
640         [EditorBrowsable(EditorBrowsableState.Never)]
641         public override void OnFocusLost()
642         {
643             base.OnFocusLost();
644             UpdateState();
645         }
646
647         /// <summary>
648         /// Tap gesture event callback.
649         /// </summary>
650         /// <param name="source">Source which recieved touch event.</param>
651         /// <param name="e">Tap gesture event argument.</param>
652         /// <since_tizen> 6 </since_tizen>
653         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
654         [EditorBrowsable(EditorBrowsableState.Never)]
655         protected override void OnTapGestureDetected(object source, TapGestureDetector.DetectedEventArgs e)
656         {
657             if (isEnabled)
658             {
659                 ClickEventArgs eventArgs = new ClickEventArgs();
660                 OnClick(eventArgs);
661                 base.OnTapGestureDetected(source, e);
662             }
663         }
664         /// <summary>
665         /// Called after a touch event is received by the owning view.<br />
666         /// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).<br />
667         /// </summary>
668         /// <param name="touch">The touch event.</param>
669         /// <returns>True if the event should be consumed.</returns>
670         /// <since_tizen> 6 </since_tizen>
671         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
672         [EditorBrowsable(EditorBrowsableState.Never)]
673         public override bool OnTouch(Touch touch)
674         {
675             PointStateType state = touch.GetState(0);
676
677             switch(state)
678             {
679                 case PointStateType.Down:
680                     isPressed = true;
681                     UpdateState();
682                     return true;
683                 case PointStateType.Interrupted:
684                     isPressed = false;
685                     UpdateState();
686                     return true;
687                 case PointStateType.Up:
688                     isPressed = false;
689                     if (Style.IsSelectable != null && Style.IsSelectable == true)
690                     {
691                         isSelected = !isSelected;
692                     }
693                     UpdateState();
694                     return true;
695                 default:
696                     break;
697             }
698             return base.OnTouch(touch);
699         }
700
701         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
702         [EditorBrowsable(EditorBrowsableState.Never)]
703         public override void ApplyStyle(ViewStyle viewStyle)
704         {
705             base.ApplyStyle(viewStyle);
706
707             ButtonStyle buttonStyle = viewStyle as ButtonStyle;
708
709             if (null != buttonStyle)
710             {
711                 if (null == overlayImage)
712                 {
713                     overlayImage = new ImageView()
714                     {
715                         WidthResizePolicy = ResizePolicyType.FillToParent,
716                         HeightResizePolicy = ResizePolicyType.FillToParent
717                     };
718                     this.Add(overlayImage);
719                 }
720
721                 if (null == buttonText)
722                 {
723                     buttonText = new TextLabel();
724                     this.Add(buttonText);
725                 }
726
727                 if (null == buttonIcon)
728                 {
729                     buttonIcon = new ImageView();
730                     buttonIcon.Relayout += OnIconRelayout;
731                     this.Add(buttonIcon);
732                 }
733
734                 overlayImage.ApplyStyle(buttonStyle.Overlay);
735                 buttonText.ApplyStyle(buttonStyle.Text);
736                 buttonIcon.ApplyStyle(buttonStyle.Icon);
737             }
738         }
739
740         /// <summary>
741         /// Get Button attribues.
742         /// </summary>
743         /// <since_tizen> 6 </since_tizen>
744         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
745         [EditorBrowsable(EditorBrowsableState.Never)]
746         protected override ViewStyle GetViewStyle()
747         {
748             return new ButtonStyle();
749         }
750
751         /// <summary>
752         /// Update Button State.
753         /// </summary>
754         /// <since_tizen> 6 </since_tizen>
755         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
756         [EditorBrowsable(EditorBrowsableState.Never)]
757         protected void UpdateState()
758         {
759             ControlStates sourceState = ControlState;
760             ControlStates targetState;
761
762             if(isEnabled)
763             {
764                 targetState = isPressed ? ControlStates.Pressed : (IsFocused ? (IsSelected ? ControlStates.SelectedFocused : ControlStates.Focused) : (IsSelected ? ControlStates.Selected : ControlStates.Normal));
765             }
766             else
767             {
768                 targetState = IsSelected ? ControlStates.DisabledSelected : (IsFocused ? ControlStates.DisabledFocused : ControlStates.Disabled);
769             }
770
771             if(sourceState != targetState)
772             {
773                 ControlState = targetState;
774
775                 OnUpdate();
776
777                 StateChangedEventArgs e = new StateChangedEventArgs
778                 {
779                     PreviousState = sourceState,
780                     CurrentState = targetState
781                 };
782                 stateChangeHander?.Invoke(this, e);
783             }
784         }
785
786         /// <summary>
787         /// It is hijack by using protected, attributes copy problem when class inherited from Button.
788         /// </summary>
789         /// <since_tizen> 6 </since_tizen>
790         private void Initialize()
791         {
792             UpdateState();
793             LayoutDirectionChanged += OnLayoutDirectionChanged;
794         }
795
796         /// <summary>
797         /// Measure text, it can be override.
798         /// </summary>
799         /// <since_tizen> 6 </since_tizen>
800         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
801         [EditorBrowsable(EditorBrowsableState.Never)]
802         protected virtual void MeasureText()
803         {
804             if (Style.IconRelativeOrientation == null || buttonIcon == null || buttonText == null)
805             {
806                 return;
807             }
808             buttonText.WidthResizePolicy = ResizePolicyType.Fixed;
809             buttonText.HeightResizePolicy = ResizePolicyType.Fixed;
810             int textPaddingStart = Style.Text.Padding.Start;
811             int textPaddingEnd = Style.Text.Padding.End;
812             int textPaddingTop = Style.Text.Padding.Top;
813             int textPaddingBottom = Style.Text.Padding.Bottom;
814
815             int iconPaddingStart = Style.Icon.Padding.Start;
816             int iconPaddingEnd = Style.Icon.Padding.End;
817             int iconPaddingTop = Style.Icon.Padding.Top;
818             int iconPaddingBottom = Style.Icon.Padding.Bottom;
819
820             if (IconRelativeOrientation == IconOrientation.Top || IconRelativeOrientation == IconOrientation.Bottom)
821             {
822                 buttonText.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd;
823                 buttonText.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom - iconPaddingTop - iconPaddingBottom - buttonIcon.SizeHeight;
824             }
825             else
826             {
827                 buttonText.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd - iconPaddingStart - iconPaddingEnd - buttonIcon.SizeWidth;
828                 buttonText.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom;
829             }
830         }
831         /// <summary>
832         /// Layout child, it can be override.
833         /// </summary>
834         /// <since_tizen> 6 </since_tizen>
835         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
836         [EditorBrowsable(EditorBrowsableState.Never)]
837         protected virtual void LayoutChild()
838         {
839             if (Style.IconRelativeOrientation == null || buttonIcon == null || buttonText == null)
840             {
841                 return;
842             }
843
844             int textPaddingStart = Style.Text.Padding.Start;
845             int textPaddingEnd = Style.Text.Padding.End;
846             int textPaddingTop = Style.Text.Padding.Top;
847             int textPaddingBottom = Style.Text.Padding.Bottom;
848
849             int iconPaddingStart = Style.Icon.Padding.Start;
850             int iconPaddingEnd = Style.Icon.Padding.End;
851             int iconPaddingTop = Style.Icon.Padding.Top;
852             int iconPaddingBottom = Style.Icon.Padding.Bottom;
853
854             switch (IconRelativeOrientation)
855             {
856                 case IconOrientation.Top:
857                     buttonIcon.PositionUsesPivotPoint = true;
858                     buttonIcon.ParentOrigin = NUI.ParentOrigin.TopCenter;
859                     buttonIcon.PivotPoint = NUI.PivotPoint.TopCenter;
860                     buttonIcon.Position2D = new Position2D(0, iconPaddingTop);
861
862                     buttonText.PositionUsesPivotPoint = true;
863                     buttonText.ParentOrigin = NUI.ParentOrigin.BottomCenter;
864                     buttonText.PivotPoint = NUI.PivotPoint.BottomCenter;
865                     buttonText.Position2D = new Position2D(0, -textPaddingBottom);
866                     break;
867                 case IconOrientation.Bottom:
868                     buttonIcon.PositionUsesPivotPoint = true;
869                     buttonIcon.ParentOrigin = NUI.ParentOrigin.BottomCenter;
870                     buttonIcon.PivotPoint = NUI.PivotPoint.BottomCenter;
871                     buttonIcon.Position2D = new Position2D(0, -iconPaddingBottom);
872
873                     buttonText.PositionUsesPivotPoint = true;
874                     buttonText.ParentOrigin = NUI.ParentOrigin.TopCenter;
875                     buttonText.PivotPoint = NUI.PivotPoint.TopCenter;
876                     buttonText.Position2D = new Position2D(0, textPaddingTop);
877                     break;
878                 case IconOrientation.Left:
879                     if (LayoutDirection == ViewLayoutDirectionType.LTR)
880                     {
881                         buttonIcon.PositionUsesPivotPoint = true;
882                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft;
883                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft;
884                         buttonIcon.Position2D = new Position2D(iconPaddingStart, 0);
885
886                         buttonText.PositionUsesPivotPoint = true;
887                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight;
888                         buttonText.PivotPoint = NUI.PivotPoint.CenterRight;
889                         buttonText.Position2D = new Position2D(-textPaddingEnd, 0);
890                     }
891                     else
892                     {
893                         buttonIcon.PositionUsesPivotPoint = true;
894                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight;
895                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight;
896                         buttonIcon.Position2D = new Position2D(-iconPaddingStart, 0);
897
898                         buttonText.PositionUsesPivotPoint = true;
899                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft;
900                         buttonText.PivotPoint = NUI.PivotPoint.CenterLeft;
901                         buttonText.Position2D = new Position2D(textPaddingEnd, 0);
902                     }
903
904                     break;
905                 case IconOrientation.Right:
906                     if (LayoutDirection == ViewLayoutDirectionType.RTL)
907                     {
908                         buttonIcon.PositionUsesPivotPoint = true;
909                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft;
910                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft;
911                         buttonIcon.Position2D = new Position2D(iconPaddingEnd, 0);
912
913                         buttonText.PositionUsesPivotPoint = true;
914                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight;
915                         buttonText.PivotPoint = NUI.PivotPoint.CenterRight;
916                         buttonText.Position2D = new Position2D(-textPaddingStart, 0);
917                     }
918                     else
919                     {
920                         buttonIcon.PositionUsesPivotPoint = true;
921                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight;
922                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight;
923                         buttonIcon.Position2D = new Position2D(-iconPaddingEnd, 0);
924
925                         buttonText.PositionUsesPivotPoint = true;
926                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft;
927                         buttonText.PivotPoint = NUI.PivotPoint.CenterLeft;
928                         buttonText.Position2D = new Position2D(textPaddingStart, 0);
929                     }
930                     break;
931                 default:
932                     break;
933             }
934         }
935         /// <summary>
936         /// Theme change callback when theme is changed, this callback will be trigger.
937         /// </summary>
938         /// <since_tizen> 6 </since_tizen>
939         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
940         [EditorBrowsable(EditorBrowsableState.Never)]
941         protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
942         {
943             ButtonStyle tempAttributes = StyleManager.Instance.GetAttributes(style) as ButtonStyle;
944             if (tempAttributes != null)
945             {
946                 Style.CopyFrom(tempAttributes);
947                 UpdateUIContent();
948             }
949         }
950
951         private void UpdateUIContent()
952         {
953             MeasureText();
954             LayoutChild();
955
956             Sensitive = isEnabled;
957         }
958
959         private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
960         {
961             MeasureText();
962             LayoutChild();
963         }
964
965         private void OnClick(ClickEventArgs eventArgs)
966         {
967             ClickEvent?.Invoke(this, eventArgs);
968         }
969
970         private void OnIconRelayout(object sender, EventArgs e)
971         {
972             MeasureText();
973             LayoutChild();
974         }
975
976         /// <summary>
977         /// ClickEventArgs is a class to record button click event arguments which will sent to user.
978         /// </summary>
979         /// <since_tizen> 6 </since_tizen>
980         public class ClickEventArgs : EventArgs
981         {
982         }
983         /// <summary>
984         /// StateChangeEventArgs is a class to record button state change event arguments which will sent to user.
985         /// </summary>
986         /// <since_tizen> 6 </since_tizen>
987         public class StateChangedEventArgs : EventArgs
988         {
989             /// <summary> previous state of Button </summary>
990             /// <since_tizen> 6 </since_tizen>
991             public ControlStates PreviousState;
992             /// <summary> current state of Button </summary>
993             /// <since_tizen> 6 </since_tizen>
994             public ControlStates CurrentState;
995         }
996
997     }
998 }