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_internal.h"
00028 #include "../ui_font.h"
00029 #include "../ui_actions.h"
00030 #include "../ui_parse.h"
00031 #include "../ui_render.h"
00032 #include "ui_node_text2.h"
00033 #include "ui_node_abstractnode.h"
00034
00035 #include "../../client.h"
00036 #include "../../../shared/parse.h"
00037
00038 #define EXTRADATA_TYPE text2ExtraData_t
00039 #define EXTRADATA(node) UI_EXTRADATA(node, EXTRADATA_TYPE)
00040 #define EXTRADATACONST(node) UI_EXTRADATACONST(node, EXTRADATA_TYPE)
00041
00042 static void UI_TextUpdateCache(uiNode_t *node);
00043
00044 static void UI_TextNodeGenerateLineSplit (uiNode_t *node)
00045 {
00046 const char *data;
00047 int bufferSize = 1024;
00048 char *buffer = (char *)Mem_Alloc(bufferSize);
00049
00050 LIST_Delete(&EXTRADATA(node).lineSplit);
00051
00052 if (node->text != NULL)
00053 data = UI_GetReferenceString(node, node->text);
00054 else if (EXTRADATA(node).super.dataID != TEXT_NULL) {
00055 const uiSharedData_t *shared;
00056 shared = &ui_global.sharedData[EXTRADATA(node).super.dataID];
00057 switch (shared->type) {
00058 case UI_SHARED_TEXT:
00059 data = UI_GetText(EXTRADATA(node).super.dataID);
00060 break;
00061 case UI_SHARED_LINKEDLISTTEXT:
00062 return;
00063 default:
00064 return;
00065 }
00066 } else
00067 return;
00068
00069 if (data[0] == '_')
00070 data = _(data + 1);
00071
00072 while (data[0] != '\0') {
00073 const char *next = strchr(data, '\n');
00074 int lineSize;
00075 if (next == NULL)
00076 lineSize = strlen(data);
00077 else
00078 lineSize = next - data;
00079
00080 if (lineSize + 1 > bufferSize) {
00081 bufferSize = lineSize + 1;
00082 Mem_Free(buffer);
00083 buffer = (char *)Mem_Alloc(bufferSize);
00084 }
00085
00086 Q_strncpyz(buffer, data, lineSize + 1);
00087 LIST_AddString(&EXTRADATA(node).lineSplit, buffer);
00088
00089 if (next == NULL)
00090 break;
00091 data = next + 1;
00092 }
00093
00094 Mem_Free(buffer);
00095 }
00096
00097 static void UI_TextValidateCache (uiNode_t *node)
00098 {
00099 int v;
00100 if (EXTRADATA(node).super.dataID == TEXT_NULL || node->text != NULL)
00101 return;
00102
00103 v = UI_GetDataVersion(EXTRADATA(node).super.dataID);
00104 if (v != EXTRADATA(node).super.versionId) {
00105 UI_TextUpdateCache(node);
00106 }
00107 }
00108
00116 static int UI_TextNodeGetLine (const uiNode_t *node, int x, int y)
00117 {
00118 int lineHeight;
00119 int line;
00120 assert(UI_NodeInstanceOf(node, "text"));
00121
00122 lineHeight = EXTRADATACONST(node).super.lineHeight;
00123 if (lineHeight == 0) {
00124 const char *font = UI_GetFontFromNode(node);
00125 lineHeight = UI_FontGetHeight(font);
00126 }
00127
00128 UI_NodeAbsoluteToRelativePos(node, &x, &y);
00129 y -= node->padding;
00130
00131
00132 if (y < 0)
00133 return -1;
00134 line = (int) (y / lineHeight) + EXTRADATACONST(node).super.super.scrollY.viewPos;
00135
00136
00137 if (line >= EXTRADATACONST(node).super.super.scrollY.fullSize)
00138 return -1;
00139
00140 return line;
00141 }
00142
00143 static void UI_TextNodeMouseMove (uiNode_t *node, int x, int y)
00144 {
00145 EXTRADATA(node).super.lineUnderMouse = UI_TextNodeGetLine(node, x, y);
00146 }
00147
00156 static void UI_TextNodeDrawText (uiNode_t* node, const linkedList_t* list, qboolean noDraw)
00157 {
00158 char newFont[MAX_VAR];
00159 const char* oldFont = NULL;
00160 vec4_t colorHover;
00161 vec4_t colorSelectedHover;
00162 int fullSizeY;
00163 int x1;
00164 const char *font = UI_GetFontFromNode(node);
00165 vec2_t pos;
00166 int x, y, width;
00167 int viewSizeY;
00168
00169 UI_GetNodeAbsPos(node, pos);
00170
00171 if (UI_AbstractScrollableNodeIsSizeChange(node)) {
00172 int lineHeight = EXTRADATA(node).super.lineHeight;
00173 if (lineHeight == 0) {
00174 const char *font = UI_GetFontFromNode(node);
00175 lineHeight = UI_FontGetHeight(font);
00176 }
00177 viewSizeY = node->size[1] / lineHeight;
00178 } else {
00179 viewSizeY = EXTRADATA(node).super.super.scrollY.viewSize;
00180 }
00181
00182
00183 x = pos[0] + node->padding;
00184 y = pos[1] + node->padding;
00185 width = node->size[0] - node->padding - node->padding;
00186
00187
00188 VectorScale(node->color, 0.8, colorHover);
00189 colorHover[3] = node->color[3];
00190
00191
00192 VectorScale(node->selectedColor, 0.8, colorSelectedHover);
00193 colorSelectedHover[3] = node->selectedColor[3];
00194
00195
00196 switch (node->textalign % 3) {
00197 case 0:
00198 break;
00199 case 1:
00200 x += width / 2;
00201 break;
00202 case 2:
00203 x += width;
00204 break;
00205 }
00206
00207 R_Color(node->color);
00208
00209 fullSizeY = 0;
00210 while (list) {
00211 const char *cur = (const char*)list->data;
00212
00213
00214 x1 = x;
00215 if (oldFont) {
00216 font = oldFont;
00217 oldFont = NULL;
00218 }
00219
00220
00221 if (cur[0] == '^') {
00222 switch (toupper(cur[1])) {
00223 case 'B':
00224 Com_sprintf(newFont, sizeof(newFont), "%s_bold", font);
00225 oldFont = font;
00226 font = newFont;
00227 cur += 2;
00228 break;
00229 }
00230 }
00231
00232
00233 if (!cur) {
00234 fullSizeY++;
00235 } else {
00236 if (noDraw) {
00237 int lines = 0;
00238 R_FontTextSize (font, cur, width, EXTRADATA(node).super.longlines, NULL, NULL, &lines, NULL);
00239 fullSizeY += lines;
00240 } else
00241 UI_DrawString(font, node->textalign, x1, y, x, width, EXTRADATA(node).super.lineHeight, cur, viewSizeY, EXTRADATA(node).super.super.scrollY.viewPos, &fullSizeY, qtrue, EXTRADATA(node).super.longlines);
00242 }
00243
00244 list = list->next;
00245 }
00246
00247
00248 UI_AbstractScrollableNodeSetY(node, -1, viewSizeY, fullSizeY);
00249
00250 R_Color(NULL);
00251 }
00252
00253 static void UI_TextUpdateCache (uiNode_t *node)
00254 {
00255 const uiSharedData_t *shared;
00256
00257 UI_TextNodeGenerateLineSplit(node);
00258
00259 if (EXTRADATA(node).super.dataID == TEXT_NULL && node->text != NULL) {
00260 UI_TextNodeDrawText(node, EXTRADATA(node).lineSplit, qtrue);
00261 return;
00262 }
00263
00264 shared = &ui_global.sharedData[EXTRADATA(node).super.dataID];
00265
00266 if (shared->type == UI_SHARED_LINKEDLISTTEXT) {
00267 UI_TextNodeDrawText(node, shared->data.linkedListText, qtrue);
00268 } else {
00269 UI_TextNodeDrawText(node, EXTRADATA(node).lineSplit, qtrue);
00270 }
00271
00272 EXTRADATA(node).super.versionId = shared->versionId;
00273 }
00274
00278 static void UI_TextNodeDraw (uiNode_t *node)
00279 {
00280 const uiSharedData_t *shared;
00281
00282 UI_TextValidateCache(node);
00283
00284 if (EXTRADATA(node).super.dataID == TEXT_NULL && node->text != NULL) {
00285 UI_TextNodeDrawText(node, EXTRADATA(node).lineSplit, qfalse);
00286 return;
00287 }
00288
00289 shared = &ui_global.sharedData[EXTRADATA(node).super.dataID];
00290
00291 switch (shared->type) {
00292 case UI_SHARED_TEXT:
00293 UI_TextNodeDrawText(node, EXTRADATA(node).lineSplit, qfalse);
00294 break;
00295 case UI_SHARED_LINKEDLISTTEXT:
00296 UI_TextNodeDrawText(node, shared->data.linkedListText, qfalse);
00297 break;
00298 default:
00299 break;
00300 }
00301
00302 EXTRADATA(node).super.versionId = shared->versionId;
00303 }
00304
00309 static void UI_TextNodeClick (uiNode_t * node, int x, int y)
00310 {
00311 int line = UI_TextNodeGetLine(node, x, y);
00312
00313 if (line < 0 || line >= EXTRADATA(node).super.super.scrollY.fullSize)
00314 return;
00315
00316 UI_TextNodeSelectLine(node, line);
00317
00318 if (node->onClick)
00319 UI_ExecuteEventActions(node, node->onClick);
00320 }
00321
00326 static void UI_TextNodeRightClick (uiNode_t * node, int x, int y)
00327 {
00328 int line = UI_TextNodeGetLine(node, x, y);
00329
00330 if (line < 0 || line >= EXTRADATA(node).super.super.scrollY.fullSize)
00331 return;
00332
00333 UI_TextNodeSelectLine(node, line);
00334
00335 if (node->onRightClick)
00336 UI_ExecuteEventActions(node, node->onRightClick);
00337 }
00338
00339 static void UI_TextNodeMouseWheel (uiNode_t *node, qboolean down, int x, int y)
00340 {
00341 UI_AbstractScrollableNodeScrollY(node, (down ? 1 : -1));
00342 if (node->onWheelUp && !down)
00343 UI_ExecuteEventActions(node, node->onWheelUp);
00344 if (node->onWheelDown && down)
00345 UI_ExecuteEventActions(node, node->onWheelDown);
00346 if (node->onWheel)
00347 UI_ExecuteEventActions(node, node->onWheel);
00348 }
00349
00350 static void UI_TextNodeLoading (uiNode_t *node)
00351 {
00352 EXTRADATA(node).super.textLineSelected = -1;
00353 Vector4Set(node->selectedColor, 1.0, 1.0, 1.0, 1.0);
00354 Vector4Set(node->color, 1.0, 1.0, 1.0, 1.0);
00355 }
00356
00357 static void UI_TextNodeLoaded (uiNode_t *node)
00358 {
00359 int lineheight = EXTRADATA(node).super.lineHeight;
00360
00361
00362 if (lineheight == 0) {
00363
00364 const char *font = UI_GetFontFromNode(node);
00365 lineheight = UI_FontGetHeight(font);
00366 }
00367
00368
00369 if (EXTRADATA(node).super.super.scrollY.viewSize == 0) {
00370 if (node->size[1] != 0 && lineheight != 0) {
00371 EXTRADATA(node).super.super.scrollY.viewSize = node->size[1] / lineheight;
00372 } else {
00373 EXTRADATA(node).super.super.scrollY.viewSize = 1;
00374 Com_Printf("UI_TextNodeLoaded: node '%s' has no rows value\n", UI_GetPath(node));
00375 }
00376 }
00377
00378
00379 if (node->size[1] == 0) {
00380 node->size[1] = EXTRADATA(node).super.super.scrollY.viewSize * lineheight;
00381 }
00382
00383
00384 if (EXTRADATA(node).super.dataID >= UI_MAX_DATAID)
00385 Com_Error(ERR_DROP, "Error in node %s - max shared data id exceeded (num: %i, max: %i)", UI_GetPath(node), EXTRADATA(node).super.dataID, UI_MAX_DATAID);
00386
00387 #ifdef DEBUG
00388 if (EXTRADATA(node).super.super.scrollY.viewSize != (int)(node->size[1] / lineheight)) {
00389 Com_Printf("UI_TextNodeLoaded: rows value (%i) of node '%s' differs from size (%.0f) and format (%i) values\n",
00390 EXTRADATA(node).super.super.scrollY.viewSize, UI_GetPath(node), node->size[1], lineheight);
00391 }
00392 #endif
00393
00394 if (node->text == NULL && EXTRADATA(node).super.dataID == TEXT_NULL)
00395 Com_Printf("UI_TextNodeLoaded: 'textid' property of node '%s' is not set\n", UI_GetPath(node));
00396 }
00397
00398 static const value_t properties[] = {
00399 {NULL, V_NULL, 0, 0}
00400 };
00401
00402 void UI_RegisterText2Node (uiBehaviour_t *behaviour)
00403 {
00404 behaviour->name = "text2";
00405 behaviour->extends = "text";
00406 behaviour->draw = UI_TextNodeDraw;
00407 behaviour->leftClick = UI_TextNodeClick;
00408 behaviour->rightClick = UI_TextNodeRightClick;
00409 behaviour->mouseWheel = UI_TextNodeMouseWheel;
00410 behaviour->mouseMove = UI_TextNodeMouseMove;
00411 behaviour->loading = UI_TextNodeLoading;
00412 behaviour->loaded = UI_TextNodeLoaded;
00413 behaviour->properties = properties;
00414 behaviour->extraDataSize = sizeof(EXTRADATA_TYPE);
00415 }