/* * Copyright(c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ using System; using System.ComponentModel; using System.Diagnostics; using Tizen.NUI.BaseComponents; using Tizen.NUI.Binding; using Tizen.NUI.Accessibility; namespace Tizen.NUI.Components { /// /// ClickedEventArgs is a class to record button click event arguments which will sent to user. /// /// 8 public class ClickedEventArgs : EventArgs { } /// /// SelectedChangedEventArgs is a class to record item selected arguments which will sent to user. /// /// 8 public class SelectedChangedEventArgs : EventArgs { /// Selected state /// 8 public bool IsSelected { get; set; } } /// /// Button is one kind of common component, a button clearly describes what action will occur when the user selects it. /// Button may contain text or an icon. /// /// 6 public partial class Button : Control { /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] public static readonly BindableProperty IconRelativeOrientationProperty = BindableProperty.Create(nameof(IconRelativeOrientation), typeof(IconOrientation?), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) => { var instance = (Button)bindable; var newIconOrientation = (IconOrientation?)newValue; if (instance.iconRelativeOrientation != newIconOrientation) { instance.iconRelativeOrientation = newIconOrientation; instance.LayoutItems(); } }, defaultValueCreator: (bindable) => ((Button)bindable).iconRelativeOrientation ); /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] public static readonly BindableProperty IsEnabledProperty = BindableProperty.Create(nameof(IsEnabled), typeof(bool), typeof(Button), true, propertyChanged: (bindable, oldValue, newValue) => { var instance = (Button)bindable; if (newValue != null) { bool newEnabled = (bool)newValue; if (instance.isEnabled != newEnabled) { instance.isEnabled = newEnabled; instance.Sensitive = newEnabled; instance.UpdateState(); } } }, defaultValueCreator: (bindable) => ((Button)bindable).isEnabled); /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(Button), true, propertyChanged: (bindable, oldValue, newValue) => { var instance = (Button)bindable; if (newValue != null) { bool newSelected = (bool)newValue; if (instance.isSelected != newSelected) { instance.isSelected = newSelected; if (instance.isSelectable) { instance.UpdateState(); } } } }, defaultValueCreator: (bindable) => { var instance = (Button)bindable; return instance.isSelectable && instance.isSelected; }); /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] public static readonly BindableProperty IsSelectableProperty = BindableProperty.Create(nameof(IsSelectable), typeof(bool), typeof(Button), true, propertyChanged: (bindable, oldValue, newValue) => { var instance = (Button)bindable; if (newValue != null) { bool newSelectable = (bool)newValue; if (instance.isSelectable != newSelectable) { instance.isSelectable = newSelectable; instance.UpdateState(); } } }, defaultValueCreator: (bindable) => ((Button)bindable).isSelectable); /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] public static readonly BindableProperty IconPaddingProperty = BindableProperty.Create(nameof(IconPadding), typeof(Extents), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) => { var instance = (Button)bindable; instance.iconPadding = (Extents)((Extents)newValue).Clone(); if (instance.buttonIcon != null) { instance.buttonIcon.Margin = instance.iconPadding; } }, defaultValueCreator: (bindable) => ((Button)bindable).iconPadding); /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] public static readonly BindableProperty TextPaddingProperty = BindableProperty.Create(nameof(TextPadding), typeof(Extents), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) => { var instance = (Button)bindable; instance.textPadding = (Extents)((Extents)newValue).Clone(); if (instance.buttonText != null) { instance.buttonText.Margin = instance.textPadding; } }, defaultValueCreator: (bindable) => ((Button)bindable).textPadding); private IconOrientation? iconRelativeOrientation = IconOrientation.Left; private bool isSelected = false; private bool isSelectable = false; private bool isEnabled = true; private Extents iconPadding; private Extents textPadding; static Button() { } /// /// Creates a new instance of a Button. /// /// 6 public Button() : base() { } /// /// Creates a new instance of a Button with style. /// /// Create Button by special style defined in UX. /// 8 public Button(string style) : base(style) { } /// /// Creates a new instance of a Button with style. /// /// Create Button by style customized by user. /// 8 public Button(ButtonStyle buttonStyle) : base(buttonStyle) { } /// /// Calculates current states for the button
///
[EditorBrowsable(EditorBrowsableState.Never)] protected override AccessibilityStates AccessibilityCalculateStates() { var states = base.AccessibilityCalculateStates(); states.Set(AccessibilityState.Enabled, this.IsEnabled); return states; } /// /// An event for the button clicked signal which can be used to subscribe or unsubscribe the event handler provided by the user.
///
/// 6 [Obsolete("Deprecated in API8; Will be removed in API10. Please use Clicked event instead.")] public event EventHandler ClickEvent; /// /// An event for the button clicked signal which can be used to subscribe or unsubscribe the event handler provided by the user. /// /// 8 public event EventHandler Clicked; /// /// An event for the button state changed signal which can be used to subscribe or unsubscribe the event handler provided by the user.
///
/// 6 [Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEvent")] public event EventHandler StateChangedEvent { add { stateChangeHandler += value; } remove { stateChangeHandler -= value; } } /// /// Icon orientation. /// /// 6 public enum IconOrientation { /// /// Top. /// /// 6 Top, /// /// Bottom. /// /// 6 Bottom, /// /// Left. /// /// 6 Left, /// /// Right. /// /// 6 Right, } /// /// Button's icon part. /// /// 8 public ImageView Icon { get => buttonIcon; internal set { buttonIcon = value; } } /// /// Button's overlay image part. /// /// 8 public ImageView OverlayImage { get { if (null == overlayImage) { overlayImage = CreateOverlayImage(); if (null != Extension) { overlayImage = Extension.OnCreateOverlayImage(this, overlayImage); } if (null != overlayImage) { overlayImage.ExcludeLayouting = true; Add(overlayImage); } } return overlayImage; } internal set { overlayImage = value; } } /// /// Button's text part. /// /// 8 public TextLabel TextLabel { get => buttonText; internal set { buttonText = value; AccessibilityManager.Instance.SetAccessibilityAttribute(this, AccessibilityManager.AccessibilityAttribute.Label, buttonText.Text); } } /// /// Return currently applied style. /// /// /// Modifying contents in style may cause unexpected behaviour. /// /// 8 public ButtonStyle Style => (ButtonStyle)(ViewStyle as ButtonStyle)?.Clone(); /// /// The text of Button. /// /// 6 public string Text { get { return TextLabel.Text; } set { TextLabel.Text = value; if (IsHighlighted && String.IsNullOrEmpty(AccessibilityName) && GetAccessibilityNameSignal().Empty()) { EmitAccessibilityEvent(ObjectPropertyChangeEvent.Name); } } } /// /// Flag to decide Button can be selected or not. /// /// 6 public bool IsSelectable { get { return (bool)GetValue(IsSelectableProperty); } set { SetValue(IsSelectableProperty, value); } } /// /// Translate text string in Button. /// /// 6 public string TranslatableText { get { return TextLabel.TranslatableText; } set { TextLabel.TranslatableText = value; } } /// /// Text point size in Button. /// /// 6 public float PointSize { get { return TextLabel.PointSize; } set { TextLabel.PointSize = value; } } /// /// Text font family in Button. /// /// 6 public string FontFamily { get { return TextLabel.FontFamily; } set { TextLabel.FontFamily = value; } } /// /// Text color in Button. /// /// 6 public Color TextColor { get { return TextLabel.TextColor; } set { TextLabel.TextColor = value; } } /// /// Text horizontal alignment in Button. /// /// 6 public HorizontalAlignment TextAlignment { get { return TextLabel.HorizontalAlignment; } set { TextLabel.HorizontalAlignment = value; } } /// /// Icon image's resource url in Button. /// /// 6 public string IconURL { get { return Icon.ResourceUrl; } set { Icon.ResourceUrl = value; } } /// /// Text string selector in Button. /// Getter returns copied selector value if exist, null otherwise. /// Thrown when setting null value. /// /// 6 public StringSelector TextSelector { get => buttonText == null ? null : new StringSelector((Selector)buttonText.GetValue(TextLabel.TextSelectorProperty)); set { if (value == null || buttonText == null) { throw new NullReferenceException("Button.TextSelector is null"); } else { buttonText.SetValue(TextLabel.TextSelectorProperty, value); } } } /// /// Translatable text string selector in Button. /// Getter returns copied selector value if exist, null otherwise. /// /// Thrown when setting null value. /// 6 public StringSelector TranslatableTextSelector { get => buttonText == null ? null : new StringSelector((Selector)buttonText.GetValue(TextLabel.TranslatableTextSelectorProperty)); set { if (value == null || buttonText == null) { throw new NullReferenceException("Button.TranslatableTextSelector is null"); } else { buttonText.SetValue(TextLabel.TranslatableTextSelectorProperty, value); } } } /// /// Text color selector in Button. /// Getter returns copied selector value if exist, null otherwise. /// /// Thrown when setting null value. /// 6 public ColorSelector TextColorSelector { get => buttonText == null ? null : new ColorSelector((Selector)buttonText.GetValue(TextLabel.TextColorSelectorProperty)); set { if (value == null || buttonText == null) { throw new NullReferenceException("Button.TextColorSelectorProperty is null"); } else { buttonText.SetValue(TextLabel.TextColorSelectorProperty, value); } } } /// /// Text font size selector in Button. /// Getter returns copied selector value if exist, null otherwise. /// /// Thrown when setting null value. /// 6 public FloatSelector PointSizeSelector { get => buttonText == null ? null : new FloatSelector((Selector)buttonText.GetValue(TextLabel.PointSizeSelectorProperty)); set { if (value == null || buttonText == null) { throw new NullReferenceException("Button.PointSizeSelector is null"); } else { buttonText.SetValue(TextLabel.PointSizeSelectorProperty, value); } } } /// /// Icon image's resource url selector in Button. /// Getter returns copied selector value if exist, null otherwise. /// /// Thrown when setting null value. /// 6 public StringSelector IconURLSelector { get => buttonIcon == null ? null : new StringSelector((Selector)buttonIcon.GetValue(ImageView.ResourceUrlSelectorProperty)); set { if (value == null || buttonIcon == null) { throw new NullReferenceException("Button.IconURLSelector is null"); } else { buttonIcon.SetValue(ImageView.ResourceUrlSelectorProperty, value); } } } /// /// Flag to decide selected state in Button. /// /// 6 public bool IsSelected { get { return (bool)GetValue(IsSelectedProperty); } set { SetValue(IsSelectedProperty, value); } } /// /// Flag to decide enable or disable in Button. /// /// 6 public bool IsEnabled { get { return (bool)GetValue(IsEnabledProperty); } set { SetValue(IsEnabledProperty, value); } } /// /// Icon relative orientation in Button, work only when show icon and text. /// /// 8 public IconOrientation? IconRelativeOrientation { get { return (IconOrientation?)GetValue(IconRelativeOrientationProperty) ?? IconOrientation.Left; } set { SetValue(IconRelativeOrientationProperty, value); } } /// /// Icon padding in Button, work only when show icon and text. /// /// 6 public Extents IconPadding { get => (Extents)GetValue(IconPaddingProperty) ?? new Extents(); set => SetValue(IconPaddingProperty, value); } /// /// Text padding in Button, work only when show icon and text. /// /// 6 public Extents TextPadding { get => (Extents)GetValue(TextPaddingProperty) ?? new Extents(); set => SetValue(TextPaddingProperty, value); } /// /// Called after a key event is received by the view that has had its focus set. /// /// The key event. /// True if the key event should be consumed. /// 6 public override bool OnKey(Key key) { if (!IsEnabled || null == key) { return false; } if (key.State == Key.StateType.Down) { if (key.KeyPressedName == "Return") { isPressed = true; UpdateState(); } } else if (key.State == Key.StateType.Up) { if (key.KeyPressedName == "Return") { bool clicked = isPressed && IsEnabled; isPressed = false; if (IsSelectable) { IsSelected = !IsSelected; } else { UpdateState(); } if (clicked) { ClickedEventArgs eventArgs = new ClickedEventArgs(); OnClickedInternal(eventArgs); } } } return base.OnKey(key); } /// /// 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. /// /// 8 public override void OnFocusGained() { base.OnFocusGained(); UpdateState(); } /// /// 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. /// /// 8 public override void OnFocusLost() { base.OnFocusLost(); UpdateState(); } /// /// Called after a touch event is received by the owning view.
/// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).
///
/// The touch event. /// True if the event should be consumed. /// 8 [Obsolete("Deprecated in API8; Will be removed in API10. Please use OnClicked instead.")] #pragma warning disable CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10 public override bool OnTouch(Touch touch) #pragma warning restore CS0809 // Obsolete member overrides non-obsolete member, It will be removed in API10 { return base.OnTouch(touch); } /// /// Apply style to button. /// /// The style to apply. /// 8 public override void ApplyStyle(ViewStyle viewStyle) { Debug.Assert(buttonIcon != null && buttonText != null); styleApplied = false; base.ApplyStyle(viewStyle); if (viewStyle is ButtonStyle buttonStyle) { Extension = buttonStyle.CreateExtension(); if (buttonStyle.Overlay != null) { OverlayImage?.ApplyStyle(buttonStyle.Overlay); } if (Extension != null) { buttonIcon.Unparent(); buttonText.Unparent(); buttonIcon = Extension.OnCreateIcon(this, buttonIcon); buttonText = Extension.OnCreateText(this, buttonText); LayoutItems(); } if (buttonStyle.Text != null) { buttonText.ApplyStyle(buttonStyle.Text); } if (buttonStyle.Icon != null) { buttonIcon.ApplyStyle(buttonStyle.Icon); } } styleApplied = true; UpdateState(); } /// /// ClickEventArgs is a class to record button click event arguments which will sent to user. /// /// 6 [Obsolete("Deprecated in API8; Will be removed in API10. Please use ClickedEventArgs instead.")] [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")] public class ClickEventArgs : EventArgs { } /// /// StateChangeEventArgs is a class to record button state change event arguments which will sent to user. /// /// 6 [Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEventArgs")] [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")] public class StateChangedEventArgs : EventArgs { /// previous state of Button /// 6 /// It will be removed in API10 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")] [Obsolete("Deprecated in API8; Will be removed in API10")] public ControlStates PreviousState; /// current state of Button /// 6 /// It will be removed in API10 [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")] [Obsolete("Deprecated in API8; Will be removed in API10")] public ControlStates CurrentState; } } }