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