UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ui_node_tab.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 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"
37 #include "ui_node_abstractnode.h"
38 #include "ui_node_abstractoption.h"
39 
40 #include "../../cl_language.h"
41 #include "../../input/cl_input.h"
42 
43 #include "../../../common/scripts_lua.h"
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 
49 typedef enum {
56 
57 static const int TILE_WIDTH = 33;
58 static const int TILE_HEIGHT = 36;
59 
68 static 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 
122 void 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;
170  ui_tabStatus_t status = UI_TAB_NORMAL;
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 
232 void 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 }
void draw(uiNode_t *node) override
vec2_t size
Definition: ui_nodes.h:52
uiNode_t * next
Definition: ui_nodes.h:91
const char * name
Definition: ui_behaviour.h:41
static const int TILE_WIDTH
Definition: ui_node_tab.cpp:57
const char * UI_AbstractOption_GetCurrentValue(uiNode_t *node)
uiBehaviour_t * behaviour
Definition: ui_nodes.h:83
UINodePtr manager
Definition: ui_behaviour.h:43
void UI_DrawSpriteInBox(bool flip, const uiSprite_t *sprite, uiSpriteStatus_t status, int posX, int posY, int sizeX, int sizeY)
Definition: ui_sprite.cpp:187
void UI_PlaySound(const char *soundFile)
Plays a ui sound.
Definition: ui_sound.cpp:35
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
void onLeftClick(uiNode_t *node, int x, int y) override
Handles tab clicks.
bool invis
Definition: ui_nodes.h:101
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, without actually rendering it. Any of the output parameters may be nullptr.
Definition: r_font.cpp:524
#define OPTIONEXTRADATA(node)
bool state
Definition: ui_nodes.h:106
int mousePosY
Definition: cl_input.cpp:80
SharedPtr< uiNode > UINodePtr
int UI_DrawTooltip(const char *string, int x, int y, int maxWidth)
Generic tooltip function.
Definition: ui_tooltip.cpp:40
const char * UI_GetPath(const uiNode_t *node)
Return a path from a window to a node.
Definition: ui_nodes.cpp:174
void * lua_SWIG_typeinfo
Definition: ui_behaviour.h:57
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition: shared.cpp:587
void onWindowOpened(uiNode_t *node, linkedList_t *params) override
#define EXTRADATACONST(node)
Definition: ui_node_tab.cpp:47
ui_tabStatus_t
Definition: ui_node_tab.cpp:49
bool drawItselfChild
Definition: ui_behaviour.h:50
void UI_AbstractOption_SetCurrentValue(uiNode_t *node, const char *value)
Atomic structure used to define most of the UI.
Definition: ui_nodes.h:80
void * UI_SWIG_TypeQuery(const char *name)
This function queries the SWIG type table for a type information structure. It is used in combination...
bool disabled
Definition: ui_nodes.h:102
void UI_GetNodeAbsPos(const uiNode_t *node, vec2_t pos)
Returns the absolute position of a node.
Definition: ui_node.cpp:514
#define EXTRADATA(node)
Definition: ui_node_tab.cpp:46
static const int TILE_HEIGHT
Definition: ui_node_tab.cpp:58
void drawTooltip(const uiNode_t *node, int x, int y) const override
Custom tooltip of tab node.
const char * CL_Translate(const char *t)
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_NodeAbsoluteToRelativePos(const uiNode_t *node, int *x, int *y)
Update an absolute position to a relative one.
Definition: ui_node.cpp:592
node behaviour, how a node work
Definition: ui_behaviour.h:39
const char * extends
Definition: ui_behaviour.h:42
uiSpriteStatus_t
Definition: ui_sprite.h:32
static uiNode_t * UI_TabNodeTabAtPosition(const uiNode_t *node, int x, int y)
Return a tab located at a screen position.
Definition: ui_node_tab.cpp:68
vec_t vec2_t[2]
Definition: ufotypes.h:38
void UI_RegisterTabNode(uiBehaviour_t *behaviour)
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)
Definition: ui_render.cpp:371
cvar_t * Cvar_ForceSet(const char *varName, const char *value)
Will set the variable even if NOSET or LATCH.
Definition: cvar.cpp:604
uiNode_t * firstChild
Definition: ui_nodes.h:89
#define Q_streq(a, b)
Definition: shared.h:136
uiBox_t box
Definition: ui_nodes.h:96
int mousePosX
Definition: cl_input.cpp:80
const uiBehaviour_t * ui_optionBehaviour
cvar_t * Cvar_FindVar(const char *varName)
Searches for a cvar given by parameter.
Definition: cvar.cpp:106