00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "gui/widgets/control.hpp"
00016
00017 #include "font.hpp"
00018 #include "foreach.hpp"
00019 #include "gui/widgets/helper.hpp"
00020 #include "gui/widgets/window.hpp"
00021 #include "log.hpp"
00022 #include "marked-up_text.hpp"
00023 #include "util.hpp"
00024 #include "sdl_utils.hpp"
00025
00026 #define DBG_G LOG_STREAM_INDENT(debug, gui)
00027 #define LOG_G LOG_STREAM_INDENT(info, gui)
00028 #define WRN_G LOG_STREAM_INDENT(warn, gui)
00029 #define ERR_G LOG_STREAM_INDENT(err, gui)
00030
00031 #define DBG_G_D LOG_STREAM_INDENT(debug, gui_draw)
00032 #define LOG_G_D LOG_STREAM_INDENT(info, gui_draw)
00033 #define WRN_G_D LOG_STREAM_INDENT(warn, gui_draw)
00034 #define ERR_G_D LOG_STREAM_INDENT(err, gui_draw)
00035
00036 #define DBG_G_E LOG_STREAM_INDENT(debug, gui_event)
00037 #define LOG_G_E LOG_STREAM_INDENT(info, gui_event)
00038 #define WRN_G_E LOG_STREAM_INDENT(warn, gui_event)
00039 #define ERR_G_E LOG_STREAM_INDENT(err, gui_event)
00040
00041 #define DBG_G_P LOG_STREAM_INDENT(debug, gui_parse)
00042 #define LOG_G_P LOG_STREAM_INDENT(info, gui_parse)
00043 #define WRN_G_P LOG_STREAM_INDENT(warn, gui_parse)
00044 #define ERR_G_P LOG_STREAM_INDENT(err, gui_parse)
00045
00046 namespace gui2 {
00047
00048 tcontrol::tcontrol(const unsigned canvas_count) :
00049 visible_(true),
00050 multiline_label_(false),
00051 wrapped_label_(),
00052 label_(),
00053 tooltip_(),
00054 help_message_(),
00055 canvas_(canvas_count),
00056 restorer_(),
00057 config_(0)
00058 {
00059 }
00060
00061 void tcontrol::mouse_hover(tevent_handler& event)
00062 {
00063 DBG_G_E << "Control: mouse hover.\n";
00064 event.show_tooltip(tooltip_, settings::popup_show_time);
00065 }
00066
00067 void tcontrol::help_key(tevent_handler& event)
00068 {
00069 DBG_G_E << "Control: help key.\n";
00070 event.show_help_popup(help_message_, settings::help_show_time);
00071 }
00072
00073 void tcontrol::set_size(const SDL_Rect& rect)
00074 {
00075
00076 foreach(tcanvas& canvas, canvas_) {
00077 canvas.set_width(rect.w);
00078 canvas.set_height(rect.h);
00079 }
00080
00081
00082 wrapped_label_.clear();
00083
00084
00085 twidget::set_size(rect);
00086 }
00087
00088 void tcontrol::set_label(const t_string& label)
00089 {
00090 if(label == label_) {
00091 return;
00092 }
00093
00094 label_ = label;
00095 wrapped_label_.clear();
00096 set_canvas_text();
00097 set_dirty();
00098 }
00099
00100 tpoint tcontrol::get_minimum_size() const
00101 {
00102 assert(config_);
00103 const tpoint min_size(config_->min_width, config_->min_height);
00104 if(label_.empty()) {
00105 return min_size;
00106 }
00107
00108 if(!multiline_label_) {
00109 return get_single_line_best_size(min_size);
00110 } else {
00111 return get_multi_line_best_size(min_size);
00112 }
00113 }
00114
00115 tpoint tcontrol::get_best_size() const
00116 {
00117 assert(config_);
00118
00119
00120 const tpoint default_size(config_->default_width, config_->default_height);
00121 if(label_.empty()) {
00122 return default_size;
00123 }
00124
00125 if(!multiline_label_) {
00126 return get_single_line_best_size(default_size);
00127 } else {
00128 return get_multi_line_best_size(default_size);
00129 }
00130 }
00131
00132 tpoint tcontrol::get_maximum_size() const
00133 {
00134 assert(config_);
00135 return tpoint(config_->max_width, config_->max_height);
00136 }
00137
00138 tpoint tcontrol::get_single_line_best_size(const tpoint& config_size) const
00139 {
00140 assert(!label_.empty());
00141
00142
00143 SDL_Rect rect = font::line_size(label_, config_->text_font_size, config_->text_font_style);
00144 const tpoint text_size(rect.w + config_->text_extra_width, rect.h + config_->text_extra_height);
00145
00146
00147 tpoint size(0, 0);
00148 if(config_size == size) {
00149 size = text_size;
00150 } else if(!config_size.x) {
00151 size = tpoint(text_size.x, maximum(config_size.y, text_size.y));
00152 } else if(!config_size.y) {
00153 size = tpoint(maximum(config_size.x, text_size.x), text_size.y);
00154 } else {
00155 size = maximum(config_size, text_size);
00156 }
00157
00158
00159 const tpoint maximum_size(config_->max_width, config_->max_height);
00160 if(maximum_size.x && size.x > maximum_size.x) {
00161 size.x = maximum_size.x;
00162 }
00163 if(maximum_size.y && size.y > maximum_size.y) {
00164 size.y = maximum_size.y;
00165 }
00166 return size;
00167 }
00168
00169 tpoint tcontrol::get_multi_line_best_size(const tpoint& config_size) const
00170 {
00171 assert(!label_.empty());
00172
00173
00174
00175 const tpoint maximum_size(config_->max_width, config_->max_height);
00176 if(config_size.y || maximum_size.y) {
00177 WRN_G << "Control: Multiline items don't respect the wanted height.\n";
00178 }
00179 unsigned width = 0;
00180 if(!config_size.x && !maximum_size.x) {
00181
00182
00183
00184
00185
00186
00187
00188 ERR_G << "Control: Multiline items want a width, no window setting hardcoded.\n";
00189 width = 100;
00190
00191 } else {
00192
00193 if(!config_size.x) {
00194 width = maximum_size.x;
00195 } else if(!maximum_size.x) {
00196 width = config_size.x;
00197 } else {
00198 width = minimum(config_size.x, maximum_size.x);
00199 }
00200 }
00201
00202 static const SDL_Color col = {0, 0, 0, 0};
00203 const std::string& wrapped_message = font::word_wrap_text(label_, config_->text_font_size, width);
00204 surface surf = font::get_rendered_text(wrapped_message, config_->text_font_size, col);
00205 assert(surf);
00206
00207 return tpoint(surf->w + config_->text_extra_width, surf->h + config_->text_extra_height);
00208 }
00209
00210
00211 bool tcontrol::full_redraw() const
00212 {
00213 assert(config());
00214 return config()->state[get_state()].full_redraw;
00215 }
00216
00217
00218 void tcontrol::set_canvas_text()
00219 {
00220
00221 foreach(tcanvas& canvas, canvas_) {
00222 canvas.set_variable("text", variant(label_));
00223 }
00224 }
00225
00226 void tcontrol::set_definition(const std::string& definition)
00227 {
00228 assert(!config());
00229 twidget::set_definition(definition);
00230 load_config();
00231 assert(config());
00232 }
00233
00234 void tcontrol::draw(surface& surface)
00235 {
00236 assert(config_);
00237
00238 set_dirty(false);
00239 SDL_Rect rect = get_rect();
00240
00241 if(!visible_) {
00242
00243
00244 if(restorer_) {
00245 DBG_G_D << "Control: drawing setting invisible.\n";
00246 restore_background(surface);
00247 restorer_ = 0;
00248 }
00249 return;
00250 }
00251
00252 DBG_G_D << "Control: drawing.\n";
00253 if(!restorer_) {
00254 save_background(surface);
00255 } else if(full_redraw()) {
00256 restore_background(surface);
00257 }
00258
00259 if(multiline_label_) {
00260
00261 if(wrapped_label_.empty()) {
00262 wrapped_label_ = font::word_wrap_text(label_, config_->text_font_size, get_width());
00263 }
00264 canvas(get_state()).set_variable("text", variant(wrapped_label_));
00265 }
00266
00267 canvas(get_state()).draw(true);
00268 blit_surface(canvas(get_state()).surf(), 0, surface, &rect);
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278 void tcontrol::save_background(const surface& src)
00279 {
00280 assert(!restorer_);
00281
00282 restorer_ = gui2::save_background(src, get_rect());
00283 }
00284
00285
00286
00287
00288
00289
00290 void tcontrol::restore_background(surface& dst)
00291 {
00292 gui2::restore_background(restorer_, dst, get_rect());
00293 }
00294
00295
00296
00297
00298
00299
00300 void tcontrol::load_config()
00301 {
00302 if(!config()) {
00303 set_config(get_control(get_control_type(), definition()));
00304
00305 assert(canvas().size() == config()->state.size());
00306 for(size_t i = 0; i < canvas().size(); ++i) {
00307 canvas(i) = config()->state[i].canvas;
00308 }
00309
00310 set_canvas_text();
00311
00312 load_config_extra();
00313 }
00314 }
00315
00316 }
00317
00318