/// <summary>
        /// Tries to handle cursor activity. If this returns true, then either this element or one of its
        /// children handled the activity.
        /// </summary>
        /// <param name="cursor">Reference to the cursor object</param>
        /// <returns>Whether this or one of its children handled the cursor activity, blocking other windows from receiving cursor input this frame.</returns>
        /// <remarks>This method will always allow children to handle the activity first, as children draw in front of their parents. Only components
        /// can have UI elements. Standard elements such as Sprites or Containers cannot themselves handle the activity, but they do give their children the
        /// opportunity to handle activity. This is because components (such as buttons) may be part of a container for stacking or other organization.
        ///
        /// Ultimately this hierarchical logic exists because only the top-most parent is added to the GuiManager, and it is responsible for
        /// giving its children the opportunity to perform cursor-related input. </remarks>
        private bool TryHandleCursorActivity(Cursor cursor, HandledActions handledActions)
        {
            bool handledByChild = false;
            bool handledByThis  = false;

            bool isOver = HasCursorOver(cursor);


            // Even though the cursor is over "this", we need to check if the cursor is over any children in case "this" exposes its children events:
            if (isOver && this.ExposeChildrenEvents)
            {
                #region Try handling by children

                // Let's see if any children have the cursor over:
                for (int i = this.Children.Count - 1; i > -1; i--)
                {
                    var child = this.Children[i];
                    if (child is GraphicalUiElement)
                    {
                        var asGue = child as GraphicalUiElement;
                        // Children should always have the opportunity to handle activity,
                        // even if they are not components, because they may contain components as their children

                        // If the child either has events or exposes children events, then give it a chance to handle this activity.

                        if ((asGue.HasEvents || asGue.ExposeChildrenEvents) && asGue.HasCursorOver(cursor))
                        {
                            handledByChild = asGue.TryHandleCursorActivity(cursor, handledActions);

                            if (handledByChild)
                            {
                                break;
                            }
                        }
                    }
                }

                #endregion
            }
            if (isOver)
            {
                if (this.IsComponentOrInstanceOfComponent())
                {
                    if (!handledByChild)
                    {
                        // Feb. 21, 2018
                        // If not handled by
                        // children, then this
                        // can only handle if this
                        // exposes events. Otherwise,
                        // it shouldn't handle anything
                        // and the parent should be given
                        // the opportunity.
                        // I'm not sure why this was outside
                        // of the if(this.HasEvents)...seems intentional
                        // but it causes problems when the rootmost object
                        // exposes children events but doesn't handle its own
                        // events...
                        //handledByThis = true;

                        if (this.HasEvents)
                        {
                            // moved from above, see comments there...
                            handledByThis     = true;
                            cursor.WindowOver = this;

                            if (cursor.PrimaryPush && Enabled)
                            {
                                cursor.WindowPushed = this;

                                if (Push != null)
                                {
                                    Push(this);
                                }


                                cursor.GrabWindow(this);
                            }

                            if (cursor.PrimaryClick && Enabled) // both pushing and clicking can occur in one frame because of buffered input
                            {
                                if (cursor.WindowPushed == this)
                                {
                                    if (Click != null)
                                    {
                                        Click(this);
                                    }
                                    if (cursor.PrimaryClickNoSlide && ClickNoSlide != null)
                                    {
                                        ClickNoSlide(this);
                                    }

                                    // if (cursor.PrimaryDoubleClick && DoubleClick != null)
                                    //   DoubleClick(this);
                                }
                                else
                                {
                                    if (SlideOnClick != null)
                                    {
                                        SlideOnClick(this);
                                    }
                                }
                            }
                        }
                    }
                    if (HasEvents && Enabled)
                    {
                        if (handledActions.HandledRollOver == false)
                        {
                            FlatRedBall.Gui.RoutedEventArgs args = new FlatRedBall.Gui.RoutedEventArgs();
                            RollOverBubbling?.Invoke(this, args);
                            handledActions.HandledRollOver = args.Handled;
                        }


                        if (cursor.ZVelocity != 0 && handledActions.HandledMouseWheel == false)
                        {
                            FlatRedBall.Gui.RoutedEventArgs args = new FlatRedBall.Gui.RoutedEventArgs();
                            MouseWheelScroll?.Invoke(this, args);
                            handledActions.HandledMouseWheel = args.Handled;
                        }
                    }
                }
            }

            return(handledByThis || handledByChild);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Tries to handle cursor activity. If this returns true, then either this element or one of its
        /// children handled the activity.
        /// </summary>
        /// <param name="cursor">Reference to the cursor object</param>
        /// <returns>Whether this or one of its children handled the cursor activity, blocking other windows from receiving cursor input this frame.</returns>
        /// <remarks>This method will always allow children to handle the activity first, as children draw in front of their parents. Only components
        /// can have UI elements. Standard elements such as Sprites or Containers cannot themselves handle the activity, but they do give their children the
        /// opportunity to handle activity. This is because components (such as buttons) may be part of a container for stacking or other organization.
        ///
        /// Ultimately this hierarchical logic exists because only the top-most parent is added to the GuiManager, and it is responsible for
        /// giving its children the opportunity to perform cursor-related input. </remarks>
        private bool TryHandleCursorActivity(Cursor cursor, HandledActions handledActions)
        {
            bool handledByChild = false;
            bool handledByThis  = false;

            bool isOver = HasCursorOver(cursor);


            // Even though the cursor is over "this", we need to check if the cursor is over any children in case "this" exposes its children events:
            if (isOver && this.ExposeChildrenEvents)
            {
                #region Try handling by children

                // Let's see if any children have the cursor over:
                for (int i = this.Children.Count - 1; i > -1; i--)
                {
                    var child = this.Children[i];
                    if (child is GraphicalUiElement)
                    {
                        var asGue = child as GraphicalUiElement;
                        // Children should always have the opportunity to handle activity,
                        // even if they are not components, because they may contain components as their children

                        // If the child either has events or exposes children events, then give it a chance to handle this activity.

                        if ((asGue.HasEvents || asGue.ExposeChildrenEvents) && asGue.HasCursorOver(cursor))
                        {
                            handledByChild = asGue.TryHandleCursorActivity(cursor, handledActions);

                            if (handledByChild)
                            {
                                break;
                            }
                        }
                    }
                }

                #endregion
            }
            if (isOver)
            {
                if (this.IsComponentOrInstanceOfComponent())
                {
                    if (!handledByChild)
                    {
                        handledByThis = true;

                        if (this.HasEvents)
                        {
                            cursor.WindowOver = this;

                            if (cursor.PrimaryPush && Enabled)
                            {
                                cursor.WindowPushed = this;

                                if (Push != null)
                                {
                                    Push(this);
                                }


                                cursor.GrabWindow(this);
                            }

                            if (cursor.PrimaryClick && Enabled) // both pushing and clicking can occur in one frame because of buffered input
                            {
                                if (cursor.WindowPushed == this)
                                {
                                    if (Click != null)
                                    {
                                        Click(this);
                                    }
                                    if (cursor.PrimaryClickNoSlide && ClickNoSlide != null)
                                    {
                                        ClickNoSlide(this);
                                    }

                                    // if (cursor.PrimaryDoubleClick && DoubleClick != null)
                                    //   DoubleClick(this);
                                }
                                else
                                {
                                    if (SlideOnClick != null)
                                    {
                                        SlideOnClick(this);
                                    }
                                }
                            }
                        }
                    }
                    if (HasEvents && cursor.ZVelocity != 0 && handledActions.HandledMouseWheel == false &&
                        Enabled)
                    {
                        FlatRedBall.Gui.RoutedEventArgs args = new FlatRedBall.Gui.RoutedEventArgs();
                        MouseWheelScroll?.Invoke(this, args);
                        handledActions.HandledMouseWheel = args.Handled;
                    }
                }
            }

            return(handledByThis || handledByChild);
        }