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();
103 defaultValueCreator: (bindable) =>
105 var instance = (Button)bindable;
106 return instance.isSelectable && instance.isSelected;
108 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
109 [EditorBrowsable(EditorBrowsableState.Never)]
110 public static readonly BindableProperty IsSelectableProperty = BindableProperty.Create(nameof(IsSelectable), typeof(bool), typeof(Button), true, propertyChanged: (bindable, oldValue, newValue) =>
112 var instance = (Button)bindable;
113 if (newValue != null)
115 bool newSelectable = (bool)newValue;
116 if (instance.isSelectable != newSelectable)
118 instance.isSelectable = newSelectable;
119 instance.UpdateState();
123 defaultValueCreator: (bindable) => ((Button)bindable).isSelectable);
125 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
126 [EditorBrowsable(EditorBrowsableState.Never)]
127 public static readonly BindableProperty IconPaddingProperty = BindableProperty.Create(nameof(IconPadding), typeof(Extents), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
129 var instance = (Button)bindable;
130 if (instance.buttonIcon == null)
134 instance.buttonIcon.Padding = (Extents)newValue;
136 defaultValueCreator: (bindable) => ((Button)bindable).buttonIcon?.Padding);
138 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
139 [EditorBrowsable(EditorBrowsableState.Never)]
140 public static readonly BindableProperty TextPaddingProperty = BindableProperty.Create(nameof(TextPadding), typeof(Extents), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
142 var instance = (Button)bindable;
143 if (instance.buttonText == null)
147 instance.buttonText.Padding = (Extents)newValue;
149 defaultValueCreator: (bindable) => ((Button)bindable).buttonText?.Padding);
151 /// <summary> The bindable property of ItemAlignment. </summary>
152 [EditorBrowsable(EditorBrowsableState.Never)]
153 internal static readonly BindableProperty ItemAlignmentProperty = BindableProperty.Create(nameof(ItemAlignment), typeof(LinearLayout.Alignment), typeof(Button), LinearLayout.Alignment.Center, propertyChanged: (bindable, oldValue, newValue) =>
155 var instance = (Button)bindable;
156 instance.itemAlignment = (LinearLayout.Alignment)newValue;
157 instance.LayoutItems();
159 defaultValueCreator: (bindable) => ((Button)bindable).itemAlignment);
161 /// <summary> The bindable property of ItemSpacing. </summary>
162 [EditorBrowsable(EditorBrowsableState.Never)]
163 internal static readonly BindableProperty ItemSpacingProperty = BindableProperty.Create(nameof(ItemSpacing), typeof(Size2D), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
165 var instance = (Button)bindable;
166 instance.itemSpacing = (Size2D)newValue;
167 instance.UpdateSizeAndSpacing();
169 defaultValueCreator: (bindable) => ((Button)bindable).itemSpacing);
171 private IconOrientation? iconRelativeOrientation = IconOrientation.Left;
172 private bool isSelected = false;
173 private bool isSelectable = false;
174 private bool isEnabled = true;
175 private Size2D itemSpacing;
176 private LinearLayout.Alignment itemAlignment;
181 /// Creates a new instance of a Button.
183 /// <since_tizen> 6 </since_tizen>
184 public Button() : base()
189 /// Creates a new instance of a Button with style.
191 /// <param name="style">Create Button by special style defined in UX.</param>
192 /// <since_tizen> 8 </since_tizen>
193 public Button(string style) : base(style)
198 /// Creates a new instance of a Button with style.
200 /// <param name="buttonStyle">Create Button by style customized by user.</param>
201 /// <since_tizen> 8 </since_tizen>
202 public Button(ButtonStyle buttonStyle) : base(buttonStyle)
207 /// Calculates current states for the button<br />
209 [EditorBrowsable(EditorBrowsableState.Never)]
210 protected override AccessibilityStates AccessibilityCalculateStates()
212 var states = base.AccessibilityCalculateStates();
213 states.Set(AccessibilityState.Checked, this.IsSelected);
214 states.Set(AccessibilityState.Enabled, this.IsEnabled);
219 /// An event for the button clicked signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
221 /// <since_tizen> 6 </since_tizen>
222 [Obsolete("Deprecated in API8; Will be removed in API10. Please use Clicked event instead.")]
223 public event EventHandler<ClickEventArgs> ClickEvent;
226 /// An event for the button clicked signal which can be used to subscribe or unsubscribe the event handler provided by the user.
228 /// <since_tizen> 8 </since_tizen>
229 public event EventHandler<ClickedEventArgs> Clicked;
232 /// An event for the button state changed signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
234 /// <since_tizen> 6 </since_tizen>
235 [Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEvent")]
236 public event EventHandler<StateChangedEventArgs> StateChangedEvent
240 stateChangeHandler += value;
244 stateChangeHandler -= value;
249 /// Icon orientation.
251 /// <since_tizen> 6 </since_tizen>
252 public enum IconOrientation
257 /// <since_tizen> 6 </since_tizen>
262 /// <since_tizen> 6 </since_tizen>
267 /// <since_tizen> 6 </since_tizen>
272 /// <since_tizen> 6 </since_tizen>
277 /// Button's icon part.
279 /// <since_tizen> 8 </since_tizen>
280 public ImageView Icon
290 /// Button's overlay image part.
292 /// <since_tizen> 8 </since_tizen>
293 public ImageView OverlayImage
297 if (null == overlayImage)
299 overlayImage = CreateOverlayImage();
300 if (null != Extension)
302 overlayImage = Extension.OnCreateOverlayImage(this, overlayImage);
304 if (null != overlayImage)
306 overlayImage.ExcludeLayouting = true;
314 overlayImage = value;
319 /// Button's text part.
321 /// <since_tizen> 8 </since_tizen>
322 public TextLabel TextLabel
328 AccessibilityManager.Instance.SetAccessibilityAttribute(this, AccessibilityManager.AccessibilityAttribute.Label, buttonText.Text);
333 /// Return currently applied style.
336 /// Modifying contents in style may cause unexpected behaviour.
338 /// <since_tizen> 8 </since_tizen>
339 public ButtonStyle Style => (ButtonStyle)(ViewStyle as ButtonStyle)?.Clone();
342 /// The text of Button.
344 /// <since_tizen> 6 </since_tizen>
349 return TextLabel.Text;
353 TextLabel.Text = value;
355 if (IsHighlighted && String.IsNullOrEmpty(AccessibilityName) && GetAccessibilityNameSignal().Empty())
357 EmitAccessibilityEvent(ObjectPropertyChangeEvent.Name);
363 /// Flag to decide Button can be selected or not.
365 /// <since_tizen> 6 </since_tizen>
366 public bool IsSelectable
370 return (bool)GetValue(IsSelectableProperty);
374 SetValue(IsSelectableProperty, value);
379 /// Translate text string in Button.
381 /// <since_tizen> 6 </since_tizen>
382 public string TranslatableText
386 return TextLabel.TranslatableText;
390 TextLabel.TranslatableText = value;
395 /// Text point size in Button.
397 /// <since_tizen> 6 </since_tizen>
398 public float PointSize
402 return TextLabel.PointSize;
406 TextLabel.PointSize = value;
411 /// Text font family in Button.
413 /// <since_tizen> 6 </since_tizen>
414 public string FontFamily
418 return TextLabel.FontFamily;
422 TextLabel.FontFamily = value;
427 /// Text color in Button.
429 /// <since_tizen> 6 </since_tizen>
430 public Color TextColor
434 return TextLabel.TextColor;
438 TextLabel.TextColor = value;
443 /// Text horizontal alignment in Button.
445 /// <since_tizen> 6 </since_tizen>
446 public HorizontalAlignment TextAlignment
450 return TextLabel.HorizontalAlignment;
454 TextLabel.HorizontalAlignment = value;
459 /// Icon image's resource url in Button.
461 /// <since_tizen> 6 </since_tizen>
462 public string IconURL
466 return Icon.ResourceUrl;
470 Icon.ResourceUrl = value;
475 /// Text string selector in Button.
476 /// Getter returns copied selector value if exist, null otherwise.
477 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
479 /// <since_tizen> 6 </since_tizen>
480 public StringSelector TextSelector
482 get => buttonText == null ? null : new StringSelector((Selector<string>)buttonText.GetValue(TextLabel.TextSelectorProperty));
485 if (value == null || buttonText == null)
487 throw new NullReferenceException("Button.TextSelector is null");
491 buttonText.SetValue(TextLabel.TextSelectorProperty, value);
497 /// Translatable text string selector in Button.
498 /// Getter returns copied selector value if exist, null otherwise.
500 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
501 /// <since_tizen> 6 </since_tizen>
502 public StringSelector TranslatableTextSelector
504 get => buttonText == null ? null : new StringSelector((Selector<string>)buttonText.GetValue(TextLabel.TranslatableTextSelectorProperty));
507 if (value == null || buttonText == null)
509 throw new NullReferenceException("Button.TranslatableTextSelector is null");
513 buttonText.SetValue(TextLabel.TranslatableTextSelectorProperty, value);
519 /// Text color selector in Button.
520 /// Getter returns copied selector value if exist, null otherwise.
522 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
523 /// <since_tizen> 6 </since_tizen>
524 public ColorSelector TextColorSelector
526 get => buttonText == null ? null : new ColorSelector((Selector<Color>)buttonText.GetValue(TextLabel.TextColorSelectorProperty));
529 if (value == null || buttonText == null)
531 throw new NullReferenceException("Button.TextColorSelectorProperty is null");
535 buttonText.SetValue(TextLabel.TextColorSelectorProperty, value);
541 /// Text font size selector in Button.
542 /// Getter returns copied selector value if exist, null otherwise.
544 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
545 /// <since_tizen> 6 </since_tizen>
546 public FloatSelector PointSizeSelector
548 get => buttonText == null ? null : new FloatSelector((Selector<float?>)buttonText.GetValue(TextLabel.PointSizeSelectorProperty));
551 if (value == null || buttonText == null)
553 throw new NullReferenceException("Button.PointSizeSelector is null");
557 buttonText.SetValue(TextLabel.PointSizeSelectorProperty, value);
563 /// Icon image's resource url selector in Button.
564 /// Getter returns copied selector value if exist, null otherwise.
566 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
567 /// <since_tizen> 6 </since_tizen>
568 public StringSelector IconURLSelector
570 get => buttonIcon == null ? null : new StringSelector((Selector<string>)buttonIcon.GetValue(ImageView.ResourceUrlSelectorProperty));
573 if (value == null || buttonIcon == null)
575 throw new NullReferenceException("Button.IconURLSelector is null");
579 buttonIcon.SetValue(ImageView.ResourceUrlSelectorProperty, value);
585 /// Flag to decide selected state in Button.
587 /// <since_tizen> 6 </since_tizen>
588 public bool IsSelected
592 return (bool)GetValue(IsSelectedProperty);
596 SetValue(IsSelectedProperty, value);
601 /// Flag to decide enable or disable in Button.
603 /// <since_tizen> 6 </since_tizen>
604 public bool IsEnabled
608 return (bool)GetValue(IsEnabledProperty);
612 SetValue(IsEnabledProperty, value);
617 /// Icon relative orientation in Button, work only when show icon and text.
619 /// <since_tizen> 8 </since_tizen>
620 public IconOrientation? IconRelativeOrientation
624 return (IconOrientation?)GetValue(IconRelativeOrientationProperty) ?? IconOrientation.Left;
628 SetValue(IconRelativeOrientationProperty, value);
633 /// Icon padding in Button. It is shortcut of Icon.Padding.
635 /// <since_tizen> 6 </since_tizen>
636 public Extents IconPadding
638 get => (Extents)GetValue(IconPaddingProperty) ?? new Extents();
639 set => SetValue(IconPaddingProperty, value);
643 /// Text padding in Button. It is shortcut of TextLabel.Padding.
645 /// <since_tizen> 6 </since_tizen>
646 public Extents TextPadding
648 get => (Extents)GetValue(TextPaddingProperty) ?? new Extents();
649 set => SetValue(TextPaddingProperty, value);
653 /// The item (text or icon or both) alignment.
655 [EditorBrowsable(EditorBrowsableState.Never)]
656 public LinearLayout.Alignment ItemAlignment
658 get => (LinearLayout.Alignment)GetValue(ItemAlignmentProperty);
659 set => SetValue(ItemAlignmentProperty, value);
663 /// The space between icon and text.
664 /// The value is applied when there exist icon and text both.
665 /// The width value is used when the items are arranged horizontally. Otherwise, the height value is used.
667 [EditorBrowsable(EditorBrowsableState.Never)]
668 public Size2D ItemSpacing
670 get => (Size2D)GetValue(ItemSpacingProperty);
671 set => SetValue(ItemSpacingProperty, value);
675 /// Called after a key event is received by the view that has had its focus set.
677 /// <param name="key">The key event.</param>
678 /// <returns>True if the key event should be consumed.</returns>
679 /// <since_tizen> 6 </since_tizen>
680 public override bool OnKey(Key key)
682 if (!IsEnabled || null == key)
687 if (key.State == Key.StateType.Down)
689 if (key.KeyPressedName == "Return")
695 else if (key.State == Key.StateType.Up)
697 if (key.KeyPressedName == "Return")
699 bool clicked = isPressed && IsEnabled;
705 IsSelected = !IsSelected;
714 ClickedEventArgs eventArgs = new ClickedEventArgs();
715 OnClickedInternal(eventArgs);
719 return base.OnKey(key);
723 /// 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.
725 /// <since_tizen> 8 </since_tizen>
726 public override void OnFocusGained()
728 base.OnFocusGained();
733 /// 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.
735 /// <since_tizen> 8 </since_tizen>
736 public override void OnFocusLost()
743 /// Called after a touch event is received by the owning view.<br />
744 /// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).<br />
746 /// <param name="touch">The touch event.</param>
747 /// <returns>True if the event should be consumed.</returns>
748 /// <since_tizen> 8 </since_tizen>
749 [Obsolete("Deprecated in API8; Will be removed in API10. Please use OnClicked instead.")]
750 #pragma warning disable CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
751 public override bool OnTouch(Touch touch)
752 #pragma warning restore CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10
754 return base.OnTouch(touch);
758 /// Apply style to button.
760 /// <param name="viewStyle">The style to apply.</param>
761 /// <since_tizen> 8 </since_tizen>
762 public override void ApplyStyle(ViewStyle viewStyle)
764 Debug.Assert(buttonIcon != null && buttonText != null);
766 styleApplied = false;
768 base.ApplyStyle(viewStyle);
770 if (viewStyle is ButtonStyle buttonStyle)
772 Extension = buttonStyle.CreateExtension();
774 if (buttonStyle.Overlay != null)
776 OverlayImage?.ApplyStyle(buttonStyle.Overlay);
779 if (Extension != null)
781 buttonIcon.Unparent();
782 buttonIcon = Extension.OnCreateIcon(this, buttonIcon);
784 buttonText.Unparent();
785 buttonText = Extension.OnCreateText(this, buttonText);
790 if (buttonStyle.Text != null)
792 buttonText.ApplyStyle(buttonStyle.Text);
795 if (buttonStyle.Icon != null)
797 buttonIcon.ApplyStyle(buttonStyle.Icon);
806 /// ClickEventArgs is a class to record button click event arguments which will sent to user.
808 /// <since_tizen> 6 </since_tizen>
809 [Obsolete("Deprecated in API8; Will be removed in API10. Please use ClickedEventArgs instead.")]
810 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
811 public class ClickEventArgs : EventArgs
816 /// StateChangeEventArgs is a class to record button state change event arguments which will sent to user.
818 /// <since_tizen> 6 </since_tizen>
819 [Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEventArgs")]
820 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
821 public class StateChangedEventArgs : EventArgs
823 /// <summary> previous state of Button </summary>
824 /// <since_tizen> 6 </since_tizen>
825 /// It will be removed in API10
826 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
827 [Obsolete("Deprecated in API8; Will be removed in API10")]
828 public ControlStates PreviousState;
829 /// <summary> current state of Button </summary>
830 /// <since_tizen> 6 </since_tizen>
831 /// It will be removed in API10
832 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
833 [Obsolete("Deprecated in API8; Will be removed in API10")]
834 public ControlStates CurrentState;