예제 #1
0
        /// <summary>Called when a button on the game pad has been released</summary>
        /// <param name="button">Button that has been released</param>
        internal void ProcessButtonRelease(Buttons button)
        {
            // If we're the top level control, we will receive button presses and their related
            // releases even if nobody was interested in the button presses. Thus, we silently
            // ignore those presses we didn't accept.
            if (_heldButtonCount == 0)
            {
                return;
            }

            // If we receive a release, we must have a control on which the mouse
            // was pressed (possibly even ourselves)
            Debug.Assert(
                _activatedControl != null,
                "ProcessButtonRelease() had no control a button was pressed on; " +
                "ProcessButtonRelease() was called on a control instance, but the control " +
                "did not register a prior button press for itself or any of its child controls"
                );

            --_heldButtonCount;
            if (_activatedControl != this)
            {
                _activatedControl.ProcessButtonRelease(button);
            }
            else
            {
                OnButtonReleased(button);
            }

            // If no more keys buttons are being held down, clear the activated control
            if (!AnyKeysOrButtonsPressed)
            {
                _activatedControl = null;
            }
        }
예제 #2
0
        /// <summary>Called when a mouse button has been pressed down</summary>
        /// <param name="button">Index of the button that has been pressed</param>
        /// <returns>Whether the control has processed the mouse press</returns>
        internal bool ProcessMousePress(MouseButton button)
        {
            // We remember the control the mouse was pressed over and won't replace it for
            // as long as the mouse is being held down. This ensures the mouse release
            // notification is always delivered to a control, even if the mouse is released
            // after moving it away from the control.
            if (_activatedControl == null)
            {
                _activatedControl = _mouseOverControl;

                // If we received an initial mouse press outside of our control area,
                // someone is feeding us notifications we shouldn't be receiving. The best
                // thing we can do is ignore this notification. This is a normal situation
                // for the top level control which does the input filtering.
                if (_activatedControl == null)
                {
                    return(false);
                }

                // If we're a control that can appear on top of or below our siblings in
                // the z order, bring us into foreground since the user just clicked on us.
                if (_activatedControl != this)
                {
                    if (_activatedControl._affectsOrdering)
                    {
                        _children.MoveToStart(_children.IndexOf(_activatedControl));
                    }
                }
            }

            // Add the buttons to the list of mouse buttons being held down. This is used
            // to track when we should clear the mouse-over control again.
            _heldMouseButtons |= button;

            // If the mouse is over another control, pass on the mouse press.
            if (_activatedControl != this)
            {
                return(_activatedControl.ProcessMousePress(button));
            }
            // Otherwise, the mouse press applies to us

            // If this control can take the input focus, make it the focused control
            if (_screen != null)
            {
                var focusable = this as IFocusable;
                if ((focusable != null) && focusable.CanGetFocus)
                {
                    _screen.FocusedControl = this;
                }
            }

            // Deliver the notification to the control deriving from us
            OnMousePressed(button);
            return(true);
        }
예제 #3
0
        /// <summary>Switches the mouse over control to a different control</summary>
        /// <param name="newMouseOverControl">New control the mouse is hovering over</param>
        private void SwitchMouseOverControl(GuiControl newMouseOverControl, float x, float y)
        {
            if (_mouseOverControl != newMouseOverControl)
            {
                // Tell the previous mouse-over control that the mouse is no longer
                // hovering over it
                if (_mouseOverControl != null)
                {
                    _mouseOverControl.ProcessMouseLeave(x, y);
                }

                _mouseOverControl = newMouseOverControl;

                // Inform the new mouse-over control that the mouse is now over it
                newMouseOverControl.OnMouseEntered();
            }
        }
예제 #4
0
        /// <summary>Assigns a new parent to the control</summary>
        /// <param name="parent">New parent to assign to the control</param>
        internal void SetParent(GuiControl parent)
        {
            _parent = parent;

            // Have we been assigned to a parent?
            if (_parent != null)
            {
                // If this ownership change transferred us to a different gui, we will
                // have to migrate our visual and also the visuals of all our children.
                if (!ReferenceEquals(_screen, parent._screen))
                {
                    SetScreen(parent._screen);
                }
            }
            else
            {
                // No parent, we're now officially an orphan ;)

                // Orphans don't have screens!
                SetScreen(null);
            }
        }
예제 #5
0
        /// <summary>Called when a mouse button has been released again</summary>
        /// <param name="button">Index of the button that has been released</param>
        internal void ProcessMouseRelease(MouseButton button)
        {
            // When the mouse is clicked on game window's border and the user drags it
            // into the GUI area, we will get a rogue mouse release message without
            // the related mouse press. We ignore such rogue mouse release messages.
            if ((_heldMouseButtons & button) != button)
            {
                return;
            }

            // If we receive a release, we must have a control on which the mouse
            // was pressed (possibly even ourselves)
            Debug.Assert(
                _activatedControl != null,
                "ProcessMouseRelease() had no control the mouse was pressed on; " +
                "ProcessMouseRelease() was called on a control instance, but the control " +
                "did not register a prior mouse press over itself or any of its child controls"
                );

            // Remove the button from the list of mouse buttons being held down. This
            // allows us to see when we can clear the mouse-press control.
            _heldMouseButtons &= ~button;

            // If the mouse was held over one of our childs, pass on the notification
            if (_activatedControl != this)
            {
                _activatedControl.ProcessMouseRelease(button);
            }
            else
            {
                OnMouseReleased(button);
            }

            // If no more mouse buttons are being held down, clear the mouse-press control
            if (!AnyKeysOrButtonsPressed)
            {
                _activatedControl = null;
            }
        }
예제 #6
0
        /// <summary>
        ///     Called when the mouse has left the control and is no longer hovering over it
        /// </summary>
        internal void ProcessMouseLeave(float x, float y)
        {
            // Because the mouse has left us, if we have a mouse-over control, it also
            // cannot be over one of our children Children leaving the parent container
            // are not supported by design and for consistency, the behavior is tweaked
            // so the children are left when the parent is left - this avoids strange
            // behavior like being able to select a control if entering it with the mouse
            // from the container side but being unable to select it if entering from
            // the outside.
            if (_mouseOverControl != null)
            {
                if (_mouseOverControl != this)
                {
                    _mouseOverControl.ProcessMouseLeave(x, y);
                }
                else
                {
                    OnMouseLeft(x, y);
                }

                _mouseOverControl = null;
            }
        }
예제 #7
0
        /// <summary>Called when a key on the keyboard has been released again</summary>
        /// <param name="keyCode">Code of the key that was released</param>
        internal void ProcessKeyRelease(Keys keyCode)
        {
            // Any key release should have an associated key press, otherwise, someone
            // delivered notifications to us we should not have received.
            Debug.Assert(
                _heldKeyCount > 0,
                "ProcessKeyRelease() called more often then ProcessKeyPress(); " +
                "ProcessKeyRelease() was called more often the ProcessKeyPress() has been " +
                "called with the repetition parameter set to false"
                );

            // If we receive a release, we must have a control on which the mouse
            // was pressed (possibly even ourselves)
            Debug.Assert(
                _activatedControl != null,
                "ProcessKeyRelease() had no control a key was pressed on; " +
                "ProcessKeyRelease() was called on a control instance, but the control " +
                "did not register a prior key press for itself or any of its child controls"
                );

            --_heldKeyCount;
            if (_activatedControl != this)
            {
                _activatedControl.ProcessKeyRelease(keyCode);
            }
            else
            {
                OnKeyReleased(keyCode);
            }

            // If no more keys buttons are being held down, clear the activated control
            if (!AnyKeysOrButtonsPressed)
            {
                _activatedControl = null;
            }
        }
예제 #8
0
        /// <summary>Called when a key on the keyboard has been pressed down</summary>
        /// <param name="keyCode">Code of the key that was pressed</param>
        /// <param name="repetition">Whether the key press is due to the user holding down a key</param>
        internal bool ProcessKeyPress(Keys keyCode, bool repetition)
        {
            // If there's an activated control (one being held down by the mouse or having
            // accepted a previous key press), this control will get the key press delivered,
            // whether it wants to or not. We don't want to track for each key which control
            // is currently processing it. ;-)
            if (_activatedControl != null)
            {
                if (!repetition)
                {
                    ++_heldKeyCount;
                }

                // If one of our children is the activated control, pass on the message
                if (_activatedControl != this)
                {
                    _activatedControl.ProcessKeyPress(keyCode, repetition);
                }
                else
                {
                    OnKeyPressed(keyCode); // We're the activated control
                }
                return(true);              // Ignore user code and always accept the key press
            }

            // A key has been pressed but no control is activated currently. This means we
            // have to look for a control which feels responsible for the key press, starting
            // with ourselves.

            // Does the user code in our derived class feel responsible for this key?
            // If so, we're the new activated control and the key has been handled.
            if (OnKeyPressed(keyCode))
            {
                _activatedControl = this;
                ++_heldKeyCount;
                return(true);
            }

            // Nope, we have to ask our children (and they, potentially recursively, theirs)
            // to find a control that feels responsible.
            var encounteredOrderingControl = false;

            for (var index = 0; index < _children.Count; ++index)
            {
                var child = _children[index];

                // We only process one child that has the affectsOrdering field set. This
                // ensures that key presses will not be delivered to windows sitting behind
                // another window. Other siblings that are not windows are asked still.
                if (child._affectsOrdering)
                {
                    if (encounteredOrderingControl)
                    {
                        continue;
                    }
                    else
                    {
                        encounteredOrderingControl = true;
                    }
                }

                // Does this child feel responsible for the key press?
                if (child.ProcessKeyPress(keyCode, repetition))
                {
                    _activatedControl = child;
                    ++_heldKeyCount;
                    return(true);
                }
            }

            // Neither we nor any of our children felt responsible for the key. Give up.
            return(false);
        }
예제 #9
0
        /// <summary>Called when a button on the game pad has been pressed</summary>
        /// <param name="button">Button that has been pressed</param>
        /// <returns>
        ///     True if the button press was processed by the control and future game pad
        ///     input belongs to the control until all buttons are released again
        /// </returns>
        internal bool ProcessButtonPress(Buttons button)
        {
            // If there's an activated control (one being held down by the mouse or having
            // accepted a previous button press), this control will get the button press
            // delivered, whether it wants to or not.
            if (_activatedControl != null)
            {
                ++_heldButtonCount;

                // If one of our children is the activated control, pass on the message
                if (_activatedControl != this)
                {
                    _activatedControl.ProcessButtonPress(button);
                }
                else
                {
                    OnButtonPressed(button);
                }

                // We're already activated, so this button press is accepted in any case
                return(true);
            }

            // A button has been pressed but no control is activated currently. This means we
            // have to look for a control which feels responsible for the button press,
            // starting with ourselves.

            // Does the user code in our derived class feel responsible for this button?
            // If so, we're the new activated control and the button has been handled.
            if (OnButtonPressed(button))
            {
                _activatedControl = this;
                ++_heldButtonCount;
                return(true);
            }

            // Nope, we have to ask our children to find a control that feels responsible.
            var encounteredOrderingControl = false;

            foreach (var child in _children)
            {
                // We only process one child that has the affectsOrdering field set. This
                // ensures that key presses will not be delivered to windows sitting behind
                // another window. Other siblings that are not windows are asked still, so
                // a bunch of buttons on the desktop would be asked in addition to a window.
                if (child._affectsOrdering)
                {
                    if (encounteredOrderingControl)
                    {
                        continue;
                    }

                    encounteredOrderingControl = true;
                }

                // Does this child feel responsible for the button press?
                if (child.ProcessButtonPress(button))
                {
                    _activatedControl = child;
                    ++_heldButtonCount;
                    return(true);
                }
            }

            // Neither we nor any of our children felt responsible for the button. Give up.
            return(false);
        }
예제 #10
0
 /// <summary>Initializes a new control event args instance</summary>
 /// <param name="control">Control to provide to the subscribers of the event</param>
 public ControlEventArgs(GuiControl control)
 {
     _control = control;
 }