UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ui_node_vscrollbar.cpp
Go to the documentation of this file.
1 
7 /*
8 Copyright (C) 2002-2020 UFO: Alien Invasion.
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 See the GNU General Public License for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25 */
26 
27 #include "../ui_nodes.h"
28 #include "../ui_behaviour.h"
29 #include "../ui_parse.h"
30 #include "../ui_timer.h"
31 #include "../ui_actions.h"
32 #include "../ui_input.h"
33 #include "../ui_render.h"
34 #include "../ui_lua.h"
35 
36 #include "ui_node_abstractnode.h"
38 #include "ui_node_vscrollbar.h"
39 
40 #include "../../input/cl_input.h"
41 #include "../../input/cl_keys.h"
42 
43 #include "../../../common/scripts_lua.h"
44 
45 static const int TILE_WIDTH = 32;
46 static const int TILE_HEIGHT = 18;
47 static const int ELEMENT_WIDTH = 19;
48 static const int ELEMENT_HEIGHT = 16;
49 
50 static int oldPos;
51 static int oldMouseY;
53 static int capturedElement;
54 
55 #define EXTRADATA(node) UI_EXTRADATA(node, abstractScrollbarExtraData_t)
56 
60 static void UI_VScrollbarNodeGetElementSize (uiNode_t* node, int description[5])
61 {
62  const int cuttableSize = node->box.size[1] - (ELEMENT_HEIGHT * 4);
63  const int low = cuttableSize * ((float)(EXTRADATA(node).pos + 0) / (float)EXTRADATA(node).fullsize);
64  const int middle = cuttableSize * ((float)(EXTRADATA(node).viewsize) / (float)EXTRADATA(node).fullsize);
65  const int hight = cuttableSize - low - middle;
66  description[0] = ELEMENT_HEIGHT;
67  description[1] = low;
68  description[2] = middle + 2 * ELEMENT_HEIGHT;
69  description[3] = hight;
70  description[4] = ELEMENT_HEIGHT;
71  assert(description[0] + description[1] + description[2] + description[3] + description[4] == node->box.size[1]);
72 }
73 
80 static int UI_VScrollbarNodeGetElement (uiNode_t* node, int description[5], int x, int y)
81 {
82  UI_NodeAbsoluteToRelativePos(node, &x, &y);
83  for (int i = 0; i < 5; i++) {
84  if (y < description[i])
85  return i;
86  y -= description[i];
87  }
88  return -1;
89 }
90 
91 
95 static inline void UI_VScrollbarNodeDiff (uiNode_t* node, int value)
96 {
97  UI_AbstractScrollbarNodeSet(node, EXTRADATA(node).pos + value);
98 }
99 
100 static inline void UI_VScrollbarNodeAction(uiNode_t* node, int hoveredElement, bool allowCapture);
101 
103 {
105  if (timer->calledTime == 1) {
106  timer->delay = 50;
107  }
108 }
109 
115 static inline void UI_VScrollbarNodeAction (uiNode_t* node, int hoveredElement, bool allowCapture)
116 {
117  switch (hoveredElement) {
118  case 0:
119  UI_VScrollbarNodeDiff(node, -1);
120  if (allowCapture) {
121  UI_SetMouseCapture(node);
122  capturedElement = hoveredElement;
123  capturedTimer = UI_AllocTimer(node, 500, UI_VScrollbarNodeRepeat);
124  UI_TimerStart(capturedTimer);
125  }
126  break;
127  case 1:
128  UI_VScrollbarNodeDiff(node, -10);
129  if (allowCapture) {
130  UI_SetMouseCapture(node);
131  capturedElement = hoveredElement;
132  capturedTimer = UI_AllocTimer(node, 500, UI_VScrollbarNodeRepeat);
133  UI_TimerStart(capturedTimer);
134  }
135  break;
136  case 2:
137  if (allowCapture) {
138  UI_SetMouseCapture(node);
139  /* save start value */
141  oldPos = EXTRADATA(node).pos;
142  capturedElement = hoveredElement;
143  }
144  break;
145  case 3:
146  UI_VScrollbarNodeDiff(node, 10);
147  if (allowCapture) {
148  UI_SetMouseCapture(node);
149  capturedElement = hoveredElement;
150  capturedTimer = UI_AllocTimer(node, 500, UI_VScrollbarNodeRepeat);
151  UI_TimerStart(capturedTimer);
152  }
153  break;
154  case 4:
155  UI_VScrollbarNodeDiff(node, 1);
156  if (allowCapture) {
157  UI_SetMouseCapture(node);
158  capturedElement = hoveredElement;
159  capturedTimer = UI_AllocTimer(node, 500, UI_VScrollbarNodeRepeat);
160  UI_TimerStart(capturedTimer);
161  }
162  break;
163  default:
164  assert(false);
165  break;
166  }
167 }
168 
169 void uiVScrollbarNode::onMouseDown (uiNode_t* node, int x, int y, int button)
170 {
171  if (EXTRADATA(node).fullsize == 0 || EXTRADATA(node).fullsize < EXTRADATA(node).viewsize)
172  return;
173  if (button != K_MOUSE1)
174  return;
175 
176  int description[5];
177  UI_VScrollbarNodeGetElementSize(node, description);
178  const int hoveredElement = UI_VScrollbarNodeGetElement(node, description, x, y);
179  UI_VScrollbarNodeAction(node, hoveredElement, true);
180 }
181 
182 void uiVScrollbarNode::onMouseUp (uiNode_t* node, int x, int y, int button)
183 {
184  if (EXTRADATA(node).fullsize == 0 || EXTRADATA(node).fullsize < EXTRADATA(node).viewsize)
185  return;
186  if (button != K_MOUSE1)
187  return;
188 
189  if (UI_GetMouseCapture() == node) {
190  UI_MouseRelease();
191  }
192 }
193 
199 {
200  if (capturedTimer) {
201  UI_TimerRelease(capturedTimer);
202  capturedTimer = nullptr;
203  }
204 }
205 
209 bool uiVScrollbarNode::onScroll (uiNode_t* node, int deltaX, int deltaY)
210 {
211  if (deltaY == 0)
212  return false;
213  if (EXTRADATA(node).fullsize == 0 || EXTRADATA(node).fullsize < EXTRADATA(node).viewsize)
214  return false;
215  UI_AbstractScrollbarNodeSet(node, EXTRADATA(node).pos + deltaY);
216  return true;
217 }
218 
223 {
224  if (capturedElement != 2)
225  return;
226 
227  const int posSize = EXTRADATA(node).fullsize;
228  const int graphicSize = node->box.size[1] - (4 * ELEMENT_HEIGHT);
229 
230  /* compute mouse mouse */
231  y -= oldMouseY;
232 
233  /* compute pos projection */
234  const int pos = oldPos + (((float)y * (float)posSize) / (float)graphicSize);
235 
236  UI_AbstractScrollbarNodeSet(node, pos);
237 }
238 
243 {
244  vec2_t pos;
245  int texX = 0;
246  int texY = 0;
247 
248  UI_GetNodeAbsPos(node, pos);
249  int y = pos[1];
250 
251  const char* texture = UI_GetReferenceString(node, node->image);
252  if (!texture)
253  return;
254 
255  const image_t* image = UI_LoadImage(texture);
256 
257  if (EXTRADATA(node).fullsize == 0 || EXTRADATA(node).fullsize <= EXTRADATA(node).viewsize) {
258  /* hide the scrollbar */
259  if (EXTRADATA(node).hideWhenUnused)
260  return;
261 
262  texX = TILE_WIDTH * 3;
263 
264  /* top */
265  UI_DrawNormImage(false, pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
266  texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
267  image);
268  texY += TILE_HEIGHT;
269  y += ELEMENT_HEIGHT;
270 
271  /* top to bottom */
272  UI_DrawNormImage(false, pos[0], y, ELEMENT_WIDTH, node->box.size[1] - (ELEMENT_HEIGHT * 2),
273  texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
274  image);
275  texY += TILE_HEIGHT * 5;
276  y += node->box.size[1] - (ELEMENT_HEIGHT * 2);
277  assert(y == pos[1] + node->box.size[1] - ELEMENT_HEIGHT);
278 
279  /* bottom */
280  UI_DrawNormImage(false, pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
281  texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
282  image);
283 
284  } else {
285  int hoveredElement = -1;
286  int description[5];
287  UI_VScrollbarNodeGetElementSize(node, description);
288  if (UI_GetMouseCapture() == node)
289  hoveredElement = capturedElement;
290  else if (node->state)
291  hoveredElement = UI_VScrollbarNodeGetElement(node, description,
293 
294  /* top */
295  texX = (hoveredElement == 0) ? TILE_WIDTH : 0;
296  UI_DrawNormImage(false, pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
297  texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY, image);
298  texY += TILE_HEIGHT;
299  y += ELEMENT_HEIGHT;
300 
301  /* top to slider */
302  if (description[1]) {
303  texX = (hoveredElement == 1) ? TILE_WIDTH : 0;
304  UI_DrawNormImage(false, pos[0], y, ELEMENT_WIDTH, description[1],
305  texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
306  image);
307  y += description[1];
308  }
309  texY += TILE_HEIGHT;
310 
311  /* slider */
312  texX = (hoveredElement == 2) ? TILE_WIDTH : 0;
313 
314  /* top slider */
315  UI_DrawNormImage(false, pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
316  texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY, image);
317  texY += TILE_HEIGHT;
318  y += ELEMENT_HEIGHT;
319 
320  /* middle slider */
321  if (description[2]) {
322  UI_DrawNormImage(false, pos[0], y, ELEMENT_WIDTH,
323  description[2] - ELEMENT_HEIGHT - ELEMENT_HEIGHT,
324  texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
325  image);
326  y += description[2] - ELEMENT_HEIGHT - ELEMENT_HEIGHT;
327  }
328  texY += TILE_HEIGHT;
329 
330  /* bottom slider */
331  UI_DrawNormImage(false, pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
332  texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY, image);
333  texY += TILE_HEIGHT;
334  y += ELEMENT_HEIGHT;
335 
336  /* slider to bottom */
337  if (description[3]) {
338  texX = (hoveredElement == 3) ? TILE_WIDTH : 0;
339  UI_DrawNormImage(false, pos[0], y, ELEMENT_WIDTH, description[3],
340  texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
341  image);
342  y += description[3];
343  }
344  texY += TILE_HEIGHT;
345  assert(y == pos[1] + node->box.size[1] - ELEMENT_HEIGHT);
346 
347  /* bottom */
348  texX = (hoveredElement == 4) ? TILE_WIDTH : 0;
349  UI_DrawNormImage(false, pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
350  texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY, image);
351  }
352 }
353 
355 {
356  node->box.size[0] = 19;
357 }
358 
360 {
361 #ifdef DEBUG
362  if (node->box.size[1] - (ELEMENT_HEIGHT * 4) < 0)
363  Com_DPrintf(DEBUG_CLIENT, "Node '%s' too small. It can create graphical glitches\n", UI_GetPath(node));
364 #endif
365 }
366 
368 {
369  behaviour->name = "vscrollbar";
370  behaviour->extends = "abstractscrollbar";
371  behaviour->manager = UINodePtr(new uiVScrollbarNode());
372  behaviour->lua_SWIG_typeinfo = UI_SWIG_TypeQuery("uiVScrollBarNode_t *");
373 
374  /* Image to use. Each behaviour use it like they want.
375  * @todo use V_REF_OR_STRING when its possible ('image' is never a cvar)
376  */
377  UI_RegisterNodeProperty(behaviour, "image", V_CVAR_OR_STRING, uiNode_t, image);
378 }
static int oldMouseY
vec2_t size
Definition: ui_nodes.h:52
static const int TILE_HEIGHT
void UI_AbstractScrollbarNodeSet(uiNode_t *node, int value)
Set the position of the scrollbar to a value.
const char * name
Definition: ui_behaviour.h:41
void onCapturedMouseMove(uiNode_t *node, int x, int y) override
Called when the node is captured by the mouse.
UINodePtr manager
Definition: ui_behaviour.h:43
bool onScroll(uiNode_t *node, int deltaX, int deltaY) override
Called when the user wheel the mouse over the node.
#define EXTRADATA(node)
static int capturedElement
static void UI_VScrollbarNodeGetElementSize(uiNode_t *node, int description[5])
Return size of all elements of the scrollbar.
static int oldPos
#define UI_RegisterNodeProperty(BEHAVIOUR, NAME, TYPE, OBJECTTYPE, ATTRIBUTE)
Initialize a property.
Definition: ui_behaviour.h:91
uiTimer_t * UI_AllocTimer(uiNode_t *node, int firstDelay, timerCallback_t callback)
Allocate a new time for a node.
Definition: ui_timer.cpp:123
Definition: common.cpp:82
void UI_MouseRelease(void)
Release the captured node.
Definition: ui_input.cpp:526
static void UI_VScrollbarNodeRepeat(uiNode_t *node, uiTimer_t *timer)
int delay
Definition: ui_timer.h:45
static const int ELEMENT_WIDTH
static void UI_VScrollbarNodeAction(uiNode_t *node, int hoveredElement, bool allowCapture)
void onLoaded(uiNode_t *node) override
#define DEBUG_CLIENT
Definition: defines.h:59
bool state
Definition: ui_nodes.h:106
void UI_RegisterVScrollbarNode(uiBehaviour_t *behaviour)
int mousePosY
Definition: cl_input.cpp:80
SharedPtr< uiNode > UINodePtr
void onCapturedMouseLost(uiNode_t *node) override
Called when the node have lost the captured node We clean cached data.
void draw(uiNode_t *node) override
Call to draw the node.
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 UI_TimerRelease(uiTimer_t *timer)
Release the timer. It no more exists.
Definition: ui_timer.cpp:176
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
void onMouseUp(uiNode_t *node, int x, int y, int button) override
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition: common.cpp:398
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
static const int TILE_WIDTH
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 GLint i
Definition: r_gl.h:113
static int UI_VScrollbarNodeGetElement(uiNode_t *node, int description[5], int x, int y)
Get an element of the scrollbar at a position.
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
void onMouseDown(uiNode_t *node, int x, int y, int button) override
vec_t vec2_t[2]
Definition: ufotypes.h:38
char * image
Definition: ui_nodes.h:123
#define V_CVAR_OR_STRING
Definition: ui_parse.h:69
uiBox_t box
Definition: ui_nodes.h:96
static uiTimer_t * capturedTimer
int mousePosX
Definition: cl_input.cpp:80
static const int ELEMENT_HEIGHT
int calledTime
Definition: ui_timer.h:43
void UI_TimerStart(uiTimer_t *timer)
Restart a timer.
Definition: ui_timer.cpp:150
void onLoading(uiNode_t *node) override
static void UI_VScrollbarNodeDiff(uiNode_t *node, int value)
Translate the position to a value.