UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ui_node_selectbox.cpp
Go to the documentation of this file.
1 
26 /*
27 Copyright (C) 2002-2020 UFO: Alien Invasion.
28 
29 This program is free software; you can redistribute it and/or
30 modify it under the terms of the GNU General Public License
31 as published by the Free Software Foundation; either version 2
32 of the License, or (at your option) any later version.
33 
34 This program is distributed in the hope that it will be useful,
35 but WITHOUT ANY WARRANTY; without even the implied warranty of
36 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37 
38 See the GNU General Public License for more details.
39 
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43 
44 */
45 
46 #include "../ui_main.h"
47 #include "../ui_internal.h"
48 #include "../ui_parse.h"
49 #include "../ui_font.h"
50 #include "../ui_input.h"
51 #include "../ui_draw.h"
52 #include "../ui_render.h"
53 #include "ui_node_selectbox.h"
54 #include "ui_node_abstractoption.h"
55 #include "ui_node_abstractnode.h"
56 #include "ui_node_option.h"
57 
58 #include "../../cl_language.h"
59 
60 #include "../../../common/scripts_lua.h"
61 
62 #define EXTRADATA(node) UI_EXTRADATA(node, abstractOptionExtraData_t)
63 
64 #define SELECTBOX_DEFAULT_HEIGHT 20.0f
65 
66 #define SELECTBOX_SIDE_WIDTH 7.0f
67 #define SELECTBOX_RIGHT_WIDTH 20.0f
68 
69 #define SELECTBOX_SPACER 2.0f
70 #define SELECTBOX_BOTTOM_HEIGHT 4.0f
71 
77 {
78  UI_NodeAbsoluteToRelativePos(node, &x, &y);
79 
80  /* test bounded box */
81  if (x < 0 || y < 0 || x > node->box.size[0] || y > node->box.size[1] * (EXTRADATA(node).count + 1)) {
82  return;
83  }
84 
85  int posy = node->box.size[1];
86  for (uiNode_t* option = UI_AbstractOption_GetFirstOption(node); option; option = option->next) {
87  if (option->invis)
88  continue;
89  OPTIONEXTRADATA(option).hovered = (posy <= y && y < posy + node->box.size[1]);
90  posy += node->box.size[1];
91  }
92 }
93 
95 {
96  vec2_t nodepos;
97  static vec4_t invisColor = {1.0, 1.0, 1.0, 0.7};
98 
99  const char* ref = UI_AbstractOption_GetCurrentValue(node);
100  if (ref == nullptr)
101  return;
102 
103  UI_GetNodeAbsPos(node, nodepos);
104  const char* imageName = UI_GetReferenceString(node, node->image);
105  if (!imageName)
106  imageName = "ui/selectbox";
107 
108  const image_t* image = UI_LoadImage(imageName);
109 
110  const char* font = UI_GetFontFromNode(node);
111  int selBoxX = nodepos[0] + SELECTBOX_SIDE_WIDTH;
112  int selBoxY = nodepos[1] + SELECTBOX_SPACER;
113 
114  /* left border */
115  UI_DrawNormImage(false, nodepos[0], nodepos[1], SELECTBOX_SIDE_WIDTH, node->box.size[1],
116  SELECTBOX_SIDE_WIDTH, SELECTBOX_DEFAULT_HEIGHT, 0.0f, 0.0f, image);
117  /* stretched middle bar */
118  UI_DrawNormImage(false, nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1], node->box.size[0]-SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, node->box.size[1],
119  12.0f, SELECTBOX_DEFAULT_HEIGHT, 7.0f, 0.0f, image);
120  /* right border (arrow) */
121  UI_DrawNormImage(false, nodepos[0] + node->box.size[0] - SELECTBOX_RIGHT_WIDTH, nodepos[1], SELECTBOX_DEFAULT_HEIGHT, node->box.size[1],
122  12.0f + SELECTBOX_RIGHT_WIDTH, SELECTBOX_DEFAULT_HEIGHT, 12.0f, 0.0f, image);
123 
124  /* draw the label for the current selected option */
125  for (uiNode_t* option = UI_AbstractOption_GetFirstOption(node); option; option = option->next) {
126  if (!Q_streq(OPTIONEXTRADATA(option).value, ref))
127  continue;
128 
129  if (option->invis)
130  R_Color(invisColor);
131 
132  const char* label = CL_Translate(OPTIONEXTRADATA(option).label);
133 
134  UI_DrawString(font, ALIGN_UL, selBoxX, selBoxY,
135  selBoxX, node->box.size[0] - 4,
136  0, label, 0, 0, nullptr, false, LONGLINES_PRETTYCHOP);
137 
138  R_Color(nullptr);
139  break;
140  }
141 
142  /* must we draw the drop-down list */
143  if (UI_GetMouseCapture() == node) {
144  UI_CaptureDrawOver(node);
145  }
146 }
147 
149 {
150  const char* ref = UI_AbstractOption_GetCurrentValue(node);
151  if (ref == nullptr)
152  return;
153 
154  vec2_t nodepos;
155  UI_GetNodeAbsPos(node, nodepos);
156 
157  const char* imageName = UI_GetReferenceString(node, node->image);
158  if (!imageName)
159  imageName = "ui/selectbox";
160 
161  const image_t* image = UI_LoadImage(imageName);
162 
163  const char* font = UI_GetFontFromNode(node);
164  int selBoxX = nodepos[0] + SELECTBOX_SIDE_WIDTH;
165  int selBoxY = nodepos[1] + SELECTBOX_SPACER;
166 
167  selBoxY += node->box.size[1];
168 
169  /* drop down list */
170  /* left side */
171  UI_DrawNormImage(false, nodepos[0], nodepos[1] + node->box.size[1], SELECTBOX_SIDE_WIDTH, node->box.size[1] * EXTRADATA(node).count,
172  7.0f, 28.0f, 0.0f, 21.0f, image);
173 
174  /* stretched middle bar */
175  UI_DrawNormImage(false, nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1] + node->box.size[1], node->box.size[0] -SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, node->box.size[1] * EXTRADATA(node).count,
176  16.0f, 28.0f, 7.0f, 21.0f, image);
177 
178  /* right side */
179  UI_DrawNormImage(false, nodepos[0] + node->box.size[0] -SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, nodepos[1] + node->box.size[1], SELECTBOX_SIDE_WIDTH, node->box.size[1] * EXTRADATA(node).count,
180  23.0f, 28.0f, 16.0f, 21.0f, image);
181 
182  /* now draw all available options for this selectbox */
183  int check = 0;
184  for (uiNode_t* option = UI_AbstractOption_GetFirstOption(node); option; option = option->next) {
185  if (option->invis)
186  continue;
187  /* draw the hover effect */
188  if (OPTIONEXTRADATA(option).hovered)
189  UI_DrawFill(selBoxX, selBoxY, node->box.size[0] -SELECTBOX_SIDE_WIDTH - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH,
191  /* print the option label */
192  const char* label = CL_Translate(OPTIONEXTRADATA(option).label);
193  UI_DrawString(font, ALIGN_UL, selBoxX, selBoxY,
194  selBoxX, node->box.size[0] - 4,
195  0, label, 0, 0, nullptr, false, LONGLINES_PRETTYCHOP);
196  /* next entries' position */
197  selBoxY += node->box.size[1];
198  check++;
199  }
200 
202  if (check != EXTRADATA(node).count) {
204  Com_Printf("uiSelectBoxNode::drawOverWindow: Node '%s' contains unsynchronized option list. Fixed.\n", UI_GetPath(node));
205  EXTRADATA(node).versionId = 0;
206  }
207 
208  /* left side */
209  UI_DrawNormImage(false, nodepos[0], selBoxY - SELECTBOX_SPACER, SELECTBOX_SIDE_WIDTH, SELECTBOX_BOTTOM_HEIGHT,
210  7.0f, 32.0f, 0.0f, 28.0f, image);
211 
212  /* stretched middle bar */
213  UI_DrawNormImage(false, nodepos[0] + SELECTBOX_SIDE_WIDTH, selBoxY - SELECTBOX_SPACER, node->box.size[0] - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH,
215  16.0f, 32.0f, 7.0f, 28.0f, image);
216 
217  /* right bottom side */
218  UI_DrawNormImage(false, nodepos[0] + node->box.size[0] - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH, selBoxY - SELECTBOX_SPACER,
219  SELECTBOX_SIDE_WIDTH, SELECTBOX_BOTTOM_HEIGHT,
220  23.0f, 32.0f, 16.0f, 28.0f, image);
221 }
222 
226 void uiSelectBoxNode::onLeftClick (uiNode_t* node, int x, int y)
227 {
228  /* dropdown the node */
229  if (UI_GetMouseCapture() == nullptr) {
230  UI_SetMouseCapture(node);
231  return;
232  }
233 
234  vec2_t pos;
235  UI_GetNodeAbsPos(node, pos);
236  int clickedAtOption = (y - pos[1]);
237 
238  /* we click outside */
239  if (x < pos[0] || y < pos[1] || x >= pos[0] + node->box.size[0] || y >= pos[1] + node->box.size[1] * (EXTRADATA(node).count + 1)) {
240  UI_MouseRelease();
241  return;
242  }
243 
244  /* we click on the head */
245  if (clickedAtOption < node->box.size[1]) {
246  UI_MouseRelease();
247  return;
248  }
249 
250  clickedAtOption = (clickedAtOption - node->box.size[1]) / node->box.size[1];
251  if (clickedAtOption < 0 || clickedAtOption >= EXTRADATA(node).count)
252  return;
253 
254  if (UI_AbstractOption_GetCurrentValue(node) == nullptr)
255  return;
256 
257  /* select the right option */
259  for (; option; option = option->next) {
260  if (option->invis)
261  continue;
262  if (clickedAtOption == 0)
263  break;
264  clickedAtOption--;
265  }
266 
267  /* update the status */
268  if (option)
270 
271  /* close the dropdown */
272  UI_MouseRelease();
273 }
274 
279 {
280  Vector4Set(node->color, 0.6, 0.6, 0.6, 0.3);
281 }
282 
284 {
285  /* force a size (according to the texture) */
286  node->box.size[1] = SELECTBOX_DEFAULT_HEIGHT;
287 }
288 
290 {
291  behaviour->name = "selectbox";
292  behaviour->extends = "abstractoption";
293  behaviour->manager = UINodePtr(new uiSelectBoxNode());
294  behaviour->drawItselfChild = true;
295  behaviour->lua_SWIG_typeinfo = UI_SWIG_TypeQuery("uiSelectBoxNode_t *");
296 }
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
void UI_CaptureDrawOver(uiNode_t *node)
Capture a node we will draw over all nodes (per window)
Definition: ui_draw.cpp:64
void onLeftClick(uiNode_t *node, int x, int y) override
Handles selectboxes clicks.
const char * UI_AbstractOption_GetCurrentValue(uiNode_t *node)
void onCapturedMouseMove(uiNode_t *node, int x, int y) override
call when the mouse move is the node is captured
void drawOverWindow(uiNode_t *node) override
UINodePtr manager
Definition: ui_behaviour.h:43
void UI_RegisterSelectBoxNode(uiBehaviour_t *behaviour)
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
#define EXTRADATA(node)
void UI_MouseRelease(void)
Release the captured node.
Definition: ui_input.cpp:526
void R_Color(const vec4_t rgba)
Change the color to given value.
Definition: r_state.cpp:1011
#define SELECTBOX_SIDE_WIDTH
bool invis
Definition: ui_nodes.h:101
#define OPTIONEXTRADATA(node)
#define SELECTBOX_BOTTOM_HEIGHT
#define Vector4Set(v, r, g, b, a)
Definition: vector.h:62
SharedPtr< uiNode > UINodePtr
const struct image_s * UI_LoadImage(const char *name)
Searches for an image in the image array.
Definition: ui_render.cpp:91
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
void UI_SetMouseCapture(uiNode_t *node)
Captured the mouse into a node.
Definition: ui_input.cpp:516
void UI_DrawNormImage(bool flip, float x, float y, float w, float h, float sh, float th, float sl, float tl, const image_t *image)
Draw a normalized (to the screen) image.
Definition: ui_render.cpp:126
bool drawItselfChild
Definition: ui_behaviour.h:50
void UI_AbstractOption_SetCurrentValue(uiNode_t *node, const char *value)
const char * UI_GetReferenceString(const uiNode_t *const node, const char *ref)
Definition: ui_parse.cpp:1406
uiNode_t * UI_GetMouseCapture(void)
Return the captured node.
Definition: ui_input.cpp:508
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...
void UI_GetNodeAbsPos(const uiNode_t *node, vec2_t pos)
Returns the absolute position of a node.
Definition: ui_node.cpp:514
QGL_EXTERN GLuint count
Definition: r_gl.h:99
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
#define SELECTBOX_DEFAULT_HEIGHT
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
vec4_t color
Definition: ui_nodes.h:127
const char * extends
Definition: ui_behaviour.h:42
vec_t vec2_t[2]
Definition: ufotypes.h:38
char * image
Definition: ui_nodes.h:123
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
#define Q_streq(a, b)
Definition: shared.h:136
uiBox_t box
Definition: ui_nodes.h:96
void UI_DrawFill(int x, int y, int w, int h, const vec4_t color)
Fills a box of pixels with a single color.
Definition: ui_render.cpp:37
void onLoading(uiNode_t *node) override
Called before loading. Used to set default attribute values.
void onLoaded(uiNode_t *node) override
#define SELECTBOX_SPACER
#define SELECTBOX_RIGHT_WIDTH
uiNode_t * UI_AbstractOption_GetFirstOption(uiNode_t *node)
Return the first option of the node.
vec_t vec4_t[4]
Definition: ufotypes.h:40