6a9123a9bd9dd7a8d38b2ac6ecfcbef96f4369c7
[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 FontPtr get_font_by_format_char(char format_char) {
30   switch(format_char)
31   {
32     case ' ':
33       return Resources::small_font;
34       break;
35     case '-':
36       return Resources::big_font;
37       break;
38     case '\t':
39     case '*':
40     case '#':
41     case '!':
42       return Resources::normal_font;
43     break;
44     default:
45       return Resources::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(Resources::normal_font), 
107   color(),
108   text(text), 
109   image()
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) 
115   {
116     image = Surface::create(text);
117   }
118 }
119
120 InfoBoxLine::~InfoBoxLine()
121 {
122 }
123
124 const std::vector<InfoBoxLine*>
125 InfoBoxLine::split(const std::string& text, float width)
126 {
127   std::vector<InfoBoxLine*> lines;
128
129   std::string::size_type i = 0;
130   std::string::size_type l;
131   char format_char = '#';
132   while(i < text.size()) {
133     // take care of empty lines - represent them as blank lines of normal text
134     if (text[i] == '\n') {
135       lines.push_back(new InfoBoxLine('\t', ""));
136       i++;
137       continue;
138     }
139
140     // extract the format_char
141     format_char = text[i];
142     i++;
143     if (i >= text.size()) break;
144
145     // extract one line
146     l = text.find("\n", i);
147     if (l == std::string::npos) l=text.size();
148     std::string s = text.substr(i, l-i);
149     i = l+1;
150
151     // if we are dealing with an image, just store the line
152     if (format_char == '!') {
153       lines.push_back(new InfoBoxLine(format_char, s));
154       continue;
155     }
156
157     // append wrapped parts of line into list
158     std::string overflow;
159     do {
160       FontPtr font = get_font_by_format_char(format_char);
161       std::string s2 = s;
162       if (font) s2 = font->wrap_to_width(s2, width, &overflow);
163       lines.push_back(new InfoBoxLine(format_char, s2));
164       s = overflow;
165     } while (s.length() > 0);
166   }
167
168   return lines;
169 }
170
171 void
172 InfoBoxLine::draw(DrawingContext& context, const Rectf& bbox, int layer)
173 {
174   Vector position = bbox.p1;
175   switch (lineType) {
176     case IMAGE:
177       context.draw_surface(image, Vector( (bbox.p1.x + bbox.p2.x - image->get_width()) / 2, position.y), layer);
178       break;
179     case NORMAL_LEFT:
180       context.draw_text(font, text, Vector(position.x, position.y), ALIGN_LEFT, layer, color);
181       break;
182     default:
183       context.draw_text(font, text, Vector((bbox.p1.x + bbox.p2.x) / 2, position.y), ALIGN_CENTER, layer, color);
184       break;
185   }
186 }
187
188 float
189 InfoBoxLine::get_height()
190 {
191   switch (lineType) {
192     case IMAGE:
193       return image->get_height() + ITEMS_SPACE;
194     case NORMAL_LEFT:
195       return font->get_height() + ITEMS_SPACE;
196     default:
197       return font->get_height() + ITEMS_SPACE;
198   }
199 }
200
201 /* EOF */