[NUI]Refactor Components (#1152)
[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                 Style.Text.Text = value;
201             }
202         }
203
204         /// <summary>
205         /// Flag to decide Button can be selected or not.
206         /// </summary>
207         /// <since_tizen> 6 </since_tizen>
208         public bool IsSelectable
209         {
210             get
211             {
212                 return (bool)GetValue(IsSelectableProperty);
213             }
214             set
215             {
216                 SetValue(IsSelectableProperty, value);
217             }
218         }
219
220         private bool privateIsSelectable
221         {
222             get
223             {
224                 return Style?.IsSelectable ?? false;
225             }
226             set
227             {
228                 Style.IsSelectable = value;
229             }
230         }
231
232         /// <summary>
233         /// Translate text string in Button.
234         /// </summary>
235         /// <since_tizen> 6 </since_tizen>
236         public string TranslatableText
237         {
238             get
239             {
240                 return Style?.Text?.TranslatableText?.All;
241             }
242             set
243             {
244                 if (value != null)
245                 {
246                     if (Style.Text.TranslatableText == null)
247                     {
248                         Style.Text.TranslatableText = new Selector<string>();
249                     }
250                     Style.Text.TranslatableText.All = value;
251                 }
252             }
253         }
254
255         /// <summary>
256         /// Text point size in Button.
257         /// </summary>
258         /// <since_tizen> 6 </since_tizen>
259         public float PointSize
260         {
261             get
262             {
263                 return Style?.Text?.PointSize?.All ?? 0;
264             }
265             set
266             {
267                 if (Style.Text.PointSize == null)
268                 {
269                     Style.Text.PointSize = new Selector<float?>();
270                 }
271                 Style.Text.PointSize.All = value;
272             }
273         }
274
275         /// <summary>
276         /// Text font family in Button.
277         /// </summary>
278         /// <since_tizen> 6 </since_tizen>
279         public string FontFamily
280         {
281             get
282             {
283                 return Style?.Text?.FontFamily.All;
284             }
285             set
286             {
287                 Style.Text.FontFamily = value;
288             }
289         }
290         /// <summary>
291         /// Text color in Button.
292         /// </summary>
293         /// <since_tizen> 6 </since_tizen>
294         public Color TextColor
295         {
296             get
297             {
298                 return Style?.Text?.TextColor?.All;
299             }
300             set
301             {
302                 if (Style.Text.TextColor == null)
303                 {
304                     Style.Text.TextColor = new Selector<Color>();
305                 }
306                 Style.Text.TextColor.All = value;
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                 Style.Text.HorizontalAlignment = value;
322             }
323         }
324         /// <summary>
325         /// Icon image's resource url in Button.
326         /// </summary>
327         /// <since_tizen> 6 </since_tizen>
328         public string IconURL
329         {
330             get
331             {
332                 return Style?.Icon?.ResourceUrl?.All;
333             }
334             set
335             {
336                 if (value != null)
337                 {
338                     if (Style.Icon.ResourceUrl == null)
339                     {
340                         Style.Icon.ResourceUrl = new Selector<string>();
341                     }
342                     Style.Icon.ResourceUrl.All = value;
343                 }
344             }
345         }
346         /// <summary>
347         /// Text string selector in Button.
348         /// </summary>
349         /// <since_tizen> 6 </since_tizen>
350         public StringSelector TextSelector
351         {
352             get
353             {
354                 return (StringSelector)Style?.Text?.Text;
355             }
356             set
357             {
358                 if (value != null)
359                 {
360                     Style.Text.Text = value.Clone() as StringSelector;
361                 }
362             }
363         }
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 (StringSelector)Style?.Text?.TranslatableText;
373             }
374             set
375             {
376                 if (value != null)
377                 {
378                     Style.Text.TranslatableText = value.Clone() as StringSelector;
379                 }
380             }
381         }
382
383         /// <summary>
384         /// Text color selector in Button.
385         /// </summary>
386         /// <since_tizen> 6 </since_tizen>
387         public ColorSelector TextColorSelector
388         {
389             get
390             {
391                 return (ColorSelector)Style?.Text?.TextColor;
392             }
393             set
394             {
395                 if(value != null)
396                 {
397                     Style.Text.TextColor = value.Clone() as ColorSelector;
398                 }
399             }
400         }
401
402         /// <summary>
403         /// Text font size selector in Button.
404         /// </summary>
405         /// <since_tizen> 6 </since_tizen>
406         public FloatSelector PointSizeSelector
407         {
408             get
409             {
410                 return (FloatSelector)Style?.Text?.PointSize;
411             }
412             set
413             {
414                 if (value != null)
415                 {
416                     Style.Text.PointSize = value.Clone() as FloatSelector;
417                 }
418             }
419         }
420
421         /// <summary>
422         /// Icon image's resource url selector in Button.
423         /// </summary>
424         /// <since_tizen> 6 </since_tizen>
425         public StringSelector IconURLSelector
426         {
427             get
428             {
429                 return (StringSelector)Style?.Icon?.ResourceUrl;
430             }
431             set
432             {
433                 if (value != null)
434                 {
435                     Style.Icon.ResourceUrl = value.Clone() as StringSelector;
436                 }
437             }
438         }
439
440         /// <summary>
441         /// Flag to decide selected state in Button.
442         /// </summary>
443         /// <since_tizen> 6 </since_tizen>
444         public bool IsSelected
445         {
446             get
447             {
448                 return (bool)GetValue(IsSelectedProperty);
449             }
450             set
451             {
452                 SetValue(IsSelectedProperty, value);
453             }
454         }
455         private bool privateIsSelected
456         {
457             get
458             {
459                 return isSelected;
460             }
461             set
462             {
463                 isSelected = value;
464                 UpdateState();
465             }
466         }
467         /// <summary>
468         /// Flag to decide enable or disable in Button.
469         /// </summary>
470         /// <since_tizen> 6 </since_tizen>
471         public bool IsEnabled
472         {
473             get
474             {
475                 return (bool)GetValue(IsEnabledProperty);
476             }
477             set
478             {
479                 SetValue(IsEnabledProperty, value);
480             }
481         }
482         private bool privateIsEnabled
483         {
484             get
485             {
486                 return isEnabled;
487             }
488             set
489             {
490                 isEnabled = value;
491                 UpdateState();
492             }
493         }
494
495         /// <summary>
496         /// Icon relative orientation in Button, work only when show icon and text.
497         /// </summary>
498         /// <since_tizen> 6 </since_tizen>
499         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
500         [EditorBrowsable(EditorBrowsableState.Never)]
501         public IconOrientation? IconRelativeOrientation
502         {
503             get
504             {
505                 return (IconOrientation?)GetValue(IconRelativeOrientationProperty);
506             }
507             set
508             {
509                 SetValue(IconRelativeOrientationProperty, value);
510             }
511         }
512         private IconOrientation? privateIconRelativeOrientation
513         {
514             get
515             {
516                 return Style?.IconRelativeOrientation;
517             }
518             set
519             {
520                 if(Style != null && Style.IconRelativeOrientation != value)
521                 {
522                     Style.IconRelativeOrientation = value;
523                     UpdateUIContent();
524                 }
525             }
526         }
527
528         /// <summary>
529         /// Icon padding in Button, work only when show icon and text.
530         /// </summary>
531         /// <since_tizen> 6 </since_tizen>
532         public Extents IconPadding
533         {
534             get
535             {
536                 return Style.Icon.Padding;
537             }
538             set
539             {
540                 if (null != value)
541                 {
542                     Style.Icon.Padding.CopyFrom(value);
543                 }
544             }
545         }
546
547         /// <summary>
548         /// Text padding in Button, work only when show icon and text.
549         /// </summary>
550         /// <since_tizen> 6 </since_tizen>
551         public Extents TextPadding
552         {
553             get
554             {
555                 return Style.Text.Padding;
556             }
557             set
558             {
559                 if (null != value)
560                 {
561                     Style.Text.Padding.CopyFrom(value);
562                 }
563             }
564         }
565
566         /// <summary>
567         /// Dispose Button and all children on it.
568         /// </summary>
569         /// <param name="type">Dispose type.</param>
570         /// <since_tizen> 6 </since_tizen>
571         protected override void Dispose(DisposeTypes type)
572         {
573             if (disposed)
574             {
575                 return;
576             }
577
578             if (type == DisposeTypes.Explicit)
579             {
580                 if (buttonIcon != null)
581                 {
582                     buttonIcon.Relayout -= OnIconRelayout;
583                     Utility.Dispose(buttonIcon);
584                 }
585                 if (buttonText != null)
586                 {
587                     Utility.Dispose(buttonText);
588                 }
589                 if (overlayImage != null)
590                 {
591                     Utility.Dispose(overlayImage);
592                 }
593             }
594
595             base.Dispose(type);
596         }
597         /// <summary>
598         /// Called after a key event is received by the view that has had its focus set.
599         /// </summary>
600         /// <param name="key">The key event.</param>
601         /// <returns>True if the key event should be consumed.</returns>
602         /// <since_tizen> 6 </since_tizen>
603         public override bool OnKey(Key key)
604         {
605             if (key.State == Key.StateType.Down)
606             {
607                 if (key.KeyPressedName == "Return")
608                 {
609                     isPressed = true;
610                     UpdateState();
611                     if(isEnabled)
612                     {
613                         ClickEventArgs eventArgs = new ClickEventArgs();
614                         OnClick(eventArgs);
615                     }
616                 }
617             }
618             else if (key.State == Key.StateType.Up)
619             {
620                 if (key.KeyPressedName == "Return")
621                 {
622                     isPressed = false;
623                     if (Style.IsSelectable != null && Style.IsSelectable == true)
624                     {
625                         isSelected = !isSelected;
626                     }
627                     UpdateState();
628                 }
629             }
630             return base.OnKey(key);
631         }
632
633         /// <summary>
634         /// 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.
635         /// </summary>
636         /// <since_tizen> 6 </since_tizen>
637         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
638         [EditorBrowsable(EditorBrowsableState.Never)]
639         public override void OnFocusGained()
640         {
641             base.OnFocusGained();
642             UpdateState();
643         }
644         /// <summary>
645         /// 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.
646         /// </summary>
647         /// <since_tizen> 6 </since_tizen>
648         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
649         [EditorBrowsable(EditorBrowsableState.Never)]
650         public override void OnFocusLost()
651         {
652             base.OnFocusLost();
653             UpdateState();
654         }
655
656         /// <summary>
657         /// Tap gesture event callback.
658         /// </summary>
659         /// <param name="source">Source which recieved touch event.</param>
660         /// <param name="e">Tap gesture event argument.</param>
661         /// <since_tizen> 6 </since_tizen>
662         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
663         [EditorBrowsable(EditorBrowsableState.Never)]
664         protected override void OnTapGestureDetected(object source, TapGestureDetector.DetectedEventArgs e)
665         {
666             if (isEnabled)
667             {
668                 ClickEventArgs eventArgs = new ClickEventArgs();
669                 OnClick(eventArgs);
670                 base.OnTapGestureDetected(source, e);
671             }
672         }
673         /// <summary>
674         /// Called after a touch event is received by the owning view.<br />
675         /// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).<br />
676         /// </summary>
677         /// <param name="touch">The touch event.</param>
678         /// <returns>True if the event should be consumed.</returns>
679         /// <since_tizen> 6 </since_tizen>
680         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
681         [EditorBrowsable(EditorBrowsableState.Never)]
682         public override bool OnTouch(Touch touch)
683         {
684             PointStateType state = touch.GetState(0);
685
686             switch(state)
687             {
688                 case PointStateType.Down:
689                     isPressed = true;
690                     UpdateState();
691                     return true;
692                 case PointStateType.Interrupted:
693                     isPressed = false;
694                     UpdateState();
695                     return true;
696                 case PointStateType.Up:
697                     isPressed = false;
698                     if (Style.IsSelectable != null && Style.IsSelectable == true)
699                     {
700                         isSelected = !isSelected;
701                     }
702                     UpdateState();
703                     return true;
704                 default:
705                     break;
706             }
707             return base.OnTouch(touch);
708         }
709
710         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
711         [EditorBrowsable(EditorBrowsableState.Never)]
712         public override void ApplyStyle(ViewStyle viewStyle)
713         {
714             base.ApplyStyle(viewStyle);
715
716             ButtonStyle buttonStyle = viewStyle as ButtonStyle;
717
718             if (null != buttonStyle)
719             {
720                 if (null == overlayImage)
721                 {
722                     overlayImage = new ImageView()
723                     {
724                         WidthResizePolicy = ResizePolicyType.FillToParent,
725                         HeightResizePolicy = ResizePolicyType.FillToParent
726                     };
727                     this.Add(overlayImage);
728                 }
729
730                 if (null == buttonText)
731                 {
732                     buttonText = new TextLabel();
733                     this.Add(buttonText);
734                 }
735
736                 if (null == buttonIcon)
737                 {
738                     buttonIcon = new ImageView();
739                     buttonIcon.Relayout += OnIconRelayout;
740                     this.Add(buttonIcon);
741                 }
742
743                 overlayImage.ApplyStyle(buttonStyle.Overlay);
744                 buttonText.ApplyStyle(buttonStyle.Text);
745                 buttonIcon.ApplyStyle(buttonStyle.Icon);
746             }
747         }
748
749         /// <summary>
750         /// Get Button attribues.
751         /// </summary>
752         /// <since_tizen> 6 </since_tizen>
753         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
754         [EditorBrowsable(EditorBrowsableState.Never)]
755         protected override ViewStyle GetViewStyle()
756         {
757             return new ButtonStyle();
758         }
759
760         /// <summary>
761         /// Update Button State.
762         /// </summary>
763         /// <since_tizen> 6 </since_tizen>
764         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
765         [EditorBrowsable(EditorBrowsableState.Never)]
766         protected void UpdateState()
767         {
768             ControlStates sourceState = ControlState;
769             ControlStates targetState;
770
771             if(isEnabled)
772             {
773                 targetState = isPressed ? ControlStates.Pressed : (IsFocused ? (IsSelected ? ControlStates.SelectedFocused : ControlStates.Focused) : (IsSelected ? ControlStates.Selected : ControlStates.Normal));
774             }
775             else
776             {
777                 targetState = IsSelected ? ControlStates.DisabledSelected : (IsFocused ? ControlStates.DisabledFocused : ControlStates.Disabled);
778             }
779
780             if(sourceState != targetState)
781             {
782                 ControlState = targetState;
783
784                 OnUpdate();
785
786                 StateChangedEventArgs e = new StateChangedEventArgs
787                 {
788                     PreviousState = sourceState,
789                     CurrentState = targetState
790                 };
791                 stateChangeHander?.Invoke(this, e);
792             }
793         }
794
795         /// <summary>
796         /// It is hijack by using protected, attributes copy problem when class inherited from Button.
797         /// </summary>
798         /// <since_tizen> 6 </since_tizen>
799         private void Initialize()
800         {
801             UpdateState();
802             LayoutDirectionChanged += OnLayoutDirectionChanged;
803         }
804
805         /// <summary>
806         /// Measure text, it can be override.
807         /// </summary>
808         /// <since_tizen> 6 </since_tizen>
809         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
810         [EditorBrowsable(EditorBrowsableState.Never)]
811         protected virtual void MeasureText()
812         {
813             if (Style.IconRelativeOrientation == null || buttonIcon == null || buttonText == null)
814             {
815                 return;
816             }
817             buttonText.WidthResizePolicy = ResizePolicyType.Fixed;
818             buttonText.HeightResizePolicy = ResizePolicyType.Fixed;
819             int textPaddingStart = Style.Text.Padding.Start;
820             int textPaddingEnd = Style.Text.Padding.End;
821             int textPaddingTop = Style.Text.Padding.Top;
822             int textPaddingBottom = Style.Text.Padding.Bottom;
823
824             int iconPaddingStart = Style.Icon.Padding.Start;
825             int iconPaddingEnd = Style.Icon.Padding.End;
826             int iconPaddingTop = Style.Icon.Padding.Top;
827             int iconPaddingBottom = Style.Icon.Padding.Bottom;
828
829             if (IconRelativeOrientation == IconOrientation.Top || IconRelativeOrientation == IconOrientation.Bottom)
830             {
831                 buttonText.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd;
832                 buttonText.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom - iconPaddingTop - iconPaddingBottom - buttonIcon.SizeHeight;
833             }
834             else
835             {
836                 buttonText.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd - iconPaddingStart - iconPaddingEnd - buttonIcon.SizeWidth;
837                 buttonText.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom;
838             }
839         }
840         /// <summary>
841         /// Layout child, it can be override.
842         /// </summary>
843         /// <since_tizen> 6 </since_tizen>
844         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
845         [EditorBrowsable(EditorBrowsableState.Never)]
846         protected virtual void LayoutChild()
847         {
848             if (Style.IconRelativeOrientation == null || buttonIcon == null || buttonText == null)
849             {
850                 return;
851             }
852
853             int textPaddingStart = Style.Text.Padding.Start;
854             int textPaddingEnd = Style.Text.Padding.End;
855             int textPaddingTop = Style.Text.Padding.Top;
856             int textPaddingBottom = Style.Text.Padding.Bottom;
857
858             int iconPaddingStart = Style.Icon.Padding.Start;
859             int iconPaddingEnd = Style.Icon.Padding.End;
860             int iconPaddingTop = Style.Icon.Padding.Top;
861             int iconPaddingBottom = Style.Icon.Padding.Bottom;
862
863             switch (IconRelativeOrientation)
864             {
865                 case IconOrientation.Top:
866                     buttonIcon.PositionUsesPivotPoint = true;
867                     buttonIcon.ParentOrigin = NUI.ParentOrigin.TopCenter;
868                     buttonIcon.PivotPoint = NUI.PivotPoint.TopCenter;
869                     buttonIcon.Position2D = new Position2D(0, iconPaddingTop);
870
871                     buttonText.PositionUsesPivotPoint = true;
872                     buttonText.ParentOrigin = NUI.ParentOrigin.BottomCenter;
873                     buttonText.PivotPoint = NUI.PivotPoint.BottomCenter;
874                     buttonText.Position2D = new Position2D(0, -textPaddingBottom);
875                     break;
876                 case IconOrientation.Bottom:
877                     buttonIcon.PositionUsesPivotPoint = true;
878                     buttonIcon.ParentOrigin = NUI.ParentOrigin.BottomCenter;
879                     buttonIcon.PivotPoint = NUI.PivotPoint.BottomCenter;
880                     buttonIcon.Position2D = new Position2D(0, -iconPaddingBottom);
881
882                     buttonText.PositionUsesPivotPoint = true;
883                     buttonText.ParentOrigin = NUI.ParentOrigin.TopCenter;
884                     buttonText.PivotPoint = NUI.PivotPoint.TopCenter;
885                     buttonText.Position2D = new Position2D(0, textPaddingTop);
886                     break;
887                 case IconOrientation.Left:
888                     if (LayoutDirection == ViewLayoutDirectionType.LTR)
889                     {
890                         buttonIcon.PositionUsesPivotPoint = true;
891                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft;
892                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft;
893                         buttonIcon.Position2D = new Position2D(iconPaddingStart, 0);
894
895                         buttonText.PositionUsesPivotPoint = true;
896                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight;
897                         buttonText.PivotPoint = NUI.PivotPoint.CenterRight;
898                         buttonText.Position2D = new Position2D(-textPaddingEnd, 0);
899                     }
900                     else
901                     {
902                         buttonIcon.PositionUsesPivotPoint = true;
903                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight;
904                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight;
905                         buttonIcon.Position2D = new Position2D(-iconPaddingStart, 0);
906
907                         buttonText.PositionUsesPivotPoint = true;
908                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft;
909                         buttonText.PivotPoint = NUI.PivotPoint.CenterLeft;
910                         buttonText.Position2D = new Position2D(textPaddingEnd, 0);
911                     }
912
913                     break;
914                 case IconOrientation.Right:
915                     if (LayoutDirection == ViewLayoutDirectionType.RTL)
916                     {
917                         buttonIcon.PositionUsesPivotPoint = true;
918                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft;
919                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft;
920                         buttonIcon.Position2D = new Position2D(iconPaddingEnd, 0);
921
922                         buttonText.PositionUsesPivotPoint = true;
923                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight;
924                         buttonText.PivotPoint = NUI.PivotPoint.CenterRight;
925                         buttonText.Position2D = new Position2D(-textPaddingStart, 0);
926                     }
927                     else
928                     {
929                         buttonIcon.PositionUsesPivotPoint = true;
930                         buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight;
931                         buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight;
932                         buttonIcon.Position2D = new Position2D(-iconPaddingEnd, 0);
933
934                         buttonText.PositionUsesPivotPoint = true;
935                         buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft;
936                         buttonText.PivotPoint = NUI.PivotPoint.CenterLeft;
937                         buttonText.Position2D = new Position2D(textPaddingStart, 0);
938                     }
939                     break;
940                 default:
941                     break;
942             }
943         }
944         /// <summary>
945         /// Theme change callback when theme is changed, this callback will be trigger.
946         /// </summary>
947         /// <since_tizen> 6 </since_tizen>
948         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
949         [EditorBrowsable(EditorBrowsableState.Never)]
950         protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
951         {
952             ButtonStyle tempAttributes = StyleManager.Instance.GetAttributes(style) as ButtonStyle;
953             if (tempAttributes != null)
954             {
955                 Style.CopyFrom(tempAttributes);
956                 UpdateUIContent();
957             }
958         }
959
960         private void UpdateUIContent()
961         {
962             MeasureText();
963             LayoutChild();
964
965             Sensitive = isEnabled;
966         }
967
968         private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
969         {
970             MeasureText();
971             LayoutChild();
972         }
973
974         private void OnClick(ClickEventArgs eventArgs)
975         {
976             ClickEvent?.Invoke(this, eventArgs);
977         }
978
979         private void OnIconRelayout(object sender, EventArgs e)
980         {
981             MeasureText();
982             LayoutChild();
983         }
984
985         /// <summary>
986         /// ClickEventArgs is a class to record button click event arguments which will sent to user.
987         /// </summary>
988         /// <since_tizen> 6 </since_tizen>
989         public class ClickEventArgs : EventArgs
990         {
991         }
992         /// <summary>
993         /// StateChangeEventArgs is a class to record button state change event arguments which will sent to user.
994         /// </summary>
995         /// <since_tizen> 6 </since_tizen>
996         public class StateChangedEventArgs : EventArgs
997         {
998             /// <summary> previous state of Button </summary>
999             /// <since_tizen> 6 </since_tizen>
1000             public ControlStates PreviousState;
1001             /// <summary> current state of Button </summary>
1002             /// <since_tizen> 6 </since_tizen>
1003             public ControlStates CurrentState;
1004         }
1005
1006     }
1007 }