using System; using System.ComponentModel; using Tizen.NUI.BaseComponents; using Tizen.NUI.Components.Extension; using Tizen.NUI.Accessibility; // To use AccessibilityManager namespace Tizen.NUI.Components { public partial class Button { private ImageView overlayImage; private TextLabel buttonText; private ImageView buttonIcon; private EventHandler stateChangeHandler; private bool isPressed = false; private bool styleApplied = false; /// /// The ButtonExtension instance that is injected by ButtonStyle. /// [EditorBrowsable(EditorBrowsableState.Never)] protected ButtonExtension Extension { get; set; } /// /// Creates Button's text part. /// /// The created Button's text part. [EditorBrowsable(EditorBrowsableState.Never)] protected virtual TextLabel CreateText() { return new TextLabel { PositionUsesPivotPoint = true, ParentOrigin = NUI.ParentOrigin.Center, PivotPoint = NUI.PivotPoint.Center, WidthResizePolicy = ResizePolicyType.FillToParent, HeightResizePolicy = ResizePolicyType.FillToParent, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; } /// /// Creates Button's icon part. /// /// The created Button's icon part. [EditorBrowsable(EditorBrowsableState.Never)] protected virtual ImageView CreateIcon() { return new ImageView { PositionUsesPivotPoint = true, ParentOrigin = NUI.ParentOrigin.Center, PivotPoint = NUI.PivotPoint.Center }; } /// /// Creates Button's overlay image part. /// /// The created Button's overlay image part. [EditorBrowsable(EditorBrowsableState.Never)] protected virtual ImageView CreateOverlayImage() { return new ImageView { PositionUsesPivotPoint = true, ParentOrigin = NUI.ParentOrigin.Center, PivotPoint = NUI.PivotPoint.Center, WidthResizePolicy = ResizePolicyType.FillToParent, HeightResizePolicy = ResizePolicyType.FillToParent }; } /// /// Called when the Button is Clicked by a user /// /// The click information. [EditorBrowsable(EditorBrowsableState.Never)] protected virtual void OnClicked(ClickedEventArgs eventArgs) { } /// /// Get Button style. /// /// The default button style. /// 8 protected override ViewStyle CreateViewStyle() { return new ButtonStyle(); } /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] protected override void OnUpdate() { base.OnUpdate(); UpdateUIContent(); Extension?.OnRelayout(this); } /// [EditorBrowsable(EditorBrowsableState.Never)] protected override bool HandleControlStateOnTouch(Touch touch) { if (!IsEnabled || null == touch) { return false; } PointStateType state = touch.GetState(0); switch (state) { case PointStateType.Down: isPressed = true; Extension?.SetTouchInfo(touch); UpdateState(); return true; case PointStateType.Interrupted: isPressed = false; UpdateState(); return true; case PointStateType.Up: { bool clicked = isPressed && IsEnabled; isPressed = false; if (IsSelectable) { Extension?.SetTouchInfo(touch); IsSelected = !IsSelected; } else { Extension?.SetTouchInfo(touch); UpdateState(); } if (clicked) { ClickedEventArgs eventArgs = new ClickedEventArgs(); OnClickedInternal(eventArgs); } return true; } default: break; } return base.HandleControlStateOnTouch(touch); } /// /// Update Button State. /// /// The touch information in case the state has changed by touching. /// 6 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] protected void UpdateState() { if (!styleApplied) return; ControlState sourceState = ControlState; ControlState targetState; // Normal, Disabled targetState = IsEnabled ? ControlState.Normal : ControlState.Disabled; // Selected, DisabledSelected if (IsSelected) targetState += ControlState.Selected; // Pressed, PressedSelected if (isPressed) targetState += ControlState.Pressed; // Focused, FocusedPressed, FocusedPressedSelected, DisabledFocused, DisabledSelectedFocused if (IsFocused) targetState += ControlState.Focused; if (sourceState != targetState) { ControlState = targetState; OnUpdate(); StateChangedEventArgs e = new StateChangedEventArgs { PreviousState = ControlStatesExtension.FromControlStateClass(sourceState), CurrentState = ControlStatesExtension.FromControlStateClass(targetState) }; stateChangeHandler?.Invoke(this, e); Extension?.OnControlStateChanged(this, new ControlStateChangedEventArgs(sourceState, targetState)); } } /// /// Measure text, it can be override. /// /// 6 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] protected virtual void MeasureText() { if (buttonIcon == null || buttonText == null) { return; } buttonText.WidthResizePolicy = ResizePolicyType.Fixed; buttonText.HeightResizePolicy = ResizePolicyType.Fixed; int textPaddingStart = buttonStyle.TextPadding.Start; int textPaddingEnd = buttonStyle.TextPadding.End; int textPaddingTop = buttonStyle.TextPadding.Top; int textPaddingBottom = buttonStyle.TextPadding.Bottom; int iconPaddingStart = buttonStyle.IconPadding.Start; int iconPaddingEnd = buttonStyle.IconPadding.End; int iconPaddingTop = buttonStyle.IconPadding.Top; int iconPaddingBottom = buttonStyle.IconPadding.Bottom; if (IconRelativeOrientation == IconOrientation.Top || IconRelativeOrientation == IconOrientation.Bottom) { buttonText.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd; buttonText.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom - iconPaddingTop - iconPaddingBottom - buttonIcon.SizeHeight; } else { buttonText.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd - iconPaddingStart - iconPaddingEnd - buttonIcon.SizeWidth; buttonText.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom; } } /// /// Layout child, it can be override. /// /// 6 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] protected virtual void LayoutChild() { if (buttonIcon == null || buttonText == null) { return; } int textPaddingStart = buttonStyle.TextPadding.Start; int textPaddingEnd = buttonStyle.TextPadding.End; int textPaddingTop = buttonStyle.TextPadding.Top; int textPaddingBottom = buttonStyle.TextPadding.Bottom; int iconPaddingStart = buttonStyle.IconPadding.Start; int iconPaddingEnd = buttonStyle.IconPadding.End; int iconPaddingTop = buttonStyle.IconPadding.Top; int iconPaddingBottom = buttonStyle.IconPadding.Bottom; switch (IconRelativeOrientation) { case IconOrientation.Top: buttonIcon.PositionUsesPivotPoint = true; buttonIcon.ParentOrigin = NUI.ParentOrigin.TopCenter; buttonIcon.PivotPoint = NUI.PivotPoint.TopCenter; buttonIcon.Position2D = new Position2D(0, iconPaddingTop); buttonText.PositionUsesPivotPoint = true; buttonText.ParentOrigin = NUI.ParentOrigin.BottomCenter; buttonText.PivotPoint = NUI.PivotPoint.BottomCenter; buttonText.Position2D = new Position2D(0, -textPaddingBottom); break; case IconOrientation.Bottom: buttonIcon.PositionUsesPivotPoint = true; buttonIcon.ParentOrigin = NUI.ParentOrigin.BottomCenter; buttonIcon.PivotPoint = NUI.PivotPoint.BottomCenter; buttonIcon.Position2D = new Position2D(0, -iconPaddingBottom); buttonText.PositionUsesPivotPoint = true; buttonText.ParentOrigin = NUI.ParentOrigin.TopCenter; buttonText.PivotPoint = NUI.PivotPoint.TopCenter; buttonText.Position2D = new Position2D(0, textPaddingTop); break; case IconOrientation.Left: if (LayoutDirection == ViewLayoutDirectionType.LTR) { buttonIcon.PositionUsesPivotPoint = true; buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft; buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft; buttonIcon.Position2D = new Position2D(iconPaddingStart, 0); buttonText.PositionUsesPivotPoint = true; buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight; buttonText.PivotPoint = NUI.PivotPoint.CenterRight; buttonText.Position2D = new Position2D(-textPaddingEnd, 0); } else { buttonIcon.PositionUsesPivotPoint = true; buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight; buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight; buttonIcon.Position2D = new Position2D(-iconPaddingStart, 0); buttonText.PositionUsesPivotPoint = true; buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft; buttonText.PivotPoint = NUI.PivotPoint.CenterLeft; buttonText.Position2D = new Position2D(textPaddingEnd, 0); } break; case IconOrientation.Right: if (LayoutDirection == ViewLayoutDirectionType.RTL) { buttonIcon.PositionUsesPivotPoint = true; buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft; buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft; buttonIcon.Position2D = new Position2D(iconPaddingEnd, 0); buttonText.PositionUsesPivotPoint = true; buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight; buttonText.PivotPoint = NUI.PivotPoint.CenterRight; buttonText.Position2D = new Position2D(-textPaddingStart, 0); } else { buttonIcon.PositionUsesPivotPoint = true; buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight; buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight; buttonIcon.Position2D = new Position2D(-iconPaddingEnd, 0); buttonText.PositionUsesPivotPoint = true; buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft; buttonText.PivotPoint = NUI.PivotPoint.CenterLeft; buttonText.Position2D = new Position2D(textPaddingStart, 0); } break; default: break; } if (string.IsNullOrEmpty(buttonText.Text)) { buttonIcon.ParentOrigin = NUI.ParentOrigin.Center; buttonIcon.PivotPoint = NUI.PivotPoint.Center; } } /// /// Dispose Button and all children on it. /// /// Dispose type. /// 6 protected override void Dispose(DisposeTypes type) { if (disposed) { return; } if (type == DisposeTypes.Explicit) { Extension?.OnDispose(this); if (buttonIcon != null) { Utility.Dispose(buttonIcon); } if (buttonText != null) { Utility.Dispose(buttonText); } if (overlayImage != null) { Utility.Dispose(overlayImage); } } base.Dispose(type); } /// [EditorBrowsable(EditorBrowsableState.Never)] protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo) { base.OnControlStateChanged(controlStateChangedInfo); var stateEnabled = !controlStateChangedInfo.CurrentState.Contains(ControlState.Disabled); if (IsEnabled != stateEnabled) { IsEnabled = stateEnabled; } var statePressed = controlStateChangedInfo.CurrentState.Contains(ControlState.Pressed); if (isPressed != statePressed) { isPressed = statePressed; } } /// /// It is hijack by using protected, style copy problem when class inherited from Button. /// /// 6 private void Initialize() { EnableControlStatePropagation = true; UpdateState(); LayoutDirectionChanged += OnLayoutDirectionChanged; AccessibilityManager.Instance.SetAccessibilityAttribute(this, AccessibilityManager.AccessibilityAttribute.Trait, "Button"); } private void UpdateUIContent() { MeasureText(); LayoutChild(); Sensitive = IsEnabled; } private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e) { MeasureText(); LayoutChild(); } private void OnClickedInternal(ClickedEventArgs eventArgs) { Command?.Execute(CommandParameter); OnClicked(eventArgs); Extension?.OnClicked(this, eventArgs); ClickEventArgs nestedEventArgs = new ClickEventArgs(); ClickEvent?.Invoke(this, nestedEventArgs); Clicked?.Invoke(this, eventArgs); } private void OnIconRelayout(object sender, EventArgs e) { MeasureText(); LayoutChild(); } internal override bool OnAccessibilityActivated() { if (!IsEnabled) { return false; } // Touch Down isPressed = true; UpdateState(); // Touch Up bool clicked = isPressed && IsEnabled; isPressed = false; if (IsSelectable) { IsSelected = !IsSelected; } else { UpdateState(); } if (clicked) { ClickedEventArgs eventArgs = new ClickedEventArgs(); OnClickedInternal(eventArgs); } return true; } } }