[NUI] Fix Button Theme not to set fixed size
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Button.Internal.cs
old mode 100755 (executable)
new mode 100644 (file)
index d57c4f0..ea06e8f
@@ -1,7 +1,26 @@
-using System;
+/*
+ * Copyright(c) 2022 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.Components.Extension;
+using Tizen.NUI.Accessibility; // To use AccessibilityManager
 
 namespace Tizen.NUI.Components
 {
@@ -10,19 +29,21 @@ namespace Tizen.NUI.Components
         private ImageView overlayImage;
         private TextLabel buttonText;
         private ImageView buttonIcon;
+        private Vector2 size;
 
-        private EventHandler<StateChangedEventArgs> stateChangeHander;
+        private EventHandler<StateChangedEventArgs> stateChangeHandler;
 
-        private bool isSelected = false;
-        private bool isEnabled = true;
         private bool isPressed = false;
+        internal int styleApplying = 0;
 
-        private StringSelector textSelector = new StringSelector();
-        private StringSelector translatableTextSelector = new StringSelector();
-        private ColorSelector textColorSelector = new ColorSelector();
-        private FloatSelector pointSizeSelector = new FloatSelector();
-
-        private StringSelector iconURLSelector = new StringSelector();
+        /// <summary>
+        /// Gets accessibility name.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override string AccessibilityGetName()
+        {
+            return Text;
+        }
 
         /// <summary>
         /// The ButtonExtension instance that is injected by ButtonStyle.
@@ -37,7 +58,12 @@ namespace Tizen.NUI.Components
         [EditorBrowsable(EditorBrowsableState.Never)]
         protected virtual TextLabel CreateText()
         {
-            return new TextLabel();
+            return new TextLabel(new TextLabelStyle())
+            {
+                HorizontalAlignment = HorizontalAlignment.Center,
+                VerticalAlignment = VerticalAlignment.Center,
+                AccessibilityHidden = true,
+            };
         }
 
         /// <summary>
@@ -47,7 +73,10 @@ namespace Tizen.NUI.Components
         [EditorBrowsable(EditorBrowsableState.Never)]
         protected virtual ImageView CreateIcon()
         {
-            return new ImageView();
+            return new ImageView()
+            {
+                AccessibilityHidden = true,
+            };
         }
 
         /// <summary>
@@ -57,7 +86,15 @@ namespace Tizen.NUI.Components
         [EditorBrowsable(EditorBrowsableState.Never)]
         protected virtual ImageView CreateOverlayImage()
         {
-            return new ImageView();
+            return new ImageView
+            {
+                PositionUsesPivotPoint = true,
+                ParentOrigin = NUI.ParentOrigin.Center,
+                PivotPoint = NUI.PivotPoint.Center,
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent,
+                AccessibilityHidden = true,
+            };
         }
 
         /// <summary>
@@ -65,7 +102,7 @@ namespace Tizen.NUI.Components
         /// </summary>
         /// <param name="eventArgs">The click information.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        protected virtual void OnClick(ClickEventArgs eventArgs)
+        protected virtual void OnClicked(ClickedEventArgs eventArgs)
         {
         }
 
@@ -84,20 +121,80 @@ namespace Tizen.NUI.Components
         protected override void OnUpdate()
         {
             base.OnUpdate();
-            UpdateUIContent();
-
             Extension?.OnRelayout(this);
         }
 
+        /// <inheritdoc/>
+        [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:
+                    {
+                        if (!isPressed)
+                        {
+                            return false;
+                        }
+
+                        isPressed = false;
+
+                        if (IsSelectable)
+                        {
+                            Extension?.SetTouchInfo(touch);
+                            IsSelected = !IsSelected;
+                        }
+                        else
+                        {
+                            Extension?.SetTouchInfo(touch);
+                            UpdateState();
+                        }
+
+                        ClickedEventArgs eventArgs = new ClickedEventArgs();
+                        OnClickedInternal(eventArgs, touch);
+
+                        return true;
+                    }
+                default:
+                    break;
+            }
+            return base.HandleControlStateOnTouch(touch);
+        }
+
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void OnEnabled(bool enabled)
+        {
+            base.OnEnabled(enabled);
+            UpdateState();
+        }
+
         /// <summary>
         /// Update Button State.
         /// </summary>
-        /// <param name="touchInfo">The touch information in case the state has changed by touching.</param>
         /// <since_tizen> 6 </since_tizen>
         /// 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 (styleApplying > 0) return;
+
             ControlState sourceState = ControlState;
             ControlState targetState;
 
@@ -123,270 +220,265 @@ namespace Tizen.NUI.Components
                     PreviousState = ControlStatesExtension.FromControlStateClass(sourceState),
                     CurrentState = ControlStatesExtension.FromControlStateClass(targetState)
                 };
-                stateChangeHander?.Invoke(this, e);
+                stateChangeHandler?.Invoke(this, e);
 
                 Extension?.OnControlStateChanged(this, new ControlStateChangedEventArgs(sourceState, targetState));
             }
         }
 
         /// <summary>
-        /// Measure text, it can be override.
+        /// Dispose Button and all children on it.
         /// </summary>
+        /// <param name="type">Dispose type.</param>
         /// <since_tizen> 6 </since_tizen>
-        /// 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()
+        protected override void Dispose(DisposeTypes type)
         {
-            if (Style.IconRelativeOrientation == null || Icon == null || TextLabel == null)
+            if (disposed)
             {
                 return;
             }
-            TextLabel.WidthResizePolicy = ResizePolicyType.Fixed;
-            TextLabel.HeightResizePolicy = ResizePolicyType.Fixed;
-            int textPaddingStart = Style.TextPadding.Start;
-            int textPaddingEnd = Style.TextPadding.End;
-            int textPaddingTop = Style.TextPadding.Top;
-            int textPaddingBottom = Style.TextPadding.Bottom;
-
-            int iconPaddingStart = Style.IconPadding.Start;
-            int iconPaddingEnd = Style.IconPadding.End;
-            int iconPaddingTop = Style.IconPadding.Top;
-            int iconPaddingBottom = Style.IconPadding.Bottom;
-
-            if (IconRelativeOrientation == IconOrientation.Top || IconRelativeOrientation == IconOrientation.Bottom)
-            {
-                TextLabel.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd;
-                TextLabel.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom - iconPaddingTop - iconPaddingBottom - Icon.SizeHeight;
-            }
-            else
+
+            if (type == DisposeTypes.Explicit)
             {
-                TextLabel.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd - iconPaddingStart - iconPaddingEnd - Icon.SizeWidth;
-                TextLabel.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom;
+                Extension?.OnDispose(this);
+
+                if (buttonIcon != null)
+                {
+                    Utility.Dispose(buttonIcon);
+                }
+                if (buttonText != null)
+                {
+                    Utility.Dispose(buttonText);
+                }
+                if (overlayImage != null)
+                {
+                    Utility.Dispose(overlayImage);
+                }
             }
+
+            base.Dispose(type);
         }
 
         /// <summary>
-        /// Layout child, it can be override.
+        /// Initializes AT-SPI object.
         /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        /// 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()
+        public override void OnInitialize()
+        {
+            base.OnInitialize();
+
+            AccessibilityRole = Role.PushButton;
+            AccessibilityHighlightable = true;
+            EnableControlStatePropagation = true;
+
+            AccessibilityManager.Instance.SetAccessibilityAttribute(this, AccessibilityManager.AccessibilityAttribute.Trait, "Button");
+
+            buttonText = CreateText();
+            buttonIcon = CreateIcon();
+            LayoutItems();
+
+            Feedback = true;
+        }
+
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override void OnRelayout(Vector2 size, RelayoutContainer container)
         {
-            if (Style.IconRelativeOrientation == null || Icon == null || TextLabel == null)
+            if (size == null) return;
+
+            if (size.Equals(this.size))
             {
                 return;
             }
 
-            var buttonIcon = Icon;
-            var buttonText = TextLabel;
+            this.size = new Vector2(size);
 
-            int textPaddingStart = Style.TextPadding.Start;
-            int textPaddingEnd = Style.TextPadding.End;
-            int textPaddingTop = Style.TextPadding.Top;
-            int textPaddingBottom = Style.TextPadding.Bottom;
+            UpdateSizeAndSpacing();
+        }
 
-            int iconPaddingStart = Style.IconPadding.Start;
-            int iconPaddingEnd = Style.IconPadding.End;
-            int iconPaddingTop = Style.IconPadding.Top;
-            int iconPaddingBottom = Style.IconPadding.Bottom;
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo)
+        {
+            base.OnControlStateChanged(controlStateChangedInfo);
 
-            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);
-                    }
+            var stateEnabled = !controlStateChangedInfo.CurrentState.Contains(ControlState.Disabled);
 
-                    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 (IsEnabled != stateEnabled)
+            {
+                IsEnabled = stateEnabled;
             }
-            if (string.IsNullOrEmpty(buttonText.Text))
+
+            var statePressed = controlStateChangedInfo.CurrentState.Contains(ControlState.Pressed);
+
+            if (isPressed != statePressed)
             {
-                buttonIcon.ParentOrigin = NUI.ParentOrigin.Center;
-                buttonIcon.PivotPoint = NUI.PivotPoint.Center;
+                isPressed = statePressed;
             }
-        }
 
-        /// <summary>
-        /// Theme change callback when theme is changed, this callback will be trigger.
-        /// </summary>
-        /// <param name="sender">The sender</param>
-        /// <param name="e">The event data</param>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
-        {
-            ButtonStyle buttonStyle = StyleManager.Instance.GetViewStyle(StyleName) as ButtonStyle;
-            if (buttonStyle != null)
+            if (IsSelectable)
             {
-                Style.CopyFrom(buttonStyle);
-                UpdateUIContent();
+                var stateSelected = controlStateChangedInfo.CurrentState.Contains(ControlState.Selected);
+
+                if (IsSelected != stateSelected)
+                {
+                    IsSelected = stateSelected;
+                }
             }
         }
 
         /// <summary>
-        /// Dispose Button and all children on it.
+        /// Put sub items (e.g. buttonText, buttonIcon) to the right place.
         /// </summary>
-        /// <param name="type">Dispose type.</param>
-        /// <since_tizen> 6 </since_tizen>
-        protected override void Dispose(DisposeTypes type)
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected virtual void LayoutItems()
         {
-            if (disposed)
+            if (buttonIcon == null || buttonText == null)
             {
                 return;
             }
 
-            if (type == DisposeTypes.Explicit)
+            buttonIcon.Unparent();
+            buttonText.Unparent();
+            overlayImage?.Unparent();
+
+#pragma warning disable CA2000
+            Size2D cellPadding = String.IsNullOrEmpty(buttonText.Text) ? new Size2D(0, 0) : itemSpacing;
+#pragma warning restore CA2000
+
+            if (IconRelativeOrientation == IconOrientation.Left)
             {
-                Extension?.OnDispose(this);
+                Layout = new LinearLayout()
+                {
+                    LinearOrientation = LinearLayout.Orientation.Horizontal,
+                    HorizontalAlignment = itemHorizontalAlignment,
+                    VerticalAlignment = itemVerticalAlignment,
+                    CellPadding = cellPadding
+                };
 
-                if (Icon != null)
+                Add(buttonIcon);
+                Add(buttonText);
+            }
+            else if (IconRelativeOrientation == IconOrientation.Right)
+            {
+                Layout = new LinearLayout()
                 {
-                    Utility.Dispose(Icon);
-                }
-                if (TextLabel != null)
+                    LinearOrientation = LinearLayout.Orientation.Horizontal,
+                    HorizontalAlignment = itemHorizontalAlignment,
+                    VerticalAlignment = itemVerticalAlignment,
+                    CellPadding = cellPadding
+                };
+
+                Add(buttonText);
+                Add(buttonIcon);
+            }
+            else if (IconRelativeOrientation == IconOrientation.Top)
+            {
+                Layout = new LinearLayout()
                 {
-                    Utility.Dispose(TextLabel);
-                }
-                if (OverlayImage != null)
+                    LinearOrientation = LinearLayout.Orientation.Vertical,
+                    HorizontalAlignment = itemHorizontalAlignment,
+                    VerticalAlignment = itemVerticalAlignment,
+                    CellPadding = cellPadding
+                };
+
+                Add(buttonIcon);
+                Add(buttonText);
+            }
+            else if (IconRelativeOrientation == IconOrientation.Bottom)
+            {
+                Layout = new LinearLayout()
                 {
-                    Utility.Dispose(OverlayImage);
-                }
+                    LinearOrientation = LinearLayout.Orientation.Vertical,
+                    HorizontalAlignment = itemHorizontalAlignment,
+                    VerticalAlignment = itemVerticalAlignment,
+                    CellPadding = cellPadding
+                };
+
+                Add(buttonText);
+                Add(buttonIcon);
             }
 
-            base.Dispose(type);
+            if (overlayImage != null)
+            {
+                overlayImage.ExcludeLayouting = true;
+                Add(overlayImage);
+            }
         }
 
-        /// <inheritdoc/>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo)
+        private void UpdateSizeAndSpacing()
         {
-            base.OnControlStateChanged(controlStateChangedInfo);
+            if (size == null || buttonIcon == null || buttonText == null)
+            {
+                return;
+            }
 
-            var stateEnabled = !controlStateChangedInfo.CurrentState.Contains(ControlState.Disabled);
+            LinearLayout layout = Layout as LinearLayout;
 
-            if (isEnabled != stateEnabled)
+            if (layout == null)
             {
-                isEnabled = stateEnabled;
+                return;
             }
 
-            var statePressed = controlStateChangedInfo.CurrentState.Contains(ControlState.Pressed);
+            float lengthWithoutText = 0;
+            Size2D cellPadding = null;
+            Extents iconMargin = buttonIcon.Margin ?? new Extents(0);
+            Extents textMargin = buttonText.Margin ?? new Extents(0);
 
-            if (isPressed != statePressed)
+            if (buttonIcon.Size.Width != 0 && buttonIcon.Size.Height != 0)
             {
-                isPressed = statePressed;
-            }
-        }
+                lengthWithoutText = buttonIcon.Size.Width;
 
-        /// <summary>
-        /// It is hijack by using protected, style copy problem when class inherited from Button.
-        /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        private void Initialize()
-        {
-            var style = (ButtonStyle)Style;
-            EnableControlStatePropagation = true;
-            UpdateState();
-            LayoutDirectionChanged += OnLayoutDirectionChanged;
-        }
+                if (!String.IsNullOrEmpty(buttonText.Text))
+                {
+                    cellPadding = itemSpacing;
 
-        private void UpdateUIContent()
-        {
-            MeasureText();
-            LayoutChild();
+                    if (iconRelativeOrientation == IconOrientation.Left || iconRelativeOrientation == IconOrientation.Right)
+                    {
+                        lengthWithoutText += (itemSpacing?.Width ?? 0) + iconMargin.Start + iconMargin.End + textMargin.Start + textMargin.End + Padding.Start + Padding.End;
+                    }
+                    else
+                    {
+                        lengthWithoutText += (itemSpacing?.Height ?? 0) + iconMargin.Top + iconMargin.Bottom + textMargin.Top + textMargin.Bottom + Padding.Top + Padding.Bottom;
+                    }
+                }
+            }
 
-            Sensitive = isEnabled;
+            layout.CellPadding = cellPadding ?? new Size2D(0, 0);
+
+            // If the button has fixed width and the text is not empty, the text should not exceed button boundary.
+            if (WidthSpecification != LayoutParamPolicies.WrapContent && !String.IsNullOrEmpty(buttonText.Text))
+            {
+                buttonText.MaximumSize = new Size2D((int)Math.Max(size.Width - lengthWithoutText, Math.Max(buttonText.MinimumSize.Width, 1)), (int)size.Height);
+            }
         }
 
-        private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e)
+        private void OnClickedInternal(ClickedEventArgs eventArgs, Touch touch)
         {
-            MeasureText();
-            LayoutChild();
+            // If GrabTouchAfterLeave is true, Up will result in Finished rather than Interrupted even if it is out of the button area.
+            // So, it is necessary to check whether it is Up in the button area.
+            if (GrabTouchAfterLeave == true)
+            {
+                Vector2 localPosition = touch.GetLocalPosition(0);
+                if ((localPosition != null && Size != null &&
+                    0 <= localPosition.X && localPosition.X <= Size.Width &&
+                    0 <= localPosition.Y && localPosition.Y <= Size.Height) == false)
+                {
+                    return;
+                }
+            }
+            OnClickedInternal(eventArgs);
         }
 
-        private void OnClickInternal(ClickEventArgs eventArgs)
+        private void OnClickedInternal(ClickedEventArgs eventArgs)
         {
             Command?.Execute(CommandParameter);
-            OnClick(eventArgs);
-            Extension?.OnClick(this, eventArgs);
-            ClickEvent?.Invoke(this, eventArgs);
-        }
+            OnClicked(eventArgs);
+            Extension?.OnClicked(this, eventArgs);
 
-        private void OnIconRelayout(object sender, EventArgs e)
-        {
-            MeasureText();
-            LayoutChild();
+            ClickEventArgs nestedEventArgs = new ClickEventArgs();
+            ClickEvent?.Invoke(this, nestedEventArgs);
+            Clicked?.Invoke(this, eventArgs);
         }
-
     }
 }