/*
- * Copyright(c) 2020 Samsung Electronics Co., Ltd.
+ * 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.
*/
using System;
using System.ComponentModel;
+using System.Diagnostics;
using Tizen.NUI.BaseComponents;
using Tizen.NUI.Binding;
-using Tizen.NUI.Components.Extension;
using Tizen.NUI.Accessibility;
namespace Tizen.NUI.Components
}
/// <summary>
+ /// SelectedChangedEventArgs is a class to record item selected arguments which will sent to user.
+ /// </summary>
+ /// <since_tizen> 8 </since_tizen>
+ public class SelectedChangedEventArgs : EventArgs
+ {
+ /// <summary> Selected state </summary>
+ /// <since_tizen> 8 </since_tizen>
+ public bool IsSelected { get; set; }
+ }
+
+ /// <summary>
/// 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.
/// </summary>
public static readonly BindableProperty IconRelativeOrientationProperty = BindableProperty.Create(nameof(IconRelativeOrientation), typeof(IconOrientation?), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
{
var instance = (Button)bindable;
- if (newValue != null)
+ var newIconOrientation = (IconOrientation?)newValue;
+ if (instance.iconRelativeOrientation != newIconOrientation)
{
- if (instance.buttonStyle != null && instance.buttonStyle.IconRelativeOrientation != (IconOrientation?)newValue)
- {
- instance.buttonStyle.IconRelativeOrientation = (IconOrientation?)newValue;
- instance.UpdateUIContent();
- }
+ instance.iconRelativeOrientation = newIconOrientation;
+ instance.LayoutItems();
}
},
- defaultValueCreator: (bindable) =>
- {
- var instance = (Button)bindable;
- return instance.buttonStyle?.IconRelativeOrientation;
- });
+ 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)
{
- if (instance.buttonStyle != null && (!instance.styleApplied || instance.buttonStyle.IsEnabled != (bool)newValue))
+ bool newEnabled = (bool)newValue;
+ if (instance.isEnabled != newEnabled)
{
- instance.buttonStyle.IsEnabled = (bool)newValue;
+ instance.isEnabled = newEnabled;
+ instance.Sensitive = newEnabled;
instance.UpdateState();
}
}
},
- defaultValueCreator: (bindable) =>
- {
- var instance = (Button)bindable;
- return instance.buttonStyle?.IsEnabled ?? true;
- });
+ 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)
{
- if (instance.buttonStyle != null && instance.IsSelectable && (!instance.styleApplied || instance.buttonStyle.IsSelected != (bool)newValue))
+ bool newSelected = (bool)newValue;
+ if (instance.isSelected != newSelected)
{
- instance.buttonStyle.IsSelected = (bool)newValue;
- instance.UpdateState();
+ instance.isSelected = newSelected;
+
+ if (instance.isSelectable)
+ {
+ instance.UpdateState();
+ }
}
}
},
defaultValueCreator: (bindable) =>
{
var instance = (Button)bindable;
- return instance.IsSelectable && (instance.buttonStyle.IsSelected ?? false);
+ 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)]
var instance = (Button)bindable;
if (newValue != null)
{
- if (instance.buttonStyle != null && (!instance.styleApplied || instance.buttonStyle.IsSelectable != (bool)newValue))
+ bool newSelectable = (bool)newValue;
+ if (instance.isSelectable != newSelectable)
{
- instance.buttonStyle.IsSelectable = (bool)newValue;
+ instance.isSelectable = newSelectable;
+ instance.UpdateState();
}
}
},
- defaultValueCreator: (bindable) =>
- {
- var instance = (Button)bindable;
- return instance.buttonStyle?.IsSelectable ?? false;
- });
+ 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;
- if (null != newValue && null != instance.buttonStyle?.IconPadding)
+ if (instance.buttonIcon == null)
{
- instance.buttonStyle.IconPadding.CopyFrom((Extents)newValue);
- instance.UpdateUIContent();
+ return;
}
+ instance.buttonIcon.Padding = (Extents)newValue;
},
- defaultValueCreator: (bindable) =>
- {
- var instance = (Button)bindable;
- return instance.buttonStyle?.IconPadding;
- });
+ defaultValueCreator: (bindable) => ((Button)bindable).buttonIcon?.Padding);
+
/// 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;
- if (null != newValue && null != instance.buttonStyle?.TextPadding)
+ if (instance.buttonText == null)
{
- instance.buttonStyle.TextPadding.CopyFrom((Extents)newValue);
- instance.UpdateUIContent();
+ return;
}
+ instance.buttonText.Padding = (Extents)newValue;
},
- defaultValueCreator: (bindable) =>
+ defaultValueCreator: (bindable) => ((Button)bindable).buttonText?.Padding);
+
+ /// <summary> The bindable property of ItemAlignment. </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal static readonly BindableProperty ItemAlignmentProperty = BindableProperty.Create(nameof(ItemAlignment), typeof(LinearLayout.Alignment), typeof(Button), LinearLayout.Alignment.Center, propertyChanged: (bindable, oldValue, newValue) =>
{
var instance = (Button)bindable;
- return instance.buttonStyle?.TextPadding;
- });
+ instance.itemAlignment = (LinearLayout.Alignment)newValue;
+ instance.LayoutItems();
+ },
+ defaultValueCreator: (bindable) => ((Button)bindable).itemAlignment);
+
+ /// <summary> The bindable property of ItemSpacing. </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal static readonly BindableProperty ItemSpacingProperty = BindableProperty.Create(nameof(ItemSpacing), typeof(Size2D), typeof(Button), null, propertyChanged: (bindable, oldValue, newValue) =>
+ {
+ var instance = (Button)bindable;
+ instance.itemSpacing = (Size2D)newValue;
+ instance.UpdateSizeAndSpacing();
+ },
+ defaultValueCreator: (bindable) => ((Button)bindable).itemSpacing);
+
+ private IconOrientation? iconRelativeOrientation = IconOrientation.Left;
+ private bool isSelected = false;
+ private bool isSelectable = false;
+ private bool isEnabled = true;
+ private Size2D itemSpacing;
+ private LinearLayout.Alignment itemAlignment;
static Button() { }
/// <since_tizen> 6 </since_tizen>
public Button() : base()
{
- Initialize();
}
/// <summary>
/// <since_tizen> 8 </since_tizen>
public Button(string style) : base(style)
{
- Initialize();
}
/// <summary>
/// <since_tizen> 8 </since_tizen>
public Button(ButtonStyle buttonStyle) : base(buttonStyle)
{
- Initialize();
+ }
+
+ /// <summary>
+ /// Calculates current states for the button<br />
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override AccessibilityStates AccessibilityCalculateStates()
+ {
+ var states = base.AccessibilityCalculateStates();
+ states.Set(AccessibilityState.Checked, this.IsSelected);
+ states.Set(AccessibilityState.Enabled, this.IsEnabled);
+ return states;
}
/// <summary>
/// <since_tizen> 8 </since_tizen>
public ImageView Icon
{
- get
- {
- if (null == buttonIcon)
- {
- buttonIcon = CreateIcon();
- if (null != Extension)
- {
- buttonIcon = Extension.OnCreateIcon(this, buttonIcon);
- }
- Add(buttonIcon);
- buttonIcon.Relayout += OnIconRelayout;
- }
- return buttonIcon;
- }
+ get => buttonIcon;
internal set
{
buttonIcon = value;
{
overlayImage = Extension.OnCreateOverlayImage(this, overlayImage);
}
- overlayImage.WidthResizePolicy = ResizePolicyType.FillToParent;
- overlayImage.HeightResizePolicy = ResizePolicyType.FillToParent;
- Add(overlayImage);
+ if (null != overlayImage)
+ {
+ overlayImage.ExcludeLayouting = true;
+ Add(overlayImage);
+ }
}
return overlayImage;
}
/// <since_tizen> 8 </since_tizen>
public TextLabel TextLabel
{
- get
- {
- if (null == buttonText)
- {
- buttonText = CreateText();
- if (null != Extension)
- {
- buttonText = Extension.OnCreateText(this, buttonText);
- }
- buttonText.HorizontalAlignment = HorizontalAlignment.Center;
- buttonText.VerticalAlignment = VerticalAlignment.Center;
- Add(buttonText);
- }
- return buttonText;
- }
+ get => buttonText;
internal set
{
buttonText = value;
}
/// <summary>
- /// Return a copied Style instance of Button
+ /// Return currently applied style.
/// </summary>
/// <remarks>
- /// It returns copied Style instance and changing it does not effect to the Button.
- /// Style setting is possible by using constructor or the function of ApplyStyle(ViewStyle viewStyle)
+ /// Modifying contents in style may cause unexpected behaviour.
/// </remarks>
/// <since_tizen> 8 </since_tizen>
- public new ButtonStyle Style
- {
- get
- {
- var result = (ButtonStyle)ViewStyle.Clone();
- result.CopyPropertiesFromView(this);
- result.Text.CopyPropertiesFromView(TextLabel);
- result.Icon.CopyPropertiesFromView(Icon);
- result.Overlay.CopyPropertiesFromView(OverlayImage);
- return result;
- }
- }
+ public ButtonStyle Style => (ButtonStyle)(ViewStyle as ButtonStyle)?.Clone();
/// <summary>
/// The text of Button.
set
{
TextLabel.Text = value;
+
+ if (IsHighlighted && String.IsNullOrEmpty(AccessibilityName) && GetAccessibilityNameSignal().Empty())
+ {
+ EmitAccessibilityEvent(ObjectPropertyChangeEvent.Name);
+ }
}
}
}
/// <summary>
- /// Translateable text string selector in Button.
+ /// Translatable text string selector in Button.
/// Getter returns copied selector value if exist, null otherwise.
/// </summary>
/// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
{
get
{
- return (IconOrientation?)GetValue(IconRelativeOrientationProperty);
+ return (IconOrientation?)GetValue(IconRelativeOrientationProperty) ?? IconOrientation.Left;
}
set
{
}
/// <summary>
- /// Icon padding in Button, work only when show icon and text.
+ /// Icon padding in Button. It is shortcut of Icon.Padding.
/// </summary>
/// <since_tizen> 6 </since_tizen>
public Extents IconPadding
{
- get => (Extents)GetValue(IconPaddingProperty);
+ get => (Extents)GetValue(IconPaddingProperty) ?? new Extents();
set => SetValue(IconPaddingProperty, value);
}
/// <summary>
- /// Text padding in Button, work only when show icon and text.
+ /// Text padding in Button. It is shortcut of TextLabel.Padding.
/// </summary>
/// <since_tizen> 6 </since_tizen>
public Extents TextPadding
{
- get => (Extents)GetValue(TextPaddingProperty);
+ get => (Extents)GetValue(TextPaddingProperty) ?? new Extents();
set => SetValue(TextPaddingProperty, value);
}
- private ButtonStyle buttonStyle => ViewStyle as ButtonStyle;
+ /// <summary>
+ /// The item (text or icon or both) alignment.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public LinearLayout.Alignment ItemAlignment
+ {
+ get => (LinearLayout.Alignment)GetValue(ItemAlignmentProperty);
+ set => SetValue(ItemAlignmentProperty, value);
+ }
+
+ /// <summary>
+ /// The space between icon and text.
+ /// The value is applied when there exist icon and text both.
+ /// The width value is used when the items are arranged horizontally. Otherwise, the height value is used.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Size2D ItemSpacing
+ {
+ get => (Size2D)GetValue(ItemSpacingProperty);
+ set => SetValue(ItemSpacingProperty, value);
+ }
/// <summary>
/// Called after a key event is received by the view that has had its focus set.
/// <param name="touch">The touch event.</param>
/// <returns>True if the event should be consumed.</returns>
/// <since_tizen> 8 </since_tizen>
+ [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);
}
/// <since_tizen> 8 </since_tizen>
public override void ApplyStyle(ViewStyle viewStyle)
{
+ Debug.Assert(buttonIcon != null && buttonText != null);
+
styleApplied = false;
base.ApplyStyle(viewStyle);
- if (null != buttonStyle)
+ if (viewStyle is ButtonStyle buttonStyle)
{
Extension = buttonStyle.CreateExtension();
+
if (buttonStyle.Overlay != null)
- {
+ {
OverlayImage?.ApplyStyle(buttonStyle.Overlay);
}
+ if (Extension != null)
+ {
+ buttonIcon.Unparent();
+ buttonIcon = Extension.OnCreateIcon(this, buttonIcon);
+
+ buttonText.Unparent();
+ buttonText = Extension.OnCreateText(this, buttonText);
+
+ LayoutItems();
+ }
+
if (buttonStyle.Text != null)
{
- TextLabel?.ApplyStyle(buttonStyle.Text);
+ buttonText.ApplyStyle(buttonStyle.Text);
}
if (buttonStyle.Icon != null)
{
- Icon?.ApplyStyle(buttonStyle.Icon);
+ buttonIcon.ApplyStyle(buttonStyle.Icon);
}
}
styleApplied = true;
+ UpdateState();
}
/// <summary>
/// </summary>
/// <since_tizen> 6 </since_tizen>
[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
{
}
/// </summary>
/// <since_tizen> 6 </since_tizen>
[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
{
/// <summary> previous state of Button </summary>
/// <since_tizen> 6 </since_tizen>
+ /// 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;
/// <summary> current state of Button </summary>
/// <since_tizen> 6 </since_tizen>
+ /// 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;
}
-
- /// <summary>
- /// Get current text part to the attached ButtonExtension.
- /// </summary>
- /// <remarks>
- /// It returns null if the passed extension is invalid.
- /// </remarks>
- /// <param name="extension">The extension instance that is currently attached to this Button.</param>
- /// <return>The button's text part.</return>
- [EditorBrowsable(EditorBrowsableState.Never)]
- public TextLabel GetCurrentText(ButtonExtension extension)
- {
- return (extension == Extension) ? TextLabel : null;
- }
-
- /// <summary>
- /// Get current icon part to the attached ButtonExtension.
- /// </summary>
- /// <remarks>
- /// It returns null if the passed extension is invalid.
- /// </remarks>
- /// <param name="extension">The extension instance that is currently attached to this Button.</param>
- /// <return>The button's icon part.</return>
- [EditorBrowsable(EditorBrowsableState.Never)]
- public ImageView GetCurrentIcon(ButtonExtension extension)
- {
- return (extension == Extension) ? Icon : null;
- }
-
- /// <summary>
- /// Get current overlay image part to the attached ButtonExtension.
- /// </summary>
- /// <remarks>
- /// It returns null if the passed extension is invalid.
- /// </remarks>
- /// <param name="extension">The extension instance that is currently attached to this Button.</param>
- /// <return>The button's overlay image part.</return>
- [EditorBrowsable(EditorBrowsableState.Never)]
- public ImageView GetCurrentOverlayImage(ButtonExtension extension)
- {
- return (extension == Extension) ? OverlayImage : null;
- }
}
}