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.Enabled && 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 TextLabel.Text;
363 TextLabel.Text = value;
365 if (Accessibility.Accessibility.Enabled && IsHighlighted && String.IsNullOrEmpty(AccessibilityName) && GetAccessibilityNameSignal().Empty())
367 EmitAccessibilityEvent(AccessibilityPropertyChangeEvent.Name);
373 /// Flag to decide Button can be selected or not.
375 /// <since_tizen> 6 </since_tizen>
376 public bool IsSelectable
380 return (bool)GetValue(IsSelectableProperty);
384 SetValue(IsSelectableProperty, value);
389 /// Translate text string in Button.
391 /// <since_tizen> 6 </since_tizen>
392 public string TranslatableText
396 return TextLabel.TranslatableText;
400 TextLabel.TranslatableText = value;
405 /// Text point size in Button.
407 /// <since_tizen> 6 </since_tizen>
408 public float PointSize
412 return TextLabel.PointSize;
416 TextLabel.PointSize = value;
421 /// Text font family in Button.
423 /// <since_tizen> 6 </since_tizen>
424 public string FontFamily
428 return TextLabel.FontFamily;
432 TextLabel.FontFamily = value;
437 /// Text color in Button.
439 /// <since_tizen> 6 </since_tizen>
440 public Color TextColor
444 return TextLabel.TextColor;
448 TextLabel.TextColor = value;
453 /// Text horizontal alignment in Button.
455 /// <since_tizen> 6 </since_tizen>
456 public HorizontalAlignment TextAlignment
460 return TextLabel.HorizontalAlignment;
464 TextLabel.HorizontalAlignment = value;
469 /// Icon image's resource url in Button.
471 /// <since_tizen> 6 </since_tizen>
472 public string IconURL
476 return Icon.ResourceUrl;
480 Icon.ResourceUrl = value;
485 /// Icon image's size in Button.
487 [EditorBrowsable(EditorBrowsableState.Never)]
491 set => Icon.Size = value;
495 /// Text string selector in Button.
496 /// Getter returns copied selector value if exist, null otherwise.
497 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
499 /// <since_tizen> 6 </since_tizen>
500 public StringSelector TextSelector
502 get => buttonText == null ? null : new StringSelector(buttonText.TextSelector);
505 if (value == null || buttonText == null)
507 throw new NullReferenceException("Button.TextSelector is null");
511 buttonText.TextSelector = value;
517 /// Translatable text string selector in Button.
518 /// Getter returns copied selector value if exist, null otherwise.
520 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
521 /// <since_tizen> 6 </since_tizen>
522 public StringSelector TranslatableTextSelector
524 get => buttonText == null ? null : new StringSelector(buttonText.TranslatableTextSelector);
527 if (value == null || buttonText == null)
529 throw new NullReferenceException("Button.TranslatableTextSelector is null");
533 buttonText.TranslatableTextSelector = value;
539 /// Text color selector in Button.
540 /// Getter returns copied selector value if exist, null otherwise.
542 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
543 /// <since_tizen> 6 </since_tizen>
544 public ColorSelector TextColorSelector
546 get => buttonText == null ? null : new ColorSelector(buttonText.TextColorSelector);
549 if (value == null || buttonText == null)
551 throw new NullReferenceException("Button.TextColorSelectorProperty is null");
555 buttonText.TextColorSelector = value;
561 /// Text font size selector in Button.
562 /// Getter returns copied selector value if exist, null otherwise.
564 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
565 /// <since_tizen> 6 </since_tizen>
566 public FloatSelector PointSizeSelector
568 get => buttonText == null ? null : new FloatSelector(buttonText.PointSizeSelector);
571 if (value == null || buttonText == null)
573 throw new NullReferenceException("Button.PointSizeSelector is null");
577 buttonText.PointSizeSelector = value;
583 /// Icon image's resource url selector in Button.
584 /// Getter returns copied selector value if exist, null otherwise.
586 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
587 /// <since_tizen> 6 </since_tizen>
588 public StringSelector IconURLSelector
590 get => buttonIcon == null ? null : new StringSelector(buttonIcon.ResourceUrlSelector);
593 if (value == null || buttonIcon == null)
595 throw new NullReferenceException("Button.IconURLSelector is null");
599 buttonIcon.ResourceUrlSelector = value;
605 /// Flag to decide selected state in Button.
607 /// <since_tizen> 6 </since_tizen>
608 public bool IsSelected
612 return (bool)GetValue(IsSelectedProperty);
616 SetValue(IsSelectedProperty, value);
621 /// Flag to decide enable or disable in Button.
623 /// <since_tizen> 6 </since_tizen>
624 public bool IsEnabled
628 return (bool)GetValue(IsEnabledProperty);
632 SetValue(IsEnabledProperty, value);
637 /// Icon relative orientation in Button, work only when show icon and text.
639 /// <since_tizen> 8 </since_tizen>
640 public IconOrientation? IconRelativeOrientation
644 return (IconOrientation?)GetValue(IconRelativeOrientationProperty) ?? IconOrientation.Left;
648 SetValue(IconRelativeOrientationProperty, value);
653 /// Icon padding in Button. It is shortcut of Icon.Padding.
655 /// <since_tizen> 6 </since_tizen>
656 public Extents IconPadding
658 get => (Extents)GetValue(IconPaddingProperty) ?? new Extents();
659 set => SetValue(IconPaddingProperty, value);
663 /// Text padding in Button. It is shortcut of TextLabel.Padding.
665 /// <since_tizen> 6 </since_tizen>
666 public Extents TextPadding
668 get => (Extents)GetValue(TextPaddingProperty) ?? new Extents();
669 set => SetValue(TextPaddingProperty, value);
673 /// The item (text or icon or both) alignment.
675 /// <since_tizen> 9 </since_tizen>
676 public LinearLayout.Alignment ItemAlignment
678 get => (LinearLayout.Alignment)GetValue(ItemAlignmentProperty);
679 set => SetValue(ItemAlignmentProperty, value);
683 /// The space between icon and text.
684 /// The value is applied when there exist icon and text both.
685 /// The width value is used when the items are arranged horizontally. Otherwise, the height value is used.
687 /// <since_tizen> 9 </since_tizen>
688 public Size2D ItemSpacing
690 get => (Size2D)GetValue(ItemSpacingProperty);
691 set => SetValue(ItemSpacingProperty, value);
695 /// Called after a key event is received by the view that has had its focus set.
697 /// <param name="key">The key event.</param>
698 /// <returns>True if the key event should be consumed.</returns>
699 /// <since_tizen> 6 </since_tizen>
700 public override bool OnKey(Key key)
702 if (!IsEnabled || null == key)
707 if (key.State == Key.StateType.Down)
709 if (key.KeyPressedName == "Return")
715 else if (key.State == Key.StateType.Up)
717 if (key.KeyPressedName == "Return")
719 bool clicked = isPressed && IsEnabled;
725 IsSelected = !IsSelected;
734 ClickedEventArgs eventArgs = new ClickedEventArgs();
735 OnClickedInternal(eventArgs);
739 return base.OnKey(key);
743 /// 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.
745 /// <since_tizen> 8 </since_tizen>
746 public override void OnFocusGained()
748 base.OnFocusGained();
753 /// 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.
755 /// <since_tizen> 8 </since_tizen>
756 public override void OnFocusLost()
763 /// Called after a touch event is received by the owning view.<br />
764 /// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).<br />
766 /// <param name="touch">The touch event.</param>
767 /// <returns>True if the event should be consumed.</returns>
768 /// <since_tizen> 8 </since_tizen>
769 [Obsolete("Deprecated in API8; Will be removed in API10. Please use OnClicked instead.")]
770 #pragma warning disable CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
771 public override bool OnTouch(Touch touch)
772 #pragma warning restore CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
774 return base.OnTouch(touch);
778 /// Apply style to button.
780 /// <param name="viewStyle">The style to apply.</param>
781 /// <since_tizen> 8 </since_tizen>
782 public override void ApplyStyle(ViewStyle viewStyle)
784 Debug.Assert(buttonIcon != null && buttonText != null);
786 styleApplied = false;
788 base.ApplyStyle(viewStyle);
790 if (viewStyle is ButtonStyle buttonStyle)
792 Extension = buttonStyle.CreateExtension();
794 if (buttonStyle.Overlay != null)
796 OverlayImage?.ApplyStyle(buttonStyle.Overlay);
799 if (Extension != null)
801 buttonIcon.Unparent();
802 buttonIcon = Extension.OnCreateIcon(this, buttonIcon);
804 buttonText.Unparent();
805 buttonText = Extension.OnCreateText(this, buttonText);
810 if (buttonStyle.Text != null)
812 buttonText.ThemeChangeSensitive = false;
813 buttonText.ApplyStyle(buttonStyle.Text);
816 if (buttonStyle.Icon != null)
818 buttonIcon.ApplyStyle(buttonStyle.Icon);
827 /// ClickEventArgs is a class to record button click event arguments which will sent to user.
829 /// <since_tizen> 6 </since_tizen>
830 [Obsolete("Deprecated in API8; Will be removed in API10. Please use ClickedEventArgs instead.")]
831 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
832 public class ClickEventArgs : EventArgs
837 /// StateChangeEventArgs is a class to record button state change event arguments which will sent to user.
839 /// <since_tizen> 6 </since_tizen>
840 [Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEventArgs")]
841 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
842 public class StateChangedEventArgs : EventArgs
844 /// <summary> previous state of Button </summary>
845 /// <since_tizen> 6 </since_tizen>
846 /// It will be removed in API10
847 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
848 [Obsolete("Deprecated in API8; Will be removed in API10")]
849 public ControlStates PreviousState;
850 /// <summary> current state of Button </summary>
851 /// <since_tizen> 6 </since_tizen>
852 /// It will be removed in API10
853 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
854 [Obsolete("Deprecated in API8; Will be removed in API10")]
855 public ControlStates CurrentState;