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);
}
Example #2
0
/**
 * @brief Call after the script initialized the node
 */
static void UI_ConFuncNodeLoaded (uiNode_t *node)
{
	/* register confunc non inherited */
	if (node->super == NULL) {
		/* don't add a callback twice */
		if (!Cmd_Exists(node->name)) {
			Cmd_AddCommand(node->name, UI_ConfuncCommand_f, "Confunc callback");
			Cmd_AddUserdata(node->name, node);
		} else {
			Com_Printf("UI_ParseNodeBody: Command name for confunc '%s' already registered\n", UI_GetPath(node));
		}
	} else {
		uiNode_t *dummy;

		/* convert a confunc to an "inherited" confunc if it is possible */
		if (Cmd_Exists(node->name)) {
			if (UI_ConFuncIsVirtual(node))
				return;
		}

		dummy = UI_AllocNode(node->name, "confunc", qfalse);
		Cmd_AddCommand(node->name, UI_ConfuncCommand_f, "Inherited confunc callback");
		Cmd_AddUserdata(dummy->name, dummy);
	}
}
Example #3
0
/**
 * @brief Initializes an option with a very little set of values.
 * @param[in] name The name of the new node
 * @param[in] label label displayed
 * @param[in] value value used when this option is selected
 */
uiNode_t* UI_AllocOptionNode (const char* name, const char* label, const char* value)
{
	uiNode_t* option;
	option = UI_AllocNode(name, "option", true);
	UI_InitOption(option, label, value);
	return option;
}
Example #4
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;
}
Example #5
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;
}
Example #6
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);
}
Example #7
0
/**
 * @brief Append an option to an option list.
 * @param[in,out] tree first option of the list/tree of options
 * @param[in] name name of the option (should be unique in the option list)
 * @param[in] label label displayed
 * @param[in] value value used when this option is selected
 * @return The new option
 */
uiNode_t* UI_AddOption (uiNode_t** tree, const char* name, const char* label, const char* value)
{
	uiNode_t *last;
	uiNode_t *option;
	assert(tree != NULL);

	option = UI_AllocNode(name, "option", qtrue);
	UI_InitOption(option, label, value);

	/* append the option */
	last = *tree;
	if (last != NULL) {
		while (last->next)
			last = last->next;
	}

	if (last)
		last->next = option;
	else
		*tree = option;

	return option;
}
Example #8
0
/**
 * @brief Parse a window
 * @sa CL_ParseClientData
 * @code
 * window windowName {
 * }
 * @endcode
 */
bool UI_ParseWindow (const char* type, const char* name, const char** text)
{
	const char* errhead = "UI_ParseWindow: unexpected end of file (window";
	uiNode_t* window;
	const char* token;
	int i;

	if (!Q_streq(type, "window")) {
		Com_Error(ERR_FATAL, "UI_ParseWindow: '%s %s' is not a window node\n", type, name);
		return false;	/* never reached */
	}

	if (!UI_TokenIsName(name, Com_GetType(text) == TT_QUOTED_WORD)) {
		Com_Printf("UI_ParseWindow: \"%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_ParseWindow: \"%s\" is a reserved token, we can't call a node with it (node \"%s\")\n", name, name);
		return false;
	}

	/* search for windows with same name */
	for (i = 0; i < ui_global.numWindows; i++)
		if (!strncmp(name, ui_global.windows[i]->name, sizeof(ui_global.windows[i]->name)))
			break;

	if (i < ui_global.numWindows) {
		Com_Printf("UI_ParseWindow: %s \"%s\" with same name found, second ignored\n", type, name);
	}

	if (ui_global.numWindows >= UI_MAX_WINDOWS) {
		Com_Error(ERR_FATAL, "UI_ParseWindow: max windows exceeded (%i) - ignore '%s'\n", UI_MAX_WINDOWS, name);
		return false;	/* never reached */
	}

	/* get window body */
	token = Com_Parse(text);

	/* does this window inherit data from another window? */
	if (Q_streq(token, "extends")) {
		uiNode_t* superWindow;
		token = Com_Parse(text);
		superWindow = UI_GetWindow(token);
		if (superWindow == nullptr)
			Sys_Error("Could not get the super window \"%s\"", token);
		window = UI_CloneNode(superWindow, nullptr, true, name, false);
		token = Com_Parse(text);
	} else {
		window = UI_AllocNode(name, type, false);
		window->root = window;
	}

	UI_InsertWindow(window);

	/* parse it's body */
	bool result = UI_ParseNodeBody(window, text, &token, errhead);
	if (!result) {
		Com_Error(ERR_FATAL, "UI_ParseWindow: window \"%s\" has a bad body\n", window->name);
	}

	UI_Node_Loaded(window);
	return true;
}
Example #9
0
/**
 * @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;
}
Example #10
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;
}