/**
 * @brief Create a top-down flow layout with child of the node.
 * Child position is automatically set, child height don't change
 * and child width is set according to node width and padding
 * @param[in,out] node The panel node to render the children for
 * @param[in] margin The margin between all children nodes in their y-position of the panel
 * @note test only
 */
static void UI_TopDownFlowLayout (uiNode_t *node, int margin)
{
	const int width = node->size[0] - node->padding - node->padding;
	int positionY = node->padding;
	uiNode_t *child = node->firstChild;
	vec2_t newSize = {width, 0};

	while (child) {
		newSize[1] = child->size[1];
		UI_NodeSetSize(child, newSize);
		child->pos[0] = node->padding;
		child->pos[1] = positionY;
		positionY += child->size[1] + margin;
		child = child->next;
	}

	/* fix scroll */
	{
		qboolean updated;

		updated = UI_SetScroll(&EXTRADATA(node).super.scrollX, -1, node->size[0], node->size[0]);
		updated = UI_SetScroll(&EXTRADATA(node).super.scrollY, -1, node->size[1], positionY + node->padding) || updated;
		if (updated && EXTRADATA(node).super.onViewChange)
			UI_ExecuteEventActions(node, EXTRADATA(node).super.onViewChange);
	}

}
/**
 * @brief Handle mouse wheel scrolling
 * @param[in, out] node UI node to scroll
 * @param[in] deltaX horizontal scrolling value (not used)
 * @param[in] deltaX vertical scrolling value
 */
static qboolean UI_PanelNodeMouseWheel (uiNode_t *node, int deltaX, int deltaY)
{
	qboolean down = deltaY > 0;
	qboolean updated;

	/* @todo remove wheelScrollable after 2.4 release */
	if (!EXTRADATA(node).wheelScrollable || deltaY == 0)
		return qfalse;

	updated = UI_SetScroll(&EXTRADATA(node).super.scrollY, EXTRADATA(node).super.scrollY.viewPos + deltaY * 50, -1, -1);
	if (EXTRADATA(node).super.onViewChange && updated)
		UI_ExecuteEventActions(node, EXTRADATA(node).super.onViewChange);

	/* @todo use super behaviour */
	if (node->onWheelUp && !down) {
		UI_ExecuteEventActions(node, node->onWheelUp);
		updated = qtrue;
	}
	if (node->onWheelDown && down) {
		UI_ExecuteEventActions(node, node->onWheelDown);
		updated = qtrue;
	}
	if (node->onWheel) {
		UI_ExecuteEventActions(node, node->onWheel);
		updated = qtrue;
	}
	return updated;
}
/**
 * @brief Auto scroll the list
 */
static qboolean UI_OptionListNodeMouseWheel (uiNode_t *node, int deltaX, int deltaY)
{
	qboolean down = deltaY > 0;
	qboolean updated;
	if (deltaY == 0)
		return qfalse;
	updated = UI_SetScroll(&EXTRADATA(node).scrollY, EXTRADATA(node).scrollY.viewPos + (down ? 1 : -1), -1, -1);
	if (EXTRADATA(node).onViewChange && updated)
		UI_ExecuteEventActions(node, EXTRADATA(node).onViewChange);

	/* @todo use super behaviour */
	if (node->onWheelUp && !down) {
		UI_ExecuteEventActions(node, node->onWheelUp);
		updated = qtrue;
	}
	if (node->onWheelDown && down) {
		UI_ExecuteEventActions(node, node->onWheelDown);
		updated = qtrue;
	}
	if (node->onWheel) {
		UI_ExecuteEventActions(node, node->onWheel);
		updated = qtrue;
	}
	return updated;
}
/**
 * @brief Set the Y scroll to a position, and call event if need
 * @param[in] node Context node
 * @param[in] viewPos New position to set, else -1 if no change
 * @param[in] viewSize New view size to set, else -1 if no change
 * @param[in] fullSize New full size to set, else -1 if no change
 * @return True, if something have change
 */
qboolean UI_AbstractScrollableNodeSetY (uiNode_t *node, int viewPos, int viewSize, int fullSize)
{
	qboolean updated;
	assert(UI_NodeInstanceOf(node, "abstractscrollable"));

	updated = UI_SetScroll(&EXTRADATA(node).scrollY, viewPos, viewSize, fullSize);

	if (updated && EXTRADATA(node).onViewChange)
		UI_ExecuteEventActions(node, EXTRADATA(node).onViewChange);

	return updated;
}
Exemple #5
0
static void UI_OptionTreeSetSelectedValue (uiNode_t *node, const uiCallContext_t *context)
{
	uiOptionIterator_t iterator;
	uiNode_t *option;
	uiNode_t *firstOption;
	const char* value;
	int pos, i;

	if (UI_GetParamNumber(context) != 1) {
		Com_Printf("UI_OptionTreeSetSelectedValue: Invalide number of param\n");
		return;
	}

	value = UI_GetParam(context, 1);

	/* is the option exists */
	firstOption = UI_OptionTreeNodeGetFirstOption(node);
	UI_InitOptionIteratorAtIndex(0, firstOption, &iterator);
	/** @todo merge that into the Init iterator function */
	iterator.skipCollapsed = qfalse;
	option = UI_FindOptionByValue(&iterator, value);

	/* update the selection */
	if (option) {
		UI_AbstractOptionSetCurrentValue(node, OPTIONEXTRADATA(option).value);
	} else {
		Com_Printf("UI_OptionTreeSetSelectedValue: Option value \"%s\" not found\n", value);
		return;
	}

	/* expend parents */
	for (i = 0; i < iterator.depthPos; i++)
		OPTIONEXTRADATA(iterator.depthCache[i]).collapsed = qfalse;
	UI_OptionTreeNodeUpdateCache(node);
	UI_OptionTreeNodeUpdateScroll(node);

	/* fix scroll bar */
	firstOption = UI_OptionTreeNodeGetFirstOption(node);
	UI_InitOptionIteratorAtIndex(0, firstOption, &iterator);
	pos = UI_FindOptionPosition(&iterator, option);
	if (pos == -1)
		return;
	if (pos < EXTRADATA(node).scrollY.viewPos || pos >= EXTRADATA(node).scrollY.viewPos + EXTRADATA(node).scrollY.viewSize) {
		qboolean updated;
		updated = UI_SetScroll(&EXTRADATA(node).scrollY, pos, -1, -1);
		if (updated && EXTRADATA(node).onViewChange)
			UI_ExecuteEventActions(node, EXTRADATA(node).onViewChange);
	}
}
/**
 * Update the client zone
 */
static void UI_ClientLayout (uiNode_t *node)
{
	int width = 0;
	int height = 0;
	uiNode_t *child;
	qboolean updated;
	for (child = node->firstChild; child; child = child->next) {
		int value;
		value = child->pos[0] + child->size[0];
		if (value > width)
			width = value;
		value = child->pos[1] + child->size[1];
		if (value > height)
			height = value;
	}

	width += node->padding;
	height += node->padding;

	updated = UI_SetScroll(&EXTRADATA(node).super.scrollX, -1, node->size[0], width);
	updated = UI_SetScroll(&EXTRADATA(node).super.scrollY, -1, node->size[1], height) || updated;
	if (updated && EXTRADATA(node).super.onViewChange)
		UI_ExecuteEventActions(node, EXTRADATA(node).super.onViewChange);
}
Exemple #7
0
/**
 * @brief Update the scroll according to the number
 * of items and the size of the node
 */
static void UI_OptionTreeNodeUpdateScroll (uiNode_t *node)
{
	const char *font;
	int fontHeight;
	qboolean updated;
	int elements;

	font = UI_GetFontFromNode(node);
	fontHeight = EXTRADATA(node).lineHeight;
	if (fontHeight == 0)
		fontHeight = UI_FontGetHeight(font);

	elements = (node->size[1] - node->padding - node->padding) / fontHeight;
	updated = UI_SetScroll(&EXTRADATA(node).scrollY, -1, elements, EXTRADATA(node).count);
	if (updated && EXTRADATA(node).onViewChange)
		UI_ExecuteEventActions(node, EXTRADATA(node).onViewChange);
}
Exemple #8
0
/**
 * @brief Auto scroll the list
 */
static void UI_OptionTreeNodeMouseWheel (uiNode_t *node, int deltaX, int deltaY)
{
	qboolean down = deltaY > 0;
	qboolean updated;
	if (deltaY == 0)
		return;
	updated = UI_SetScroll(&EXTRADATA(node).scrollY, EXTRADATA(node).scrollY.viewPos + (down ? 1 : -1), -1, -1);
	if (EXTRADATA(node).onViewChange && updated)
		UI_ExecuteEventActions(node, EXTRADATA(node).onViewChange);

	if (node->onWheelUp && !down)
		UI_ExecuteEventActions(node, node->onWheelUp);
	if (node->onWheelDown && down)
		UI_ExecuteEventActions(node, node->onWheelDown);
	if (node->onWheel)
		UI_ExecuteEventActions(node, node->onWheel);
}
static void UI_OptionListNodeCapturedMouseMove (uiNode_t *node, int x, int y)
{
	const int lineHeight = node->behaviour->getCellHeight(node);
	const int deltaY = (mouseScrollY - y) / lineHeight;
	/* We're doing only vertical scroll, that's enough for the most instances */
	if (deltaY != 0) {
		qboolean updated;
		updated = UI_SetScroll(&EXTRADATA(node).scrollY, EXTRADATA(node).scrollY.viewPos + deltaY, -1, -1);
		if (EXTRADATA(node).onViewChange && updated)
			UI_ExecuteEventActions(node, EXTRADATA(node).onViewChange);
		/* @todo not accurate */
		mouseScrollX = x;
		mouseScrollY = y;
	}
	if (node->behaviour->mouseMove)
		node->behaviour->mouseMove(node, x, y);
}
/**
 * @brief Do column layout. A grid layout according to a fixed number of column.
 * Check to first row to see the needed size of columns, and the height. All rows
 * will use the same row.
 * @todo Use child\@align to align each nodes inside respective cell.
 * @image html http://ufoai.org/wiki/images/Layout_column.png
 */
static void UI_ColumnLayout (uiNode_t *node)
{
	int columnPos[EXTRADATA(node).layoutColumns];
	int columnSize[EXTRADATA(node).layoutColumns];
	int rowHeight = 0;
	int i;
	int y;
	uiNode_t *child;

	if (EXTRADATA(node).layoutColumns <= 0) {
		Com_Printf("UI_ColumnLayout: Column number must be positive (%s). Layout ignored.", UI_GetPath(node));
		return;
	}

	/* check the first row */
	child = node->firstChild;
	for (i = 0; i < EXTRADATA(node).layoutColumns; i++) {
		if (child == NULL)
			break;
		columnSize[i] = child->size[0];
		if (child->size[1] > rowHeight) {
			rowHeight = child->size[1];
		}
		child = child->next;
	}

	/* compute column position */
	columnPos[0] = node->padding;
	for (i = 1; i < EXTRADATA(node).layoutColumns; i++) {
		columnPos[i] = columnPos[i - 1] + columnSize[i - 1] + EXTRADATA(node).layoutMargin;
	}

	/* fix child position */
	i = 0;
	y = -1;
	for (child = node->firstChild; child; child = child->next) {
		const int column = i % EXTRADATA(node).layoutColumns;
		if (column == 0) {
			if (y < 0) {
				y = node->padding;
			} else {
				y += rowHeight + EXTRADATA(node).layoutMargin;
			}
		}
		child->pos[0] = columnPos[column];
		child->pos[1] = y;
		/*UI_NodeSetSize(child, node->size);*/
		child->behaviour->doLayout(child);
		i++;
	}

	/* fix scroll */
	{
		const int column = EXTRADATA(node).layoutColumns;
		int width = columnPos[column - 1] + columnSize[column - 1] + node->padding;
		int height = y + rowHeight + node->padding;
		qboolean updated;

		updated = UI_SetScroll(&EXTRADATA(node).super.scrollX, -1, node->size[0], width);
		updated = UI_SetScroll(&EXTRADATA(node).super.scrollY, -1, node->size[1], height) || updated;
		if (updated && EXTRADATA(node).super.onViewChange)
			UI_ExecuteEventActions(node, EXTRADATA(node).super.onViewChange);
	}
}