2 * Copyright(c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 using System.ComponentModel;
19 using System.Diagnostics;
20 using Tizen.NUI.BaseComponents;
21 using Tizen.NUI.Binding;
22 using Tizen.NUI.Accessibility;
24 namespace Tizen.NUI.Components
27 /// ClickedEventArgs is a class to record button click event arguments which will sent to user.
29 /// <since_tizen> 8 </since_tizen>
30 public class ClickedEventArgs : EventArgs
35 /// SelectedChangedEventArgs is a class to record item selected arguments which will sent to user.
37 /// <since_tizen> 8 </since_tizen>
38 public class SelectedChangedEventArgs : EventArgs
40 /// <summary> Selected state </summary>
41 /// <since_tizen> 8 </since_tizen>
42 public bool IsSelected { get; set; }
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.
49 /// <since_tizen> 6 </since_tizen>
50 public partial class Button : Control
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) =>
56 var instance = (Button)bindable;
57 var newIconOrientation = (IconOrientation?)newValue;
58 if (instance.iconRelativeOrientation != newIconOrientation)
60 instance.iconRelativeOrientation = newIconOrientation;
61 instance.LayoutItems();
64 defaultValueCreator: (bindable) => ((Button)bindable).iconRelativeOrientation
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 IsEnabledProperty = BindableProperty.Create(nameof(IsEnabled), typeof(bool), typeof(Button), true, propertyChanged: (bindable, oldValue, newValue) =>
71 var instance = (Button)bindable;
74 bool newEnabled = (bool)newValue;
75 if (instance.isEnabled != newEnabled)
77 instance.isEnabled = newEnabled;
78 instance.Sensitive = newEnabled;
79 instance.UpdateState();
83 defaultValueCreator: (bindable) => ((Button)bindable).isEnabled);
84 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
85 [EditorBrowsable(EditorBrowsableState.Never)]
86 public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(Button), false, propertyChanged: (bindable, oldValue, newValue) =>
88 var instance = (Button)bindable;
91 bool newSelected = (bool)newValue;
92 if (instance.isSelected != newSelected)
94 instance.isSelected = newSelected;
96 if (instance.isSelectable)
98 instance.UpdateState();
101 if (Accessibility.Accessibility.IsEnabled && instance.IsHighlighted)
103 instance.EmitAccessibilityStatesChangedEvent(AccessibilityStates.Checked, newSelected);
108 defaultValueCreator: (bindable) =>
110 var instance = (Button)bindable;
111 return instance.isSelectable && instance.isSelected;
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 IsSelectableProperty = BindableProperty.Create(nameof(IsSelectable), typeof(bool), typeof(Button), true, propertyChanged: (bindable, oldValue, newValue) =>
117 var instance = (Button)bindable;
118 if (newValue != null)
120 bool newSelectable = (bool)newValue;
121 if (instance.isSelectable != newSelectable)
123 instance.isSelectable = newSelectable;
124 instance.UpdateState();
128 defaultValueCreator: (bindable) => ((Button)bindable).isSelectable);
130 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
131 [EditorBrowsable(EditorBrowsableState.Never)]
132 public static readonly BindableProperty IconPaddingProperty = BindableProperty.Create(nameof(IconPadding), typeof(Extents), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
134 var instance = (Button)bindable;
135 if (instance.buttonIcon == null)
139 instance.buttonIcon.Padding = (Extents)newValue;
141 defaultValueCreator: (bindable) => ((Button)bindable).buttonIcon?.Padding);
143 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
144 [EditorBrowsable(EditorBrowsableState.Never)]
145 public static readonly BindableProperty TextPaddingProperty = BindableProperty.Create(nameof(TextPadding), typeof(Extents), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
147 var instance = (Button)bindable;
148 if (instance.buttonText == null)
152 instance.buttonText.Padding = (Extents)newValue;
154 defaultValueCreator: (bindable) => ((Button)bindable).buttonText?.Padding);
156 /// <summary> The bindable property of ItemAlignment. </summary>
157 [EditorBrowsable(EditorBrowsableState.Never)]
158 internal static readonly BindableProperty ItemAlignmentProperty = BindableProperty.Create(nameof(ItemAlignment), typeof(LinearLayout.Alignment), typeof(Button), LinearLayout.Alignment.Center, propertyChanged: (bindable, oldValue, newValue) =>
160 var instance = (Button)bindable;
161 var newAlignment = (LinearLayout.Alignment)newValue;
163 if (instance.itemAlignment != newAlignment)
165 instance.itemAlignment = newAlignment;
166 instance.LayoutItems();
169 defaultValueCreator: (bindable) => ((Button)bindable).itemAlignment);
171 /// <summary> The bindable property of ItemSpacing. </summary>
172 [EditorBrowsable(EditorBrowsableState.Never)]
173 internal static readonly BindableProperty ItemSpacingProperty = BindableProperty.Create(nameof(ItemSpacing), typeof(Size2D), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
175 var instance = (Button)bindable;
176 instance.itemSpacing = (Size2D)newValue;
177 instance.UpdateSizeAndSpacing();
179 defaultValueCreator: (bindable) => ((Button)bindable).itemSpacing);
181 private IconOrientation? iconRelativeOrientation = IconOrientation.Left;
182 private bool isSelected = false;
183 private bool isSelectable = false;
184 private bool isEnabled = true;
185 private Size2D itemSpacing;
186 private LinearLayout.Alignment itemAlignment = LinearLayout.Alignment.Center;
191 /// Creates a new instance of a Button.
193 /// <since_tizen> 6 </since_tizen>
194 public Button() : base()
199 /// Creates a new instance of a Button with style.
201 /// <param name="style">Create Button by special style defined in UX.</param>
202 /// <since_tizen> 8 </since_tizen>
203 public Button(string style) : base(style)
208 /// Creates a new instance of a Button with style.
210 /// <param name="buttonStyle">Create Button by style customized by user.</param>
211 /// <since_tizen> 8 </since_tizen>
212 public Button(ButtonStyle buttonStyle) : base(buttonStyle)
217 /// Calculates current states for the button<br />
219 [EditorBrowsable(EditorBrowsableState.Never)]
220 protected override AccessibilityStates AccessibilityCalculateStates(ulong states)
222 var accessibilityStates = base.AccessibilityCalculateStates(states);
223 FlagSetter(ref accessibilityStates, AccessibilityStates.Checked, this.IsSelected);
224 FlagSetter(ref accessibilityStates, AccessibilityStates.Enabled, this.IsEnabled);
225 return accessibilityStates;
229 /// An event for the button clicked signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
231 /// <since_tizen> 6 </since_tizen>
232 [Obsolete("Deprecated in API8; Will be removed in API10. Please use Clicked event instead.")]
233 public event EventHandler<ClickEventArgs> ClickEvent;
236 /// An event for the button clicked signal which can be used to subscribe or unsubscribe the event handler provided by the user.
238 /// <since_tizen> 8 </since_tizen>
239 public event EventHandler<ClickedEventArgs> Clicked;
242 /// An event for the button state changed signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
244 /// <since_tizen> 6 </since_tizen>
245 [Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEvent")]
246 public event EventHandler<StateChangedEventArgs> StateChangedEvent
250 stateChangeHandler += value;
254 stateChangeHandler -= value;
259 /// Icon orientation.
261 /// <since_tizen> 6 </since_tizen>
262 public enum IconOrientation
267 /// <since_tizen> 6 </since_tizen>
272 /// <since_tizen> 6 </since_tizen>
277 /// <since_tizen> 6 </since_tizen>
282 /// <since_tizen> 6 </since_tizen>
287 /// Button's icon part.
289 /// <since_tizen> 8 </since_tizen>
290 public ImageView Icon
300 /// Button's overlay image part.
302 /// <since_tizen> 8 </since_tizen>
303 public ImageView OverlayImage
307 if (null == overlayImage)
309 overlayImage = CreateOverlayImage();
310 if (null != Extension)
312 overlayImage = Extension.OnCreateOverlayImage(this, overlayImage);
314 if (null != overlayImage)
316 overlayImage.ExcludeLayouting = true;
324 overlayImage = value;
329 /// Button's text part.
331 /// <since_tizen> 8 </since_tizen>
332 public TextLabel TextLabel
338 AccessibilityManager.Instance.SetAccessibilityAttribute(this, AccessibilityManager.AccessibilityAttribute.Label, buttonText.Text);
343 /// The last applied style object copy.
346 /// Modifying contents in style may cause unexpected behaviour.
348 /// <since_tizen> 8 </since_tizen>
349 public ButtonStyle Style => (ButtonStyle)(ViewStyle as ButtonStyle)?.Clone();
352 /// The text of Button.
354 /// <since_tizen> 6 </since_tizen>
359 return GetValue(TextProperty) as string;
363 SetValue(TextProperty, value);
364 NotifyPropertyChanged();
367 private string InternalText
371 return TextLabel.Text;
375 TextLabel.Text = value;
377 if (Accessibility.Accessibility.IsEnabled && IsHighlighted && String.IsNullOrEmpty(AccessibilityName) && GetAccessibilityNameSignal().Empty())
379 EmitAccessibilityEvent(AccessibilityPropertyChangeEvent.Name);
385 /// Flag to decide Button can be selected or not.
387 /// <since_tizen> 6 </since_tizen>
388 public bool IsSelectable
392 return (bool)GetValue(IsSelectableProperty);
396 SetValue(IsSelectableProperty, value);
401 /// Translate text string in Button.
403 /// <since_tizen> 6 </since_tizen>
404 public string TranslatableText
408 return GetValue(TranslatableTextProperty) as string;
412 SetValue(TranslatableTextProperty, value);
413 NotifyPropertyChanged();
416 private string InternalTranslatableText
420 return TextLabel.TranslatableText;
424 TextLabel.TranslatableText = value;
429 /// Text point size in Button.
431 /// <since_tizen> 6 </since_tizen>
432 public float PointSize
436 return (float)GetValue(PointSizeProperty);
440 SetValue(PointSizeProperty, value);
441 NotifyPropertyChanged();
444 private float InternalPointSize
448 return TextLabel.PointSize;
452 TextLabel.PointSize = value;
457 /// Text font family in Button.
459 /// <since_tizen> 6 </since_tizen>
460 public string FontFamily
464 return GetValue(FontFamilyProperty) as string;
468 SetValue(FontFamilyProperty, value);
469 NotifyPropertyChanged();
472 private string InternalFontFamily
476 return TextLabel.FontFamily;
480 TextLabel.FontFamily = value;
485 /// Text color in Button.
487 /// <since_tizen> 6 </since_tizen>
488 public Color TextColor
492 return GetValue(TextColorProperty) as Color;
496 SetValue(TextColorProperty, value);
497 NotifyPropertyChanged();
500 private Color InternalTextColor
504 return TextLabel.TextColor;
508 TextLabel.TextColor = value;
513 /// Text horizontal alignment in Button.
515 /// <since_tizen> 6 </since_tizen>
516 public HorizontalAlignment TextAlignment
520 return (HorizontalAlignment)GetValue(TextAlignmentProperty);
524 SetValue(TextAlignmentProperty, value);
525 NotifyPropertyChanged();
528 private HorizontalAlignment InternalTextAlignment
532 return TextLabel.HorizontalAlignment;
536 TextLabel.HorizontalAlignment = value;
541 /// Icon image's resource url in Button.
543 /// <since_tizen> 6 </since_tizen>
544 public string IconURL
548 return GetValue(IconURLProperty) as string;
552 SetValue(IconURLProperty, value);
553 NotifyPropertyChanged();
556 private string InternalIconURL
560 return Icon.ResourceUrl;
564 Icon.ResourceUrl = value;
569 /// Icon image's size in Button.
571 [EditorBrowsable(EditorBrowsableState.Never)]
576 return GetValue(IconSizeProperty) as Size;
580 SetValue(IconSizeProperty, value);
581 NotifyPropertyChanged();
584 private Size InternalIconSize
587 set => Icon.Size = value;
591 /// Text string selector in Button.
592 /// Getter returns copied selector value if exist, null otherwise.
593 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
595 /// <since_tizen> 6 </since_tizen>
596 public StringSelector TextSelector
600 return GetValue(TextSelectorProperty) as StringSelector;
604 SetValue(TextSelectorProperty, value);
605 NotifyPropertyChanged();
608 private StringSelector InternalTextSelector
610 get => buttonText?.TextSelector == null ? null : new StringSelector(buttonText.TextSelector);
613 if (value == null || buttonText == null)
615 throw new NullReferenceException("Button.TextSelector is null");
619 buttonText.TextSelector = value;
625 /// Translatable text string selector in Button.
626 /// Getter returns copied selector value if exist, null otherwise.
628 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
629 /// <since_tizen> 6 </since_tizen>
630 public StringSelector TranslatableTextSelector
634 return GetValue(TranslatableTextSelectorProperty) as StringSelector;
638 SetValue(TranslatableTextSelectorProperty, value);
639 NotifyPropertyChanged();
642 private StringSelector InternalTranslatableTextSelector
644 get => (buttonText?.TranslatableTextSelector == null) ? null : new StringSelector(buttonText.TranslatableTextSelector);
647 if (value == null || buttonText == null)
649 throw new NullReferenceException("Button.TranslatableTextSelector is null");
653 buttonText.TranslatableTextSelector = value;
659 /// Text color selector in Button.
660 /// Getter returns copied selector value if exist, null otherwise.
662 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
663 /// <since_tizen> 6 </since_tizen>
664 public ColorSelector TextColorSelector
668 return GetValue(TextColorSelectorProperty) as ColorSelector;
672 SetValue(TextColorSelectorProperty, value);
673 NotifyPropertyChanged();
676 private ColorSelector InternalTextColorSelector
678 get => buttonText?.TextColorSelector == null ? null : new ColorSelector(buttonText.TextColorSelector);
681 if (value == null || buttonText == null)
683 throw new NullReferenceException("Button.TextColorSelectorProperty is null");
687 buttonText.TextColorSelector = value;
693 /// Text font size selector in Button.
694 /// Getter returns copied selector value if exist, null otherwise.
696 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
697 /// <since_tizen> 6 </since_tizen>
698 public FloatSelector PointSizeSelector
702 return GetValue(PointSizeSelectorProperty) as FloatSelector;
706 SetValue(PointSizeSelectorProperty, value);
707 NotifyPropertyChanged();
710 private FloatSelector InternalPointSizeSelector
712 get => buttonText?.PointSizeSelector == null ? null : new FloatSelector(buttonText.PointSizeSelector);
715 if (value == null || buttonText == null)
717 throw new NullReferenceException("Button.PointSizeSelector is null");
721 buttonText.PointSizeSelector = value;
727 /// Icon image's resource url selector in Button.
728 /// Getter returns copied selector value if exist, null otherwise.
730 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
731 /// <since_tizen> 6 </since_tizen>
732 public StringSelector IconURLSelector
736 return GetValue(IconURLSelectorProperty) as StringSelector;
740 SetValue(IconURLSelectorProperty, value);
741 NotifyPropertyChanged();
744 private StringSelector InternalIconURLSelector
746 get => buttonIcon?.ResourceUrlSelector == null ? null : new StringSelector(buttonIcon.ResourceUrlSelector);
749 if (value == null || buttonIcon == null)
751 throw new NullReferenceException("Button.IconURLSelector is null");
755 buttonIcon.ResourceUrlSelector = value;
761 /// Flag to decide selected state in Button.
763 /// <since_tizen> 6 </since_tizen>
764 public bool IsSelected
768 return (bool)GetValue(IsSelectedProperty);
772 SetValue(IsSelectedProperty, value);
777 /// Flag to decide enable or disable in Button.
779 /// <since_tizen> 6 </since_tizen>
780 public bool IsEnabled
784 return (bool)GetValue(IsEnabledProperty);
788 SetValue(IsEnabledProperty, value);
793 /// Icon relative orientation in Button, work only when show icon and text.
795 /// <since_tizen> 8 </since_tizen>
796 public IconOrientation? IconRelativeOrientation
800 return (IconOrientation?)GetValue(IconRelativeOrientationProperty) ?? IconOrientation.Left;
804 SetValue(IconRelativeOrientationProperty, value);
809 /// Icon padding in Button. It is shortcut of Icon.Padding.
811 /// <since_tizen> 6 </since_tizen>
812 public Extents IconPadding
814 get => (Extents)GetValue(IconPaddingProperty) ?? new Extents();
815 set => SetValue(IconPaddingProperty, value);
819 /// Text padding in Button. It is shortcut of TextLabel.Padding.
821 /// <since_tizen> 6 </since_tizen>
822 public Extents TextPadding
824 get => (Extents)GetValue(TextPaddingProperty) ?? new Extents();
825 set => SetValue(TextPaddingProperty, value);
829 /// The item (text or icon or both) alignment.
831 /// <since_tizen> 9 </since_tizen>
832 public LinearLayout.Alignment ItemAlignment
834 get => (LinearLayout.Alignment)GetValue(ItemAlignmentProperty);
835 set => SetValue(ItemAlignmentProperty, value);
839 /// The space between icon and text.
840 /// The value is applied when there exist icon and text both.
841 /// The width value is used when the items are arranged horizontally. Otherwise, the height value is used.
843 /// <since_tizen> 9 </since_tizen>
844 public Size2D ItemSpacing
846 get => (Size2D)GetValue(ItemSpacingProperty);
847 set => SetValue(ItemSpacingProperty, value);
851 /// Called after a key event is received by the view that has had its focus set.
853 /// <param name="key">The key event.</param>
854 /// <returns>True if the key event should be consumed.</returns>
855 /// <since_tizen> 6 </since_tizen>
856 public override bool OnKey(Key key)
858 if (!IsEnabled || null == key)
863 if (key.State == Key.StateType.Down)
865 if (key.KeyPressedName == "Return")
871 else if (key.State == Key.StateType.Up)
873 if (key.KeyPressedName == "Return")
875 bool clicked = isPressed && IsEnabled;
881 IsSelected = !IsSelected;
890 ClickedEventArgs eventArgs = new ClickedEventArgs();
891 OnClickedInternal(eventArgs);
895 return base.OnKey(key);
899 /// 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.
901 /// <since_tizen> 8 </since_tizen>
902 public override void OnFocusGained()
904 base.OnFocusGained();
909 /// 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.
911 /// <since_tizen> 8 </since_tizen>
912 public override void OnFocusLost()
919 /// Called after a touch event is received by the owning view.<br />
920 /// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).<br />
922 /// <param name="touch">The touch event.</param>
923 /// <returns>True if the event should be consumed.</returns>
924 /// <since_tizen> 8 </since_tizen>
925 [Obsolete("Deprecated in API8; Will be removed in API10. Please use OnClicked instead.")]
926 #pragma warning disable CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
927 public override bool OnTouch(Touch touch)
928 #pragma warning restore CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
930 return base.OnTouch(touch);
934 /// Apply style to button.
936 /// <param name="viewStyle">The style to apply.</param>
937 /// <since_tizen> 8 </since_tizen>
938 public override void ApplyStyle(ViewStyle viewStyle)
940 Debug.Assert(buttonIcon != null && buttonText != null);
942 styleApplied = false;
944 base.ApplyStyle(viewStyle);
946 if (viewStyle is ButtonStyle buttonStyle)
948 Extension = buttonStyle.CreateExtension();
950 if (buttonStyle.Overlay != null)
952 OverlayImage?.ApplyStyle(buttonStyle.Overlay);
955 if (Extension != null)
957 buttonIcon.Unparent();
958 buttonIcon = Extension.OnCreateIcon(this, buttonIcon);
960 buttonText.Unparent();
961 buttonText = Extension.OnCreateText(this, buttonText);
966 if (buttonStyle.Text != null)
968 buttonText.ThemeChangeSensitive = false;
969 buttonText.ApplyStyle(buttonStyle.Text);
972 if (buttonStyle.Icon != null)
974 buttonIcon.ApplyStyle(buttonStyle.Icon);
983 /// ClickEventArgs is a class to record button click event arguments which will sent to user.
985 /// <since_tizen> 6 </since_tizen>
986 [Obsolete("Deprecated in API8; Will be removed in API10. Please use ClickedEventArgs instead.")]
987 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
988 public class ClickEventArgs : EventArgs
993 /// StateChangeEventArgs is a class to record button state change event arguments which will sent to user.
995 /// <since_tizen> 6 </since_tizen>
996 [Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEventArgs")]
997 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
998 public class StateChangedEventArgs : EventArgs
1000 /// <summary> previous state of Button </summary>
1001 /// <since_tizen> 6 </since_tizen>
1002 /// It will be removed in API10
1003 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
1004 [Obsolete("Deprecated in API8; Will be removed in API10")]
1005 public ControlStates PreviousState;
1006 /// <summary> current state of Button </summary>
1007 /// <since_tizen> 6 </since_tizen>
1008 /// It will be removed in API10
1009 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
1010 [Obsolete("Deprecated in API8; Will be removed in API10")]
1011 public ControlStates CurrentState;