2
0
Steve Grenier 12 жил өмнө
parent
commit
fe80d5accf

+ 69 - 7
gameplay/src/Container.cpp

@@ -47,7 +47,7 @@ void Container::clearContacts()
 }
 
 Container::Container()
-    : _layout(NULL), _scrollBarTopCap(NULL), _scrollBarVertical(NULL), _scrollBarBottomCap(NULL),
+    : _layout(NULL), _activeControl(NULL), _scrollBarTopCap(NULL), _scrollBarVertical(NULL), _scrollBarBottomCap(NULL),
       _scrollBarLeftCap(NULL), _scrollBarHorizontal(NULL), _scrollBarRightCap(NULL),
       _scroll(SCROLL_NONE), _scrollBarBounds(Rectangle::empty()), _scrollPosition(Vector2::zero()),
       _scrollBarsAutoHide(false), _scrollBarOpacity(1.0f), _scrolling(false),
@@ -152,6 +152,19 @@ Container* Container::create(Theme::Style* style, Properties* properties, Theme*
     container->addControls(theme, properties);
     container->_layout->update(container, container->_scrollPosition);
 
+    const char* activeControl = properties->getString("activeControl");
+    if (activeControl)
+    {
+        for (size_t i = 0, count = container->_controls.size(); i < count; ++i)
+        {
+            if (container->_controls[i]->_id == activeControl)
+            {
+                container->_activeControl = container->_controls[i];
+                break;
+            }
+        }
+    }
+
     return container;
 }
 
@@ -246,6 +259,7 @@ unsigned int Container::addControl(Control* control)
 {
     GP_ASSERT(control);
 
+    // Remove the control from its current parent
     if (control->_parent && control->_parent != this)
     {
         control->_parent->removeControl(control);
@@ -320,6 +334,9 @@ void Container::removeControl(unsigned int index)
     _controls.erase(it);
     control->_parent = NULL;
 
+    if (_activeControl == control)
+        _activeControl = NULL;
+
     Form::verifyRemovedControlState(control);
 
     SAFE_RELEASE(control);
@@ -486,6 +503,47 @@ void Container::setScrollWheelRequiresFocus(bool required)
     _scrollWheelRequiresFocus = required;
 }
 
+bool Container::setFocus()
+{
+    // If this container (or one of its children) already has focus, do nothing
+    if (Form::_focusControl && Form::_focusControl->isChild(this))
+        return true;
+
+    // First try to set focus to our active control
+    if (_activeControl)
+    {
+        if (_activeControl->setFocus())
+            return true;
+    }
+
+    // Try to set focus to one of our children
+    for (size_t i = 0, count = _controls.size(); i < count; ++i)
+    {
+        if (_controls[i]->setFocus())
+            return true;
+    }
+
+    // Lastly, try to set focus to ourself if none of our children will accept it
+    return Control::setFocus();
+}
+
+Control* Container::getActiveControl() const
+{
+    return _activeControl;
+}
+
+void Container::setActiveControl(Control* control)
+{
+    if (std::find(_controls.begin(), _controls.end(), control) != _controls.end())
+    {
+        _activeControl = control;
+
+        // If a control within this container currently has focus, switch focus to the new active control
+        if (Form::_focusControl && Form::_focusControl != control && Form::_focusControl->isChild(this))
+            Form::setFocusControl(control);
+    }
+}
+
 void Container::update(const Control* container, const Vector2& offset)
 {
     // Update this container's viewport.
@@ -783,11 +841,9 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
             vStart.set(startBounds.right(),
                         startBounds.y + startBounds.height * 0.5f);
             break;
-        case NEXT:
-            break;
         }
 
-        if (direction != NEXT)
+        if (direction != NEXT && direction != PREVIOUS)
         {
             std::vector<Control*>::const_iterator itt;
             for (itt = _controls.begin(); itt < _controls.end(); itt++)
@@ -802,7 +858,7 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
                 }
 
                 const Rectangle& nextBounds = nextControl->getAbsoluteBounds();
-                switch(direction)
+                switch (direction)
                 {
                 case UP:
                     vNext.set(nextBounds.x + nextBounds.width * 0.5f,
@@ -838,7 +894,7 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
         if (!next)
         {
             // Check for controls in the given direction in our parent container.
-            if (direction != NEXT && !outsideControl && _parent && _parent->moveFocus(direction, start))
+            if (direction != NEXT && direction != PREVIOUS && !outsideControl && _parent && _parent->moveFocus(direction, start))
                 return true;
             
             // No control is in the given direction.  Move to the next control in the focus order.
@@ -854,6 +910,9 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
             case NEXT:
                 focusDelta = 1;
                 break;
+            case PREVIOUS:
+                focusDelta = -1;
+                break;
             }
 
             // Find the index to search for.
@@ -875,6 +934,9 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
             }
             else if (focusIndex < 0)
             {
+                if (direction == PREVIOUS && !outsideControl && _parent && _parent->moveFocus(direction, start))
+                    return true;
+
                 focusIndex = _focusIndexMax;
             }
         }
@@ -1152,7 +1214,7 @@ bool Container::touchEventScroll(Touch::TouchEvent evt, int x, int y, unsigned i
             }
             _scrollBarOpacity = 1.0f;
             _dirty = true;
-            return _consumeInputEvents;
+            return false;
         }
         break;
 

+ 28 - 1
gameplay/src/Container.h

@@ -263,6 +263,28 @@ public:
      */
     void setScrollWheelRequiresFocus(bool required);
 
+    /**
+     * @see Control::setFocus
+     */
+    bool setFocus();
+
+    /**
+     * Returns the currently active control for this container.
+     *
+     * @return This container's active control.
+     */
+    Control* getActiveControl() const;
+    
+    /**
+     * Sets the active control for this container.
+     *
+     * A container's active control is the control that will receive focus
+     * when the container receives focus.
+     *
+     * @param control The container's new active control (must be a child of this container).
+     */
+    void setActiveControl(Control* control);
+
     /**
      * @see AnimationTarget::getAnimationPropertyComponentCount
      */
@@ -410,6 +432,10 @@ protected:
      * List of controls within the container.
      */
     std::vector<Control*> _controls;
+    /**
+     * The active control for the container.
+     */
+    Control* _activeControl;
     /**
      * Scrollbar top cap image.
      */
@@ -536,7 +562,8 @@ private:
         DOWN = 0x02,
         LEFT = 0x04,
         RIGHT = 0x08,
-        NEXT = 0x10
+        NEXT = 0x10,
+        PREVIOUS = 0x20
     };
 
     static const int MAX_CONTACT_INDICES = 10;

+ 12 - 1
gameplay/src/Control.cpp

@@ -437,13 +437,24 @@ bool Control::isVisibleInHierarchy() const
     return true;
 }
 
+bool Control::canFocus() const
+{
+    return false;
+}
+
 bool Control::hasFocus() const
 {
     return (Form::_focusControl == this);
 }
 
-bool Control::canFocus() const
+bool Control::setFocus()
 {
+    if (Form::_focusControl != this && canFocus())
+    {
+        Form::setFocusControl(this);
+        return true;
+    }
+
     return false;
 }
 

+ 15 - 3
gameplay/src/Control.h

@@ -1133,6 +1133,13 @@ protected:
      */
     static Alignment getAlignment(const char* alignment);
 
+    /**
+     * Determines if this control accepts focus.
+     *
+     * @return True if this control accepts focus, false if it does not.
+     */
+    virtual bool canFocus() const;
+
     /**
      * Determines if this control is currently in focus.
      *
@@ -1141,11 +1148,16 @@ protected:
     bool hasFocus() const;
 
     /**
-     * Determines if this control accepts focus.
+     * Sets input focus to this control.
      *
-     * @return True if this control accepts focus, false if it does not.
+     * If this control accepts focus (the hasFocus method returns true), input focus
+     * is set to this control. If this control is a container, the first focusable
+     * control within it gains focus.
+     *
+     * @return True if this control or one of its children successfully gained focus,
+     *      false otherwise.
      */
-    virtual bool canFocus() const;
+    virtual bool setFocus();
 
     /** 
      * The Control's ID.

+ 52 - 16
gameplay/src/Form.cpp

@@ -22,6 +22,7 @@ static std::vector<Form*> __forms;
 Control* Form::_focusControl = NULL;
 Control* Form::_activeControl = NULL;
 Control::State Form::_activeControlState = Control::NORMAL;
+static bool _shiftKeyDown = false;
 
 Form::Form() : _theme(NULL), _frameBuffer(NULL), _spriteBatch(NULL), _node(NULL),
     _nodeQuad(NULL), _nodeMaterial(NULL) , _u2(0), _v1(0)
@@ -584,20 +585,6 @@ Control* Form::handlePointerPressRelease(int* x, int* y, bool pressed)
 
             ctrl->notifyListeners(Control::Listener::PRESS);
         }
-
-        // Update focus state?
-        if (!(ctrl && ctrl->canFocus()))
-        {
-            newX = *x;
-            newY = *y;
-            ctrl = findInputControl(&newX, &newY, true);
-        }
-
-        // Update focus
-        if (_focusControl != ctrl)
-        {
-            setFocusControl(ctrl);
-        }
     }
     else // !pressed
     {
@@ -793,6 +780,11 @@ bool Form::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelt
         ctrl = handlePointerPressRelease(&formX, &formY, evt == Mouse::MOUSE_PRESS_LEFT_BUTTON);
         break;
 
+    case Mouse::MOUSE_PRESS_MIDDLE_BUTTON:
+    case Mouse::MOUSE_PRESS_RIGHT_BUTTON:
+
+        break;
+
     case Mouse::MOUSE_MOVE:
         ctrl = handlePointerMove(&formX, &formY);
         break;
@@ -825,6 +817,18 @@ bool Form::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelt
             tmp = tmp->_parent;
         }
 
+        // Handle setting focus for press events
+        switch (evt)
+        {
+        case Mouse::MOUSE_PRESS_LEFT_BUTTON:
+        case Mouse::MOUSE_PRESS_MIDDLE_BUTTON:
+        case Mouse::MOUSE_PRESS_RIGHT_BUTTON:
+            Control* focusControl = ctrl;
+            while (focusControl && !focusControl->setFocus())
+                focusControl = focusControl->_parent;
+            break;
+        }
+
         // Dispatch the event from the bottom upwards, until a control intersecting the point consumes the event
         while (ctrl)
         {
@@ -857,13 +861,36 @@ bool Form::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelt
             ctrl = ctrl->getParent();
         }
     }
+    else
+    {
+        // If this was a press event, remove all focus
+        switch (evt)
+        {
+        case Mouse::MOUSE_PRESS_LEFT_BUTTON:
+        case Mouse::MOUSE_PRESS_MIDDLE_BUTTON:
+        case Mouse::MOUSE_PRESS_RIGHT_BUTTON:
+            setFocusControl(NULL);
+            break;
+        }
+    }
 
     return false;
 }
 
 bool Form::keyEventInternal(Keyboard::KeyEvent evt, int key)
 {
-    // Ignore the escape key
+    switch (key)
+    {
+    case Keyboard::KEY_ESCAPE:
+        return false; // ignore escape key presses
+
+    case Keyboard::KEY_SHIFT:
+        if (evt == Keyboard::KEY_PRESS)
+            _shiftKeyDown = true;
+        else if (evt == Keyboard::KEY_RELEASE)
+            _shiftKeyDown = false;
+        break;
+    }
     if (key == Keyboard::KEY_ESCAPE)
         return false;
 
@@ -878,7 +905,7 @@ bool Form::keyEventInternal(Keyboard::KeyEvent evt, int key)
             case Keyboard::KEY_TAB:
                 if (_focusControl->_parent && _focusControl->_parent->isContainer())
                 {
-                    if (static_cast<Container*>(_focusControl->_parent)->moveFocus(Container::NEXT))
+                    if (static_cast<Container*>(_focusControl->_parent)->moveFocus(Container::PREVIOUS))
                         return true;
                 }
                 break;
@@ -1023,16 +1050,25 @@ void Form::setFocusControl(Control* control)
 
     _focusControl = control;
 
+    // Deactivate the old focus control
     if (oldFocus)
     {
         oldFocus->_dirty = true;
         oldFocus->notifyListeners(Control::Listener::FOCUS_LOST);
     }
 
+    // Activate the new focus control
     if (_focusControl)
     {
         _focusControl->_dirty = true;
         _focusControl->notifyListeners(Control::Listener::FOCUS_GAINED);
+
+        // Set the activeControl property of the control's parent container
+        if (_focusControl->_parent && _focusControl->_parent->isContainer())
+        {
+            Container* parent = static_cast<Container*>(_focusControl->_parent);
+            parent->_activeControl = _focusControl;
+        }
     }
 }
 

+ 1 - 1
gameplay/src/ImageControl.cpp

@@ -150,7 +150,7 @@ void ImageControl::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)
 
 void ImageControl::update(const Control* container, const Vector2& offset)
 {
-    Button::update(container, offset);
+    Control::update(container, offset);
 
     if (_batch)
     {

+ 2 - 2
gameplay/src/ImageControl.h

@@ -1,7 +1,7 @@
 #ifndef IMAGECONTROL_H_
 #define IMAGECONTROL_H_
 
-#include "Button.h"
+#include "Control.h"
 #include "Theme.h"
 #include "Image.h"
 #include "SpriteBatch.h"
@@ -33,7 +33,7 @@ namespace gameplay
      }
  @endverbatim
  */
-class ImageControl : public Button
+class ImageControl : public Control
 {
     friend class Container;
 

+ 1 - 2
gameplay/src/Keyboard.h

@@ -21,8 +21,7 @@ public:
     {
         KEY_PRESS,
         KEY_RELEASE,
-        KEY_CHAR,
-        KEY_REPEAT
+        KEY_CHAR
     };
 
     /**

+ 0 - 73
gameplay/src/lua/lua_ImageControl.cpp

@@ -70,7 +70,6 @@ void luaRegister_ImageControl()
         {"getSkinRegion", lua_ImageControl_getSkinRegion},
         {"getState", lua_ImageControl_getState},
         {"getStyle", lua_ImageControl_getStyle},
-        {"getText", lua_ImageControl_getText},
         {"getTextAlignment", lua_ImageControl_getTextAlignment},
         {"getTextColor", lua_ImageControl_getTextColor},
         {"getTextRightToLeft", lua_ImageControl_getTextRightToLeft},
@@ -116,7 +115,6 @@ void luaRegister_ImageControl()
         {"setSkinColor", lua_ImageControl_setSkinColor},
         {"setSkinRegion", lua_ImageControl_setSkinRegion},
         {"setStyle", lua_ImageControl_setStyle},
-        {"setText", lua_ImageControl_setText},
         {"setTextAlignment", lua_ImageControl_setTextAlignment},
         {"setTextColor", lua_ImageControl_setTextColor},
         {"setTextRightToLeft", lua_ImageControl_setTextRightToLeft},
@@ -2318,41 +2316,6 @@ int lua_ImageControl_getStyle(lua_State* state)
     return 0;
 }
 
-int lua_ImageControl_getText(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 1:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA))
-            {
-                ImageControl* instance = getInstance(state);
-                const char* result = instance->getText();
-
-                // Push the return value onto the stack.
-                lua_pushstring(state, result);
-
-                return 1;
-            }
-
-            lua_pushstring(state, "lua_ImageControl_getText - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 1).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
 int lua_ImageControl_getTextAlignment(lua_State* state)
 {
     // Get the number of parameters.
@@ -4563,42 +4526,6 @@ int lua_ImageControl_setStyle(lua_State* state)
     return 0;
 }
 
-int lua_ImageControl_setText(lua_State* state)
-{
-    // Get the number of parameters.
-    int paramCount = lua_gettop(state);
-
-    // Attempt to match the parameters to a valid binding.
-    switch (paramCount)
-    {
-        case 2:
-        {
-            if ((lua_type(state, 1) == LUA_TUSERDATA) &&
-                (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL))
-            {
-                // Get parameter 1 off the stack.
-                const char* param1 = gameplay::ScriptUtil::getString(2, false);
-
-                ImageControl* instance = getInstance(state);
-                instance->setText(param1);
-                
-                return 0;
-            }
-
-            lua_pushstring(state, "lua_ImageControl_setText - Failed to match the given parameters to a valid function signature.");
-            lua_error(state);
-            break;
-        }
-        default:
-        {
-            lua_pushstring(state, "Invalid number of parameters (expected 2).");
-            lua_error(state);
-            break;
-        }
-    }
-    return 0;
-}
-
 int lua_ImageControl_setTextAlignment(lua_State* state)
 {
     // Get the number of parameters.

+ 0 - 2
gameplay/src/lua/lua_ImageControl.h

@@ -47,7 +47,6 @@ int lua_ImageControl_getSkinColor(lua_State* state);
 int lua_ImageControl_getSkinRegion(lua_State* state);
 int lua_ImageControl_getState(lua_State* state);
 int lua_ImageControl_getStyle(lua_State* state);
-int lua_ImageControl_getText(lua_State* state);
 int lua_ImageControl_getTextAlignment(lua_State* state);
 int lua_ImageControl_getTextColor(lua_State* state);
 int lua_ImageControl_getTextRightToLeft(lua_State* state);
@@ -93,7 +92,6 @@ int lua_ImageControl_setSize(lua_State* state);
 int lua_ImageControl_setSkinColor(lua_State* state);
 int lua_ImageControl_setSkinRegion(lua_State* state);
 int lua_ImageControl_setStyle(lua_State* state);
-int lua_ImageControl_setText(lua_State* state);
 int lua_ImageControl_setTextAlignment(lua_State* state);
 int lua_ImageControl_setTextColor(lua_State* state);
 int lua_ImageControl_setTextRightToLeft(lua_State* state);