ui_node_selectbox.c

Go to the documentation of this file.
00001 
00026 /*
00027 Copyright (C) 2002-2010 UFO: Alien Invasion.
00028 
00029 This program is free software; you can redistribute it and/or
00030 modify it under the terms of the GNU General Public License
00031 as published by the Free Software Foundation; either version 2
00032 of the License, or (at your option) any later version.
00033 
00034 This program is distributed in the hope that it will be useful,
00035 but WITHOUT ANY WARRANTY; without even the implied warranty of
00036 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00037 
00038 See the GNU General Public License for more details.
00039 
00040 You should have received a copy of the GNU General Public License
00041 along with this program; if not, write to the Free Software
00042 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00043 
00044 */
00045 
00046 #include "../ui_main.h"
00047 #include "../ui_internal.h"
00048 #include "../ui_parse.h"
00049 #include "../ui_font.h"
00050 #include "../ui_input.h"
00051 #include "../ui_draw.h"
00052 #include "../ui_render.h"
00053 #include "ui_node_selectbox.h"
00054 #include "ui_node_abstractoption.h"
00055 #include "ui_node_abstractnode.h"
00056 #include "ui_node_option.h"
00057 
00058 #include "../../client.h" /* gettext _() */
00059 
00060 #define EXTRADATA(node) UI_EXTRADATA(node, abstractOptionExtraData_t)
00061 
00062 #define SELECTBOX_DEFAULT_HEIGHT 20.0f
00063 
00064 #define SELECTBOX_SIDE_WIDTH 7.0f
00065 #define SELECTBOX_RIGHT_WIDTH 20.0f
00066 
00067 #define SELECTBOX_SPACER 2.0f
00068 #define SELECTBOX_BOTTOM_HEIGHT 4.0f
00069 
00074 static void UI_SelectBoxNodeCapturedMouseMove (uiNode_t *node, int x, int y)
00075 {
00076     uiNode_t* option;
00077     int posy;
00078 
00079     UI_NodeAbsoluteToRelativePos(node, &x, &y);
00080 
00081     /* test bounded box */
00082     if (x < 0 || y < 0 || x > node->size[0] || y > node->size[1] * (EXTRADATA(node).count + 1)) {
00083         return;
00084     }
00085 
00086     posy = node->size[1];
00087     for (option = UI_AbstractOptionGetFirstOption(node); option; option = option->next) {
00088         if (option->invis)
00089             continue;
00090         OPTIONEXTRADATA(option).hovered = (posy <= y && y < posy + node->size[1]);
00091         posy += node->size[1];
00092     }
00093 }
00094 
00095 static void UI_SelectBoxNodeDraw (uiNode_t *node)
00096 {
00097     uiNode_t* option;
00098     int selBoxX, selBoxY;
00099     const char *ref;
00100     const char *font;
00101     vec2_t nodepos;
00102     const char* imageName;
00103     const image_t *image;
00104     static vec4_t invisColor = {1.0, 1.0, 1.0, 0.7};
00105 
00106     ref = UI_AbstractOptionGetCurrentValue(node);
00107     if (ref == NULL)
00108         return;
00109 
00110     UI_GetNodeAbsPos(node, nodepos);
00111     imageName = UI_GetReferenceString(node, node->image);
00112     if (!imageName)
00113         imageName = "ui/selectbox";
00114 
00115     image = UI_LoadImage(imageName);
00116 
00117     font = UI_GetFontFromNode(node);
00118     selBoxX = nodepos[0] + SELECTBOX_SIDE_WIDTH;
00119     selBoxY = nodepos[1] + SELECTBOX_SPACER;
00120 
00121     /* left border */
00122     UI_DrawNormImage(nodepos[0], nodepos[1], SELECTBOX_SIDE_WIDTH, node->size[1],
00123         SELECTBOX_SIDE_WIDTH, SELECTBOX_DEFAULT_HEIGHT, 0.0f, 0.0f, image);
00124     /* stretched middle bar */
00125     UI_DrawNormImage(nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1], node->size[0]-SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, node->size[1],
00126         12.0f, SELECTBOX_DEFAULT_HEIGHT, 7.0f, 0.0f, image);
00127     /* right border (arrow) */
00128     UI_DrawNormImage(nodepos[0] + node->size[0] - SELECTBOX_RIGHT_WIDTH, nodepos[1], SELECTBOX_DEFAULT_HEIGHT, node->size[1],
00129         12.0f + SELECTBOX_RIGHT_WIDTH, SELECTBOX_DEFAULT_HEIGHT, 12.0f, 0.0f, image);
00130 
00131     /* draw the label for the current selected option */
00132     for (option = UI_AbstractOptionGetFirstOption(node); option; option = option->next) {
00133         const char *label;
00134 
00135         if (strcmp(OPTIONEXTRADATA(option).value, ref) != 0)
00136             continue;
00137 
00138         if (option->invis)
00139             R_Color(invisColor);
00140 
00141         label = OPTIONEXTRADATA(option).label;
00142         if (label[0] == '_')
00143             label = _(label + 1);
00144 
00145         UI_DrawString(font, ALIGN_UL, selBoxX, selBoxY,
00146             selBoxX, node->size[0] - 4,
00147             0, label, 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00148 
00149         R_Color(NULL);
00150         break;
00151     }
00152 
00153     /* must we draw the drop-down list */
00154     if (UI_GetMouseCapture() == node) {
00155         UI_CaptureDrawOver(node);
00156     }
00157 }
00158 
00159 static void UI_SelectBoxNodeDrawOverWindow (uiNode_t *node)
00160 {
00161     uiNode_t* option;
00162     int selBoxX, selBoxY;
00163     const char *ref;
00164     const char *font;
00165     vec2_t nodepos;
00166     const char* imageName;
00167     const image_t *image;
00168 
00169     ref = UI_AbstractOptionGetCurrentValue(node);
00170     if (ref == NULL)
00171         return;
00172 
00173     UI_GetNodeAbsPos(node, nodepos);
00174     imageName = UI_GetReferenceString(node, node->image);
00175     if (!imageName)
00176         imageName = "ui/selectbox";
00177 
00178     image = UI_LoadImage(imageName);
00179 
00180     font = UI_GetFontFromNode(node);
00181     selBoxX = nodepos[0] + SELECTBOX_SIDE_WIDTH;
00182     selBoxY = nodepos[1] + SELECTBOX_SPACER;
00183 
00184     selBoxY += node->size[1];
00185 
00186     /* drop down list */
00187     /* left side */
00188     UI_DrawNormImage(nodepos[0], nodepos[1] + node->size[1], SELECTBOX_SIDE_WIDTH, node->size[1] * EXTRADATA(node).count,
00189         7.0f, 28.0f, 0.0f, 21.0f, image);
00190 
00191     /* stretched middle bar */
00192     UI_DrawNormImage(nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1] + node->size[1], node->size[0] -SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, node->size[1] * EXTRADATA(node).count,
00193         16.0f, 28.0f, 7.0f, 21.0f, image);
00194 
00195     /* right side */
00196     UI_DrawNormImage(nodepos[0] + node->size[0] -SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, nodepos[1] + node->size[1], SELECTBOX_SIDE_WIDTH, node->size[1] * EXTRADATA(node).count,
00197         23.0f, 28.0f, 16.0f, 21.0f, image);
00198 
00199     /* now draw all available options for this selectbox */
00200     for (option = UI_AbstractOptionGetFirstOption(node); option; option = option->next) {
00201         const char *label;
00202         if (option->invis)
00203             continue;
00204         /* draw the hover effect */
00205         if (OPTIONEXTRADATA(option).hovered)
00206             UI_DrawFill(selBoxX, selBoxY, node->size[0] -SELECTBOX_SIDE_WIDTH - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH,
00207                     SELECTBOX_DEFAULT_HEIGHT, node->color);
00208         /* print the option label */
00209         label = OPTIONEXTRADATA(option).label;
00210         if (label[0] == '_')
00211             label = _(label + 1);
00212         UI_DrawString(font, ALIGN_UL, selBoxX, selBoxY,
00213             selBoxX, node->size[0] - 4,
00214             0, label, 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00215         /* next entries' position */
00216         selBoxY += node->size[1];
00217     }
00218     /* left side */
00219     UI_DrawNormImage(nodepos[0], selBoxY - SELECTBOX_SPACER, SELECTBOX_SIDE_WIDTH, SELECTBOX_BOTTOM_HEIGHT,
00220         7.0f, 32.0f, 0.0f, 28.0f, image);
00221 
00222     /* stretched middle bar */
00223     UI_DrawNormImage(nodepos[0] + SELECTBOX_SIDE_WIDTH, selBoxY - SELECTBOX_SPACER, node->size[0] - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH,
00224             SELECTBOX_BOTTOM_HEIGHT,
00225         16.0f, 32.0f, 7.0f, 28.0f, image);
00226 
00227     /* right bottom side */
00228     UI_DrawNormImage(nodepos[0] + node->size[0] - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH, selBoxY - SELECTBOX_SPACER,
00229         SELECTBOX_SIDE_WIDTH, SELECTBOX_BOTTOM_HEIGHT,
00230         23.0f, 32.0f, 16.0f, 28.0f, image);
00231 }
00232 
00236 static void UI_SelectBoxNodeClick (uiNode_t *node, int x, int y)
00237 {
00238     uiNode_t* option;
00239     int clickedAtOption;
00240     vec2_t pos;
00241 
00242     /* dropdown the node */
00243     if (UI_GetMouseCapture() == NULL) {
00244         UI_SetMouseCapture(node);
00245         return;
00246     }
00247 
00248     UI_GetNodeAbsPos(node, pos);
00249     clickedAtOption = (y - pos[1]);
00250 
00251     /* we click outside */
00252     if (x < pos[0] || y < pos[1] || x >= pos[0] + node->size[0] || y >= pos[1] + node->size[1] * (EXTRADATA(node).count + 1)) {
00253         UI_MouseRelease();
00254         return;
00255     }
00256 
00257     /* we click on the head */
00258     if (clickedAtOption < node->size[1]) {
00259         UI_MouseRelease();
00260         return;
00261     }
00262 
00263     clickedAtOption = (clickedAtOption - node->size[1]) / node->size[1];
00264     if (clickedAtOption < 0 || clickedAtOption >= EXTRADATA(node).count)
00265         return;
00266 
00267     if (UI_AbstractOptionGetCurrentValue(node) == NULL)
00268         return;
00269 
00270     /* select the right option */
00271     option = UI_AbstractOptionGetFirstOption(node);
00272     for (; option; option = option->next) {
00273         if (option->invis)
00274             continue;
00275         if (clickedAtOption == 0)
00276             break;
00277         clickedAtOption--;
00278     }
00279 
00280     /* update the status */
00281     if (option)
00282         UI_AbstractOptionSetCurrentValue(node, OPTIONEXTRADATA(option).value);
00283 
00284     /* close the dropdown */
00285     UI_MouseRelease();
00286 }
00287 
00291 static void UI_SelectBoxNodeLoading (uiNode_t *node)
00292 {
00293     Vector4Set(node->color, 0.6, 0.6, 0.6, 0.3);
00294 }
00295 
00296 static void UI_SelectBoxNodeLoaded (uiNode_t *node)
00297 {
00298     /* force a size (according to the texture) */
00299     node->size[1] = SELECTBOX_DEFAULT_HEIGHT;
00300 }
00301 
00302 void UI_RegisterSelectBoxNode (uiBehaviour_t *behaviour)
00303 {
00304     behaviour->name = "selectbox";
00305     behaviour->extends = "abstractoption";
00306     behaviour->draw = UI_SelectBoxNodeDraw;
00307     behaviour->drawOverWindow = UI_SelectBoxNodeDrawOverWindow;
00308     behaviour->leftClick = UI_SelectBoxNodeClick;
00309     behaviour->loading = UI_SelectBoxNodeLoading;
00310     behaviour->loaded = UI_SelectBoxNodeLoaded;
00311     behaviour->capturedMouseMove = UI_SelectBoxNodeCapturedMouseMove;
00312     behaviour->drawItselfChild = qtrue;
00313 }

Generated by  doxygen 1.6.2