/src/MenuLog.cpp
C++ | 293 lines | 175 code | 64 blank | 54 comment | 32 complexity | 863dc4bfe93841342e0288db9af62eb9 MD5 | raw file
Possible License(s): GPL-3.0
1/* 2Copyright 2011 Clint Bellanger 3 4This file is part of FLARE. 5 6FLARE is free software: you can redistribute it and/or modify it under the terms 7of the GNU General Public License as published by the Free Software Foundation, 8either version 3 of the License, or (at your option) any later version. 9 10FLARE is distributed in the hope that it will be useful, but WITHOUT ANY 11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 12PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 14You should have received a copy of the GNU General Public License along with 15FLARE. If not, see http://www.gnu.org/licenses/ 16*/ 17 18/** 19 * class MenuLog 20 */ 21 22#include "MenuLog.h" 23#include "SharedResources.h" 24#include "WidgetLabel.h" 25 26using namespace std; 27 28 29MenuLog::MenuLog() { 30 31 visible = false; 32 33 for (int i=0; i<LOG_TYPE_COUNT; i++) { 34 log_count[i] = 0; 35 for (int j=0; j<MAX_LOG_MESSAGES; j++) { 36 msg_buffer[i][j] = NULL; 37 } 38 } 39 active_log = 0; 40 41 tab_labels[LOG_TYPE_MESSAGES] = msg->get("Messages"); 42 tab_labels[LOG_TYPE_QUESTS] = msg->get("Quests"); 43 tab_labels[LOG_TYPE_STATISTICS] = msg->get("Statistics"); 44 45 // TODO: allow menu size to be configurable 46 menu_area.x = 0; 47 menu_area.y = (VIEW_H - 416)/2; 48 menu_area.w = 320; 49 menu_area.h = 416; 50 51 list_area.x = menu_area.x + 40; 52 list_area.y = menu_area.y + 56; 53 list_area.w = 224; 54 list_area.h = 328; 55 56 tabs_area.x = menu_area.x + 32; 57 tabs_area.y = menu_area.y + 30; 58 tabs_area.w = 240; 59 tabs_area.h = 20; 60 61 tab_padding.y = 4; 62 tab_padding.x = 6; 63 paragraph_spacing = font->getLineHeight()/2; 64 65 for (int i=0; i<LOG_TYPE_COUNT; i++) { 66 tab_rect[i].y = tabs_area.y; 67 tab_rect[i].h = tabs_area.h; 68 69 if (i==0) tab_rect[i].x = tabs_area.x; 70 else tab_rect[i].x = tab_rect[i-1].x + tab_rect[i-1].w; 71 72 tab_rect[i].w = font->calc_width(tab_labels[i]) + tab_padding.x + tab_padding.x; 73 74 } 75 76 loadGraphics(); 77 78 closeButton = new WidgetButton(mods->locate("images/menus/buttons/button_x.png")); 79 closeButton->pos.x = 294; 80 closeButton->pos.y = (VIEW_H - 480)/2 + 34; 81 82} 83 84void MenuLog::loadGraphics() { 85 86 background = IMG_Load(mods->locate("images/menus/log.png").c_str()); 87 tab_active = IMG_Load(mods->locate("images/menus/tab_active.png").c_str()); 88 tab_inactive = IMG_Load(mods->locate("images/menus/tab_inactive.png").c_str()); 89 90 91 if(!background || !tab_active || !tab_inactive) { 92 fprintf(stderr, "Couldn't load image: %s\n", IMG_GetError()); 93 SDL_Quit(); 94 } 95 96 // optimize 97 SDL_Surface *cleanup = background; 98 background = SDL_DisplayFormatAlpha(background); 99 SDL_FreeSurface(cleanup); 100 101 cleanup = tab_active; 102 tab_active = SDL_DisplayFormatAlpha(tab_active); 103 SDL_FreeSurface(cleanup); 104 105 cleanup = tab_inactive; 106 tab_inactive = SDL_DisplayFormatAlpha(tab_inactive); 107 SDL_FreeSurface(cleanup); 108} 109 110/** 111 * Perform one frame of logic 112 */ 113void MenuLog::logic() { 114 if (!visible) return; 115 116 if (closeButton->checkClick()) { 117 visible = false; 118 } 119} 120 121/** 122 * Render graphics for this frame when the menu is open 123 */ 124void MenuLog::render() { 125 126 if (!visible) return; 127 128 SDL_Rect src; 129 130 // background 131 src.x = 0; 132 src.y = 0; 133 src.w = menu_area.w; 134 src.h = menu_area.h; 135 SDL_BlitSurface(background, &src, screen, &menu_area); 136 137 // close button 138 closeButton->render(); 139 140 // text overlay 141 WidgetLabel label; 142 label.set(menu_area.x+160, menu_area.y+8, JUSTIFY_CENTER, VALIGN_TOP, msg->get("Log"), FONT_WHITE); 143 label.render(); 144 145 // display tabs 146 for (int i=0; i<LOG_TYPE_COUNT; i++) { 147 renderTab(i); 148 } 149 150 // display latest log messages 151 152 int display_number = 0; 153 int total_size = 0; 154 155 // first calculate how many entire messages can fit in the log view 156 for (int i=log_count[active_log]-1; i>=0; i--) { 157 total_size += msg_buffer[active_log][i]->h + paragraph_spacing; 158 if (total_size < list_area.h) display_number++; 159 else break; 160 } 161 162 // now display these messages 163 SDL_Rect dest; 164 dest.x = list_area.x; 165 dest.y = list_area.y; 166 167 for (int i=log_count[active_log]-display_number; i<log_count[active_log]; i++) { 168 169 SDL_BlitSurface(msg_buffer[active_log][i], NULL, screen, &dest); 170 dest.y += msg_buffer[active_log][i]->h + paragraph_spacing; 171 } 172} 173 174/** 175 * Display the specified tab 176 * Render the font and tab background 177 * The active tab will look different 178 */ 179void MenuLog::renderTab(int log_type) { 180 int i = log_type; 181 182 // draw tab background 183 SDL_Rect src; 184 SDL_Rect dest; 185 src.x = src.y = 0; 186 dest.x = tab_rect[i].x; 187 dest.y = tab_rect[i].y; 188 src.w = tab_rect[i].w; 189 src.h = tab_rect[i].h; 190 191 if (i == active_log) 192 SDL_BlitSurface(tab_active, &src, screen, &dest); 193 else 194 SDL_BlitSurface(tab_inactive, &src, screen, &dest); 195 196 // draw tab right edge 197 src.x = 128 - tab_padding.x; 198 src.w = tab_padding.x; 199 dest.x = tab_rect[i].x + tab_rect[i].w - tab_padding.x; 200 201 if (i == active_log) 202 SDL_BlitSurface(tab_active, &src, screen, &dest); 203 else 204 SDL_BlitSurface(tab_inactive, &src, screen, &dest); 205 206 207 // set tab label text color 208 int tab_label_color; 209 if (i == active_log) tab_label_color = FONT_WHITE; 210 else tab_label_color = FONT_GREY; 211 212 WidgetLabel label; 213 label.set(tab_rect[i].x + tab_padding.x, tab_rect[i].y + tab_padding.y, JUSTIFY_LEFT, VALIGN_TOP, tab_labels[i], tab_label_color); 214 label.render(); 215} 216 217/** 218 * Add a new message to the log 219 */ 220void MenuLog::add(const string& s, int log_type) { 221 222 if (log_count[log_type] == MAX_LOG_MESSAGES) { 223 remove(0, log_type); 224 } 225 226 // add new message 227 log_msg[log_type][log_count[log_type]] = s; 228 229 // render the log entry and store it in a buffer 230 Point size = font->calc_size(s, list_area.w); 231 msg_buffer[log_type][log_count[log_type]] = createSurface(size.x, size.y); 232 font->renderShadowed(s, 0, 0, JUSTIFY_LEFT, msg_buffer[log_type][log_count[log_type]], list_area.w, FONT_WHITE); 233 234 log_count[log_type]++; 235} 236 237/** 238 * Remove log message with the given id 239 */ 240void MenuLog::remove(int msg_index, int log_type) { 241 242 SDL_FreeSurface(msg_buffer[log_type][msg_index]); 243 msg_buffer[log_type][msg_index] = NULL; 244 245 for (int i=msg_index; i<MAX_LOG_MESSAGES-1; i++) { 246 log_msg[log_type][i] = log_msg[log_type][i+1]; 247 msg_buffer[log_type][i] = msg_buffer[log_type][i+1]; 248 } 249 250 log_count[log_type]--; 251} 252 253/** 254 * Called by MenuManager 255 * The tab area was clicked. Change the active tab 256 */ 257void MenuLog::clickTab(Point mouse) { 258 for (int i=0; i<LOG_TYPE_COUNT; i++) { 259 if(isWithin(tab_rect[i], mouse)) { 260 active_log = i; 261 return; 262 } 263 } 264} 265 266void MenuLog::clear(int log_type) { 267 log_count[log_type] = 0; 268 for (int i=0; i<MAX_LOG_MESSAGES; i++) { 269 SDL_FreeSurface(msg_buffer[log_type][i]); 270 msg_buffer[log_type][i] = NULL; 271 } 272} 273 274void MenuLog::clear() { 275 for (int i=0; i<LOG_TYPE_COUNT; i++) { 276 clear(i); 277 } 278} 279 280MenuLog::~MenuLog() { 281 282 for (int i=0; i<LOG_TYPE_COUNT; i++) { 283 log_count[i] = 0; 284 for (int j=0; j<MAX_LOG_MESSAGES; j++) { 285 SDL_FreeSurface(msg_buffer[i][j]); 286 } 287 } 288 289 SDL_FreeSurface(background); 290 SDL_FreeSurface(tab_active); 291 SDL_FreeSurface(tab_inactive); 292 delete closeButton; 293}