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_icon.h"
00033 #include "ui_node_text.h"
00034 #include "ui_node_messagelist.h"
00035 #include "ui_node_abstractnode.h"
00036
00037 #include "../../client.h"
00038 #include "../../campaign/cp_messages.h"
00039 #include "../../../shared/parse.h"
00040
00041 #define EXTRADATA(node) UI_EXTRADATA(node, abstractScrollableExtraData_t)
00042 #define EXTRADATACONST(node) UI_EXTRADATACONST(node, abstractScrollableExtraData_t)
00043
00045 static const int LINEHEIGHT = 20;
00046
00047 static const int DATETIME_COLUUI_SIZE = 180;
00048
00052 static int UI_MessageGetLines (const uiNode_t *node, message_t *message, const char *fontID, int width)
00053 {
00054 const int column1 = DATETIME_COLUUI_SIZE;
00055 const int column2 = width - DATETIME_COLUUI_SIZE - node->padding;
00056 int lines1;
00057 int lines2;
00058 R_FontTextSize(fontID, message->timestamp, column1, LONGLINES_WRAP, NULL, NULL, &lines1, NULL);
00059 R_FontTextSize(fontID, message->text, column2, LONGLINES_WRAP, NULL, NULL, &lines2, NULL);
00060 return max(lines1, lines2);
00061 }
00062
00063 static char *lastDate;
00064
00069 static uiIcon_t *UI_MessageGetIcon (const message_t *message)
00070 {
00071 const char* iconName;
00072
00073 switch (message->type) {
00074 case MSG_DEBUG:
00075 iconName = "message_debug";
00076 break;
00077 case MSG_INFO:
00078 iconName = "message_info";
00079 break;
00080 case MSG_STANDARD:
00081 iconName = "message_info";
00082 break;
00083 case MSG_RESEARCH_PROPOSAL:
00084 iconName = "message_research";
00085 break;
00086 case MSG_RESEARCH_HALTED:
00087 iconName = "message_research";
00088 break;
00089 case MSG_RESEARCH_FINISHED:
00090 iconName = "message_research";
00091 break;
00092 case MSG_CONSTRUCTION:
00093 iconName = "message_construction";
00094 break;
00095 case MSG_UFOSPOTTED:
00096 iconName = "message_ufo";
00097 break;
00098 case MSG_TERRORSITE:
00099 iconName = "message_ufo";
00100 break;
00101 case MSG_BASEATTACK:
00102 iconName = "message_ufo";
00103 break;
00104 case MSG_TRANSFERFINISHED:
00105 iconName = "message_transfer";
00106 break;
00107 case MSG_PROMOTION:
00108 iconName = "message_promotion";
00109 break;
00110 case MSG_PRODUCTION:
00111 iconName = "message_production";
00112 break;
00113 case MSG_NEWS:
00114 iconName = "message_info";
00115 break;
00116 case MSG_DEATH:
00117 iconName = "message_death";
00118 break;
00119 case MSG_CRASHSITE:
00120 iconName = "message_ufo";
00121 break;
00122 case MSG_EVENT:
00123 iconName = "message_info";
00124 break;
00125 default:
00126 iconName = "message_info";
00127 break;
00128 }
00129
00130 return UI_GetIconByName(iconName);
00131 }
00132
00133 static void UI_MessageDraw (const uiNode_t *node, message_t *message, const char *fontID, int x, int y, int width, int *screenLines)
00134 {
00135 const int column1 = DATETIME_COLUUI_SIZE;
00136 const int column2 = width - DATETIME_COLUUI_SIZE - node->padding;
00137 int lines1 = *screenLines;
00138 int lines2 = *screenLines;
00139
00140
00141 if (lines1 < 0)
00142 lines1 = 0;
00143
00144
00145 if (lastDate == NULL || strcmp(lastDate, message->timestamp) != 0)
00146 UI_DrawString(fontID, ALIGN_UL, x, y, x, column1, LINEHEIGHT, message->timestamp, EXTRADATACONST(node).scrollY.viewSize, 0, &lines1, qtrue, LONGLINES_WRAP);
00147
00148 x += DATETIME_COLUUI_SIZE + node->padding;
00149
00150
00151 if (lines2 >= 0) {
00152 const uiIcon_t *icon;
00153 icon = UI_MessageGetIcon(message);
00154 UI_DrawIconInBox(icon, ICON_STATUS_NORMAL, x - 25, y + LINEHEIGHT * lines2 - 1, 19, 19);
00155 }
00156
00157
00158 UI_DrawString(fontID, ALIGN_UL, x, y, x, column2, LINEHEIGHT, message->text, EXTRADATACONST(node).scrollY.viewSize, 0, &lines2, qtrue, LONGLINES_WRAP);
00159 *screenLines = max(lines1, lines2);
00160 lastDate = message->timestamp;
00161 }
00162
00167 static void UI_MessageListNodeDraw (uiNode_t *node)
00168 {
00169 message_t *message;
00170 int screenLines;
00171 const char *font = UI_GetFontFromNode(node);
00172 vec2_t pos;
00173 int x, y, width;
00174 int defaultHeight;
00175 int lineNumber = 0;
00176 int posY;
00177
00178
00179 #ifdef AUTOSCROLL
00180 qboolean autoscroll;
00181 #endif
00182 UI_GetNodeAbsPos(node, pos);
00183
00184 defaultHeight = LINEHEIGHT;
00185
00186 #ifdef AUTOSCROLL
00187 autoscroll = (EXTRADATA(node).scrollY.viewPos + EXTRADATA(node).scrollY.viewSize == EXTRADATA(node).scrollY.fullSize)
00188 || (EXTRADATA(node).scrollY.fullSize < EXTRADATA(node).scrollY.viewSize);
00189 #endif
00190
00191
00192 x = pos[0] + node->padding;
00193 y = pos[1] + node->padding;
00194 width = node->size[0] - node->padding - node->padding;
00195
00196
00197 if (UI_AbstractScrollableNodeIsSizeChange(node)) {
00198
00199 message = cp_messageStack;
00200 while (message) {
00201 message->lineUsed = UI_MessageGetLines(node, message, font, width);
00202 lineNumber += message->lineUsed;
00203 message = message->next;
00204 }
00205 } else {
00206
00207 message = cp_messageStack;
00208 while (message) {
00209 if (message->lineUsed == 0)
00210 message->lineUsed = UI_MessageGetLines(node, message, font, width);
00211 lineNumber += message->lineUsed;
00212 message = message->next;
00213 }
00214 }
00215
00216
00217 #ifdef AUTOSCROLL
00218 if (autoscroll)
00219 UI_AbstractScrollableNodeSetY(node, lineNumber, node->size[1] / defaultHeight, lineNumber);
00220 else
00221 UI_AbstractScrollableNodeSetY(node, -1, node->size[1] / defaultHeight, lineNumber);
00222 #else
00223 UI_AbstractScrollableNodeSetY(node, -1, node->size[1] / defaultHeight, lineNumber);
00224 #endif
00225
00226
00227 message = cp_messageStack;
00228 posY = EXTRADATA(node).scrollY.viewPos;
00229 while (message && posY > 0) {
00230 posY -= message->lineUsed;
00231 if (posY < 0)
00232 break;
00233 message = message->next;
00234 }
00235
00236
00238 lastDate = NULL;
00239 screenLines = posY;
00240 while (message) {
00241 UI_MessageDraw(node, message, font, x, y, width, &screenLines);
00242 if (screenLines >= EXTRADATA(node).scrollY.viewSize)
00243 break;
00244 message = message->next;
00245 }
00246 }
00247
00248 static void UI_MessageListNodeMouseWheel (uiNode_t *node, qboolean down, int x, int y)
00249 {
00250 UI_AbstractScrollableNodeScrollY(node, (down ? 1 : -1));
00251 if (node->onWheelUp && !down)
00252 UI_ExecuteEventActions(node, node->onWheelUp);
00253 if (node->onWheelDown && down)
00254 UI_ExecuteEventActions(node, node->onWheelDown);
00255 if (node->onWheel)
00256 UI_ExecuteEventActions(node, node->onWheel);
00257 }
00258
00259 #ifdef DEBUG
00260 static void UI_MessageDebugUseAllIcons_f (void)
00261 {
00262 message_t *message;
00263 int i = 0;
00264 message = cp_messageStack;
00265 while (message) {
00266 message->type = i % MSG_MAX;
00267 message = message->next;
00268 i++;
00269 }
00270
00271 }
00272 #endif
00273
00274 void UI_RegisterMessageListNode (uiBehaviour_t *behaviour)
00275 {
00276 behaviour->name = "messagelist";
00277 behaviour->extends = "abstractscrollable";
00278 behaviour->draw = UI_MessageListNodeDraw;
00279 behaviour->mouseWheel = UI_MessageListNodeMouseWheel;
00280 #ifdef DEBUG
00281 Cmd_AddCommand("debug_mn_message_useallicons", UI_MessageDebugUseAllIcons_f, "Update message to use all icons");
00282 #endif
00283 }