ui_node_spinner.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "../ui_nodes.h"
00027 #include "../ui_parse.h"
00028 #include "../ui_main.h"
00029 #include "../ui_input.h"
00030 #include "../ui_timer.h"
00031 #include "../ui_actions.h"
00032 #include "../ui_render.h"
00033 #include "ui_node_spinner.h"
00034 #include "ui_node_abstractvalue.h"
00035 #include "ui_node_abstractnode.h"
00036 
00037 #include "../../input/cl_input.h"
00038 #include "../../input/cl_keys.h"
00039 
00040 #define EXTRADATA(node) UI_EXTRADATA(node, abstractValueExtraData_t)
00041 
00042 static const uiBehaviour_t const *localBehaviour;
00043 
00044 static const int TILE_SIZE = 32;
00045 static const int SPINNER_WIDTH = 15;
00046 static const int SPINNER_HEIGHT = 19;
00047 static const int BUTTON_TOP_SIZE = 9;
00048 static const int BUTTON_BOTTOM_SIZE = 10;
00049 
00055 static void UI_SpinnerNodeStep (uiNode_t *node, qboolean down)
00056 {
00057     float value = UI_GetReferenceFloat(node, EXTRADATA(node).value);
00058     const float last = value;
00059     const float delta = UI_GetReferenceFloat(node, EXTRADATA(node).delta);
00060     const float max = UI_GetReferenceFloat(node, EXTRADATA(node).max);
00061     const float min = UI_GetReferenceFloat(node, EXTRADATA(node).min);
00062 
00063     if (!down) {
00064         if (value + delta <= max) {
00065             value += delta;
00066         } else {
00067             value = max;
00068         }
00069     } else {
00070         if (value - delta >= min) {
00071             value -= delta;
00072         } else {
00073             value = min;
00074         }
00075     }
00076 
00077     /* ensure sane values */
00078     if (value < min)
00079         value = min;
00080     else if (value > max)
00081         value = max;
00082 
00083     /* nothing change? */
00084     if (last == value)
00085         return;
00086 
00087     /* save result */
00088     EXTRADATA(node).lastdiff = value - last;
00089     if (!strncmp(EXTRADATA(node).value, "*cvar:", 6))
00090         UI_SetCvar(&((char*)EXTRADATA(node).value)[6], NULL, value);
00091     else
00092         *(float*) EXTRADATA(node).value = value;
00093 
00094     /* fire change event */
00095     if (node->onChange)
00096         UI_ExecuteEventActions(node, node->onChange);
00097 }
00098 
00099 static qboolean capturedDownButton;
00100 static uiTimer_t *capturedTimer = NULL;
00101 
00102 static void UI_SpinnerNodeRepeat (uiNode_t *node, uiTimer_t *timer)
00103 {
00104     UI_SpinnerNodeStep(node, capturedDownButton);
00105     switch (timer->calledTime) {
00106     case 1:
00107         timer->delay = 50;
00108         break;
00109     }
00110 }
00111 
00112 static void UI_SpinnerNodeDown (uiNode_t *node, int x, int y, int button)
00113 {
00114     if (button == K_MOUSE1) {
00115         UI_SetMouseCapture(node);
00116         UI_NodeAbsoluteToRelativePos(node, &x, &y);
00117         capturedDownButton = y > BUTTON_TOP_SIZE;
00118         UI_SpinnerNodeStep(node, capturedDownButton);
00119         capturedTimer = UI_AllocTimer(node, 500, UI_SpinnerNodeRepeat);
00120         UI_TimerStart (capturedTimer);
00121     }
00122 }
00123 
00124 static void UI_SpinnerNodeUp (uiNode_t *node, int x, int y, int button)
00125 {
00126     if (button == K_MOUSE1) {
00127         UI_MouseRelease();
00128     }
00129 }
00130 
00135 static void UI_SpinnerNodeCapturedMouseLost (uiNode_t *node)
00136 {
00137     if (capturedTimer) {
00138         UI_TimerRelease(capturedTimer);
00139         capturedTimer = NULL;
00140     }
00141 }
00142 
00146 static void UI_SpinnerNodeWheel (uiNode_t *node, qboolean down, int x, int y)
00147 {
00148     const qboolean disabled = node->disabled || node->parent->disabled;
00149     if (disabled)
00150         return;
00151     UI_SpinnerNodeStep(node, down);
00152 }
00153 
00154 static void UI_SpinnerNodeDraw (uiNode_t *node)
00155 {
00156     vec2_t pos;
00157     int topTexX, topTexY;
00158     int bottomTexX, bottomTexY;
00159     const char* image = UI_GetReferenceString(node, node->image);
00160     const float delta = UI_GetReferenceFloat(node, EXTRADATA(node).delta);
00161     const qboolean disabled = node->disabled || node->parent->disabled;
00162 
00163     if (!image)
00164         return;
00165 
00166     UI_GetNodeAbsPos(node, pos);
00167 
00168     if (disabled || delta == 0) {
00169         topTexX = TILE_SIZE;
00170         topTexY = TILE_SIZE;
00171         bottomTexX = TILE_SIZE;
00172         bottomTexY = TILE_SIZE;
00173     } else {
00174         const float value = UI_GetReferenceFloat(node, EXTRADATA(node).value);
00175         const float min = UI_GetReferenceFloat(node, EXTRADATA(node).min);
00176         const float max = UI_GetReferenceFloat(node, EXTRADATA(node).max);
00177 
00178         /* top button status */
00179         if (value >= max) {
00180             topTexX = TILE_SIZE;
00181             topTexY = TILE_SIZE;
00182         } else if (node->state && mousePosY < pos[1] + BUTTON_TOP_SIZE) {
00183             topTexX = TILE_SIZE;
00184             topTexY = 0;
00185         } else {
00186             topTexX = 0;
00187             topTexY = 0;
00188         }
00189         /* bottom button status */
00190         if (value <= min) {
00191             bottomTexX = TILE_SIZE;
00192             bottomTexY = TILE_SIZE;
00193         } else if (node->state && mousePosY > pos[1] + BUTTON_TOP_SIZE) {
00194             bottomTexX = TILE_SIZE;
00195             bottomTexY = 0;
00196         } else {
00197             bottomTexX = 0;
00198             bottomTexY = 0;
00199         }
00200     }
00201 
00202     /* draw top button */
00203     UI_DrawNormImageByName(pos[0], pos[1], SPINNER_WIDTH, BUTTON_TOP_SIZE,
00204         topTexX + SPINNER_WIDTH, topTexY + BUTTON_TOP_SIZE, topTexX, topTexY, image);
00205     /* draw bottom button */
00206     UI_DrawNormImageByName(pos[0], pos[1] + BUTTON_TOP_SIZE, SPINNER_WIDTH, BUTTON_BOTTOM_SIZE,
00207         bottomTexX + SPINNER_WIDTH, bottomTexY + SPINNER_HEIGHT, bottomTexX, bottomTexY + SPINNER_HEIGHT - BUTTON_BOTTOM_SIZE, image);
00208 }
00209 
00210 static void UI_SpinnerNodeLoaded (uiNode_t *node)
00211 {
00212     localBehaviour->super->loaded(node);
00213     /* we can't choose a size */
00214     node->size[0] = SPINNER_WIDTH;
00215     node->size[1] = SPINNER_HEIGHT;
00216 }
00217 
00218 static const value_t properties[] = {
00219     /* @override size
00220      * The size of the widget is uneditable. Fixed to 15x19.
00221      */
00222     /* @override image
00223      * Texture used for the widget. Its a 64x64 template image with all four
00224      * status. The top button take the first vertical 9 pixels, the bottom
00225      * button use the last 10 pixels. See the sample image.
00226      * @image html http://ufoai.ninex.info/wiki/images/Spinner_blue.png
00227      */
00228 
00229     {NULL, V_NULL, 0, 0}
00230 };
00231 
00232 void UI_RegisterSpinnerNode (uiBehaviour_t *behaviour)
00233 {
00234     localBehaviour = behaviour;
00235     behaviour->name = "spinner";
00236     behaviour->extends = "abstractvalue";
00237     behaviour->mouseWheel = UI_SpinnerNodeWheel;
00238     behaviour->mouseDown = UI_SpinnerNodeDown;
00239     behaviour->mouseUp = UI_SpinnerNodeUp;
00240     behaviour->capturedMouseLost = UI_SpinnerNodeCapturedMouseLost;
00241     behaviour->draw = UI_SpinnerNodeDraw;
00242     behaviour->loaded = UI_SpinnerNodeLoaded;
00243     behaviour->properties = properties;
00244 }

Generated by  doxygen 1.6.2