static void UI_AbstractNodeCallCreateChild (uiNode_t* node, const uiCallContext_t* context) { uiNode_t* child; uiNode_t* component; const char* name; const char* type; if (UI_GetParamNumber(context) != 2) { Com_Printf("UI_AbstractNodeCallCreateChild: Invalid number of parameters\n"); return; } name = UI_GetParam(context, 1); type = UI_GetParam(context, 2); uiNode_t* existingNode = UI_GetNode(node, name); if (existingNode != nullptr) { Com_Printf("UI_AbstractNodeCallCreateChild: Node with name '%s' already exists\n", name); } component = UI_GetComponent(type); if (component) { child = UI_CloneNode(component, node->root, true, name, true); } else { child = UI_AllocNode(name, type, true); } if (child == nullptr) { Com_Printf("UI_AbstractNodeCallCreateChild: Impossible to create the node\n"); return; } UI_AppendNode(node, child); }
/** * @brief Parse a component * @sa CL_ParseClientData * @code * component panel componentName { * } * @endcode */ bool UI_ParseComponent (const char* type, const char* name, const char** text) { const char* errhead = "UI_ParseComponent: unexpected end of file (component"; const char* token; if (!Q_streq(type, "component")) { Com_Error(ERR_FATAL, "UI_ParseComponent: \"component\" expected but \"%s\" found.\n", type); return false; /* never reached */ } /* check the name */ if (!UI_TokenIsName(name, false)) { Com_Printf("UI_ParseNode: \"%s\" is not a well formed node name ([a-zA-Z_][a-zA-Z0-9_]*)\n", name); return false; } if (UI_TokenIsReserved(name)) { Com_Printf("UI_ParseNode: \"%s\" is a reserved token, we can't call a node with it\n", name); return false; } token = Com_EParse(text, errhead, ""); if (text == nullptr) return false; /* get keyword */ if (!Q_streq(token, "extends")) { Com_Printf("UI_ParseComponent: \"extends\" expected but \"%s\" found (component %s)\n", token, name); return false; } token = Com_EParse(text, errhead, ""); if (text == nullptr) return false; /* initialize component */ uiNode_t* component = nullptr; const uiBehaviour_t* behaviour = UI_GetNodeBehaviour(token); if (behaviour) { /* initialize a new node from behaviour */ component = UI_AllocNode(name, behaviour->name, false); } else { const uiNode_t* inheritedComponent = UI_GetComponent(token); if (inheritedComponent) { /* initialize from a component */ component = UI_CloneNode(inheritedComponent, nullptr, true, name, false); } else { Com_Printf("UI_ParseComponent: node behaviour/component '%s' doesn't exists (component %s)\n", token, name); return false; } } /* get body */ token = Com_EParse(text, errhead, ""); if (!*text) return false; bool result = UI_ParseNodeBody(component, text, &token, errhead); if (!result) return false; /* validate properties */ UI_Node_Loaded(component); UI_InsertComponent(component); return true; }
/** * @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; }