ui_node_vscrollbar.c

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2002-2010 UFO: Alien Invasion.
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00018 
00019 See the GNU General Public License for more details.
00020 
00021 You should have received a copy of the GNU General Public License
00022 along with this program; if not, write to the Free Software
00023 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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     /* nothing change */
00104     if (EXTRADATA(node).pos == pos)
00105         return;
00106 
00107     /* update status */
00108     EXTRADATA(node).lastdiff = pos - EXTRADATA(node).pos;
00109     EXTRADATA(node).pos = pos;
00110 
00111     /* fire change event */
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             /* save start value */
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     /* compute mouse mouse */
00283     y -= oldMouseY;
00284 
00285     /* compute pos projection */
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         /* hide the scrollbar */
00314         if (EXTRADATA(node).hideWhenUnused)
00315             return;
00316 
00317         texX = TILE_WIDTH * 3;
00318 
00319         /* top */
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         /* top to bottom */
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         /* bottom */
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         /* top */
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         /* top to slider */
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         /* slider */
00367         texX = (houveredElement == 2)?TILE_WIDTH:0;
00368 
00369         /* top slider */
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         /* middle slider */
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         /* bottom slider */
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         /* slider to bottom */
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         /* bottom */
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 }

Generated by  doxygen 1.6.2