|
@@ -57,7 +57,7 @@ Container::Container()
|
|
|
_scrollingMouseVertically(false), _scrollingMouseHorizontally(false),
|
|
_scrollingMouseVertically(false), _scrollingMouseHorizontally(false),
|
|
|
_scrollBarOpacityClip(NULL), _zIndexDefault(0),
|
|
_scrollBarOpacityClip(NULL), _zIndexDefault(0),
|
|
|
_selectButtonDown(false), _lastFrameTime(0), _totalWidth(0), _totalHeight(0),
|
|
_selectButtonDown(false), _lastFrameTime(0), _totalWidth(0), _totalHeight(0),
|
|
|
- _initializedWithScroll(false), _scrollWheelRequiresFocus(false)
|
|
|
|
|
|
|
+ _initializedWithScroll(false), _scrollWheelRequiresFocus(false), _inRelayout(false)
|
|
|
{
|
|
{
|
|
|
clearContacts();
|
|
clearContacts();
|
|
|
}
|
|
}
|
|
@@ -374,7 +374,7 @@ void Container::setScroll(Scroll scroll)
|
|
|
_canFocus = true;
|
|
_canFocus = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- setDirty(DIRTY_BOUNDS);
|
|
|
|
|
|
|
+ setDirty(DIRTY_BOUNDS | DIRTY_STATE);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -388,7 +388,7 @@ void Container::setScrollBarsAutoHide(bool autoHide)
|
|
|
if (autoHide != _scrollBarsAutoHide)
|
|
if (autoHide != _scrollBarsAutoHide)
|
|
|
{
|
|
{
|
|
|
_scrollBarsAutoHide = autoHide;
|
|
_scrollBarsAutoHide = autoHide;
|
|
|
- setDirty(DIRTY_BOUNDS);
|
|
|
|
|
|
|
+ setDirty(DIRTY_BOUNDS | DIRTY_STATE);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -501,52 +501,75 @@ void Container::setActiveControl(Control* control)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void Container::setChildrenDirty(int bits, bool recursive)
|
|
|
|
|
+{
|
|
|
|
|
+ for (size_t i = 0, count = _controls.size(); i < count; ++i)
|
|
|
|
|
+ {
|
|
|
|
|
+ Control* ctrl = _controls[i];
|
|
|
|
|
+ ctrl->setDirty(bits);
|
|
|
|
|
+ if (recursive && ctrl->isContainer())
|
|
|
|
|
+ static_cast<Container*>(ctrl)->setChildrenDirty(bits, true);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void Container::update(float elapsedTime)
|
|
void Container::update(float elapsedTime)
|
|
|
{
|
|
{
|
|
|
Control::update(elapsedTime);
|
|
Control::update(elapsedTime);
|
|
|
|
|
|
|
|
for (size_t i = 0, count = _controls.size(); i < count; ++i)
|
|
for (size_t i = 0, count = _controls.size(); i < count; ++i)
|
|
|
- {
|
|
|
|
|
_controls[i]->update(elapsedTime);
|
|
_controls[i]->update(elapsedTime);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void Container::updateState(State state)
|
|
|
|
|
+{
|
|
|
|
|
+ Control::updateState(state);
|
|
|
|
|
+
|
|
|
|
|
+ // Get scrollbar images and diminish clipping bounds to make room for scrollbars.
|
|
|
|
|
+ if ((_scroll & SCROLL_HORIZONTAL) == SCROLL_HORIZONTAL)
|
|
|
|
|
+ {
|
|
|
|
|
+ _scrollBarLeftCap = getImage("scrollBarLeftCap", state);
|
|
|
|
|
+ _scrollBarHorizontal = getImage("horizontalScrollBar", state);
|
|
|
|
|
+ _scrollBarRightCap = getImage("scrollBarRightCap", state);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ((_scroll & SCROLL_VERTICAL) == SCROLL_VERTICAL)
|
|
|
|
|
+ {
|
|
|
|
|
+ _scrollBarTopCap = getImage("scrollBarTopCap", state);
|
|
|
|
|
+ _scrollBarVertical = getImage("verticalScrollBar", state);
|
|
|
|
|
+ _scrollBarBottomCap = getImage("scrollBarBottomCap", state);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void Container::updateBounds(const Vector2& offset)
|
|
|
|
|
|
|
+bool Container::updateBounds(const Vector2& offset)
|
|
|
{
|
|
{
|
|
|
- if ((_dirtyBits & DIRTY_BOUNDS) == 0)
|
|
|
|
|
|
|
+ // Update our child bounds first
|
|
|
|
|
+ updateChildBounds();
|
|
|
|
|
+
|
|
|
|
|
+ /*if ((_dirtyBits & DIRTY_BOUNDS) == 0)
|
|
|
{
|
|
{
|
|
|
- // We're not dirty, but our children might be.
|
|
|
|
|
|
|
+ // We're not dirty, but our children might be
|
|
|
updateChildBounds();
|
|
updateChildBounds();
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- Rectangle oldAbsoluteBounds(_absoluteBounds);
|
|
|
|
|
|
|
+ // If we're still not dirty after updating our child bounds, we have nothing to do
|
|
|
|
|
+ if ((_dirtyBits & DIRTY_BOUNDS) == 0)
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }*/
|
|
|
|
|
|
|
|
- Control::updateBounds(offset);
|
|
|
|
|
|
|
+ bool changed = Control::updateBounds(offset);
|
|
|
|
|
|
|
|
Control::State state = getState();
|
|
Control::State state = getState();
|
|
|
|
|
|
|
|
// Get scrollbar images and diminish clipping bounds to make room for scrollbars.
|
|
// Get scrollbar images and diminish clipping bounds to make room for scrollbars.
|
|
|
if ((_scroll & SCROLL_HORIZONTAL) == SCROLL_HORIZONTAL)
|
|
if ((_scroll & SCROLL_HORIZONTAL) == SCROLL_HORIZONTAL)
|
|
|
{
|
|
{
|
|
|
- _scrollBarLeftCap = getImage("scrollBarLeftCap", state);
|
|
|
|
|
- _scrollBarHorizontal = getImage("horizontalScrollBar", state);
|
|
|
|
|
- _scrollBarRightCap = getImage("scrollBarRightCap", state);
|
|
|
|
|
-
|
|
|
|
|
GP_ASSERT(_scrollBarLeftCap && _scrollBarHorizontal && _scrollBarRightCap);
|
|
GP_ASSERT(_scrollBarLeftCap && _scrollBarHorizontal && _scrollBarRightCap);
|
|
|
-
|
|
|
|
|
_viewportBounds.height -= _scrollBarHorizontal->getRegion().height;
|
|
_viewportBounds.height -= _scrollBarHorizontal->getRegion().height;
|
|
|
_viewportClipBounds.height -= _scrollBarHorizontal->getRegion().height;
|
|
_viewportClipBounds.height -= _scrollBarHorizontal->getRegion().height;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if ((_scroll & SCROLL_VERTICAL) == SCROLL_VERTICAL)
|
|
if ((_scroll & SCROLL_VERTICAL) == SCROLL_VERTICAL)
|
|
|
{
|
|
{
|
|
|
- _scrollBarTopCap = getImage("scrollBarTopCap", state);
|
|
|
|
|
- _scrollBarVertical = getImage("verticalScrollBar", state);
|
|
|
|
|
- _scrollBarBottomCap = getImage("scrollBarBottomCap", state);
|
|
|
|
|
-
|
|
|
|
|
GP_ASSERT(_scrollBarTopCap && _scrollBarVertical && _scrollBarBottomCap);
|
|
GP_ASSERT(_scrollBarTopCap && _scrollBarVertical && _scrollBarBottomCap);
|
|
|
-
|
|
|
|
|
_viewportBounds.width -= _scrollBarVertical->getRegion().width;
|
|
_viewportBounds.width -= _scrollBarVertical->getRegion().width;
|
|
|
_viewportClipBounds.width -= _scrollBarVertical->getRegion().width;
|
|
_viewportClipBounds.width -= _scrollBarVertical->getRegion().width;
|
|
|
}
|
|
}
|
|
@@ -559,9 +582,12 @@ void Container::updateBounds(const Vector2& offset)
|
|
|
_layout->update(this);
|
|
_layout->update(this);
|
|
|
|
|
|
|
|
// Update bounds of our children
|
|
// Update bounds of our children
|
|
|
- updateChildBounds();
|
|
|
|
|
|
|
+ //updateChildBounds();
|
|
|
|
|
+
|
|
|
|
|
+ changed = changed || (_dirtyBits & DIRTY_BOUNDS);
|
|
|
|
|
|
|
|
// Handle automatically sizing based on our children
|
|
// Handle automatically sizing based on our children
|
|
|
|
|
+ Rectangle oldBounds(_bounds);
|
|
|
if (_autoSize != AUTO_SIZE_NONE)
|
|
if (_autoSize != AUTO_SIZE_NONE)
|
|
|
{
|
|
{
|
|
|
if (_autoSize & AUTO_SIZE_WIDTH)
|
|
if (_autoSize & AUTO_SIZE_WIDTH)
|
|
@@ -600,13 +626,29 @@ void Container::updateBounds(const Vector2& offset)
|
|
|
setHeightInternal(height);
|
|
setHeightInternal(height);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ changed = changed || (_bounds != oldBounds);
|
|
|
|
|
|
|
|
// If our bounds have changed, dirty our entire child hierarchy since at a minimum their absolute bounds
|
|
// If our bounds have changed, dirty our entire child hierarchy since at a minimum their absolute bounds
|
|
|
// will need to be recomputed to be properly offset from our new bounds.
|
|
// will need to be recomputed to be properly offset from our new bounds.
|
|
|
- if (_absoluteBounds != oldAbsoluteBounds)
|
|
|
|
|
|
|
+ if (changed)
|
|
|
{
|
|
{
|
|
|
- setDirty(DIRTY_BOUNDS);
|
|
|
|
|
|
|
+ setChildrenDirty(DIRTY_BOUNDS, true);
|
|
|
}
|
|
}
|
|
|
|
|
+ /*if ((_bounds != oldBounds) || (_dirtyBits & DIRTY_BOUNDS))
|
|
|
|
|
+ {
|
|
|
|
|
+ //setDirty(DIRTY_BOUNDS);
|
|
|
|
|
+ setChildrenDirty(DIRTY_BOUNDS, true);
|
|
|
|
|
+
|
|
|
|
|
+ if (!_inRelayout)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Perform a second pass layout to update ourself based on our children and our children based on ourself
|
|
|
|
|
+ _inRelayout = true;
|
|
|
|
|
+ //updateBounds(offset);
|
|
|
|
|
+ _inRelayout = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }*/
|
|
|
|
|
+
|
|
|
|
|
+ return changed;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Container::updateChildBounds()
|
|
void Container::updateChildBounds()
|
|
@@ -616,18 +658,19 @@ void Container::updateChildBounds()
|
|
|
Control* ctrl = _controls[i];
|
|
Control* ctrl = _controls[i];
|
|
|
GP_ASSERT(ctrl);
|
|
GP_ASSERT(ctrl);
|
|
|
|
|
|
|
|
- if (ctrl->isVisible() && (ctrl->isContainer() || ctrl->_dirtyBits & DIRTY_BOUNDS))
|
|
|
|
|
|
|
+ if (ctrl->isVisible() && (ctrl->isContainer() || (ctrl->_dirtyBits & DIRTY_BOUNDS)))
|
|
|
{
|
|
{
|
|
|
- Rectangle oldBounds(ctrl->_absoluteBounds);
|
|
|
|
|
|
|
+ //Rectangle oldBounds(ctrl->_absoluteBounds);
|
|
|
|
|
|
|
|
- ctrl->updateBounds(_scrollPosition);
|
|
|
|
|
|
|
+ bool changed = ctrl->updateBounds(_scrollPosition);
|
|
|
|
|
|
|
|
// If the child bounds have changed, dirty our bounds and all of our
|
|
// If the child bounds have changed, dirty our bounds and all of our
|
|
|
// parent bounds so that our layout and/or bounds are recomputed.
|
|
// parent bounds so that our layout and/or bounds are recomputed.
|
|
|
- if (ctrl->_absoluteBounds != oldBounds)
|
|
|
|
|
|
|
+ //if (ctrl->_absoluteBounds != oldBounds)
|
|
|
|
|
+ if (changed)
|
|
|
{
|
|
{
|
|
|
Control* parent = this;
|
|
Control* parent = this;
|
|
|
- while (parent)
|
|
|
|
|
|
|
+ while (parent && parent->_autoSize != AUTO_SIZE_NONE)
|
|
|
{
|
|
{
|
|
|
parent->setDirty(DIRTY_BOUNDS);
|
|
parent->setDirty(DIRTY_BOUNDS);
|
|
|
parent = parent->_parent;
|
|
parent = parent->_parent;
|
|
@@ -1115,6 +1158,7 @@ void Container::updateScroll()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
setDirty(DIRTY_BOUNDS);
|
|
setDirty(DIRTY_BOUNDS);
|
|
|
|
|
+ setChildrenDirty(DIRTY_BOUNDS, true);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Stop scrolling when the far edge is reached.
|
|
// Stop scrolling when the far edge is reached.
|
|
@@ -1183,7 +1227,8 @@ bool Container::touchEventScroll(Touch::TouchEvent evt, int x, int y, unsigned i
|
|
|
case Touch::TOUCH_PRESS:
|
|
case Touch::TOUCH_PRESS:
|
|
|
if (_contactIndex == INVALID_CONTACT_INDEX)
|
|
if (_contactIndex == INVALID_CONTACT_INDEX)
|
|
|
{
|
|
{
|
|
|
- _contactIndex = (int) contactIndex;
|
|
|
|
|
|
|
+ bool dirty = !_scrollingVelocity.isZero();
|
|
|
|
|
+ _contactIndex = (int)contactIndex;
|
|
|
_scrollingLastX = _scrollingFirstX = _scrollingVeryFirstX = x;
|
|
_scrollingLastX = _scrollingFirstX = _scrollingVeryFirstX = x;
|
|
|
_scrollingLastY = _scrollingFirstY = _scrollingVeryFirstY = y;
|
|
_scrollingLastY = _scrollingFirstY = _scrollingVeryFirstY = y;
|
|
|
_scrollingVelocity.set(0, 0);
|
|
_scrollingVelocity.set(0, 0);
|
|
@@ -1196,7 +1241,8 @@ bool Container::touchEventScroll(Touch::TouchEvent evt, int x, int y, unsigned i
|
|
|
_scrollBarOpacityClip = NULL;
|
|
_scrollBarOpacityClip = NULL;
|
|
|
}
|
|
}
|
|
|
_scrollBarOpacity = 1.0f;
|
|
_scrollBarOpacity = 1.0f;
|
|
|
- setDirty(DIRTY_BOUNDS);
|
|
|
|
|
|
|
+ if (dirty)
|
|
|
|
|
+ setDirty(DIRTY_BOUNDS);
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
@@ -1260,6 +1306,7 @@ bool Container::touchEventScroll(Touch::TouchEvent evt, int x, int y, unsigned i
|
|
|
|
|
|
|
|
_scrollingLastTime = gameTime;
|
|
_scrollingLastTime = gameTime;
|
|
|
setDirty(DIRTY_BOUNDS);
|
|
setDirty(DIRTY_BOUNDS);
|
|
|
|
|
+ setChildrenDirty(DIRTY_BOUNDS, true);
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
@@ -1326,6 +1373,7 @@ bool Container::mouseEventScroll(Mouse::MouseEvent evt, int x, int y, int wheelD
|
|
|
{
|
|
{
|
|
|
case Mouse::MOUSE_PRESS_LEFT_BUTTON:
|
|
case Mouse::MOUSE_PRESS_LEFT_BUTTON:
|
|
|
{
|
|
{
|
|
|
|
|
+ bool dirty = false;
|
|
|
if (_scrollBarVertical)
|
|
if (_scrollBarVertical)
|
|
|
{
|
|
{
|
|
|
float vWidth = _scrollBarVertical->getRegion().width;
|
|
float vWidth = _scrollBarVertical->getRegion().width;
|
|
@@ -1344,10 +1392,12 @@ bool Container::mouseEventScroll(Mouse::MouseEvent evt, int x, int y, int wheelD
|
|
|
if (y < vBounds.y)
|
|
if (y < vBounds.y)
|
|
|
{
|
|
{
|
|
|
_scrollPosition.y += _totalHeight / 5.0f;
|
|
_scrollPosition.y += _totalHeight / 5.0f;
|
|
|
|
|
+ dirty = true;
|
|
|
}
|
|
}
|
|
|
else if (y > vBounds.bottom())
|
|
else if (y > vBounds.bottom())
|
|
|
{
|
|
{
|
|
|
_scrollPosition.y -= _totalHeight / 5.0f;
|
|
_scrollPosition.y -= _totalHeight / 5.0f;
|
|
|
|
|
+ dirty = true;
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -1373,10 +1423,12 @@ bool Container::mouseEventScroll(Mouse::MouseEvent evt, int x, int y, int wheelD
|
|
|
if (x < hBounds.x)
|
|
if (x < hBounds.x)
|
|
|
{
|
|
{
|
|
|
_scrollPosition.x += _totalWidth / 5.0f;
|
|
_scrollPosition.x += _totalWidth / 5.0f;
|
|
|
|
|
+ dirty = true;
|
|
|
}
|
|
}
|
|
|
else if (x > hBounds.x + hBounds.width)
|
|
else if (x > hBounds.x + hBounds.width)
|
|
|
{
|
|
{
|
|
|
_scrollPosition.x -= _totalWidth / 5.0f;
|
|
_scrollPosition.x -= _totalWidth / 5.0f;
|
|
|
|
|
+ dirty = true;
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -1385,6 +1437,9 @@ bool Container::mouseEventScroll(Mouse::MouseEvent evt, int x, int y, int wheelD
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (dirty)
|
|
|
|
|
+ setChildrenDirty(DIRTY_BOUNDS, true);
|
|
|
|
|
+
|
|
|
return touchEventScroll(Touch::TOUCH_PRESS, x, y, 0);
|
|
return touchEventScroll(Touch::TOUCH_PRESS, x, y, 0);
|
|
|
}
|
|
}
|
|
|
|
|
|