Exemple #1
0
/**
 * @brief Clone a node
 * @param[in] node Node to clone
 * @param[in] recursive True if we also must clone subnodes
 * @param[in] newWindow Window where the nodes must be add (this function only link node into window, not window into the new node)
 * @param[in] newName New node name, else nullptr to use the source name
 * @param[in] isDynamic Allocate a node in static or dynamic memory
 * @todo exclude rect is not safe cloned.
 * @todo actions are not cloned. It is be a problem if we use add/remove listener into a cloned node.
 */
uiNode_t* UI_CloneNode (const uiNode_t* node, uiNode_t* newWindow, bool recursive, const char* newName, bool isDynamic)
{
	uiNode_t* newNode = UI_AllocNodeWithoutNew(nullptr, UI_Node_GetWidgetName(node), isDynamic);

	/* clone all data */
	memcpy(newNode, node, UI_Node_GetMemorySize(node));
	newNode->dynamic = isDynamic;

	/* custom name */
	if (newName != nullptr) {
		Q_strncpyz(newNode->name, newName, sizeof(newNode->name));
		if (strlen(newNode->name) != strlen(newName))
			Com_Printf("UI_CloneNode: Node name \"%s\" truncated. New name is \"%s\"\n", newName, newNode->name);
	}

	/* clean up node navigation */
	if (node->root == node && newWindow == nullptr)
		newWindow = newNode;

	newNode->root = newWindow;
	newNode->parent = nullptr;
	newNode->firstChild = nullptr;
	newNode->lastChild = nullptr;
	newNode->next = nullptr;
	newNode->super = node;

	/* clone node methods */
	if (node->nodeMethods) {
		newNode->nodeMethods = HASH_CloneTable(node->nodeMethods);
	}

	/* allocate memories */
	if (newNode->dynamic) {
		UI_Node_InitNodeDynamic(newNode);
	}

	/* typically, cloning makes a copy of all the internals of a source node; override the ::clone(node) method
	   to alter this behaviour */
	UI_Node_Clone(node, newNode);

	/* clone child */
	if (recursive) {
		for (uiNode_t* childNode = node->firstChild; childNode; childNode = childNode->next) {
			uiNode_t* newChildNode = UI_CloneNode(childNode, newWindow, recursive, nullptr, isDynamic);
			UI_AppendNode(newNode, newChildNode);
		}
	}

	return newNode;
}
Exemple #2
0
/**
 * @brief Display in the conde the tree of nodes
 */
static void UI_DebugTree (const uiNode_t *node, int depth)
{
	const uiNode_t *child = node->firstChild;
	int i;

	for (i = 0; i < depth; i++) {
		Com_Printf("    ");
	}
	Com_Printf("+ %s %s\n", UI_Node_GetWidgetName(node), node->name);

	while (child) {
		UI_DebugTree(child, depth + 1);
		child = child->next;
	}
}
Exemple #3
0
/**
 * @brief Clone a node
 * @param[in] node Node to clone
 * @param[in] recursive True if we also must clone subnodes
 * @param[in] newWindow Window where the nodes must be add (this function only link node into window, not window into the new node)
 * @param[in] newName New node name, else nullptr to use the source name
 * @param[in] isDynamic Allocate a node in static or dynamic memory
 * @todo exclude rect is not safe cloned.
 * @todo actions are not cloned. It is be a problem if we use add/remove listener into a cloned node.
 */
uiNode_t* UI_CloneNode (const uiNode_t* node, uiNode_t *newWindow, bool recursive, const char *newName, bool isDynamic)
{
	uiNode_t* newNode = UI_AllocNodeWithoutNew(nullptr, UI_Node_GetWidgetName(node), isDynamic);

	/* clone all data */
	memcpy(newNode, node, UI_Node_GetMemorySize(node));
	newNode->dynamic = isDynamic;

	/* custom name */
	if (newName != nullptr) {
		Q_strncpyz(newNode->name, newName, sizeof(newNode->name));
		if (strlen(newNode->name) != strlen(newName))
			Com_Printf("UI_CloneNode: Node name \"%s\" truncated. New name is \"%s\"\n", newName, newNode->name);
	}

	/* clean up node navigation */
	if (node->root == node && newWindow == nullptr)
		newWindow = newNode;
	newNode->root = newWindow;
	newNode->parent = nullptr;
	newNode->firstChild = nullptr;
	newNode->lastChild = nullptr;
	newNode->next = nullptr;
	newNode->super = node;

	/* clone child */
	if (recursive) {
		uiNode_t* childNode;
		for (childNode = node->firstChild; childNode; childNode = childNode->next) {
			uiNode_t* newChildNode = UI_CloneNode(childNode, newWindow, recursive, nullptr, isDynamic);
			UI_AppendNode(newNode, newChildNode);
		}
	}

	/* allocate memories */
	if (newNode->dynamic)
		UI_Node_NewNode(newNode);

	UI_Node_Clone(node, newNode);

	return newNode;
}
Exemple #4
0
/**
 * @return A string, else an empty string
 * @todo this should not work very well, because too much va are used
 * then we should locally cache values, or manage a temporary string structure
 */
const char* UI_GetStringFromExpression (uiAction_t *expression, const uiCallContext_t *context)
{
	switch (expression->type & EA_HIGHT_MASK) {
	case EA_VALUE:
		switch (expression->type) {
		case EA_VALUE_VAR:
			{
				uiValue_t *variable =  UI_GetVariable(context, expression->d.terminal.d1.integer);
				switch (variable->type) {
				case EA_VALUE_STRING:
					if (variable->value.string == nullptr) {
						Com_Printf("UI_GetStringFromExpression: String variable not initialized. Empty string returned");
						return "";
					}
					return variable->value.string;
				case EA_VALUE_FLOAT:
					{
						const float number = variable->value.number;
						const int integer = number;
						/** @todo should we add a delta? */
						if (number == integer)
							return va("%i", integer);
						else
							return va("%f", number);
					}
				case EA_VALUE_CVAR:
					{
						cvar_t *cvar = variable->value.cvar;
						if (cvar == nullptr) {
							Com_Printf("UI_GetStringFromExpression: Cvar variable not initialized. Empty string returned");
							return "";
						}
						return cvar->string;
					}
				default:
					Com_Printf("UI_GetStringFromExpression: Unsupported variable type: %i. Empty string returned", variable->type);
					return "";
				}
			}
		case EA_VALUE_STRING:
		case EA_VALUE_STRING_WITHINJECTION:
			{
				const char* string = expression->d.terminal.d1.constString;
				if (expression->type == EA_VALUE_STRING_WITHINJECTION)
					string = UI_GenInjectedString(string, false, context);
				return string;
			}
		case EA_VALUE_FLOAT:
		{
			const float number = expression->d.terminal.d1.number;
			const int integer = number;
			/** @todo should we add a delta? */
			if (number == integer)
				return va("%i", integer);
			else
				return va("%f", number);
		}
		case EA_VALUE_CVARNAME:
		case EA_VALUE_CVARNAME_WITHINJECTION:
		{
			cvar_t *cvar = nullptr;
			const char *cvarName = expression->d.terminal.d1.constString;
			if (expression->type == EA_VALUE_CVARNAME_WITHINJECTION)
				cvarName = UI_GenInjectedString(cvarName, false, context);
			cvar = Cvar_Get(cvarName, "", 0, "Cvar from UI script expression");
			return cvar->string;
		}
		case EA_VALUE_PATHPROPERTY:
		case EA_VALUE_PATHPROPERTY_WITHINJECTION:
			{
				uiNode_t *node;
				const value_t *property;
				const char* string;
				node = UI_GetNodeFromExpression(expression, context, &property);
				if (!node) {
					Com_Printf("UI_GetStringFromExpression: Node wasn't found; Empty string returned\n");
					return "";
				}
				if (!property) {
					Com_Printf("UI_GetStringFromExpression: Property wasn't found; Empty string returned\n");
					return "";
				}
				string = UI_GetStringFromNodeProperty(node, property);
				if (string == nullptr) {
					Com_Printf("UI_GetStringFromExpression: String getter for '%s@%s' property do not exists; '' returned\n", UI_Node_GetWidgetName(node), property->string);
					return "";
				}
				return string;
			}
			break;
		case EA_VALUE_PARAM:
			return UI_GetParam(context, expression->d.terminal.d1.integer);
		case EA_VALUE_PARAMCOUNT:
			return va("%i", UI_GetParamNumber(context));
		}
		break;

	case EA_OPERATOR_UNARY:
		switch (expression->type) {
		case EA_OPERATOR_PATHPROPERTYFROM:
		{
			uiNode_t *node;
			const value_t *property;
			node = UI_GetNodeFromExpression(expression, context, &property);
			return UI_GetStringFromNodeProperty(node, property);
		}
		default:
			Com_Error(ERR_FATAL, "UI_GetFloatFromExpression: (EA_OPERATOR_UNARY) Invalid expression type %i", expression->type);
		}

	case EA_OPERATOR_BOOLEAN2BOOLEAN:
	case EA_OPERATOR_FLOAT2BOOLEAN:
	case EA_OPERATOR_STRING2BOOLEAN:
		{
			const bool v = UI_GetBooleanFromExpression(expression, context);
			return (v)?"1":"0";
		}

	case EA_OPERATOR_FLOAT2FLOAT:
		{
			const float number = UI_GetFloatFromExpression(expression, context);
			const int integer = number;
			/** @todo should we add a delta? */
			if (number == integer)
				return va("%i", integer);
			else
				return va("%f", number);
		}
	}

	Com_Printf("UI_GetStringFromExpression: Unsupported expression type: %i", expression->type);
	return "";
}