00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "../ui_nodes.h"
00028 #include "../ui_parse.h"
00029 #include "../ui_timer.h"
00030 #include "../ui_actions.h"
00031 #include "../ui_input.h"
00032 #include "../ui_render.h"
00033 #include "ui_node_abstractnode.h"
00034 #include "ui_node_abstractscrollbar.h"
00035 #include "ui_node_vscrollbar.h"
00036
00037 #include "../../input/cl_input.h"
00038 #include "../../input/cl_keys.h"
00039
00040 static const int TILE_WIDTH = 32;
00041 static const int TILE_HEIGHT = 18;
00042 static const int ELEMENT_WIDTH = 19;
00043 static const int ELEMENT_HEIGHT = 16;
00044
00045 static int oldPos;
00046 static int oldMouseY;
00047 static uiTimer_t *capturedTimer;
00048 static int capturedElement;
00049
00050 #define EXTRADATA(node) UI_EXTRADATA(node, abstractScrollbarExtraData_t)
00051
00055 static void UI_VScrollbarNodeGetElementSize (uiNode_t *node, int description[5])
00056 {
00057 const int cuttableSize = node->size[1] - (ELEMENT_HEIGHT * 4);
00058 const int low = cuttableSize * ((float)(EXTRADATA(node).pos + 0) / (float)EXTRADATA(node).fullsize);
00059 const int middle = cuttableSize * ((float)(EXTRADATA(node).viewsize) / (float)EXTRADATA(node).fullsize);
00060 const int hight = cuttableSize - low - middle;
00061 description[0] = ELEMENT_HEIGHT;
00062 description[1] = low;
00063 description[2] = middle + 2 * ELEMENT_HEIGHT;
00064 description[3] = hight;
00065 description[4] = ELEMENT_HEIGHT;
00066 assert(description[0] + description[1] + description[2] + description[3] + description[4] == node->size[1]);
00067 }
00068
00076 static int UI_VScrollbarNodeGetElement (uiNode_t *node, int description[5], int x, int y)
00077 {
00078 int i;
00079 UI_NodeAbsoluteToRelativePos(node, &x, &y);
00080 for (i = 0; i < 5; i++) {
00081 if (y < description[i])
00082 return i;
00083 y -= description[i];
00084 }
00085 return -1;
00086 }
00087
00091 static void UI_VScrollbarNodeSet (uiNode_t *node, int value)
00092 {
00093 int pos = value;
00094
00095 if (pos < 0) {
00096 pos = 0;
00097 } else if (pos > EXTRADATA(node).fullsize - EXTRADATA(node).viewsize) {
00098 pos = EXTRADATA(node).fullsize - EXTRADATA(node).viewsize;
00099 }
00100 if (pos < 0)
00101 pos = 0;
00102
00103
00104 if (EXTRADATA(node).pos == pos)
00105 return;
00106
00107
00108 EXTRADATA(node).lastdiff = pos - EXTRADATA(node).pos;
00109 EXTRADATA(node).pos = pos;
00110
00111
00112 if (node->onChange) {
00113 UI_ExecuteEventActions(node, node->onChange);
00114 }
00115 }
00116
00120 static inline void UI_VScrollbarNodeDiff (uiNode_t *node, int value)
00121 {
00122 UI_VScrollbarNodeSet(node, EXTRADATA(node).pos + value);
00123 }
00124
00125 static inline void UI_VScrollbarNodeAction(uiNode_t *node, int hoveredElement, qboolean allowCapture);
00126
00127 static void UI_VScrollbarNodeRepeat (uiNode_t *node, uiTimer_t *timer)
00128 {
00129 UI_VScrollbarNodeAction(node, capturedElement, qfalse);
00130 switch (timer->calledTime) {
00131 case 1:
00132 timer->delay = 50;
00133 break;
00134 }
00135 }
00136
00137 static inline void UI_VScrollbarNodeAction (uiNode_t *node, int hoveredElement, qboolean allowCapture)
00138 {
00139 switch (hoveredElement) {
00140 case 0:
00141 UI_VScrollbarNodeDiff(node, -1);
00142 if (allowCapture) {
00143 UI_SetMouseCapture(node);
00144 capturedElement = hoveredElement;
00145 capturedTimer = UI_AllocTimer(node, 500, UI_VScrollbarNodeRepeat);
00146 UI_TimerStart(capturedTimer);
00147 }
00148 break;
00149 case 1:
00150 UI_VScrollbarNodeDiff(node, -10);
00151 if (allowCapture) {
00152 UI_SetMouseCapture(node);
00153 capturedElement = hoveredElement;
00154 capturedTimer = UI_AllocTimer(node, 500, UI_VScrollbarNodeRepeat);
00155 UI_TimerStart(capturedTimer);
00156 }
00157 break;
00158 case 2:
00159 if (allowCapture) {
00160 UI_SetMouseCapture(node);
00161
00162 oldMouseY = mousePosY;
00163 oldPos = EXTRADATA(node).pos;
00164 capturedElement = hoveredElement;
00165 }
00166 break;
00167 case 3:
00168 UI_VScrollbarNodeDiff(node, 10);
00169 if (allowCapture) {
00170 UI_SetMouseCapture(node);
00171 capturedElement = hoveredElement;
00172 capturedTimer = UI_AllocTimer(node, 500, UI_VScrollbarNodeRepeat);
00173 UI_TimerStart(capturedTimer);
00174 }
00175 break;
00176 case 4:
00177 UI_VScrollbarNodeDiff(node, 1);
00178 if (allowCapture) {
00179 UI_SetMouseCapture(node);
00180 capturedElement = hoveredElement;
00181 capturedTimer = UI_AllocTimer(node, 500, UI_VScrollbarNodeRepeat);
00182 UI_TimerStart(capturedTimer);
00183 }
00184 break;
00185 default:
00186 assert(qfalse);
00187 }
00188 }
00189
00194 static void UI_ActiveVScrollbarNode_f ()
00195 {
00196 uiNode_t *node;
00197 int actionId;
00198
00199 if (Cmd_Argc() != 3) {
00200 Com_Printf("Usage: %s <node-path> <action-id>\n", Cmd_Argv(0));
00201 return;
00202 }
00203
00204 node = UI_GetNodeByPath(Cmd_Argv(1));
00205 if (node == NULL) {
00206 Com_Printf("UI_ActiveVScrollbarNode_f: node '%s' not found\n", Cmd_Argv(1));
00207 return;
00208 }
00209 if (!UI_NodeInstanceOf(node, "vscrollbar")) {
00210 Com_Printf("UI_ActiveVScrollbarNode_f: node '%s' is not a 'vscrollbar'\n", Cmd_Argv(1));
00211 return;
00212 }
00213
00214 actionId = atoi(Cmd_Argv(2));
00215 UI_VScrollbarNodeAction(node, actionId, qfalse);
00216 }
00217
00218 static void UI_VScrollbarNodeMouseDown (uiNode_t *node, int x, int y, int button)
00219 {
00220 int hoveredElement = -1;
00221 int description[5];
00222
00223 if (EXTRADATA(node).fullsize == 0 || EXTRADATA(node).fullsize < EXTRADATA(node).viewsize)
00224 return;
00225 if (button != K_MOUSE1)
00226 return;
00227
00228 UI_VScrollbarNodeGetElementSize(node, description);
00229 hoveredElement = UI_VScrollbarNodeGetElement(node, description, x, y);
00230 UI_VScrollbarNodeAction(node, hoveredElement, qtrue);
00231 }
00232
00233 static void UI_VScrollbarNodeMouseUp (uiNode_t *node, int x, int y, int button)
00234 {
00235 if (EXTRADATA(node).fullsize == 0 || EXTRADATA(node).fullsize < EXTRADATA(node).viewsize)
00236 return;
00237 if (button != K_MOUSE1)
00238 return;
00239
00240 if (UI_GetMouseCapture() == node) {
00241 UI_MouseRelease();
00242 }
00243 }
00244
00249 static void UI_VScrollbarNodeCapturedMouseLost (uiNode_t *node)
00250 {
00251 if (capturedTimer) {
00252 UI_TimerRelease(capturedTimer);
00253 capturedTimer = NULL;
00254 }
00255 }
00256
00260 static void UI_VScrollbarNodeWheel (uiNode_t *node, qboolean down, int x, int y)
00261 {
00262 const int diff = (down)?1:-1;
00263
00264 if (EXTRADATA(node).fullsize == 0 || EXTRADATA(node).fullsize < EXTRADATA(node).viewsize)
00265 return;
00266
00267 UI_VScrollbarNodeSet(node, EXTRADATA(node).pos + diff);
00268 }
00269
00273 static void UI_VScrollbarNodeCapturedMouseMove (uiNode_t *node, int x, int y)
00274 {
00275 const int posSize = EXTRADATA(node).fullsize;
00276 const int graphicSize = node->size[1] - (4 * ELEMENT_HEIGHT);
00277 int pos = 0;
00278
00279 if (capturedElement != 2)
00280 return;
00281
00282
00283 y -= oldMouseY;
00284
00285
00286 pos = oldPos + (((float)y * (float)posSize) / (float)graphicSize);
00287
00288 UI_VScrollbarNodeSet(node, pos);
00289 }
00290
00294 static void UI_VScrollbarNodeDraw (uiNode_t *node)
00295 {
00296 vec2_t pos;
00297 int y = 0;
00298 int texX = 0;
00299 int texY = 0;
00300 const char *texture;
00301 const image_t *image;
00302
00303 UI_GetNodeAbsPos(node, pos);
00304 y = pos[1];
00305
00306 texture = UI_GetReferenceString(node, node->image);
00307 if (!texture)
00308 return;
00309
00310 image = UI_LoadImage(texture);
00311
00312 if (EXTRADATA(node).fullsize == 0 || EXTRADATA(node).fullsize <= EXTRADATA(node).viewsize) {
00313
00314 if (EXTRADATA(node).hideWhenUnused)
00315 return;
00316
00317 texX = TILE_WIDTH * 3;
00318
00319
00320 UI_DrawNormImage(pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
00321 texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
00322 image);
00323 texY += TILE_HEIGHT;
00324 y += ELEMENT_HEIGHT;
00325
00326
00327 UI_DrawNormImage(pos[0], y, ELEMENT_WIDTH, node->size[1] - (ELEMENT_HEIGHT * 2),
00328 texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
00329 image);
00330 texY += TILE_HEIGHT * 5;
00331 y += node->size[1] - (ELEMENT_HEIGHT * 2);
00332 assert(y == pos[1] + node->size[1] - ELEMENT_HEIGHT);
00333
00334
00335 UI_DrawNormImage(pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
00336 texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
00337 image);
00338
00339 } else {
00340 int houveredElement = -1;
00341 int description[5];
00342 UI_VScrollbarNodeGetElementSize(node, description);
00343 if (UI_GetMouseCapture() == node)
00344 houveredElement = capturedElement;
00345 else if (node->state)
00346 houveredElement = UI_VScrollbarNodeGetElement(node, description, mousePosX, mousePosY);
00347
00348
00349 texX = (houveredElement == 0)?TILE_WIDTH:0;
00350 UI_DrawNormImage(pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
00351 texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
00352 image);
00353 texY += TILE_HEIGHT;
00354 y += ELEMENT_HEIGHT;
00355
00356
00357 if (description[1]) {
00358 texX = (houveredElement == 1)?TILE_WIDTH:0;
00359 UI_DrawNormImage(pos[0], y, ELEMENT_WIDTH, description[1],
00360 texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
00361 image);
00362 y += description[1];
00363 }
00364 texY += TILE_HEIGHT;
00365
00366
00367 texX = (houveredElement == 2)?TILE_WIDTH:0;
00368
00369
00370 UI_DrawNormImage(pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
00371 texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
00372 image);
00373 texY += TILE_HEIGHT;
00374 y += ELEMENT_HEIGHT;
00375
00376
00377 if (description[2]) {
00378 UI_DrawNormImage(pos[0], y, ELEMENT_WIDTH, description[2]-ELEMENT_HEIGHT-ELEMENT_HEIGHT,
00379 texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
00380 image);
00381 y += description[2]-ELEMENT_HEIGHT-ELEMENT_HEIGHT;
00382 }
00383 texY += TILE_HEIGHT;
00384
00385
00386 UI_DrawNormImage(pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
00387 texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
00388 image);
00389 texY += TILE_HEIGHT;
00390 y += ELEMENT_HEIGHT;
00391
00392
00393 if (description[3]) {
00394 texX = (houveredElement == 3)?TILE_WIDTH:0;
00395 UI_DrawNormImage(pos[0], y, ELEMENT_WIDTH, description[3],
00396 texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
00397 image);
00398 y += description[3];
00399 }
00400 texY += TILE_HEIGHT;
00401 assert(y == pos[1] + node->size[1] - ELEMENT_HEIGHT);
00402
00403
00404 texX = (houveredElement == 4)?TILE_WIDTH:0;
00405 UI_DrawNormImage(pos[0], y, ELEMENT_WIDTH, ELEMENT_HEIGHT,
00406 texX + ELEMENT_WIDTH, texY + ELEMENT_HEIGHT, texX, texY,
00407 image);
00408 }
00409
00410 }
00411
00412 static void UI_VScrollbarNodeLoading (uiNode_t *node)
00413 {
00414 node->size[0] = 19;
00415 }
00416
00417 static void UI_VScrollbarNodeLoaded (uiNode_t *node)
00418 {
00419 #ifdef DEBUG
00420 if (node->size[1] - (ELEMENT_HEIGHT * 4) < 0)
00421 Com_DPrintf(DEBUG_CLIENT, "Node '%s' too small. It can create graphical glitches\n", UI_GetPath(node));
00422 #endif
00423 }
00424
00425 void UI_RegisterVScrollbarNode (uiBehaviour_t *behaviour)
00426 {
00427 behaviour->name = "vscrollbar";
00428 behaviour->extends = "abstractscrollbar";
00429 behaviour->mouseWheel = UI_VScrollbarNodeWheel;
00430 behaviour->mouseDown = UI_VScrollbarNodeMouseDown;
00431 behaviour->mouseUp = UI_VScrollbarNodeMouseUp;
00432 behaviour->capturedMouseMove = UI_VScrollbarNodeCapturedMouseMove;
00433 behaviour->capturedMouseLost = UI_VScrollbarNodeCapturedMouseLost;
00434 behaviour->draw = UI_VScrollbarNodeDraw;
00435 behaviour->loaded = UI_VScrollbarNodeLoaded;
00436 behaviour->loading = UI_VScrollbarNodeLoading;
00437
00438 Cmd_AddCommand("mn_active_vscrollbar", UI_ActiveVScrollbarNode_f, "Active an element of a scrollbar node, (dummy mouse/user)");
00439 }