ui_node_tab.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_main.h"
00027 #include "../ui_parse.h"
00028 #include "../ui_actions.h"
00029 #include "../ui_font.h"
00030 #include "../ui_input.h"
00031 #include "../ui_icon.h"
00032 #include "../ui_render.h"
00033 #include "../ui_tooltip.h"
00034 #include "ui_node_tab.h"
00035 #include "ui_node_abstractnode.h"
00036 #include "ui_node_abstractoption.h"
00037 
00038 #include "../../client.h" /* gettext _() */
00039 #include "../../input/cl_input.h"
00040 
00041 #define EXTRADATA_TYPE abstractOptionExtraData_t
00042 #define EXTRADATA(node) UI_EXTRADATA(node, EXTRADATA_TYPE)
00043 #define EXTRADATACONST(node) UI_EXTRADATACONST(node, EXTRADATA_TYPE)
00044 
00045 typedef enum {
00046     UI_TAB_NOTHING = 0,
00047     UI_TAB_NORMAL = 1,
00048     UI_TAB_SELECTED = 2,
00049     UI_TAB_HIGHLIGHTED = 3,
00050     UI_TAB_DISABLED = 4
00051 } mn_tab_type_t;
00052 
00053 static const int TILE_WIDTH = 33;
00054 static const int TILE_HEIGHT = 36;
00055 static const int TILE_SIZE = 40;
00056 
00066 static uiNode_t* UI_TabNodeTabAtPosition (const uiNode_t *node, int x, int y)
00067 {
00068     const char *font;
00069     uiNode_t* option;
00070     uiNode_t* prev = NULL;
00071     int allowedWidth;
00072 
00073     UI_NodeAbsoluteToRelativePos(node, &x, &y);
00074 
00076     allowedWidth = node->size[0] - TILE_WIDTH * (EXTRADATACONST(node).count + 1);
00077 
00078     /* Bounded box test (shound not need, but there are problem) */
00079     if (x < 0 || y < 0 || x >= node->size[0] || y >= node->size[1])
00080         return NULL;
00081 
00082     font = UI_GetFontFromNode(node);
00083 
00084     /* Text box test */
00085     for (option = node->firstChild; option; option = option->next) {
00086         int tabWidth;
00087         const char *label;
00088         assert(option->behaviour == ui_optionBehaviour);
00089 
00090         /* skip hidden options */
00091         if (option->invis)
00092             continue;
00093 
00094         if (x < TILE_WIDTH / 2)
00095             return prev;
00096 
00097         label = OPTIONEXTRADATA(option).label;
00098         if (label[0] == '_')
00099             label = _(label + 1);
00100 
00101         R_FontTextSize(font, label, 0, LONGLINES_PRETTYCHOP, &tabWidth, NULL, NULL, NULL);
00102         if (OPTIONEXTRADATA(option).icon && OPTIONEXTRADATA(option).icon->size[0] < allowedWidth) {
00103             tabWidth += OPTIONEXTRADATA(option).icon->size[0];
00104         }
00105         if (tabWidth > allowedWidth) {
00106             if (allowedWidth > 0)
00107                 tabWidth = allowedWidth;
00108             else
00109                 tabWidth = 0;
00110         }
00111 
00112         if (x < tabWidth + TILE_WIDTH)
00113             return option;
00114 
00115         allowedWidth -= tabWidth;
00116         x -= tabWidth + TILE_WIDTH;
00117         prev = option;
00118     }
00119     if (x < TILE_WIDTH / 2)
00120         return prev;
00121     return NULL;
00122 }
00123 
00127 static void UI_TabNodeClick (uiNode_t * node, int x, int y)
00128 {
00129     uiNode_t* option;
00130 
00131     if (UI_AbstractOptionGetCurrentValue(node) == NULL)
00132         return;
00133 
00134     option = UI_TabNodeTabAtPosition(node, x, y);
00135     if (option == NULL)
00136         return;
00137 
00138     if (option->disabled)
00139         return;
00140 
00141     /* only execute the click stuff if the selectbox is active */
00142     if (node->state)
00143         UI_AbstractOptionSetCurrentValue(node, OPTIONEXTRADATA(option).value);
00144 }
00145 
00154 static inline void UI_TabNodeDrawPlain (const char *image, int x, int y, int width, mn_tab_type_t type)
00155 {
00156     /* Hack sl=1 to not use the pixel on the left border on the texture (create graphic bug) */
00157     UI_DrawNormImageByName(x, y, width, TILE_HEIGHT, TILE_WIDTH + TILE_SIZE * 0, TILE_HEIGHT + TILE_SIZE * type,
00158         1 + TILE_SIZE * 0, 0 + TILE_SIZE * type, image);
00159 }
00160 
00169 static inline void UI_TabNodeDrawJunction (const char *image, int x, int y, mn_tab_type_t leftType, mn_tab_type_t rightType)
00170 {
00171     UI_DrawNormImageByName(x, y, TILE_WIDTH, TILE_HEIGHT, TILE_WIDTH + TILE_SIZE * (1 + rightType), TILE_HEIGHT + TILE_SIZE * leftType,
00172         0 + TILE_SIZE * (1 + rightType), 0 + TILE_SIZE * leftType, image);
00173 }
00174 
00175 static void UI_TabNodeDraw (uiNode_t *node)
00176 {
00177     mn_tab_type_t lastStatus = UI_TAB_NOTHING;
00178     uiNode_t* option;
00179     uiNode_t* overMouseOption = NULL;
00180     const char *ref;
00181     const char *font;
00182     int currentX;
00183     int allowedWidth;
00184     vec2_t pos;
00185 
00186     const char* image = UI_GetReferenceString(node, node->image);
00187     if (!image)
00188         image = "ui/tab";
00189 
00190     ref = UI_AbstractOptionGetCurrentValue(node);
00191     if (ref == NULL)
00192         return;
00193 
00194     font = UI_GetFontFromNode(node);
00195 
00196     if (node->state) {
00197         overMouseOption = UI_TabNodeTabAtPosition(node, mousePosX, mousePosY);
00198     }
00199 
00200     UI_GetNodeAbsPos(node, pos);
00201     currentX = pos[0];
00202     option = node->firstChild;
00203     assert(option->behaviour == ui_optionBehaviour);
00205     allowedWidth = node->size[0] - TILE_WIDTH * (EXTRADATA(node).count + 1);
00206 
00207     while (option) {
00208         int fontHeight;
00209         int fontWidth;
00210         int tabWidth;
00211         int textPos;
00212         const char *label;
00213         qboolean drawIcon = qfalse;
00214         mn_tab_type_t status = UI_TAB_NORMAL;
00215         assert(option->behaviour == ui_optionBehaviour);
00216 
00217         /* skip hidden options */
00218         if (option->invis) {
00219             option = option->next;
00220             continue;
00221         }
00222 
00223         /* Check the status of the current tab */
00224         if (!strcmp(OPTIONEXTRADATA(option).value, ref)) {
00225             status = UI_TAB_SELECTED;
00226         } else if (option->disabled || node->disabled) {
00227             status = UI_TAB_DISABLED;
00228         } else if (option == overMouseOption) {
00229             status = UI_TAB_HIGHLIGHTED;
00230         }
00231 
00232         /* Display */
00233         UI_TabNodeDrawJunction(image, currentX, pos[1], lastStatus, status);
00234         currentX += TILE_WIDTH;
00235 
00236         label = OPTIONEXTRADATA(option).label;
00237         if (label[0] == '_')
00238             label = _(label + 1);
00239 
00240         R_FontTextSize(font, label, 0, LONGLINES_PRETTYCHOP, &fontWidth, &fontHeight, NULL, NULL);
00241         tabWidth = fontWidth;
00242         if (OPTIONEXTRADATA(option).icon && OPTIONEXTRADATA(option).icon->size[0] < allowedWidth) {
00243             tabWidth += OPTIONEXTRADATA(option).icon->size[0];
00244             drawIcon = qtrue;
00245         }
00246         if (tabWidth > allowedWidth) {
00247             if (allowedWidth > 0)
00248                 tabWidth = allowedWidth;
00249             else
00250                 tabWidth = 0;
00251         }
00252 
00253         if (tabWidth > 0) {
00254             UI_TabNodeDrawPlain(image, currentX, pos[1], tabWidth, status);
00255         }
00256 
00257         textPos = currentX;
00258         if (drawIcon) {
00259             uiIconStatus_t iconStatus = ICON_STATUS_NORMAL;
00260             if (status == UI_TAB_DISABLED) {
00261                 iconStatus = ICON_STATUS_DISABLED;
00262             }
00263             UI_DrawIconInBox(OPTIONEXTRADATA(option).icon, iconStatus, currentX, pos[1], OPTIONEXTRADATA(option).icon->size[0], TILE_HEIGHT);
00264             textPos += OPTIONEXTRADATA(option).icon->size[0];
00265         }
00266 
00268         OPTIONEXTRADATA(option).truncated = tabWidth < fontWidth || tabWidth == 0;
00269         UI_DrawString(font, ALIGN_UL, textPos, pos[1] + ((node->size[1] - fontHeight) / 2),
00270             textPos, tabWidth + 1, 0, label, 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00271         currentX += tabWidth;
00272         allowedWidth -= tabWidth;
00273 
00274         /* Next */
00275         lastStatus = status;
00276         option = option->next;
00277     }
00278 
00279     /* Display last junction and end of header */
00280     UI_TabNodeDrawJunction(image, currentX, pos[1], lastStatus, UI_TAB_NOTHING);
00281     currentX += TILE_WIDTH;
00282     if (currentX < pos[0] + node->size[0])
00283         UI_TabNodeDrawPlain(image, currentX, pos[1], pos[0] + node->size[0] - currentX, UI_TAB_NOTHING);
00284 }
00285 
00292 static void UI_TabNodeDrawTooltip (uiNode_t *node, int x, int y)
00293 {
00294     uiNode_t *option;
00295     const int tooltipWidth = 250;
00296     const char *label;
00297 
00298     option = UI_TabNodeTabAtPosition(node, x, y);
00299     if (option == NULL)
00300         return;
00301 
00302     if (!OPTIONEXTRADATA(option).truncated)
00303         return;
00304 
00305     label = OPTIONEXTRADATA(option).label;
00306     if (label[0] == '_')
00307         label = _(label + 1);
00308 
00309     UI_DrawTooltip(label, x, y, tooltipWidth);
00310 }
00311 
00316 static void UI_TabNodeInit (uiNode_t *node)
00317 {
00318     const char *cvarName;
00319 
00320     /* no cvar given? */
00321     if (!(EXTRADATA(node).cvar))
00322         return;
00323 
00324     /* not a cvar? */
00325     if (strncmp((char *)(EXTRADATA(node).cvar), "*cvar:", 6) != 0) {
00326         /* normalize */
00327         Com_Printf("UI_TabNodeInit: node '%s' doesn't have a valid cvar assigned (\"%s\" read)\n", UI_GetPath(node), (char*) (EXTRADATA(node).cvar));
00328         EXTRADATA(node).cvar = NULL;
00329         return;
00330     }
00331 
00332     /* cvar do not exists? */
00333     cvarName = &((const char *)(EXTRADATA(node).cvar))[6];
00334     if (Cvar_FindVar(cvarName) == NULL) {
00335         /* search default value, if possible */
00336         uiNode_t* option = node->firstChild;
00337         assert(option->behaviour == ui_optionBehaviour);
00338         Cvar_ForceSet(cvarName, OPTIONEXTRADATA(option).value);
00339     }
00340 }
00341 
00342 void UI_RegisterTabNode (uiBehaviour_t *behaviour)
00343 {
00344     behaviour->name = "tab";
00345     behaviour->extends = "abstractoption";
00346     behaviour->draw = UI_TabNodeDraw;
00347     behaviour->drawTooltip = UI_TabNodeDrawTooltip;
00348     behaviour->leftClick = UI_TabNodeClick;
00349     behaviour->init = UI_TabNodeInit;
00350     behaviour->drawItselfChild = qtrue;
00351 }

Generated by  doxygen 1.6.2