Splitted supertux/textscroller.?pp
[supertux.git] / src / supertux / info_box_line.cpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 #include "supertux/info_box_line.hpp"
18
19 #include "supertux/textscroller.hpp"
20 #include "supertux/resources.hpp"
21 #include "video/drawing_context.hpp"
22 #include "video/font.hpp"
23 #include "video/surface.hpp"
24
25 static const float ITEMS_SPACE = 4;
26
27 namespace {
28
29 Font* get_font_by_format_char(char format_char) {
30   switch(format_char)
31   {
32     case ' ':
33       return small_font;
34       break;
35     case '-':
36       return big_font;
37       break;
38     case '\t':
39     case '*':
40     case '#':
41     case '!':
42       return normal_font;
43     break;
44     default:
45       return normal_font;
46       log_warning << "Unknown format_char: '" << format_char << "'" << std::endl;
47       break;
48   }
49 }
50
51 Color get_color_by_format_char(char format_char) {
52   switch(format_char)
53   {
54     case ' ':
55       return TextScroller::small_color;
56       break;
57     case '-':
58       return TextScroller::heading_color;
59       break;
60     case '*':
61       return TextScroller::reference_color;
62     case '\t':
63     case '#':
64     case '!':
65       return TextScroller::normal_color;
66     break;
67     default:
68       return Color(0,0,0);
69       log_warning << "Unknown format_char: '" << format_char << "'" << std::endl;
70       break;
71   }
72 }
73
74 InfoBoxLine::LineType get_linetype_by_format_char(char format_char) {
75   switch(format_char)
76   {
77     case ' ':
78       return InfoBoxLine::SMALL;
79       break;
80     case '\t':
81       return InfoBoxLine::NORMAL;
82       break;
83     case '-':
84       return InfoBoxLine::HEADING;
85       break;
86     case '*':
87       return InfoBoxLine::REFERENCE;
88       break;
89     case '#':
90       return InfoBoxLine::NORMAL_LEFT;
91       break;
92     case '!':
93       return InfoBoxLine::IMAGE;
94       break;
95     default:
96       return InfoBoxLine::SMALL;
97       log_warning << "Unknown format_char: '" << format_char << "'" << std::endl;
98       break;
99   }
100 }
101
102 } // namespace
103
104 InfoBoxLine::InfoBoxLine(char format_char, const std::string& text) : 
105   lineType(NORMAL),
106   font(normal_font), 
107   color(),
108   text(text), 
109   image(0)
110 {
111   font = get_font_by_format_char(format_char);
112   lineType = get_linetype_by_format_char(format_char);
113   color = get_color_by_format_char(format_char);
114   if (lineType == IMAGE) image = new Surface(text);
115 }
116
117 InfoBoxLine::~InfoBoxLine()
118 {
119   delete image;
120 }
121
122 const std::vector<InfoBoxLine*>
123 InfoBoxLine::split(const std::string& text, float width)
124 {
125   std::vector<InfoBoxLine*> lines;
126
127   std::string::size_type i = 0;
128   std::string::size_type l;
129   char format_char = '#';
130   while(i < text.size()) {
131     // take care of empty lines - represent them as blank lines of normal text
132     if (text[i] == '\n') {
133       lines.push_back(new InfoBoxLine('\t', ""));
134       i++;
135       continue;
136     }
137
138     // extract the format_char
139     format_char = text[i];
140     i++;
141     if (i >= text.size()) break;
142
143     // extract one line
144     l = text.find("\n", i);
145     if (l == std::string::npos) l=text.size();
146     std::string s = text.substr(i, l-i);
147     i = l+1;
148
149     // if we are dealing with an image, just store the line
150     if (format_char == '!') {
151       lines.push_back(new InfoBoxLine(format_char, s));
152       continue;
153     }
154
155     // append wrapped parts of line into list
156     std::string overflow;
157     do {
158       Font* font = get_font_by_format_char(format_char);
159       std::string s2 = s;
160       if (font) s2 = font->wrap_to_width(s2, width, &overflow);
161       lines.push_back(new InfoBoxLine(format_char, s2));
162       s = overflow;
163     } while (s.length() > 0);
164   }
165
166   return lines;
167 }
168
169 void
170 InfoBoxLine::draw(DrawingContext& context, const Rect& bbox, int layer)
171 {
172   Vector position = bbox.p1;
173   switch (lineType) {
174     case IMAGE:
175       context.draw_surface(image, Vector( (bbox.p1.x + bbox.p2.x - image->get_width()) / 2, position.y), layer);
176       break;
177     case NORMAL_LEFT:
178       context.draw_text(font, text, Vector(position.x, position.y), ALIGN_LEFT, layer, color);
179       break;
180     default:
181       context.draw_text(font, text, Vector((bbox.p1.x + bbox.p2.x) / 2, position.y), ALIGN_CENTER, layer, color);
182       break;
183   }
184 }
185
186 float
187 InfoBoxLine::get_height()
188 {
189   switch (lineType) {
190     case IMAGE:
191       return image->get_height() + ITEMS_SPACE;
192     case NORMAL_LEFT:
193       return font->get_height() + ITEMS_SPACE;
194     default:
195       return font->get_height() + ITEMS_SPACE;
196   }
197 }
198
199 /* EOF */