/** * @brief Insert a node next another one into a node. If prevNode is nullptr add the node on the head of the window * @param[in] parent Node where the newNode is inserted in * @param[in] prevNode previous node, will became before the newNode; else nullptr if newNode will become the first child of the node * @param[in] newNode node we insert */ void UI_InsertNode (uiNode_t* const parent, uiNode_t* prevNode, uiNode_t* newNode) { /* parent and newNode should be valid, or else insertion doesn't make sense */ assert(parent); assert(newNode); /* insert only a single element */ assert(!newNode->next); uiNode_t** const anchor = prevNode ? &prevNode->next : &parent->firstChild; newNode->next = *anchor; *anchor = newNode; newNode->parent = parent; UI_UpdateRoot (newNode, parent->root); if (!parent->firstChild) { parent->firstChild = newNode; } if (!parent->lastChild) { parent->lastChild = newNode; } if (!newNode->next) { parent->lastChild = newNode; } if (newNode->root && newNode->indexed) UI_WindowNodeAddIndexedNode(newNode->root, newNode); UI_Invalidate(parent); }
void UI_UpdateRoot (uiNode_t* node, uiNode_t* newRoot) { node->root = newRoot; node = node->firstChild; while (node) { UI_UpdateRoot(node, newRoot); node = node->next; } }
/** * @brief parse a node * @sa UI_ParseNodeProperties * @todo we can think about merging UI_ParseNodeProperties here * @note first token already read * @note dont read more than the need token (last right token is '}' of end of node) */ static uiNode_t* UI_ParseNode (uiNode_t* parent, const char** text, const char** token, const char* errhead) { uiNode_t* node = nullptr; uiBehaviour_t* behaviour; uiNode_t* component = nullptr; /* get the behaviour */ behaviour = UI_GetNodeBehaviour(*token); if (!behaviour) { component = UI_GetComponent(*token); } if (behaviour == nullptr && component == nullptr) { Com_Printf("UI_ParseNode: node behaviour/component '%s' doesn't exist (%s)\n", *token, UI_GetPath(parent)); return nullptr; } /* get the name */ *token = Com_EParse(text, errhead, ""); if (!*text) return nullptr; if (!UI_TokenIsName(*token, Com_GetType(text) == TT_QUOTED_WORD)) { Com_Printf("UI_ParseNode: \"%s\" is not a well formed node name ([a-zA-Z_][a-zA-Z0-9_]*)\n", *token); return nullptr; } if (UI_TokenIsReserved(*token)) { Com_Printf("UI_ParseNode: \"%s\" is a reserved token, we can't call a node with it\n", *token); return nullptr; } /* test if node already exists */ /* Already existing node should only come from inherited node, we should not have 2 definitions of the same node into the same window. */ if (parent) node = UI_GetNode(parent, *token); /* reuse a node */ if (node) { const uiBehaviour_t* test = (behaviour != nullptr) ? behaviour : (component != nullptr) ? component->behaviour : nullptr; if (node->behaviour != test) { Com_Printf("UI_ParseNode: we can't change node type (node \"%s\")\n", UI_GetPath(node)); return nullptr; } Com_DPrintf(DEBUG_CLIENT, "... over-riding node %s\n", UI_GetPath(node)); /* else initialize a component */ } else if (component) { node = UI_CloneNode(component, nullptr, true, *token, false); if (parent) { if (parent->root) UI_UpdateRoot(node, parent->root); UI_AppendNode(parent, node); } /* else initialize a new node */ } else { node = UI_AllocNode(*token, behaviour->name, false); node->parent = parent; if (parent) node->root = parent->root; /** @todo move it into caller */ if (parent) UI_AppendNode(parent, node); } /* get body */ const bool result = UI_ParseNodeBody(node, text, token, errhead); if (!result) return nullptr; /* validate properties */ UI_Node_Loaded(node); return node; }