/** * @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; }
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); }
/** * @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); }
/** * @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); } }