[NUI] Fix Switch thumb positioning
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Button.cs
1 /*
2  * Copyright(c) 2022 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 System.Diagnostics;
20 using Tizen.NUI.BaseComponents;
21 using Tizen.NUI.Binding;
22 using Tizen.NUI.Accessibility;
23
24 namespace Tizen.NUI.Components
25 {
26     /// <summary>
27     /// ClickedEventArgs is a class to record button click event arguments which will sent to user.
28     /// </summary>
29     /// <since_tizen> 8 </since_tizen>
30     public class ClickedEventArgs : EventArgs
31     {
32     }
33
34     /// <summary>
35     /// SelectedChangedEventArgs is a class to record item selected arguments which will sent to user.
36     /// </summary>
37     /// <since_tizen> 8 </since_tizen>
38     public class SelectedChangedEventArgs : EventArgs
39     {
40         /// <summary> Selected state </summary>
41         /// <since_tizen> 8 </since_tizen>
42         public bool IsSelected { get; set; }
43     }
44
45     /// <summary>
46     /// Button is one kind of common component, a button clearly describes what action will occur when the user selects it.
47     /// Button may contain text or an icon.
48     /// </summary>
49     /// <since_tizen> 6 </since_tizen>
50     public partial class Button : Control
51     {
52         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
53         [EditorBrowsable(EditorBrowsableState.Never)]
54         public static readonly BindableProperty IconRelativeOrientationProperty = BindableProperty.Create(nameof(IconRelativeOrientation), typeof(IconOrientation?), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
55         {
56             var instance = (Button)bindable;
57             var newIconOrientation = (IconOrientation?)newValue;
58             if (instance.iconRelativeOrientation != newIconOrientation)
59             {
60                 instance.iconRelativeOrientation = newIconOrientation;
61                 instance.LayoutItems();
62             }
63         },
64         defaultValueCreator: (bindable) => ((Button)bindable).iconRelativeOrientation
65         );
66
67         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
68         [EditorBrowsable(EditorBrowsableState.Never)]
69         public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(Button), false, propertyChanged: (bindable, oldValue, newValue) =>
70         {
71             var instance = (Button)bindable;
72             if (newValue != null)
73             {
74                 bool newSelected = (bool)newValue;
75                 if (instance.isSelected != newSelected)
76                 {
77                     instance.isSelected = newSelected;
78
79                     if (instance.isSelectable)
80                     {
81                         instance.UpdateState();
82                     }
83
84                     if (Accessibility.Accessibility.IsEnabled && instance.IsHighlighted)
85                     {
86                         instance.EmitAccessibilityStateChangedEvent(AccessibilityState.Checked, newSelected);
87                     }
88                 }
89             }
90         },
91         defaultValueCreator: (bindable) =>
92         {
93             var instance = (Button)bindable;
94             return instance.isSelectable && instance.isSelected;
95         });
96         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
97         [EditorBrowsable(EditorBrowsableState.Never)]
98         public static readonly BindableProperty IsSelectableProperty = BindableProperty.Create(nameof(IsSelectable), typeof(bool), typeof(Button), true, propertyChanged: (bindable, oldValue, newValue) =>
99         {
100             var instance = (Button)bindable;
101             if (newValue != null)
102             {
103                 bool newSelectable = (bool)newValue;
104                 if (instance.isSelectable != newSelectable)
105                 {
106                     instance.isSelectable = newSelectable;
107                     instance.UpdateState();
108                 }
109             }
110         },
111         defaultValueCreator: (bindable) => ((Button)bindable).isSelectable);
112
113         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
114         [EditorBrowsable(EditorBrowsableState.Never)]
115         public static readonly BindableProperty IconPaddingProperty = BindableProperty.Create(nameof(IconPadding), typeof(Extents), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
116         {
117             var instance = (Button)bindable;
118             if (instance.buttonIcon == null)
119             {
120                 return;
121             }
122             instance.buttonIcon.Padding = (Extents)newValue;
123         },
124         defaultValueCreator: (bindable) => ((Button)bindable).buttonIcon?.Padding);
125
126         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
127         [EditorBrowsable(EditorBrowsableState.Never)]
128         public static readonly BindableProperty TextPaddingProperty = BindableProperty.Create(nameof(TextPadding), typeof(Extents), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
129         {
130             var instance = (Button)bindable;
131             if (instance.buttonText == null)
132             {
133                 return;
134             }
135             instance.buttonText.Padding = (Extents)newValue;
136         },
137         defaultValueCreator: (bindable) => ((Button)bindable).buttonText?.Padding);
138
139         /// <summary> The bindable property of ItemAlignment. </summary>
140         [EditorBrowsable(EditorBrowsableState.Never)]
141         internal static readonly BindableProperty ItemAlignmentProperty = BindableProperty.Create(nameof(ItemAlignment), typeof(LinearLayout.Alignment), typeof(Button), LinearLayout.Alignment.Center, propertyChanged: (bindable, oldValue, newValue) =>
142         {
143             var instance = (Button)bindable;
144             var newAlignment = (LinearLayout.Alignment)newValue;
145
146             if (instance.itemAlignment != newAlignment)
147             {
148                 instance.itemAlignment = newAlignment;
149
150                 switch (newAlignment)
151                 {
152                     case LinearLayout.Alignment.Begin:
153                         instance.itemHorizontalAlignment = HorizontalAlignment.Begin;
154                         break;
155                     case LinearLayout.Alignment.End:
156                         instance.itemHorizontalAlignment = HorizontalAlignment.End;
157                         break;
158                     case LinearLayout.Alignment.CenterHorizontal:
159                         instance.itemHorizontalAlignment = HorizontalAlignment.Center;
160                         break;
161                     case LinearLayout.Alignment.Top:
162                         instance.itemVerticalAlignment = VerticalAlignment.Top;
163                         break;
164                     case LinearLayout.Alignment.Bottom:
165                         instance.itemVerticalAlignment = VerticalAlignment.Bottom;
166                         break;
167                     case LinearLayout.Alignment.CenterVertical:
168                         instance.itemVerticalAlignment = VerticalAlignment.Center;
169                         break;
170                     case LinearLayout.Alignment.Center:
171                         instance.itemHorizontalAlignment = HorizontalAlignment.Center;
172                         instance.itemVerticalAlignment = VerticalAlignment.Center;
173                         break;
174                     default:
175                         break;
176                 }
177
178                 instance.LayoutItems();
179             }
180         },
181         defaultValueCreator: (bindable) => ((Button)bindable).itemAlignment);
182
183         /// <summary> The bindable property of ItemHorizontalAlignment. </summary>
184         [EditorBrowsable(EditorBrowsableState.Never)]
185         internal static readonly BindableProperty ItemHorizontalAlignmentProperty = BindableProperty.Create(nameof(ItemHorizontalAlignment), typeof(HorizontalAlignment), typeof(Button), HorizontalAlignment.Center, propertyChanged: (bindable, oldValue, newValue) =>
186         {
187             var instance = (Button)bindable;
188             var newHorizontalAlignment = (HorizontalAlignment)newValue;
189
190             if (instance.itemHorizontalAlignment != newHorizontalAlignment)
191             {
192                 instance.itemHorizontalAlignment = newHorizontalAlignment;
193                 instance.LayoutItems();
194             }
195         },
196         defaultValueCreator: (bindable) => ((Button)bindable).itemHorizontalAlignment);
197
198         /// <summary> The bindable property of ItemVerticalAlignment. </summary>
199         [EditorBrowsable(EditorBrowsableState.Never)]
200         internal static readonly BindableProperty ItemVerticalAlignmentProperty = BindableProperty.Create(nameof(ItemVerticalAlignment), typeof(VerticalAlignment), typeof(Button), VerticalAlignment.Center, propertyChanged: (bindable, oldValue, newValue) =>
201         {
202             var instance = (Button)bindable;
203             var newVerticalAlignment = (VerticalAlignment)newValue;
204
205             if (instance.itemVerticalAlignment != newVerticalAlignment)
206             {
207                 instance.itemVerticalAlignment = newVerticalAlignment;
208                 instance.LayoutItems();
209             }
210         },
211         defaultValueCreator: (bindable) => ((Button)bindable).itemVerticalAlignment);
212
213         /// <summary> The bindable property of ItemSpacing. </summary>
214         [EditorBrowsable(EditorBrowsableState.Never)]
215         internal static readonly BindableProperty ItemSpacingProperty = BindableProperty.Create(nameof(ItemSpacing), typeof(Size2D), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
216         {
217             var instance = (Button)bindable;
218             instance.itemSpacing = (Size2D)newValue;
219             instance.UpdateSizeAndSpacing();
220         },
221         defaultValueCreator: (bindable) => ((Button)bindable).itemSpacing);
222
223         private IconOrientation? iconRelativeOrientation = IconOrientation.Left;
224         private bool isSelected = false;
225         private bool isSelectable = false;
226         private Size2D itemSpacing;
227         private LinearLayout.Alignment itemAlignment = LinearLayout.Alignment.Center;
228         private HorizontalAlignment itemHorizontalAlignment = HorizontalAlignment.Center;
229         private VerticalAlignment itemVerticalAlignment = VerticalAlignment.Center;
230
231         static Button() { }
232
233         /// <summary>
234         /// Creates a new instance of a Button.
235         /// </summary>
236         /// <since_tizen> 6 </since_tizen>
237         public Button() : base()
238         {
239             Focusable = true;
240         }
241
242         /// <summary>
243         /// Creates a new instance of a Button with style.
244         /// </summary>
245         /// <param name="style">Create Button by special style defined in UX.</param>
246         /// <since_tizen> 8 </since_tizen>
247         public Button(string style) : base(style)
248         {
249             Focusable = true;
250         }
251
252         /// <summary>
253         /// Creates a new instance of a Button with style.
254         /// </summary>
255         /// <param name="buttonStyle">Create Button by style customized by user.</param>
256         /// <since_tizen> 8 </since_tizen>
257         public Button(ButtonStyle buttonStyle) : base(buttonStyle)
258         {
259             Focusable = true;
260         }
261
262         /// <summary>
263         /// Calculates current states for the button<br />
264         /// </summary>
265         [EditorBrowsable(EditorBrowsableState.Never)]
266         protected override AccessibilityStates AccessibilityCalculateStates()
267         {
268             var states = base.AccessibilityCalculateStates();
269
270             states[AccessibilityState.Checked] = this.IsSelected;
271             states[AccessibilityState.Enabled] = this.IsEnabled;
272
273             return states;
274         }
275
276         /// <summary>
277         /// An event for the button clicked signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
278         /// </summary>
279         /// <since_tizen> 6 </since_tizen>
280         [Obsolete("Deprecated in API8; Will be removed in API10. Please use Clicked event instead.")]
281         public event EventHandler<ClickEventArgs> ClickEvent;
282
283         /// <summary>
284         /// An event for the button clicked signal which can be used to subscribe or unsubscribe the event handler provided by the user.
285         /// </summary>
286         /// <since_tizen> 8 </since_tizen>
287         public event EventHandler<ClickedEventArgs> Clicked;
288
289         /// <summary>
290         /// An event for the button state changed signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
291         /// </summary>
292         /// <since_tizen> 6 </since_tizen>
293         [Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEvent")]
294         public event EventHandler<StateChangedEventArgs> StateChangedEvent
295         {
296             add
297             {
298                 stateChangeHandler += value;
299             }
300             remove
301             {
302                 stateChangeHandler -= value;
303             }
304         }
305
306         /// <summary>
307         /// Icon orientation.
308         /// </summary>
309         /// <since_tizen> 6 </since_tizen>
310         public enum IconOrientation
311         {
312             /// <summary>
313             /// Top.
314             /// </summary>
315             /// <since_tizen> 6 </since_tizen>
316             Top,
317             /// <summary>
318             /// Bottom.
319             /// </summary>
320             /// <since_tizen> 6 </since_tizen>
321             Bottom,
322             /// <summary>
323             /// Left.
324             /// </summary>
325             /// <since_tizen> 6 </since_tizen>
326             Left,
327             /// <summary>
328             /// Right.
329             /// </summary>
330             /// <since_tizen> 6 </since_tizen>
331             Right,
332         }
333
334         /// <summary>
335         /// Button's icon part.
336         /// </summary>
337         /// <since_tizen> 8 </since_tizen>
338         public ImageView Icon
339         {
340             get => buttonIcon;
341             internal set
342             {
343                 buttonIcon = value;
344             }
345         }
346
347         /// <summary>
348         /// Button's overlay image part.
349         /// </summary>
350         /// <since_tizen> 8 </since_tizen>
351         public ImageView OverlayImage
352         {
353             get
354             {
355                 if (null == overlayImage)
356                 {
357                     overlayImage = CreateOverlayImage();
358                     if (null != Extension)
359                     {
360                         overlayImage = Extension.OnCreateOverlayImage(this, overlayImage);
361                     }
362                     if (null != overlayImage)
363                     {
364                         overlayImage.ExcludeLayouting = true;
365                         Add(overlayImage);
366                     }
367                 }
368                 return overlayImage;
369             }
370             internal set
371             {
372                 overlayImage = value;
373             }
374         }
375
376         /// <summary>
377         /// Button's text part.
378         /// </summary>
379         /// <since_tizen> 8 </since_tizen>
380         public TextLabel TextLabel
381         {
382             get => buttonText;
383             internal set
384             {
385                 buttonText = value;
386             }
387         }
388
389         /// <summary>
390         /// The last applied style object copy.
391         /// </summary>
392         /// <remarks>
393         /// Modifying contents in style may cause unexpected behaviour.
394         /// </remarks>
395         /// <since_tizen> 8 </since_tizen>
396         public ButtonStyle Style => (ButtonStyle)(ViewStyle as ButtonStyle)?.Clone();
397
398         /// <summary>
399         /// The text of Button.
400         /// </summary>
401         /// <since_tizen> 6 </since_tizen>
402         public string Text
403         {
404             get
405             {
406                 return GetValue(TextProperty) as string;
407             }
408             set
409             {
410                 SetValue(TextProperty, value);
411                 NotifyPropertyChanged();
412             }
413         }
414         private string InternalText
415         {
416             get
417             {
418                 return TextLabel.Text;
419             }
420             set
421             {
422                 TextLabel.Text = value;
423
424                 if (Accessibility.Accessibility.IsEnabled && IsHighlighted && String.IsNullOrEmpty(AccessibilityName) && GetAccessibilityNameSignal().Empty())
425                 {
426                     EmitAccessibilityEvent(AccessibilityPropertyChangeEvent.Name);
427                 }
428             }
429         }
430
431         /// <summary>
432         /// Flag to decide Button can be selected or not.
433         /// </summary>
434         /// <since_tizen> 6 </since_tizen>
435         public bool IsSelectable
436         {
437             get
438             {
439                 return (bool)GetValue(IsSelectableProperty);
440             }
441             set
442             {
443                 SetValue(IsSelectableProperty, value);
444             }
445         }
446
447         /// <summary>
448         /// Translate text string in Button.
449         /// </summary>
450         /// <since_tizen> 6 </since_tizen>
451         public string TranslatableText
452         {
453             get
454             {
455                 return GetValue(TranslatableTextProperty) as string;
456             }
457             set
458             {
459                 SetValue(TranslatableTextProperty, value);
460                 NotifyPropertyChanged();
461             }
462         }
463         private string InternalTranslatableText
464         {
465             get
466             {
467                 return TextLabel.TranslatableText;
468             }
469             set
470             {
471                 TextLabel.TranslatableText = value;
472             }
473         }
474
475         /// <summary>
476         /// Text point size in Button.
477         /// </summary>
478         /// <since_tizen> 6 </since_tizen>
479         public float PointSize
480         {
481             get
482             {
483                 return (float)GetValue(PointSizeProperty);
484             }
485             set
486             {
487                 SetValue(PointSizeProperty, value);
488                 NotifyPropertyChanged();
489             }
490         }
491         private float InternalPointSize
492         {
493             get
494             {
495                 return TextLabel.PointSize;
496             }
497             set
498             {
499                 TextLabel.PointSize = value;
500             }
501         }
502
503         /// <summary>
504         /// Text font family in Button.
505         /// </summary>
506         /// <since_tizen> 6 </since_tizen>
507         public string FontFamily
508         {
509             get
510             {
511                 return GetValue(FontFamilyProperty) as string;
512             }
513             set
514             {
515                 SetValue(FontFamilyProperty, value);
516                 NotifyPropertyChanged();
517             }
518         }
519         private string InternalFontFamily
520         {
521             get
522             {
523                 return TextLabel.FontFamily;
524             }
525             set
526             {
527                 TextLabel.FontFamily = value;
528             }
529         }
530
531         /// <summary>
532         /// Text color in Button.
533         /// </summary>
534         /// <since_tizen> 6 </since_tizen>
535         public Color TextColor
536         {
537             get
538             {
539                 return GetValue(TextColorProperty) as Color;
540             }
541             set
542             {
543                 SetValue(TextColorProperty, value);
544                 NotifyPropertyChanged();
545             }
546         }
547         private Color InternalTextColor
548         {
549             get
550             {
551                 return TextLabel.TextColor;
552             }
553             set
554             {
555                 TextLabel.TextColor = value;
556             }
557         }
558
559         /// <summary>
560         /// Text horizontal alignment in Button.
561         /// </summary>
562         /// <since_tizen> 6 </since_tizen>
563         public HorizontalAlignment TextAlignment
564         {
565             get
566             {
567                 return (HorizontalAlignment)GetValue(TextAlignmentProperty);
568             }
569             set
570             {
571                 SetValue(TextAlignmentProperty, value);
572                 NotifyPropertyChanged();
573             }
574         }
575         private HorizontalAlignment InternalTextAlignment
576         {
577             get
578             {
579                 return TextLabel.HorizontalAlignment;
580             }
581             set
582             {
583                 TextLabel.HorizontalAlignment = value;
584             }
585         }
586
587         /// <summary>
588         /// Icon image's resource url in Button.
589         /// </summary>
590         /// <since_tizen> 6 </since_tizen>
591         public string IconURL
592         {
593             get
594             {
595                 return GetValue(IconURLProperty) as string;
596             }
597             set
598             {
599                 SetValue(IconURLProperty, value);
600                 NotifyPropertyChanged();
601             }
602         }
603         private string InternalIconURL
604         {
605             get
606             {
607                 return Icon.ResourceUrl;
608             }
609             set
610             {
611                 Icon.ResourceUrl = value;
612             }
613         }
614
615         /// <summary>
616         /// Icon image's size in Button.
617         /// </summary>
618         [EditorBrowsable(EditorBrowsableState.Never)]
619         public Size IconSize
620         {
621             get
622             {
623                 return GetValue(IconSizeProperty) as Size;
624             }
625             set
626             {
627                 SetValue(IconSizeProperty, value);
628                 NotifyPropertyChanged();
629             }
630         }
631         private Size InternalIconSize
632         {
633             get => Icon.Size;
634             set => Icon.Size = value;
635         }
636
637         /// <summary>
638         /// Text string selector in Button.
639         /// Getter returns copied selector value if exist, null otherwise.
640         /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
641         /// </summary>
642         /// <since_tizen> 6 </since_tizen>
643         public StringSelector TextSelector
644         {
645             get
646             {
647                 return GetValue(TextSelectorProperty) as StringSelector;
648             }
649             set
650             {
651                 SetValue(TextSelectorProperty, value);
652                 NotifyPropertyChanged();
653             }
654         }
655         private StringSelector InternalTextSelector
656         {
657             get => buttonText?.TextSelector == null ? null : new StringSelector(buttonText.TextSelector);
658             set
659             {
660                 if (value == null || buttonText == null)
661                 {
662                     throw new NullReferenceException("Button.TextSelector is null");
663                 }
664                 else
665                 {
666                     buttonText.TextSelector = value;
667                 }
668             }
669         }
670
671         /// <summary>
672         /// Translatable text string selector in Button.
673         /// Getter returns copied selector value if exist, null otherwise.
674         /// </summary>
675         /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
676         /// <since_tizen> 6 </since_tizen>
677         public StringSelector TranslatableTextSelector
678         {
679             get
680             {
681                 return GetValue(TranslatableTextSelectorProperty) as StringSelector;
682             }
683             set
684             {
685                 SetValue(TranslatableTextSelectorProperty, value);
686                 NotifyPropertyChanged();
687             }
688         }
689         private StringSelector InternalTranslatableTextSelector
690         {
691             get => (buttonText?.TranslatableTextSelector == null) ? null : new StringSelector(buttonText.TranslatableTextSelector);
692             set
693             {
694                 if (value == null || buttonText == null)
695                 {
696                     throw new NullReferenceException("Button.TranslatableTextSelector is null");
697                 }
698                 else
699                 {
700                     buttonText.TranslatableTextSelector = value;
701                 }
702             }
703         }
704
705         /// <summary>
706         /// Text color selector in Button.
707         /// Getter returns copied selector value if exist, null otherwise.
708         /// </summary>
709         /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
710         /// <since_tizen> 6 </since_tizen>
711         public ColorSelector TextColorSelector
712         {
713             get
714             {
715                 return GetValue(TextColorSelectorProperty) as ColorSelector;
716             }
717             set
718             {
719                 SetValue(TextColorSelectorProperty, value);
720                 NotifyPropertyChanged();
721             }
722         }
723         private ColorSelector InternalTextColorSelector
724         {
725             get => buttonText?.TextColorSelector == null ? null : new ColorSelector(buttonText.TextColorSelector);
726             set
727             {
728                 if (value == null || buttonText == null)
729                 {
730                     throw new NullReferenceException("Button.TextColorSelectorProperty is null");
731                 }
732                 else
733                 {
734                     buttonText.TextColorSelector = value;
735                 }
736             }
737         }
738
739         /// <summary>
740         /// Text font size selector in Button.
741         /// Getter returns copied selector value if exist, null otherwise.
742         /// </summary>
743         /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
744         /// <since_tizen> 6 </since_tizen>
745         public FloatSelector PointSizeSelector
746         {
747             get
748             {
749                 return GetValue(PointSizeSelectorProperty) as FloatSelector;
750             }
751             set
752             {
753                 SetValue(PointSizeSelectorProperty, value);
754                 NotifyPropertyChanged();
755             }
756         }
757         private FloatSelector InternalPointSizeSelector
758         {
759             get => buttonText?.PointSizeSelector == null ? null : new FloatSelector(buttonText.PointSizeSelector);
760             set
761             {
762                 if (value == null || buttonText == null)
763                 {
764                     throw new NullReferenceException("Button.PointSizeSelector is null");
765                 }
766                 else
767                 {
768                     buttonText.PointSizeSelector = value;
769                 }
770             }
771         }
772
773         /// <summary>
774         /// Icon image's resource url selector in Button.
775         /// Getter returns copied selector value if exist, null otherwise.
776         /// </summary>
777         /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
778         /// <since_tizen> 6 </since_tizen>
779         public StringSelector IconURLSelector
780         {
781             get
782             {
783                 return GetValue(IconURLSelectorProperty) as StringSelector;
784             }
785             set
786             {
787                 SetValue(IconURLSelectorProperty, value);
788                 NotifyPropertyChanged();
789             }
790         }
791         private StringSelector InternalIconURLSelector
792         {
793             get => buttonIcon?.ResourceUrlSelector == null ? null : new StringSelector(buttonIcon.ResourceUrlSelector);
794             set
795             {
796                 if (value == null || buttonIcon == null)
797                 {
798                     throw new NullReferenceException("Button.IconURLSelector is null");
799                 }
800                 else
801                 {
802                     buttonIcon.ResourceUrlSelector = value;
803                 }
804             }
805         }
806
807         /// <summary>
808         /// Flag to decide selected state in Button.
809         /// </summary>
810         /// <since_tizen> 6 </since_tizen>
811         public bool IsSelected
812         {
813             get
814             {
815                 return (bool)GetValue(IsSelectedProperty);
816             }
817             set
818             {
819                 SetValue(IsSelectedProperty, value);
820             }
821         }
822
823         /// <summary>
824         /// Flag to decide enable or disable in Button.
825         /// </summary>
826         /// <since_tizen> 6 </since_tizen>
827         public new bool IsEnabled
828         {
829             get => base.IsEnabled;
830             set
831             {
832                 base.IsEnabled = value;
833             }
834         }
835
836         /// <summary>
837         /// Icon relative orientation in Button, work only when show icon and text.
838         /// </summary>
839         /// <since_tizen> 8 </since_tizen>
840         public IconOrientation? IconRelativeOrientation
841         {
842             get
843             {
844                 return (IconOrientation?)GetValue(IconRelativeOrientationProperty) ?? IconOrientation.Left;
845             }
846             set
847             {
848                 SetValue(IconRelativeOrientationProperty, value);
849             }
850         }
851
852         /// <summary>
853         /// Icon padding in Button. It is shortcut of Icon.Padding.
854         /// </summary>
855         /// <since_tizen> 6 </since_tizen>
856         public Extents IconPadding
857         {
858             get => (Extents)GetValue(IconPaddingProperty) ?? new Extents();
859             set => SetValue(IconPaddingProperty, value);
860         }
861
862         /// <summary>
863         /// Text padding in Button. It is shortcut of TextLabel.Padding.
864         /// </summary>
865         /// <since_tizen> 6 </since_tizen>
866         public Extents TextPadding
867         {
868             get => (Extents)GetValue(TextPaddingProperty) ?? new Extents();
869             set => SetValue(TextPaddingProperty, value);
870         }
871
872         /// <summary>
873         /// The item (text or icon or both) alignment.
874         /// </summary>
875         /// <since_tizen> 9 </since_tizen>
876         public LinearLayout.Alignment ItemAlignment
877         {
878             get => (LinearLayout.Alignment)GetValue(ItemAlignmentProperty);
879             set => SetValue(ItemAlignmentProperty, value);
880         }
881
882         /// <summary>
883         /// The item (text or icon or both) horizontal alignment.
884         /// </summary>
885         [EditorBrowsable(EditorBrowsableState.Never)]
886         public HorizontalAlignment ItemHorizontalAlignment
887         {
888             get => (HorizontalAlignment)GetValue(ItemHorizontalAlignmentProperty);
889             set => SetValue(ItemHorizontalAlignmentProperty, value);
890         }
891
892         /// <summary>
893         /// The item (text or icon or both) vertical alignment.
894         /// </summary>
895         [EditorBrowsable(EditorBrowsableState.Never)]
896         public VerticalAlignment ItemVerticalAlignment
897         {
898             get => (VerticalAlignment)GetValue(ItemVerticalAlignmentProperty);
899             set => SetValue(ItemVerticalAlignmentProperty, value);
900         }
901
902         /// <summary>
903         /// The space between icon and text.
904         /// The value is applied when there exist icon and text both.
905         /// The width value is used when the items are arranged horizontally. Otherwise, the height value is used.
906         /// </summary>
907         /// <since_tizen> 9 </since_tizen>
908         public Size2D ItemSpacing
909         {
910             get => (Size2D)GetValue(ItemSpacingProperty);
911             set => SetValue(ItemSpacingProperty, value);
912         }
913
914         /// <summary>
915         /// Called after a key event is received by the view that has had its focus set.
916         /// </summary>
917         /// <param name="key">The key event.</param>
918         /// <returns>True if the key event should be consumed.</returns>
919         /// <since_tizen> 6 </since_tizen>
920         public override bool OnKey(Key key)
921         {
922             bool clicked = false;
923
924             if (!IsEnabled || null == key)
925             {
926                 return false;
927             }
928
929             if (key.State == Key.StateType.Down)
930             {
931                 if (key.KeyPressedName == "Return")
932                 {
933                     isPressed = true;
934                     UpdateState();
935                 }
936             }
937             else if (key.State == Key.StateType.Up)
938             {
939                 if (key.KeyPressedName == "Return")
940                 {
941                     clicked = isPressed && IsEnabled;
942
943                     isPressed = false;
944
945                     if (IsSelectable)
946                     {
947                         IsSelected = !IsSelected;
948                     }
949                     else
950                     {
951                         UpdateState();
952                     }
953
954                     if (clicked)
955                     {
956                         ClickedEventArgs eventArgs = new ClickedEventArgs();
957                         OnClickedInternal(eventArgs);
958                     }
959                 }
960             }
961             return base.OnKey(key) || clicked;
962         }
963
964         /// <summary>
965         /// 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.
966         /// </summary>
967         /// <since_tizen> 8 </since_tizen>
968         public override void OnFocusGained()
969         {
970             base.OnFocusGained();
971             UpdateState();
972         }
973
974         /// <summary>
975         /// 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.
976         /// </summary>
977         /// <since_tizen> 8 </since_tizen>
978         public override void OnFocusLost()
979         {
980             base.OnFocusLost();
981             UpdateState();
982         }
983
984         /// <summary>
985         /// Called after a touch event is received by the owning view.<br />
986         /// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).<br />
987         /// </summary>
988         /// <param name="touch">The touch event.</param>
989         /// <returns>True if the event should be consumed.</returns>
990         /// <since_tizen> 8 </since_tizen>
991         [Obsolete("Deprecated in API8; Will be removed in API10. Please use OnClicked instead.")]
992 #pragma warning disable CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
993         public override bool OnTouch(Touch touch)
994 #pragma warning restore CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
995         {
996             return base.OnTouch(touch);
997         }
998
999         /// <summary>
1000         /// Apply style to button.
1001         /// </summary>
1002         /// <param name="viewStyle">The style to apply.</param>
1003         /// <since_tizen> 8 </since_tizen>
1004         public override void ApplyStyle(ViewStyle viewStyle)
1005         {
1006             Debug.Assert(buttonIcon != null && buttonText != null);
1007
1008             styleApplying++;
1009
1010             base.ApplyStyle(viewStyle);
1011
1012             if (viewStyle is ButtonStyle buttonStyle)
1013             {
1014                 Extension = buttonStyle.CreateExtension();
1015
1016                 if (buttonStyle.Overlay != null)
1017                 {
1018                     OverlayImage?.ApplyStyle(buttonStyle.Overlay);
1019                 }
1020
1021                 if (Extension != null)
1022                 {
1023                     buttonIcon.Unparent();
1024                     buttonIcon = Extension.OnCreateIcon(this, buttonIcon);
1025
1026                     buttonText.Unparent();
1027                     buttonText = Extension.OnCreateText(this, buttonText);
1028
1029                     LayoutItems();
1030                 }
1031
1032                 if (buttonStyle.Text != null)
1033                 {
1034                     buttonText.ThemeChangeSensitive = false;
1035                     buttonText.ApplyStyle(buttonStyle.Text);
1036                 }
1037
1038                 if (buttonStyle.Icon != null)
1039                 {
1040                     buttonIcon.ApplyStyle(buttonStyle.Icon);
1041                 }
1042             }
1043
1044             styleApplying--;
1045
1046             UpdateState();
1047         }
1048
1049         /// <summary>
1050         /// ClickEventArgs is a class to record button click event arguments which will sent to user.
1051         /// </summary>
1052         /// <since_tizen> 6 </since_tizen>
1053         [Obsolete("Deprecated in API8; Will be removed in API10. Please use ClickedEventArgs instead.")]
1054         [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
1055         public class ClickEventArgs : EventArgs
1056         {
1057         }
1058
1059         /// <summary>
1060         /// StateChangeEventArgs is a class to record button state change event arguments which will sent to user.
1061         /// </summary>
1062         /// <since_tizen> 6 </since_tizen>
1063         [Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEventArgs")]
1064         [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
1065         public class StateChangedEventArgs : EventArgs
1066         {
1067             /// <summary> previous state of Button </summary>
1068             /// <since_tizen> 6 </since_tizen>
1069             /// It will be removed in API10
1070             [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
1071             [Obsolete("Deprecated in API8; Will be removed in API10")]
1072             public ControlStates PreviousState;
1073             /// <summary> current state of Button </summary>
1074             /// <since_tizen> 6 </since_tizen>
1075             /// It will be removed in API10
1076             [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
1077             [Obsolete("Deprecated in API8; Will be removed in API10")]
1078             public ControlStates CurrentState;
1079         }
1080     }
1081 }