00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "gui/widgets/window.hpp"
00019
00020 #include "config.hpp"
00021 #include "cursor.hpp"
00022 #include "font.hpp"
00023 #include "log.hpp"
00024 #include "serialization/parser.hpp"
00025 #include "variable.hpp"
00026 #include "sdl_utils.hpp"
00027
00028 #include <cassert>
00029
00030 #define DBG_G LOG_STREAM_INDENT(debug, gui)
00031 #define LOG_G LOG_STREAM_INDENT(info, gui)
00032 #define WRN_G LOG_STREAM_INDENT(warn, gui)
00033 #define ERR_G LOG_STREAM_INDENT(err, gui)
00034
00035 #define DBG_G_D LOG_STREAM_INDENT(debug, gui_draw)
00036 #define LOG_G_D LOG_STREAM_INDENT(info, gui_draw)
00037 #define WRN_G_D LOG_STREAM_INDENT(warn, gui_draw)
00038 #define ERR_G_D LOG_STREAM_INDENT(err, gui_draw)
00039
00040 #define DBG_G_E LOG_STREAM_INDENT(debug, gui_event)
00041 #define LOG_G_E LOG_STREAM_INDENT(info, gui_event)
00042 #define WRN_G_E LOG_STREAM_INDENT(warn, gui_event)
00043 #define ERR_G_E LOG_STREAM_INDENT(err, gui_event)
00044
00045 #define DBG_G_P LOG_STREAM_INDENT(debug, gui_parse)
00046 #define LOG_G_P LOG_STREAM_INDENT(info, gui_parse)
00047 #define WRN_G_P LOG_STREAM_INDENT(warn, gui_parse)
00048 #define ERR_G_P LOG_STREAM_INDENT(err, gui_parse)
00049
00050
00051 namespace gui2{
00052
00053 twindow::twindow(CVideo& video,
00054 const int x, const int y, const int w, const int h,
00055 const bool automatic_placement,
00056 const unsigned horizontal_placement,
00057 const unsigned vertical_placement) :
00058 tpanel(),
00059 tevent_handler(),
00060 video_(video),
00061 status_(NEW),
00062 retval_(0),
00063 need_layout_(true),
00064 tooltip_(),
00065 help_popup_(),
00066 automatic_placement_(automatic_placement),
00067 horizontal_placement_(horizontal_placement),
00068 vertical_placement_(vertical_placement)
00069 {
00070
00071 load_config();
00072
00073 set_size(::create_rect(x, y, w, h));
00074
00075 tooltip_.set_definition("default");
00076 tooltip_.set_visible(false);
00077
00078 help_popup_.set_definition("default");
00079 help_popup_.set_visible(false);
00080 }
00081
00082 int twindow::show(const bool restore, void* )
00083 {
00084 log_scope2(gui_draw, "Window: show.");
00085
00086 assert(status_ == NEW);
00087
00088
00089
00090 SDL_Rect rect = get_rect();
00091 surface restorer = get_surface_portion(video_.getSurface(), rect);
00092 surface screen;
00093
00094
00095 for(status_ = SHOWING; status_ != REQUEST_CLOSE; ) {
00096 process_events();
00097
00098 if(status_ == REQUEST_CLOSE) {
00099 break;
00100 }
00101
00102 if(dirty() || need_layout_) {
00103 if(need_layout_) {
00104 screen = make_neutral_surface(restorer);
00105 }
00106 draw(screen);
00107 }
00108
00109
00110 SDL_Delay(10);
00111 flip();
00112 }
00113
00114
00115 if(restore) {
00116 rect = get_rect();
00117 SDL_BlitSurface(restorer, 0, video_.getSurface(), &rect);
00118 update_rect(get_rect());
00119 flip();
00120 }
00121
00122 return retval_;
00123 }
00124
00125 void twindow::layout(const SDL_Rect position)
00126 {
00127 need_layout_ = false;
00128
00129 DBG_G << "Window: layout area " << position.x
00130 << ',' << position.y << " x " << position.w
00131 << ',' << position.h << ".\n";
00132
00133 set_client_size(position);
00134 need_layout_ = false;
00135 }
00136
00137
00138 void twindow::draw(surface& surface)
00139 {
00140 const bool draw_foreground = need_layout_;
00141 if(need_layout_) {
00142 DBG_G << "Window: layout client area.\n";
00143 layout(get_client_rect());
00144
00145 canvas(0).draw();
00146 blit_surface(canvas(0).surf(), 0, surface, 0);
00147 }
00148
00149 for(tgrid::iterator itor = begin(); itor != end(); ++itor) {
00150 if(! *itor || !itor->dirty()) {
00151 continue;
00152 }
00153
00154 log_scope2(gui_draw, "Window: draw child.");
00155
00156 itor->draw(surface);
00157 }
00158 if(draw_foreground) {
00159 canvas(1).draw();
00160 blit_surface(canvas(1).surf(), 0, surface, 0);
00161 }
00162 if(tooltip_.dirty()) {
00163 tooltip_.draw(surface);
00164 }
00165 if(help_popup_.dirty()) {
00166 help_popup_.draw(surface);
00167 }
00168
00169 SDL_Rect rect = get_rect();
00170 SDL_BlitSurface(surface, 0, video_.getSurface(), &rect);
00171 update_rect(get_rect());
00172 set_dirty(false);
00173 }
00174
00175 void twindow::flip()
00176 {
00177
00178
00179
00180 const surface frameBuffer = get_video_surface();
00181
00182 cursor::draw(frameBuffer);
00183 video_.flip();
00184 cursor::undraw(frameBuffer);
00185 }
00186
00187 void twindow::window_resize(tevent_handler&,
00188 const unsigned new_width, const unsigned new_height)
00189 {
00190 settings::screen_width = new_width;
00191 settings::screen_height = new_height;
00192 need_layout_ = true;
00193 }
00194
00195 SDL_Rect twindow::get_client_rect() const
00196 {
00197 const twindow_definition::tresolution* conf = dynamic_cast<const twindow_definition::tresolution*>(config());
00198 assert(conf);
00199
00200 SDL_Rect result = get_rect();
00201 result.x = conf->left_border;
00202 result.y = conf->top_border;
00203 result.w -= conf->left_border + conf->right_border;
00204 result.h -= conf->top_border + conf->bottom_border;
00205
00206
00207
00208 return result;
00209
00210 }
00211
00212 void twindow::recalculate_size()
00213 {
00214 if(automatic_placement_) {
00215
00216 tpoint size = get_best_size();
00217 size.x = size.x < settings::screen_width ? size.x : settings::screen_width;
00218 size.y = size.y < settings::screen_height ? size.y : settings::screen_height;
00219
00220 tpoint position(0, 0);
00221 switch(horizontal_placement_) {
00222 case tgrid::HORIZONTAL_ALIGN_LEFT :
00223
00224 break;
00225 case tgrid::HORIZONTAL_ALIGN_CENTER :
00226 position.x = (settings::screen_width - size.x) / 2;
00227 break;
00228 case tgrid::HORIZONTAL_ALIGN_RIGHT :
00229 position.x = settings::screen_width - size.x;
00230 break;
00231 default :
00232 assert(false);
00233 }
00234 switch(vertical_placement_) {
00235 case tgrid::VERTICAL_ALIGN_TOP :
00236
00237 break;
00238 case tgrid::VERTICAL_ALIGN_CENTER :
00239 position.y = (settings::screen_height - size.y) / 2;
00240 break;
00241 case tgrid::VERTICAL_ALIGN_BOTTOM :
00242 position.y = settings::screen_height - size.y;
00243 break;
00244 default :
00245 assert(false);
00246 }
00247
00248 set_size(create_rect(position, size));
00249 }
00250 }
00251
00252 void twindow::do_show_tooltip(const tpoint& location, const t_string& tooltip)
00253 {
00254 DBG_G << "Showing tooltip message: '" << tooltip << "'.\n";
00255
00256 assert(!tooltip.empty());
00257
00258 twidget* widget = find_widget(location, true);
00259 assert(widget);
00260
00261 const SDL_Rect widget_rect = widget->get_rect();
00262 const SDL_Rect client_rect = get_client_rect();
00263
00264 tooltip_.set_label(tooltip);
00265 const tpoint size = tooltip_.get_best_size();
00266
00267 SDL_Rect tooltip_rect = {0, 0, size.x, size.y};
00268
00269
00270 if(widget_rect.y - size.y > 0) {
00271
00272 tooltip_rect.y = widget_rect.y - size.y;
00273 } else {
00274
00275 tooltip_rect.y = widget_rect.y + widget_rect.h;
00276 }
00277
00278 if(widget_rect.x + size.x < client_rect.w) {
00279
00280 tooltip_rect.x = widget_rect.x;
00281 } else {
00282
00283 tooltip_rect.x = client_rect.w - size.x;
00284 }
00285
00286 tooltip_.set_size(tooltip_rect);
00287 tooltip_.set_visible();
00288 }
00289
00290 void twindow::do_show_help_popup(const tpoint& location, const t_string& help_popup)
00291 {
00292
00293 DBG_G << "Showing help message: '" << help_popup << "'.\n";
00294
00295 if(help_popup.empty()) {
00296 return;
00297 }
00298 twidget* widget = find_widget(location, true);
00299 assert(widget);
00300
00301 const SDL_Rect widget_rect = widget->get_rect();
00302 const SDL_Rect client_rect = get_client_rect();
00303
00304 help_popup_.set_label(help_popup);
00305 const tpoint size = help_popup_.get_best_size();
00306
00307 SDL_Rect help_popup_rect = {0, 0, size.x, size.y};
00308
00309
00310 if(widget_rect.y - size.y > 0) {
00311
00312 help_popup_rect.y = widget_rect.y - size.y;
00313 } else {
00314
00315 help_popup_rect.y = widget_rect.y + widget_rect.h;
00316 }
00317
00318 if(widget_rect.x + size.x < client_rect.w) {
00319
00320 help_popup_rect.x = widget_rect.x;
00321 } else {
00322
00323 help_popup_rect.x = client_rect.w - size.x;
00324 }
00325
00326 help_popup_.set_size(help_popup_rect);
00327 help_popup_.set_visible();
00328 }
00329
00330 }
00331