|
|
@@ -51,7 +51,8 @@ Container::Container()
|
|
|
_scrollingMouseVertically(false), _scrollingMouseHorizontally(false),
|
|
|
_scrollBarOpacityClip(NULL), _zIndexDefault(0), _focusIndexDefault(0), _focusIndexMax(0),
|
|
|
_focusPressed(0), _selectButtonDown(false),
|
|
|
- _lastFrameTime(0), _focusChangeStartTime(0), _focusChangeRepeatDelay(FOCUS_CHANGE_REPEAT_DELAY), _focusChangeCount(0),
|
|
|
+ _lastFrameTime(0), _focusChangeRepeat(false),
|
|
|
+ _focusChangeStartTime(0), _focusChangeRepeatDelay(FOCUS_CHANGE_REPEAT_DELAY), _focusChangeCount(0),
|
|
|
_totalWidth(0), _totalHeight(0),
|
|
|
_contactIndices(0), _initializedWithScroll(false)
|
|
|
{
|
|
|
@@ -645,8 +646,32 @@ bool Container::keyEvent(Keyboard::KeyEvent evt, int key)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+void Container::guaranteeFocus(Control* inFocus)
|
|
|
+{
|
|
|
+ std::vector<Control*>::const_iterator it;
|
|
|
+ for (it = _controls.begin(); it < _controls.end(); it++)
|
|
|
+ {
|
|
|
+ Control* control = *it;
|
|
|
+ GP_ASSERT(control);
|
|
|
+ if (control == inFocus)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (control->isContainer())
|
|
|
+ {
|
|
|
+ ((Container*)control)->guaranteeFocus(inFocus);
|
|
|
+ }
|
|
|
+ else if (control->getState() == Control::FOCUS)
|
|
|
+ {
|
|
|
+ control->setState(NORMAL);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
bool Container::moveFocus(Direction direction, Control* outsideControl)
|
|
|
{
|
|
|
+ _direction = direction;
|
|
|
+
|
|
|
Control* start = outsideControl;
|
|
|
if (!start)
|
|
|
{
|
|
|
@@ -657,7 +682,6 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
|
|
|
GP_ASSERT(control);
|
|
|
if (control->getState() == Control::FOCUS)
|
|
|
{
|
|
|
- control->setState(Control::NORMAL);
|
|
|
start = control;
|
|
|
break;
|
|
|
}
|
|
|
@@ -671,6 +695,7 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
|
|
|
const Rectangle& startBounds = start->getAbsoluteBounds();
|
|
|
Vector2 vStart, vNext;
|
|
|
float distance = FLT_MAX;
|
|
|
+ start->setState(Control::NORMAL);
|
|
|
|
|
|
switch(direction)
|
|
|
{
|
|
|
@@ -690,6 +715,8 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
|
|
|
vStart.set(startBounds.right(),
|
|
|
startBounds.y + startBounds.height * 0.5f);
|
|
|
break;
|
|
|
+ case NEXT:
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
if (direction != NEXT)
|
|
|
@@ -699,7 +726,8 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
|
|
|
{
|
|
|
Control* nextControl = *itt;
|
|
|
|
|
|
- if (nextControl == start || nextControl->getFocusIndex() < 0)
|
|
|
+ if (nextControl == start || nextControl->getFocusIndex() < 0 ||
|
|
|
+ !nextControl->isEnabled() || !nextControl->isVisible())
|
|
|
{
|
|
|
// Control is not focusable.
|
|
|
continue;
|
|
|
@@ -745,7 +773,7 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
|
|
|
if (!outsideControl && _parent && _parent->moveFocus(direction, start))
|
|
|
{
|
|
|
setState(NORMAL);
|
|
|
- _focusPressed = 0;
|
|
|
+ _focusChangeRepeat = false;
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
@@ -808,7 +836,7 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
|
|
|
{
|
|
|
if (((Container*)next)->moveFocus(direction, start))
|
|
|
{
|
|
|
- _focusChangeStartTime = 0;
|
|
|
+ _focusChangeRepeat = false;
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
@@ -835,15 +863,18 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
|
|
|
{
|
|
|
// Control is below the viewport.
|
|
|
_scrollPosition.y = -(bounds.y + bounds.height - _viewportBounds.height);
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- _focusChangeStartTime = Game::getAbsoluteTime();
|
|
|
if (outsideControl && outsideControl->_parent)
|
|
|
{
|
|
|
- _focusPressed = direction;
|
|
|
+ _focusPressed = outsideControl->_parent->_focusPressed;
|
|
|
_focusChangeCount = outsideControl->_parent->_focusChangeCount;
|
|
|
_focusChangeRepeatDelay = outsideControl->_parent->_focusChangeRepeatDelay;
|
|
|
+ outsideControl->_parent->guaranteeFocus(next);
|
|
|
}
|
|
|
+
|
|
|
+ _focusChangeStartTime = Game::getAbsoluteTime();
|
|
|
+ _focusChangeRepeat = true;
|
|
|
addRef();
|
|
|
Game::getInstance()->schedule(_focusChangeRepeatDelay, this);
|
|
|
|
|
|
@@ -856,15 +887,15 @@ bool Container::moveFocus(Direction direction, Control* outsideControl)
|
|
|
void Container::timeEvent(long timeDiff, void* cookie)
|
|
|
{
|
|
|
double time = Game::getAbsoluteTime();
|
|
|
- if (_focusPressed && abs(time - timeDiff - _focusChangeRepeatDelay - _focusChangeStartTime) < 50)
|
|
|
+ if (_focusChangeRepeat && _state == FOCUS && _focusPressed &&
|
|
|
+ abs(time - timeDiff - _focusChangeRepeatDelay - _focusChangeStartTime) < 50)
|
|
|
{
|
|
|
++_focusChangeCount;
|
|
|
if (_focusChangeCount == 5)
|
|
|
{
|
|
|
_focusChangeRepeatDelay *= 0.5;
|
|
|
}
|
|
|
-
|
|
|
- moveFocus((Direction)_focusPressed);
|
|
|
+ moveFocus(_direction);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -905,6 +936,8 @@ bool Container::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsign
|
|
|
{
|
|
|
addRef();
|
|
|
|
|
|
+ bool eventConsumed = false;
|
|
|
+
|
|
|
// Pass the event to any control that is active or in focus.
|
|
|
std::vector<Control*>::const_iterator it;
|
|
|
for (it = _controls.begin(); it < _controls.end(); it++)
|
|
|
@@ -913,11 +946,8 @@ bool Container::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsign
|
|
|
GP_ASSERT(control);
|
|
|
if (control->getState() == Control::FOCUS || control->getState() == Control::ACTIVE)
|
|
|
{
|
|
|
- if (control->gamepadEvent(evt, gamepad, analogIndex))
|
|
|
- {
|
|
|
- release();
|
|
|
- return true;
|
|
|
- }
|
|
|
+ eventConsumed |= control->gamepadEvent(evt, gamepad, analogIndex);
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -928,6 +958,8 @@ bool Container::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsign
|
|
|
gamepad->isButtonDown(Gamepad::BUTTON_X))
|
|
|
{
|
|
|
_selectButtonDown = true;
|
|
|
+ _focusChangeRepeat = false;
|
|
|
+ eventConsumed |= _consumeInputEvents;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
@@ -939,10 +971,11 @@ bool Container::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsign
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- bool eventConsumed = false;
|
|
|
+ Vector2 joystick;
|
|
|
+ gamepad->getJoystickValues(analogIndex, &joystick);
|
|
|
|
|
|
// Don't allow focus changes or scrolling while a selection button is down.
|
|
|
- if (!_selectButtonDown)
|
|
|
+ if (!_selectButtonDown && !eventConsumed)
|
|
|
{
|
|
|
switch (evt)
|
|
|
{
|
|
|
@@ -953,169 +986,157 @@ bool Container::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsign
|
|
|
gamepad->isButtonDown(Gamepad::BUTTON_DOWN))
|
|
|
{
|
|
|
_focusPressed |= DOWN;
|
|
|
- if (!moveFocus(DOWN))
|
|
|
- {
|
|
|
- startScrolling(0, -GAMEPAD_SCROLL_SPEED);
|
|
|
- }
|
|
|
- eventConsumed |= _consumeInputEvents;
|
|
|
- }
|
|
|
- else if ((_focusPressed & DOWN) &&
|
|
|
- !gamepad->isButtonDown(Gamepad::BUTTON_DOWN))
|
|
|
- {
|
|
|
- _focusPressed &= ~DOWN;
|
|
|
eventConsumed |= _consumeInputEvents;
|
|
|
+ if (moveFocus(DOWN))
|
|
|
+ break;
|
|
|
+ else
|
|
|
+ startScrolling(0, -GAMEPAD_SCROLL_SPEED);
|
|
|
}
|
|
|
|
|
|
if (!(_focusPressed & RIGHT) &&
|
|
|
gamepad->isButtonDown(Gamepad::BUTTON_RIGHT))
|
|
|
{
|
|
|
_focusPressed |= RIGHT;
|
|
|
- if (!moveFocus(RIGHT))
|
|
|
- {
|
|
|
- startScrolling(GAMEPAD_SCROLL_SPEED, 0);
|
|
|
- }
|
|
|
- eventConsumed |= _consumeInputEvents;
|
|
|
- }
|
|
|
- else if ((_focusPressed & RIGHT) &&
|
|
|
- !gamepad->isButtonDown(Gamepad::BUTTON_RIGHT))
|
|
|
- {
|
|
|
- _focusPressed &= ~RIGHT;
|
|
|
eventConsumed |= _consumeInputEvents;
|
|
|
+ if (moveFocus(RIGHT))
|
|
|
+ break;
|
|
|
+ else
|
|
|
+ startScrolling(GAMEPAD_SCROLL_SPEED, 0);
|
|
|
}
|
|
|
|
|
|
if (!(_focusPressed & UP) &&
|
|
|
gamepad->isButtonDown(Gamepad::BUTTON_UP))
|
|
|
{
|
|
|
_focusPressed |= UP;
|
|
|
- if (!moveFocus(UP))
|
|
|
- {
|
|
|
- startScrolling(0, GAMEPAD_SCROLL_SPEED);
|
|
|
- }
|
|
|
- eventConsumed |= _consumeInputEvents;
|
|
|
- }
|
|
|
- else if ((_focusPressed & UP) &&
|
|
|
- !gamepad->isButtonDown(Gamepad::BUTTON_UP))
|
|
|
- {
|
|
|
- _focusPressed &= ~UP;
|
|
|
eventConsumed |= _consumeInputEvents;
|
|
|
+ if (moveFocus(UP))
|
|
|
+ break;
|
|
|
+ else
|
|
|
+ startScrolling(0, GAMEPAD_SCROLL_SPEED);
|
|
|
}
|
|
|
|
|
|
if (!(_focusPressed & LEFT) &&
|
|
|
gamepad->isButtonDown(Gamepad::BUTTON_LEFT))
|
|
|
{
|
|
|
_focusPressed |= LEFT;
|
|
|
- if (!moveFocus(LEFT))
|
|
|
- {
|
|
|
- startScrolling(-GAMEPAD_SCROLL_SPEED, 0);
|
|
|
- }
|
|
|
- eventConsumed |= _consumeInputEvents;
|
|
|
- }
|
|
|
- else if ((_focusPressed & LEFT) &&
|
|
|
- !gamepad->isButtonDown(Gamepad::BUTTON_LEFT))
|
|
|
- {
|
|
|
- _focusPressed &= ~LEFT;
|
|
|
eventConsumed |= _consumeInputEvents;
|
|
|
+ if (moveFocus(LEFT))
|
|
|
+ break;
|
|
|
+ else
|
|
|
+ startScrolling(-GAMEPAD_SCROLL_SPEED, 0);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
case Gamepad::JOYSTICK_EVENT:
|
|
|
{
|
|
|
- Vector2 joystick;
|
|
|
- gamepad->getJoystickValues(analogIndex, &joystick);
|
|
|
-
|
|
|
switch (analogIndex)
|
|
|
{
|
|
|
case 0:
|
|
|
// The left analog stick can be used in the same way as the DPad.
|
|
|
+ eventConsumed |= _consumeInputEvents;
|
|
|
if (!(_focusPressed & RIGHT) &&
|
|
|
joystick.x > JOYSTICK_THRESHOLD)
|
|
|
{
|
|
|
_focusPressed |= RIGHT;
|
|
|
- if (!moveFocus(RIGHT))
|
|
|
- {
|
|
|
+ if (moveFocus(RIGHT))
|
|
|
+ break;
|
|
|
+ else
|
|
|
startScrolling(GAMEPAD_SCROLL_SPEED * joystick.x, 0);
|
|
|
- }
|
|
|
- }
|
|
|
- else if (_focusPressed & RIGHT &&
|
|
|
- joystick.x < JOYSTICK_THRESHOLD)
|
|
|
- {
|
|
|
- _focusPressed &= ~RIGHT;
|
|
|
}
|
|
|
|
|
|
if (!(_focusPressed & DOWN) &&
|
|
|
joystick.y < -JOYSTICK_THRESHOLD)
|
|
|
{
|
|
|
_focusPressed |= DOWN;
|
|
|
- if (!moveFocus(DOWN))
|
|
|
- {
|
|
|
+ if (moveFocus(DOWN))
|
|
|
+ break;
|
|
|
+ else
|
|
|
startScrolling(0, GAMEPAD_SCROLL_SPEED * joystick.y);
|
|
|
- }
|
|
|
- }
|
|
|
- else if (_focusPressed & DOWN &&
|
|
|
- joystick.y > -JOYSTICK_THRESHOLD)
|
|
|
- {
|
|
|
- _focusPressed &= ~DOWN;
|
|
|
}
|
|
|
|
|
|
if (!(_focusPressed & LEFT) &&
|
|
|
joystick.x < -JOYSTICK_THRESHOLD)
|
|
|
{
|
|
|
_focusPressed |= LEFT;
|
|
|
- if (!moveFocus(LEFT))
|
|
|
- {
|
|
|
+ if (moveFocus(LEFT))
|
|
|
+ break;
|
|
|
+ else
|
|
|
startScrolling(GAMEPAD_SCROLL_SPEED * joystick.x, 0);
|
|
|
- }
|
|
|
- }
|
|
|
- else if (_focusPressed & LEFT &&
|
|
|
- joystick.x > -JOYSTICK_THRESHOLD)
|
|
|
- {
|
|
|
- _focusPressed &= ~LEFT;
|
|
|
}
|
|
|
|
|
|
if (!(_focusPressed & UP) &&
|
|
|
joystick.y > JOYSTICK_THRESHOLD)
|
|
|
{
|
|
|
_focusPressed |= UP;
|
|
|
- if (!moveFocus(UP))
|
|
|
- {
|
|
|
+ if (moveFocus(UP))
|
|
|
+ break;
|
|
|
+ else
|
|
|
startScrolling(0, GAMEPAD_SCROLL_SPEED * joystick.y);
|
|
|
- }
|
|
|
}
|
|
|
- else if (_focusPressed & UP &&
|
|
|
- joystick.y < JOYSTICK_THRESHOLD)
|
|
|
- {
|
|
|
- _focusPressed &= ~UP;
|
|
|
- }
|
|
|
- eventConsumed |= _consumeInputEvents;
|
|
|
break;
|
|
|
|
|
|
case 1:
|
|
|
// The right analog stick can be used to scroll.
|
|
|
- if (_scrolling)
|
|
|
+ if (_scroll != SCROLL_NONE)
|
|
|
{
|
|
|
- if (joystick.isZero())
|
|
|
+ if (_scrolling)
|
|
|
{
|
|
|
- stopScrolling();
|
|
|
+ if (joystick.isZero())
|
|
|
+ {
|
|
|
+ stopScrolling();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ startScrolling(GAMEPAD_SCROLL_SPEED * joystick.x, GAMEPAD_SCROLL_SPEED * joystick.y, false);
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- startScrolling(GAMEPAD_SCROLL_SPEED * joystick.x, GAMEPAD_SCROLL_SPEED * joystick.y, false);
|
|
|
+ startScrolling(GAMEPAD_SCROLL_SPEED * joystick.x, GAMEPAD_SCROLL_SPEED * joystick.y);
|
|
|
}
|
|
|
+ release();
|
|
|
+ return _consumeInputEvents;
|
|
|
}
|
|
|
- else
|
|
|
- {
|
|
|
- startScrolling(GAMEPAD_SCROLL_SPEED * joystick.x, GAMEPAD_SCROLL_SPEED * joystick.y);
|
|
|
- }
|
|
|
- release();
|
|
|
- return _consumeInputEvents;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ if ((evt == Gamepad::BUTTON_EVENT || evt == Gamepad::JOYSTICK_EVENT) &&
|
|
|
+ analogIndex == 0)
|
|
|
{
|
|
|
- eventConsumed |= _consumeInputEvents;
|
|
|
+ if ((_focusPressed & DOWN) &&
|
|
|
+ !gamepad->isButtonDown(Gamepad::BUTTON_DOWN) &&
|
|
|
+ joystick.y > -JOYSTICK_THRESHOLD)
|
|
|
+ {
|
|
|
+ _focusPressed &= ~DOWN;
|
|
|
+ eventConsumed |= _consumeInputEvents;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((_focusPressed & RIGHT) &&
|
|
|
+ !gamepad->isButtonDown(Gamepad::BUTTON_RIGHT) &&
|
|
|
+ joystick.x < JOYSTICK_THRESHOLD)
|
|
|
+ {
|
|
|
+ _focusPressed &= ~RIGHT;
|
|
|
+ eventConsumed |= _consumeInputEvents;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((_focusPressed & UP) &&
|
|
|
+ !gamepad->isButtonDown(Gamepad::BUTTON_UP) &&
|
|
|
+ joystick.y < JOYSTICK_THRESHOLD)
|
|
|
+ {
|
|
|
+ _focusPressed &= ~UP;
|
|
|
+ eventConsumed |= _consumeInputEvents;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((_focusPressed & LEFT) &&
|
|
|
+ !gamepad->isButtonDown(Gamepad::BUTTON_LEFT) &&
|
|
|
+ joystick.x > -JOYSTICK_THRESHOLD)
|
|
|
+ {
|
|
|
+ _focusPressed &= ~LEFT;
|
|
|
+ eventConsumed |= _consumeInputEvents;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (!_focusPressed && _scrolling)
|