bool UINode::onMouseButtonPress (int32_t x, int32_t y, unsigned char button)
{
	if (!_enabled)
		return false;

	for (UINodeListRevIter i = _nodes.rbegin(); i != _nodes.rend(); ++i) {
		UINode* nodePtr = *i;
		if (!nodePtr->hasFocus())
			continue;
		if ((*i)->onMouseButtonPress(x - getRenderX(), y - getRenderY(), button)) {
			return true;
		}
	}

	switch (button) {
	case SDL_BUTTON_LEFT:
		initDrag(x, y);
		onMouseLeftPress(x, y);
		return true;
	case SDL_BUTTON_RIGHT:
		return onMouseRightPress(x, y);
	case SDL_BUTTON_MIDDLE:
		return onMouseMiddlePress(x, y);
	}

	return false;
}
void UINode::onMouseMotion (int32_t x, int32_t y, int32_t relX, int32_t relY)
{
	for (UINodeListRevIter i = _nodes.rbegin(); i != _nodes.rend(); ++i) {
		UINode* nodePtr = *i;
		if (!nodePtr->hasFocus())
			continue;
		nodePtr->onMouseMotion(x - getRenderX(), y - getRenderY(), relX, relY);
	}
}
bool UINode::onMouseWheel (int32_t x, int32_t y)
{
	bool handled = false;
	for (UINodeListRevIter i = _nodes.rbegin(); i != _nodes.rend(); ++i) {
		UINode* nodePtr = *i;
		if (!nodePtr->hasFocus())
			continue;
		handled |= (*i)->onMouseWheel(x, y);
	}
	return handled;
}
bool UINode::onJoystickButtonPress (int x, int y, uint8_t button)
{
	for (UINodeListRevIter i = _nodes.rbegin(); i != _nodes.rend(); ++i) {
		UINode* nodePtr = *i;
		if (!nodePtr->hasFocus())
			continue;
		if ((*i)->onJoystickButtonPress(x - getRenderX(), y - getRenderY(), button)) {
			return true;
		}
	}
	return false;
}
bool UINode::onControllerButtonPress (int x, int y, const std::string& button)
{
	for (UINodeListRevIter i = _nodes.rbegin(); i != _nodes.rend(); ++i) {
		UINode* nodePtr = *i;
		if (!nodePtr->hasFocus())
			continue;
		if ((*i)->onControllerButtonPress(x - getRenderX(), y - getRenderY(), button)) {
			return true;
		}
	}
	return false;
}
bool UINode::onTextInput (const std::string& text)
{
	for (UINodeListConstIter i = _nodes.begin(); i != _nodes.end(); ++i) {
		UINode* nodePtr = *i;
		if (!nodePtr->hasFocus())
			continue;
		if (nodePtr->onTextInput(text))
			return true;
	}

	return false;
}
void UINode::initDrag (int32_t x, int32_t y)
{
	for (UINodeListConstIter i = _nodes.begin(); i != _nodes.end(); ++i) {
		UINode* node = *i;
		if (!node->hasFocus())
			continue;
		node->initDrag(x - getRenderX(), y - getRenderY());
		break;
	}

	_dragStartX = x;
	_dragStartY = y;
}
bool UINode::onFingerMotion (int64_t finger, uint16_t x, uint16_t y, int16_t dx, int16_t dy)
{
	const bool focus = checkFocus(x, y);
	if (!focus)
		return false;

	for (UINodeListRevIter i = _nodes.rbegin(); i != _nodes.rend(); ++i) {
		UINode* nodePtr = *i;
		if (!nodePtr->hasFocus())
			continue;
		nodePtr->onFingerMotion(finger, x - getRenderX(), y - getRenderY(), dx, dy);
	}
	return focus;
}
bool UINode::onFingerRelease (int64_t finger, uint16_t x, uint16_t y)
{
	handleDrop(x, y);
	execute();
	for (UINodeListRevIter i = _nodes.rbegin(); i != _nodes.rend(); ++i) {
		UINode* nodePtr = *i;
		if (!nodePtr->hasFocus())
			continue;
		if (nodePtr->onFingerRelease(finger, x - getRenderX(), y - getRenderY())) {
			return true;
		}
	}

	return false;
}
bool UINode::onGestureRecord (int64_t gestureId)
{
	if (!_enabled)
		return false;

	for (UINodeListRevIter i = _nodes.rbegin(); i != _nodes.rend(); ++i) {
		UINode* nodePtr = *i;
		if (!nodePtr->hasFocus())
			continue;
		if ((*i)->onGestureRecord(gestureId)) {
			return true;
		}
	}

	return false;
}
bool UINode::onGesture (int64_t gestureId, float error, int32_t numFingers)
{
	if (!_enabled)
		return false;

	for (UINodeListRevIter i = _nodes.rbegin(); i != _nodes.rend(); ++i) {
		UINode* nodePtr = *i;
		if (!nodePtr->hasFocus())
			continue;
		if ((*i)->onGesture(gestureId, error, numFingers)) {
			return true;
		}
	}

	return false;
}
bool UINode::onMultiGesture (float theta, float dist, int32_t numFingers)
{
	if (!_enabled)
		return false;

	for (UINodeListRevIter i = _nodes.rbegin(); i != _nodes.rend(); ++i) {
		UINode* nodePtr = *i;
		if (!nodePtr->hasFocus())
			continue;
		if ((*i)->onMultiGesture(theta, dist, numFingers)) {
			return true;
		}
	}

	return false;
}
void UINode::removeFocus ()
{
	if (!_focus)
		return;
	Log::debug(LOG_CLIENT, "remove focus for %s", getId().c_str());
	_focus = false;
	_focusMouseX = -1;
	_focusMouseY = -1;
	for (Listeners::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
		(*i)->onRemoveFocus();
	}
	if (!fequals(_focusAlpha, 0.0f))
		restoreAlpha();

	for (UINodeListIter i = _nodes.begin(); i != _nodes.end(); ++i) {
		UINode* node = *i;
		if (!node->hasFocus())
			continue;
		node->removeFocus();
	}
}
bool UINode::nextFocus ()
{
	if (_nodes.empty()) {
		if (!isActive())
			return false;
		if (hasFocus())
			return false;
		addFocus(0, 0);
		return true;
	}

	for (UINodeListIter i = _nodes.begin(); i != _nodes.end(); ++i) {
		UINode* nodePtr = *i;
		// search the node that currently has the focus
		if (!nodePtr->hasFocus())
			continue;

		if (nodePtr->nextFocus()) {
			addFocus(0, 0);
			return true;
		}

		nodePtr->removeFocus();
		for (++i; i != _nodes.end(); ++i) {
			UINode* focusNodePtr = *i;
			if (focusNodePtr->addFirstFocus()) {
				addFocus(0, 0);
				return true;
			}
		}
		break;
	}

	removeFocus();

	return false;
}