00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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"
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
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
00085 for (option = node->firstChild; option; option = option->next) {
00086 int tabWidth;
00087 const char *label;
00088 assert(option->behaviour == ui_optionBehaviour);
00089
00090
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
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
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
00218 if (option->invis) {
00219 option = option->next;
00220 continue;
00221 }
00222
00223
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
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
00275 lastStatus = status;
00276 option = option->next;
00277 }
00278
00279
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
00321 if (!(EXTRADATA(node).cvar))
00322 return;
00323
00324
00325 if (strncmp((char *)(EXTRADATA(node).cvar), "*cvar:", 6) != 0) {
00326
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
00333 cvarName = &((const char *)(EXTRADATA(node).cvar))[6];
00334 if (Cvar_FindVar(cvarName) == NULL) {
00335
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 }