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);
}
示例#2
0
/**
 * @brief Create/remove drag button.
 */
void UI_Window_SetDragButton (uiNode_t* node, bool value) {
	if (value) {
		// create the drag node
		uiNode_t* control = UI_AllocNode(WINDOW_DRAG_BUTTON_NAME, "controls", node->dynamic);
		control->root = node;
		control->box.size[0] = node->box.size[0];
		control->box.size[1] = TOP_HEIGHT;
		control->box.pos[0] = 0;
		control->box.pos[1] = 0;
		control->tooltip = _("Drag to move window");
		/* if there is a close button already on this windown, then insert the drag button before the close
		   button; this is needed so the drag button is "below" the close button; if we don't do this, the
		   drag button recieves input events for the close button first making the close button no longer
		   working */
		uiNode_t* close = UI_FindNode(node, WINDOW_CLOSE_BUTTON_NAME);
		if (close != nullptr) {
			// get the previous node of close
			close = UI_GetPrevNode(close);
			UI_InsertNode(node, close, control);
		}
		else {
			UI_AppendNode(node, control);
		}
	}
	else {
		// drop the drag node
		uiNode_t* control = UI_FindNode(node, WINDOW_DRAG_BUTTON_NAME);
		if (control) {
			UI_RemoveNode (node, control);
		}
	}
	EXTRADATA(node).dragButton = value;
}
示例#3
0
/**
 * @brief Create/remove close button on window.
 * @note Creates a onClick event handler, should be refactored.
 */
void UI_Window_SetCloseButton (uiNode_t* node, bool value) {
	if (value) {
		uiNode_t* control = UI_AllocNode(WINDOW_CLOSE_BUTTON_NAME, "button", node->dynamic);
		const int positionFromRight = CONTROLS_PADDING;
		static const char* closeCommand = "ui_close <path:root>;";

		control->root = node;
		UI_NodeSetProperty(control, UI_GetPropertyFromBehaviour(control->behaviour, "icon"), "icons/system_close");
		/** @todo Once @c image_t is known on the client, use @c image->width resp. @c image->height here */
		control->box.size[0] = CONTROLS_IMAGE_DIMENSIONS;
		control->box.size[1] = CONTROLS_IMAGE_DIMENSIONS;
		control->box.pos[0] = node->box.size[0] - positionFromRight - control->box.size[0];
		control->box.pos[1] = CONTROLS_PADDING;
		control->tooltip = _("Close the window");
		control->onClick = UI_AllocStaticCommandAction(closeCommand);
		UI_AppendNode(node, control);
	}
	else {
		// drop the close node
		uiNode_t* control = UI_FindNode(node, WINDOW_CLOSE_BUTTON_NAME);
		if (control) {
			UI_RemoveNode (node, control);
		}
	}
	EXTRADATA(node).closeButton = value;
}
示例#4
0
/**
 * @brief Called at the end of the load from script
 */
void uiWindowNode::onLoaded (uiNode_t* node)
{
	/* create a drag zone, if it is requested */
	if (EXTRADATA(node).dragButton) {
		uiNode_t* control = UI_AllocNode("move_window_button", "controls", node->dynamic);
		control->root = node;
		control->box.size[0] = node->box.size[0];
		control->box.size[1] = TOP_HEIGHT;
		control->box.pos[0] = 0;
		control->box.pos[1] = 0;
		control->tooltip = _("Drag to move window");
		UI_AppendNode(node, control);
	}

	/* create a close button, if it is requested */
	if (EXTRADATA(node).closeButton) {
		uiNode_t* button = UI_AllocNode("close_window_button", "button", node->dynamic);
		const int positionFromRight = CONTROLS_PADDING;
		static const char* closeCommand = "ui_close <path:root>;";

		button->root = node;
		UI_NodeSetProperty(button, UI_GetPropertyFromBehaviour(button->behaviour, "icon"), "icons/system_close");
		/** @todo Once @c image_t is known on the client, use @c image->width resp. @c image->height here */
		button->box.size[0] = CONTROLS_IMAGE_DIMENSIONS;
		button->box.size[1] = CONTROLS_IMAGE_DIMENSIONS;
		button->box.pos[0] = node->box.size[0] - positionFromRight - button->box.size[0];
		button->box.pos[1] = CONTROLS_PADDING;
		button->tooltip = _("Close the window");
		button->onClick = UI_AllocStaticCommandAction(closeCommand);
		UI_AppendNode(node, button);
	}

	EXTRADATA(node).isFullScreen = node->box.size[0] == VID_NORM_WIDTH
			&& node->box.size[1] == VID_NORM_HEIGHT;

	if (EXTRADATA(node).starLayout)
		UI_Invalidate(node);
}
示例#5
0
文件: ui_nodes.cpp 项目: ufoai/ufoai
/**
 * @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;
}
示例#6
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 NULL 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, qboolean recursive, const char *newName, qboolean isDynamic)
{
	uiNode_t* newNode = UI_AllocNodeWithoutNew(NULL, node->behaviour->name, isDynamic);

	/* clone all data */
	memcpy(newNode, node, sizeof(*node) + node->behaviour->extraDataSize);
	newNode->dynamic = isDynamic;

	/* custom name */
	if (newName != NULL) {
		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 == NULL)
		newWindow = newNode;
	newNode->root = newWindow;
	newNode->parent = NULL;
	newNode->firstChild = NULL;
	newNode->lastChild = NULL;
	newNode->next = NULL;
	newNode->super = *(uiNode_t**) ((void*)&node);

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

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

	newNode->behaviour->clone(node, newNode);

	return newNode;
}
示例#7
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;
}
示例#8
0
/**
 * @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;
}