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), true, 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 (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()
222 var states = base.AccessibilityCalculateStates();
223 FlagSetter(ref states, AccessibilityStates.Checked, this.IsSelected);
224 FlagSetter(ref states, AccessibilityStates.Enabled, this.IsEnabled);
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 (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 /// Text string selector in Button.
486 /// Getter returns copied selector value if exist, null otherwise.
487 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
489 /// <since_tizen> 6 </since_tizen>
490 public StringSelector TextSelector
492 get => buttonText == null ? null : new StringSelector(buttonText.TextSelector);
495 if (value == null || buttonText == null)
497 throw new NullReferenceException("Button.TextSelector is null");
501 buttonText.TextSelector = value;
507 /// Translatable text string selector in Button.
508 /// Getter returns copied selector value if exist, null otherwise.
510 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
511 /// <since_tizen> 6 </since_tizen>
512 public StringSelector TranslatableTextSelector
514 get => buttonText == null ? null : new StringSelector(buttonText.TranslatableTextSelector);
517 if (value == null || buttonText == null)
519 throw new NullReferenceException("Button.TranslatableTextSelector is null");
523 buttonText.TranslatableTextSelector = value;
529 /// Text color selector in Button.
530 /// Getter returns copied selector value if exist, null otherwise.
532 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
533 /// <since_tizen> 6 </since_tizen>
534 public ColorSelector TextColorSelector
536 get => buttonText == null ? null : new ColorSelector(buttonText.TextColorSelector);
539 if (value == null || buttonText == null)
541 throw new NullReferenceException("Button.TextColorSelectorProperty is null");
545 buttonText.TextColorSelector = value;
551 /// Text font size selector in Button.
552 /// Getter returns copied selector value if exist, null otherwise.
554 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
555 /// <since_tizen> 6 </since_tizen>
556 public FloatSelector PointSizeSelector
558 get => buttonText == null ? null : new FloatSelector(buttonText.PointSizeSelector);
561 if (value == null || buttonText == null)
563 throw new NullReferenceException("Button.PointSizeSelector is null");
567 buttonText.PointSizeSelector = value;
573 /// Icon image's resource url selector in Button.
574 /// Getter returns copied selector value if exist, null otherwise.
576 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
577 /// <since_tizen> 6 </since_tizen>
578 public StringSelector IconURLSelector
580 get => buttonIcon == null ? null : new StringSelector(buttonIcon.ResourceUrlSelector);
583 if (value == null || buttonIcon == null)
585 throw new NullReferenceException("Button.IconURLSelector is null");
589 buttonIcon.ResourceUrlSelector = value;
595 /// Flag to decide selected state in Button.
597 /// <since_tizen> 6 </since_tizen>
598 public bool IsSelected
602 return (bool)GetValue(IsSelectedProperty);
606 SetValue(IsSelectedProperty, value);
611 /// Flag to decide enable or disable in Button.
613 /// <since_tizen> 6 </since_tizen>
614 public bool IsEnabled
618 return (bool)GetValue(IsEnabledProperty);
622 SetValue(IsEnabledProperty, value);
627 /// Icon relative orientation in Button, work only when show icon and text.
629 /// <since_tizen> 8 </since_tizen>
630 public IconOrientation? IconRelativeOrientation
634 return (IconOrientation?)GetValue(IconRelativeOrientationProperty) ?? IconOrientation.Left;
638 SetValue(IconRelativeOrientationProperty, value);
643 /// Icon padding in Button. It is shortcut of Icon.Padding.
645 /// <since_tizen> 6 </since_tizen>
646 public Extents IconPadding
648 get => (Extents)GetValue(IconPaddingProperty) ?? new Extents();
649 set => SetValue(IconPaddingProperty, value);
653 /// Text padding in Button. It is shortcut of TextLabel.Padding.
655 /// <since_tizen> 6 </since_tizen>
656 public Extents TextPadding
658 get => (Extents)GetValue(TextPaddingProperty) ?? new Extents();
659 set => SetValue(TextPaddingProperty, value);
663 /// The item (text or icon or both) alignment.
665 /// <since_tizen> 9 </since_tizen>
666 public LinearLayout.Alignment ItemAlignment
668 get => (LinearLayout.Alignment)GetValue(ItemAlignmentProperty);
669 set => SetValue(ItemAlignmentProperty, value);
673 /// The space between icon and text.
674 /// The value is applied when there exist icon and text both.
675 /// The width value is used when the items are arranged horizontally. Otherwise, the height value is used.
677 /// <since_tizen> 9 </since_tizen>
678 public Size2D ItemSpacing
680 get => (Size2D)GetValue(ItemSpacingProperty);
681 set => SetValue(ItemSpacingProperty, value);
685 /// Called after a key event is received by the view that has had its focus set.
687 /// <param name="key">The key event.</param>
688 /// <returns>True if the key event should be consumed.</returns>
689 /// <since_tizen> 6 </since_tizen>
690 public override bool OnKey(Key key)
692 if (!IsEnabled || null == key)
697 if (key.State == Key.StateType.Down)
699 if (key.KeyPressedName == "Return")
705 else if (key.State == Key.StateType.Up)
707 if (key.KeyPressedName == "Return")
709 bool clicked = isPressed && IsEnabled;
715 IsSelected = !IsSelected;
724 ClickedEventArgs eventArgs = new ClickedEventArgs();
725 OnClickedInternal(eventArgs);
729 return base.OnKey(key);
733 /// 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.
735 /// <since_tizen> 8 </since_tizen>
736 public override void OnFocusGained()
738 base.OnFocusGained();
743 /// 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.
745 /// <since_tizen> 8 </since_tizen>
746 public override void OnFocusLost()
753 /// Called after a touch event is received by the owning view.<br />
754 /// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).<br />
756 /// <param name="touch">The touch event.</param>
757 /// <returns>True if the event should be consumed.</returns>
758 /// <since_tizen> 8 </since_tizen>
759 [Obsolete("Deprecated in API8; Will be removed in API10. Please use OnClicked instead.")]
760 #pragma warning disable CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
761 public override bool OnTouch(Touch touch)
762 #pragma warning restore CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
764 return base.OnTouch(touch);
768 /// Apply style to button.
770 /// <param name="viewStyle">The style to apply.</param>
771 /// <since_tizen> 8 </since_tizen>
772 public override void ApplyStyle(ViewStyle viewStyle)
774 Debug.Assert(buttonIcon != null && buttonText != null);
776 styleApplied = false;
778 base.ApplyStyle(viewStyle);
780 if (viewStyle is ButtonStyle buttonStyle)
782 Extension = buttonStyle.CreateExtension();
784 if (buttonStyle.Overlay != null)
786 OverlayImage?.ApplyStyle(buttonStyle.Overlay);
789 if (Extension != null)
791 buttonIcon.Unparent();
792 buttonIcon = Extension.OnCreateIcon(this, buttonIcon);
794 buttonText.Unparent();
795 buttonText = Extension.OnCreateText(this, buttonText);
800 if (buttonStyle.Text != null)
802 buttonText.ThemeChangeSensitive = false;
803 buttonText.ApplyStyle(buttonStyle.Text);
806 if (buttonStyle.Icon != null)
808 buttonIcon.ApplyStyle(buttonStyle.Icon);
817 /// ClickEventArgs is a class to record button click event arguments which will sent to user.
819 /// <since_tizen> 6 </since_tizen>
820 [Obsolete("Deprecated in API8; Will be removed in API10. Please use ClickedEventArgs instead.")]
821 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
822 public class ClickEventArgs : EventArgs
827 /// StateChangeEventArgs is a class to record button state change 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 View.ControlStateChangedEventArgs")]
831 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
832 public class StateChangedEventArgs : EventArgs
834 /// <summary> previous state of Button </summary>
835 /// <since_tizen> 6 </since_tizen>
836 /// It will be removed in API10
837 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
838 [Obsolete("Deprecated in API8; Will be removed in API10")]
839 public ControlStates PreviousState;
840 /// <summary> current state of Button </summary>
841 /// <since_tizen> 6 </since_tizen>
842 /// It will be removed in API10
843 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
844 [Obsolete("Deprecated in API8; Will be removed in API10")]
845 public ControlStates CurrentState;