/** * @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; }
/** * @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; }
/** * Delete the node and remove it from his parent * @param node The node we want to delete */ void UI_DeleteNode (uiNode_t* node) { uiBehaviour_t *behaviour; if (!node->dynamic) return; UI_BeforeDeletingNode(node); UI_DeleteAllChild(node); if (node->firstChild != NULL) { Com_Printf("UI_DeleteNode: Node '%s' contain static nodes. We can't delete it.", UI_GetPath(node)); return; } if (node->parent) UI_RemoveNode(node->parent, node); /* delete all allocated properties */ for (behaviour = node->behaviour; behaviour; behaviour = behaviour->super) { const value_t *property = behaviour->properties; if (property == NULL) continue; while (property->string != NULL) { if ((property->type & V_UI_MASK) == V_UI_CVAR) { void *mem = ((byte *) node + property->ofs); if (*(void**)mem != NULL) { UI_FreeStringProperty(*(void**)mem); *(void**)mem = NULL; } } /** @todo We must delete all EA_LISTENER too */ property++; } } if (node->behaviour->deleteNode) node->behaviour->deleteNode(node); }
/** * Delete the node and remove it from his parent * @param node The node we want to delete */ void UI_DeleteNode (uiNode_t* node) { uiBehaviour_t *behaviour; if (!node->dynamic) return; UI_BeforeDeletingNode(node); UI_DeleteAllChild(node); if (node->firstChild != nullptr) { Com_Printf("UI_DeleteNode: Node '%s' contain static nodes. We can't delete it.\n", UI_GetPath(node)); return; } if (node->parent) UI_RemoveNode(node->parent, node); /* delete all allocated properties */ for (behaviour = node->behaviour; behaviour; behaviour = behaviour->super) { const value_t **property = behaviour->localProperties; if (property == nullptr) continue; while (*property) { if (((*property)->type & V_UI_MASK) == V_UI_CVAR) { if (void*& mem = Com_GetValue<void*>(node, *property)) { UI_FreeStringProperty(mem); mem = 0; } } /** @todo We must delete all EA_LISTENER too */ property++; } } UI_Node_DeleteNode(node); }