UFO: Alien Invasion
Loading...
Searching...
No Matches
ui_node_tab.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26#include "../ui_main.h"
27#include "../ui_behaviour.h"
28#include "../ui_parse.h"
29#include "../ui_actions.h"
30#include "../ui_font.h"
31#include "../ui_input.h"
32#include "../ui_sound.h"
33#include "../ui_sprite.h"
34#include "../ui_render.h"
35#include "../ui_tooltip.h"
36#include "ui_node_tab.h"
39
40#include "../../cl_language.h"
42
44
45#define EXTRADATA_TYPE abstractOptionExtraData_t
46#define EXTRADATA(node) UI_EXTRADATA(node, EXTRADATA_TYPE)
47#define EXTRADATACONST(node) UI_EXTRADATACONST(node, EXTRADATA_TYPE)
48
56
57static const int TILE_WIDTH = 33;
58static const int TILE_HEIGHT = 36;
59
68static uiNode_t* UI_TabNodeTabAtPosition (const uiNode_t* node, int x, int y)
69{
70 UI_NodeAbsoluteToRelativePos(node, &x, &y);
71
73 int allowedWidth = node->box.size[0] - TILE_WIDTH * (EXTRADATACONST(node).count + 1);
74
75 /* Bounded box test (should not be need, but there are problems without it) */
76 if (x < 0 || y < 0 || x >= node->box.size[0] || y >= node->box.size[1])
77 return nullptr;
78
79 const char* font = UI_GetFontFromNode(node);
80
81 /* Text box test */
82 uiNode_t* prev = nullptr;
83 for (uiNode_t* option = node->firstChild; option; option = option->next) {
84 int tabWidth;
85 assert(option->behaviour == ui_optionBehaviour);
86
87 /* skip hidden options */
88 if (option->invis)
89 continue;
90
91 if (x < TILE_WIDTH / 2)
92 return prev;
93
94 const char* label = CL_Translate(OPTIONEXTRADATA(option).label);
95
96 R_FontTextSize(font, label, 0, LONGLINES_PRETTYCHOP, &tabWidth, nullptr, nullptr, nullptr);
97 if (OPTIONEXTRADATA(option).icon && OPTIONEXTRADATA(option).icon->size[0] < allowedWidth) {
98 tabWidth += OPTIONEXTRADATA(option).icon->size[0];
99 }
100 if (tabWidth > allowedWidth) {
101 if (allowedWidth > 0)
102 tabWidth = allowedWidth;
103 else
104 tabWidth = 0;
105 }
106
107 if (x < tabWidth + TILE_WIDTH)
108 return option;
109
110 allowedWidth -= tabWidth;
111 x -= tabWidth + TILE_WIDTH;
112 prev = option;
113 }
114 if (x < TILE_WIDTH / 2)
115 return prev;
116 return nullptr;
117}
118
122void uiTabNode::onLeftClick (uiNode_t* node, int x, int y)
123{
124 uiNode_t* option;
125
126 if (UI_AbstractOption_GetCurrentValue(node) == nullptr)
127 return;
128
129 option = UI_TabNodeTabAtPosition(node, x, y);
130 if (option == nullptr)
131 return;
132
133 if (option->disabled)
134 return;
135
136 /* only execute the click stuff if the selectbox is active */
137 if (node->state)
139
140 UI_PlaySound("click1");
141}
142
144{
145 const char* ref = UI_AbstractOption_GetCurrentValue(node);
146 if (ref == nullptr)
147 return;
148
149 const char* font = UI_GetFontFromNode(node);
150
151 uiNode_t* overMouseOption = nullptr;
152 if (node->state) {
153 overMouseOption = UI_TabNodeTabAtPosition(node, mousePosX, mousePosY);
154 }
155
156 vec2_t pos;
157 UI_GetNodeAbsPos(node, pos);
158 int currentX = pos[0];
159 uiNode_t* option = node->firstChild;
160 assert(option->behaviour == ui_optionBehaviour);
162 int allowedWidth = node->box.size[0] - TILE_WIDTH * (EXTRADATA(node).count + 1);
163
164 while (option) {
165 int fontHeight;
166 int fontWidth;
167 int tabWidth;
168 int textPos;
169 bool drawIcon = false;
171 assert(option->behaviour == ui_optionBehaviour);
172
173 /* skip hidden options */
174 if (option->invis) {
175 option = option->next;
176 continue;
177 }
178
179 /* Check the status of the current tab */
180 if (Q_streq(OPTIONEXTRADATA(option).value, ref)) {
181 status = UI_TAB_SELECTED;
182 } else if (option->disabled || node->disabled) {
183 status = UI_TAB_DISABLED;
184 } else if (option == overMouseOption) {
185 status = UI_TAB_HIGHLIGHTED;
186 }
187
188 currentX += TILE_WIDTH;
189
190 const char* label = CL_Translate(OPTIONEXTRADATA(option).label);
191
192 R_FontTextSize(font, label, 0, LONGLINES_PRETTYCHOP, &fontWidth, &fontHeight, nullptr, nullptr);
193 tabWidth = fontWidth;
194 if (OPTIONEXTRADATA(option).icon && OPTIONEXTRADATA(option).icon->size[0] < allowedWidth) {
195 tabWidth += OPTIONEXTRADATA(option).icon->size[0];
196 drawIcon = true;
197 }
198 if (tabWidth > allowedWidth) {
199 if (allowedWidth > 0)
200 tabWidth = allowedWidth;
201 else
202 tabWidth = 0;
203 }
204
205 textPos = currentX;
206 if (drawIcon) {
208 if (status == UI_TAB_DISABLED) {
209 iconStatus = SPRITE_STATUS_DISABLED;
210 }
211 UI_DrawSpriteInBox(OPTIONEXTRADATA(option).flipIcon, OPTIONEXTRADATA(option).icon, iconStatus, currentX, pos[1], OPTIONEXTRADATA(option).icon->size[0], TILE_HEIGHT);
212 textPos += OPTIONEXTRADATA(option).icon->size[0];
213 }
214
216 OPTIONEXTRADATA(option).truncated = tabWidth < fontWidth || tabWidth == 0;
217 UI_DrawString(font, ALIGN_UL, textPos, pos[1] + ((node->box.size[1] - fontHeight) / 2),
218 textPos, tabWidth + 1, 0, label, 0, 0, nullptr, false, LONGLINES_PRETTYCHOP);
219 currentX += tabWidth;
220 allowedWidth -= tabWidth;
221
222 /* Next */
223 option = option->next;
224 }
225}
226
232void uiTabNode::drawTooltip (const uiNode_t* node, int x, int y) const
233{
234 uiNode_t* option;
235 const int tooltipWidth = 250;
236
237 option = UI_TabNodeTabAtPosition(node, x, y);
238 if (option == nullptr)
239 return;
240
241 if (!OPTIONEXTRADATA(option).truncated)
242 return;
243
244 const char* label = CL_Translate(OPTIONEXTRADATA(option).label);
245 UI_DrawTooltip(label, x, y, tooltipWidth);
246}
247
253{
254 /* no cvar given? */
255 if (!(EXTRADATA(node).cvar))
256 return;
257
258 /* not a cvar? */
259 char const* const cvarName = Q_strstart(EXTRADATA(node).cvar, "*cvar:");
260 if (!cvarName) {
261 /* normalize */
262 Com_Printf("UI_TabNodeInit: node '%s' doesn't have a valid cvar assigned (\"%s\" read)\n", UI_GetPath(node), EXTRADATA(node).cvar);
263 EXTRADATA(node).cvar = nullptr;
264 return;
265 }
266
267 /* cvar does not exist? */
268 if (Cvar_FindVar(cvarName) == nullptr) {
269 /* search default value, if possible */
270 uiNode_t* option = node->firstChild;
271 assert(option->behaviour == ui_optionBehaviour);
272 Cvar_ForceSet(cvarName, OPTIONEXTRADATA(option).value);
273 }
274}
275
277{
278 behaviour->name = "tab";
279 behaviour->extends = "abstractoption";
280 behaviour->manager = UINodePtr(new uiTabNode());
281 behaviour->drawItselfChild = true;
282 behaviour->lua_SWIG_typeinfo = UI_SWIG_TypeQuery("uiTabNode_t *");
283}
int mousePosY
Definition cl_input.cpp:76
int mousePosX
Definition cl_input.cpp:76
External (non-keyboard) input devices.
const char * CL_Translate(const char *t)
void R_FontTextSize(const char *fontId, const char *text, int maxWidth, longlines_t method, int *width, int *height, int *lines, bool *isTruncated)
Supply information about the size of the text when it is linewrapped and rendered,...
Definition r_font.cpp:522
@ LONGLINES_PRETTYCHOP
void draw(uiNode_t *node) override
void onLeftClick(uiNode_t *node, int x, int y) override
Handles tab clicks.
void onWindowOpened(uiNode_t *node, linkedList_t *params) override
void drawTooltip(const uiNode_t *node, int x, int y) const override
Custom tooltip of tab node.
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
cvar_t * Cvar_ForceSet(const char *varName, const char *value)
Will set the variable even if NOSET or LATCH.
Definition cvar.cpp:604
cvar_t * Cvar_FindVar(const char *varName)
Searches for a cvar given by parameter.
Definition cvar.cpp:106
@ ALIGN_UL
Definition scripts.h:90
Header for lua script functions.
#define Q_streq(a, b)
Definition shared.h:136
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition shared.cpp:587
node behaviour, how a node work
const char * name
void * lua_SWIG_typeinfo
UINodePtr manager
const char * extends
vec2_t size
Definition ui_nodes.h:52
Atomic structure used to define most of the UI.
Definition ui_nodes.h:80
bool disabled
Definition ui_nodes.h:102
uiNode_t * firstChild
Definition ui_nodes.h:89
bool invis
Definition ui_nodes.h:101
uiNode_t * next
Definition ui_nodes.h:91
uiBehaviour_t * behaviour
Definition ui_nodes.h:83
uiBox_t box
Definition ui_nodes.h:96
bool state
Definition ui_nodes.h:106
vec_t vec2_t[2]
Definition ufotypes.h:38
const char * UI_GetFontFromNode(const uiNode_t *const node)
Return the font for a specific node or default font.
Definition ui_font.cpp:145
void * UI_SWIG_TypeQuery(const char *name)
This function queries the SWIG type table for a type information structure. It is used in combination...
void UI_NodeAbsoluteToRelativePos(const uiNode_t *node, int *x, int *y)
Update an absolute position to a relative one.
Definition ui_node.cpp:604
void UI_GetNodeAbsPos(const uiNode_t *node, vec2_t pos)
Returns the absolute position of a node.
Definition ui_node.cpp:526
SharedPtr< uiNode > UINodePtr
const char * UI_AbstractOption_GetCurrentValue(uiNode_t *node)
#define EXTRADATA(node)
void UI_AbstractOption_SetCurrentValue(uiNode_t *node, const char *value)
const uiBehaviour_t * ui_optionBehaviour
#define OPTIONEXTRADATA(node)
static uiNode_t * UI_TabNodeTabAtPosition(const uiNode_t *node, int x, int y)
Return a tab located at a screen position.
static const int TILE_HEIGHT
ui_tabStatus_t
@ UI_TAB_NORMAL
@ UI_TAB_NOTHING
@ UI_TAB_HIGHLIGHTED
@ UI_TAB_DISABLED
@ UI_TAB_SELECTED
static const int TILE_WIDTH
#define EXTRADATACONST(node)
void UI_RegisterTabNode(uiBehaviour_t *behaviour)
const char * UI_GetPath(const uiNode_t *node)
Return a path from a window to a node.
Definition ui_nodes.cpp:174
int UI_DrawString(const char *fontID, align_t align, int x, int y, int absX, int maxWidth, int lineHeight, const char *c, int boxHeight, int scrollPos, int *curLine, bool increaseLine, longlines_t method)
void UI_PlaySound(const char *soundFile)
Plays a ui sound.
Definition ui_sound.cpp:35
void UI_DrawSpriteInBox(bool flip, const uiSprite_t *sprite, uiSpriteStatus_t status, int posX, int posY, int sizeX, int sizeY)
uiSpriteStatus_t
Definition ui_sprite.h:32
@ SPRITE_STATUS_DISABLED
Definition ui_sprite.h:35
@ SPRITE_STATUS_NORMAL
Definition ui_sprite.h:33
int UI_DrawTooltip(const char *string, int x, int y, int maxWidth)
Generic tooltip function.