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