ui_node_messagelist.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_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     /* also display the first date on wraped message we only see the end */
00141     if (lines1 < 0)
00142         lines1 = 0;
00143 
00144     /* display the date */
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     /* identify the begin of a message with a mark */
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     /* draw the message */
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 /* #define AUTOSCROLL */        
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     /* text box */
00192     x = pos[0] + node->padding;
00193     y = pos[1] + node->padding;
00194     width = node->size[0] - node->padding - node->padding;
00195 
00196     /* update message cache */
00197     if (UI_AbstractScrollableNodeIsSizeChange(node)) {
00198         /* recompute all line size */
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         /* only check unvalidated messages */
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     /* update scroll status */
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     /* found the first message we must display */
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     /* draw */
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 }

Generated by  doxygen 1.6.2