1
2 /* Battle Tanks Game
3 * Copyright (C) 2006-2009 Battle Tanks team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 /*
21 * Additional rights can be granted beyond the GNU General Public License
22 * on the terms provided in the Exception. If you modify this file,
23 * you may extend this exception to your version of the file,
24 * but you are not obligated to do so. If you do not wish to provide this
25 * exception without modification, you must delete this exception statement
26 * from your version and license this file solely under the GPL without exception.
27 */
28
29 #include <ctype.h>
30 #include "tooltip.h"
31
32 #include "mrt/logger.h"
33 #include "menu/box.h"
34 #include "resource_manager.h"
35 #include "config.h"
36 #include "sdlx/font.h"
37 #include "mrt/utf8_utils.h"
38 #include "i18n.h"
39
40 #include <math.h>
41 #include <assert.h>
42 #include <deque>
43
Tooltip(const std::string & area,const std::string & message,const bool use_background,int w)44 Tooltip::Tooltip(const std::string &area, const std::string &message, const bool use_background, int w) :
45 area(area), message(message) {
46 init(I18n->get(area, message), use_background, w);
47 }
48
Tooltip(const std::string & area,const std::string & message,const std::string & text,const bool use_background,int w)49 Tooltip::Tooltip(const std::string &area, const std::string &message, const std::string &text, const bool use_background, int w) :
50 area(area), message(message) {
51 init(text, use_background, w);
52 }
53
init(const std::string & _text,const bool use_background,int width)54 void Tooltip::init(const std::string &_text, const bool use_background, int width) {
55 _use_background = use_background;
56 std::string text;
57 bool space = true;
58 size_t i;
59 for(i = 0; i < _text.size(); ++i) {
60 const char c = _text[i];
61 const bool c_space = c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == '\f';
62 if (c == '\\' && i + 1 < _text.size() && _text[i + 1] == 'n') {
63 //\n hack :)
64 ++i;
65 if (space) {
66 text += "\n ";
67 } else {
68 text += " \n ";
69 space = true;
70 }
71 continue;
72 }
73
74 //LOG_DEBUG(("%d '%c': %s %s", c, c, space?"true":"false", c_space?"true":"false"));
75 if (space) {
76 if (c_space)
77 continue;
78 space = false;
79 text += c;
80 } else {
81 if (c_space) {
82 space = true;
83 text += ' ';
84 } else
85 text += c;
86 }
87 }
88 if (text.empty())
89 throw_ex(("tooltip with empty text is not allowed"));
90 //LOG_DEBUG(("trimmed string : '%s'", text.c_str()));
91
92 GET_CONFIG_VALUE("engine.tooltip-speed", float, td, 20);
93 _time = ((float)mrt::utf8_length(text)) / td;
94
95 std::vector<std::string> words;
96 mrt::split(words, text, " ");
97 for(size_t i = 0; i < words.size(); ++i) {
98 mrt::replace(words[i], "\\s", " ");
99 }
100 std::vector<int> lens;
101 lens.resize(words.size());
102
103 const sdlx::Font * font = ResourceManager->loadFont("small", false);
104 int line_h = font->get_height();
105
106 int total = 0, nl_n = 0;
107 for(size_t i = 0; i < words.size(); ++i) {
108 const std::string &word = words[i];
109 if (word == "\n") {
110 nl_n += line_h;
111 continue;
112 }
113
114 lens[i] = font->render(NULL, 0, 0, word + " ");
115 total += lens[i] * line_h;
116 }
117 bool hard;
118 if (width == 0) {
119 width = (int)(sqrt(total * 2 / 3.0f + nl_n * nl_n / 4.0f) + 0.5f);
120 hard = false;
121 } else {
122 hard = !_use_background;
123 }
124
125 std::vector<std::string> lines;
126
127 int line_w = 0, real_width = 1;
128 std::string line;
129 for(size_t i = 0; i < words.size(); ++i) {
130 const std::string &word = words[i];
131 const int len = lens[i];
132 line_w += len;
133
134 bool last = i + 1 == words.size();
135 bool nl = line_w >= width || word == "\n" || last;
136
137 if (nl) {
138 if (hard && !line.empty() && !last) { //hard edge
139 line_w -= len;
140 if (line_w > real_width)
141 real_width = line_w;
142 lines.push_back(line);
143 line = word + " ";
144 line_w = len;
145 } else {
146 if (line_w > real_width)
147 real_width = line_w;
148 lines.push_back(line + word);
149 line.clear();
150 line_w = 0;
151 }
152 } else {
153 line += word + " ";
154 }
155 }
156
157 //LOG_DEBUG(("line width: %d, lines: %u", width, lines.size()));
158 int xp = 0, yp = 0;
159 int height = line_h * lines.size();
160 if (_use_background) {
161 const sdlx::Surface *bg = ResourceManager->load_surface("menu/background_box.png");
162 int mx = bg->get_width() / 3, my = bg->get_height() / 3;
163 _background.init("menu/background_box.png", real_width + mx * 2, height + my * 2);
164 _surface.create_rgb(_background.w, _background.h, 32, SDL_SRCALPHA);
165 xp = (_background.w - real_width) / 2;
166 yp = (_background.h - height) / 2;
167 } else {
168 _surface.create_rgb(real_width, height, 32, SDL_SRCALPHA);
169 }
170 _surface.display_format_alpha();
171
172 for(size_t i = 0; i < lines.size(); ++i) {
173 font->render(_surface, xp, yp + i * line_h, lines[i]);
174 }
175 }
176
render(sdlx::Surface & surface,const int x,const int y) const177 void Tooltip::render(sdlx::Surface &surface, const int x, const int y) const {
178 if (_use_background)
179 _background.render(surface, x, y);
180 surface.blit(_surface, x, y);
181 }
182
get_size(int & w,int & h) const183 void Tooltip::get_size(int &w, int &h) const {
184 w = _surface.get_width();
185 h = _surface.get_height();
186 }
187