settings.cpp

Go to the documentation of this file.
00001 /* $Id: settings.cpp 26800 2008-05-23 18:25:20Z mordante $ */
00002 /*
00003    Copyright (C) 2007 - 2008 by Mark de Wever <koraq@xs4all.nl>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 //! @file setting.cpp
00016 //! Implementation of settings.hpp.
00017 
00018 #include "gui/widgets/settings.hpp"
00019 
00020 #include "filesystem.hpp"
00021 #include "gettext.hpp"
00022 #include "gui/widgets/helper.hpp"
00023 #include "log.hpp"
00024 #include "serialization/parser.hpp"
00025 #include "serialization/preprocessor.hpp"
00026 #include "util.hpp"
00027 #include "video.hpp"
00028 #include "wml_exception.hpp"
00029 
00030 #include <cassert>
00031 
00032 #define DBG_G LOG_STREAM_INDENT(debug, gui)
00033 #define LOG_G LOG_STREAM_INDENT(info, gui)
00034 #define WRN_G LOG_STREAM_INDENT(warn, gui)
00035 #define ERR_G LOG_STREAM_INDENT(err, gui)
00036 
00037 #define DBG_G_D LOG_STREAM_INDENT(debug, gui_draw)
00038 #define LOG_G_D LOG_STREAM_INDENT(info, gui_draw)
00039 #define WRN_G_D LOG_STREAM_INDENT(warn, gui_draw)
00040 #define ERR_G_D LOG_STREAM_INDENT(err, gui_draw)
00041 
00042 #define DBG_G_E LOG_STREAM_INDENT(debug, gui_event)
00043 #define LOG_G_E LOG_STREAM_INDENT(info, gui_event)
00044 #define WRN_G_E LOG_STREAM_INDENT(warn, gui_event)
00045 #define ERR_G_E LOG_STREAM_INDENT(err, gui_event)
00046 
00047 #define DBG_G_P LOG_STREAM_INDENT(debug, gui_parse)
00048 #define LOG_G_P LOG_STREAM_INDENT(info, gui_parse)
00049 #define WRN_G_P LOG_STREAM_INDENT(warn, gui_parse)
00050 #define ERR_G_P LOG_STREAM_INDENT(err, gui_parse)
00051 
00052 namespace gui2 {
00053 
00054 namespace settings {
00055     unsigned screen_width = 0;
00056     unsigned screen_height = 0;
00057 
00058     unsigned popup_show_delay = 0;
00059     unsigned popup_show_time = 0;
00060     unsigned help_show_time = 0;
00061     unsigned double_click_time = 0;
00062 
00063 } // namespace settings
00064 
00065 namespace {
00066 
00067     //! Map with all known windows, (the builder class builds a window).
00068     std::map<std::string, twindow_builder> windows;
00069 
00070     //! Map with all known guis.
00071     std::map<std::string, tgui_definition> guis;
00072 
00073     //! Points to the current gui.
00074     std::map<std::string, tgui_definition>::const_iterator current_gui = guis.end();
00075 
00076     //! Vector with all known windows, these are validated on existance on startup.
00077     //! The enum twindow_type is the index of the array.
00078     std::vector<std::string> window_type_list(DUMMY);
00079 } // namespace 
00080 
00081 static void fill_window_types() 
00082 {
00083     window_type_list[ADDON_CONNECT] = "addon_connect";
00084     window_type_list[LANGUAGE_SELECTION] = "language_selection";
00085     window_type_list[MP_METHOD_SELECTION] = "mp_method_selection";
00086 }
00087 
00088 const std::string& get_id(const twindow_type window_type)
00089 {
00090     assert(window_type >= 0 && window_type < DUMMY);
00091 
00092     return window_type_list[window_type];
00093 }
00094 
00095 void load_settings() 
00096 {
00097     LOG_G << "Setting: init gui.\n";
00098 
00099     // Init.
00100     fill_window_types();
00101 
00102     const SDL_Rect rect = screen_area();
00103     settings::screen_width = rect.w;
00104     settings::screen_height = rect.h;
00105 
00106     // Read file.
00107     config cfg;
00108     const std::string& filename = "data/gui/default.cfg";
00109     try {
00110         scoped_istream stream = preprocess_file(filename);
00111         read(cfg, *stream);
00112     } catch(config::error&) {
00113         ERR_G_P << "Setting: could not read file '" << filename << "'.\n";
00114     }
00115 
00116     // Parse guis
00117     const config::child_list& gui_cfgs = cfg.get_children("gui");
00118     for(std::vector<config*>::const_iterator itor = gui_cfgs.begin();
00119             itor != gui_cfgs.end(); ++itor) {
00120 
00121         std::pair<std::string, tgui_definition> child;
00122         child.first = child.second.read(**itor);
00123         guis.insert(child);
00124     }
00125 
00126     VALIDATE(guis.find("default") != guis.end(), _ ("No default gui defined."));
00127 
00128     current_gui = guis.find("default");
00129     current_gui->second.activate();
00130 }
00131 
00132 const std::string& tgui_definition::read(const config& cfg)
00133 {
00134 /*WIKI
00135  * @page = GUIToolkitWML
00136  * @order = 1
00137  *
00138  * = GUI =
00139  *
00140  * The gui class contains the definitions of all widgets and windows used in
00141  * the game. This can be seen as a skin and it allows the user to define the
00142  * visual aspect of the various items. The visual aspect can be determined
00143  * depending on the size of the game window.
00144  * 
00145  * Widgets have a definition and an instance, the definition contains the 
00146  * general info/looks of a widget and the instance the actual looks. Eg the
00147  * where the button text is placed is the same for every button, but the
00148  * text of every button might differ. 
00149  *
00150  * The default gui has the id ''default'' and must exist, in the default gui
00151  * there must a definition of every widget with the id ''default'' and every
00152  * window needs to be defined. If the definition of a widget with a certain
00153  * id doesn't exist it will fall back to default in the current gui, if it's
00154  * not defined there either it will fall back to the default widget in the
00155  * default theme. That way it's possible to slowly create your own gui and
00156  * test it.
00157  *
00158  * The gui has the following data:
00159  * @start_table = config
00160  *     id (string)                   Unique id for this gui (theme).
00161  *     description (t_string)        Unique translatable name for this gui.
00162  *
00163  *     widget_definitions (section)  The defintions of all 
00164  *                                   [[#widget_list|widgets]].
00165  *     window (section)              The defintions of all 
00166  *                                   [[#window_list|windows]].
00167  *     settings (section)            The settings for the gui.
00168  * @end_table
00169  *
00170  * <span id="widget_list"></span>List of available widgets:
00171  * @start_table = widget_definition
00172  *     button_definition             A push button.
00173  *     label_definition              A label.
00174  *     listbox_definition            A listbox.
00175  *     panel_definition              A panel.
00176  *     spacer_definition             A spacer.
00177  *     text_box_definition           A single line text box.
00178  *     toggle_button_definition      A kind of button with two 'states' normal 
00179  *                                   and selected. This is a more generic widget
00180  *                                   which is used for eg checkboxes and
00181  *                                   radioboxes.
00182  *     tooltip_definition            A small tooltip with help.
00183  *     vertical_scrollbar_definition A vertical scrollbar.
00184  *     window_definition             A window.
00185  * @end_table
00186  *
00187  * <span id="window_list"></span>List of available windows:
00188  * @start_table = window_definition
00189  *     addon_connect                 The dialog to connect to the addon server
00190  *                                   and maintain locally installed addons.
00191  *     language_selection            The dialog to select the primairy language.  
00192  * @end_table
00193  *
00194  */
00195     id = cfg["id"];
00196     description = cfg["description"];
00197 
00198     VALIDATE(!id.empty(), missing_mandatory_wml_key("gui", "id"));
00199     VALIDATE(!description.empty(), missing_mandatory_wml_key("gui", "description"));
00200 
00201     DBG_G_P << "Parsing gui " << id << '\n';
00202 
00203     /***** Control definitions *****/
00204     load_definitions<tbutton_definition>("button", cfg.get_children("button_definition"));
00205     load_definitions<tlabel_definition>("label", cfg.get_children("label_definition"));
00206     load_definitions<tlistbox_definition>("listbox", cfg.get_children("listbox_definition"));
00207     load_definitions<tpanel_definition>("panel", cfg.get_children("panel_definition"));
00208     load_definitions<tspacer_definition>("spacer", cfg.get_children("spacer_definition"));
00209     load_definitions<ttext_box_definition>("text_box", cfg.get_children("text_box_definition"));
00210     load_definitions<ttoggle_button_definition>("toggle_button", cfg.get_children("toggle_button_definition"));
00211     load_definitions<ttooltip_definition>("tooltip", cfg.get_children("tooltip_definition"));
00212     load_definitions<tvertical_scrollbar_definition>
00213         ("vertical_scrollbar", cfg.get_children("vertical_scrollbar_definition"));
00214     load_definitions<twindow_definition>("window", cfg.get_children("window_definition"));
00215 
00216     /***** Window types *****/
00217     const config::child_list& window_instance_cfgs = cfg.get_children("window");
00218     for(std::vector<config*>::const_iterator itor = window_instance_cfgs.begin();
00219             itor != window_instance_cfgs.end(); ++itor) {
00220 
00221         std::pair<std::string, twindow_builder> child;
00222         child.first = child.second.read(**itor);
00223         window_types.insert(child);
00224     }
00225 
00226     if(id == "default") {
00227         // The default gui needs to define all window types since we're the 
00228         // fallback in case another gui doesn't define the window type.
00229         for(std::vector<std::string>::const_iterator itor = window_type_list.begin();
00230                 itor != window_type_list.end(); ++itor) {
00231 
00232             VALIDATE(window_types.find(*itor) != window_types.end(), _("Window not defined.")); 
00233         }
00234     }
00235 
00236     /***** settings *****/
00237 /*WIKI
00238  * @page = GUIToolkitWML
00239  * @order = 1
00240  *
00241  * A setting section has the following variables:
00242  * @start_table = config
00243  *     popup_show_delay (unsigned = 0) The time it take before the popup shows
00244  *                                     if the mouse moves over the widget. 0 
00245  *                                     means show directly.
00246  *     popup_show_time (unsigned = 0)  The time a shown popup remains visible.
00247  *                                     0 means until the mouse leaves the 
00248  *                                     widget.
00249  *     help_show_time (unsigned = 0)   The time a shown help remains visible.
00250  *                                     0 means until the mouse leaves the 
00251  *                                     widget.
00252  *     double_click_time (unsigned)    The time between two clicks to still be a
00253  *                                     double click.
00254  */
00255     const config& settings = *cfg.child("settings");
00256 
00257     popup_show_delay_ = lexical_cast_default<unsigned>(settings["popup_show_delay"]);
00258     popup_show_time_ = lexical_cast_default<unsigned>(settings["popup_show_time"]);
00259     help_show_time_ = lexical_cast_default<unsigned>(settings["help_show_time"]);
00260     double_click_time_ = lexical_cast_default<unsigned>(settings["double_click_time"]);
00261 
00262     VALIDATE(double_click_time_, missing_mandatory_wml_key("settings", "double_click_time"));
00263 
00264     return id;
00265 }
00266 
00267 void tgui_definition::activate() const
00268 {
00269     settings::popup_show_delay = popup_show_delay_;
00270     settings::popup_show_time = popup_show_time_;
00271     settings::help_show_time = help_show_time_;
00272     settings::double_click_time = double_click_time_;
00273 }
00274 
00275 template<class T>
00276 void tgui_definition::load_definitions(
00277     const std::string& definition_type, const config::child_list& definition_list)
00278 {
00279     for(std::vector<config*>::const_iterator itor = definition_list.begin();
00280             itor != definition_list.end(); ++itor) {
00281 
00282         T* def = new T(**itor);
00283 
00284         control_definition[definition_type].insert(std::make_pair(def->id, def));
00285     }
00286 
00287     utils::string_map symbols;
00288     symbols["definition"] = definition_type;
00289     symbols["id"] = "default";
00290     t_string msg(vgettext(
00291         "Widget defintion '$definition' doesn't contain the defintion for '$id'.",
00292         symbols));
00293     VALIDATE(control_definition[definition_type].find("default") 
00294         != control_definition[definition_type].end(), msg);
00295 }
00296 
00297 tcontrol_definition::tcontrol_definition(const config& cfg) :
00298     id(cfg["id"]),
00299     description(cfg["description"]),
00300     resolutions()
00301 {
00302 /*WIKI
00303  * @page = GUIToolkitWML
00304  * @order = 1_widget
00305  *
00306  * = Widget defintion =
00307  *
00308  * Every widget has some parts in common, first of all every definition has the
00309  * following fields.
00310  *
00311  * @start_table = config
00312  *     id (string)                   Unique id for this gui (theme).
00313  *     description (t_string)        Unique translatable name for this gui.
00314  *
00315  *     resolution (section)          The definitions of the widget in various
00316  *                                   resolutions.
00317  * @end_table
00318  *
00319  */
00320 
00321     VALIDATE(!id.empty(), missing_mandatory_wml_key("gui", "id"));
00322     VALIDATE(!description.empty(), missing_mandatory_wml_key("gui", "description"));
00323 
00324 }
00325 
00326 tresolution_definition_::tresolution_definition_(const config& cfg) :
00327     window_width(lexical_cast_default<unsigned>(cfg["window_width"])),
00328     window_height(lexical_cast_default<unsigned>(cfg["window_height"])),
00329     min_width(lexical_cast_default<unsigned>(cfg["min_width"])),
00330     min_height(lexical_cast_default<unsigned>(cfg["min_height"])),
00331     default_width(lexical_cast_default<unsigned>(cfg["default_width"])),
00332     default_height(lexical_cast_default<unsigned>(cfg["default_height"])),
00333     max_width(lexical_cast_default<unsigned>(cfg["max_width"])),
00334     max_height(lexical_cast_default<unsigned>(cfg["max_height"])),
00335     text_extra_width(lexical_cast_default<unsigned>(cfg["text_extra_width"])),
00336     text_extra_height(lexical_cast_default<unsigned>(cfg["text_extra_height"])),
00337     text_font_size(lexical_cast_default<unsigned>(cfg["text_font_size"])),
00338     text_font_style(decode_font_style(cfg["text_font_style"])),
00339     state()
00340 {
00341 /*WIKI
00342  * @page = GUIToolkitWML
00343  * @order = 1_widget
00344  *
00345  * == Resolution ==
00346  *
00347  * Depending on the resolution a widget can look different. Resolutions are
00348  * evaluated in order of appearance. The ''window_width'' and ''window_height''
00349  * are the upper limit this resolution is valid for. When one of the sizes
00350  * gets above the limit, the next resolution is selected. There's one special
00351  * case where both values are ''0''. This resolution always matches. (Resolution
00352  * definitions behind that one will never be picked.) This resolution can be
00353  * used as upper limit or if there's only one resolution.
00354  *
00355  * The default (and also minimum) size of a button is determined by two items, 
00356  * the wanted default size and the size needed for the text. The size of the
00357  * text differs per used widget so needs to be determined per button. 
00358  *
00359  * Container widgets like panels and windows have other rules for their sizes.
00360  * Their sizes are based on the size of their children (and the border they need
00361  * themselves). It's wise to set all sizes to 0 for these kind of widgets.
00362  *
00363  * @start_table = config
00364  *     window_width (unsigned = 0)   Width of the application window.
00365  *     window_height (unsigned = 0) 
00366  *                                   Height of the application window.
00367  *     min_width (unsigned = 0)      The minimum width of the widget.
00368  *     min_height (unsigned = 0)     The minimum height of the widget.
00369  *
00370  *     default_width (unsigned = 0)  The default width of the widget.
00371  *     default_height (unsigned = 0) The default height of the widget.
00372  *
00373  *     max_width (unsigned = 0)      The maximum width of the widget.
00374  *     max_height (unsigned = 0)     The maximum height of the widget.
00375  *
00376  *     text_extra_width (unsigned = 0)
00377  *                                   The extra width needed to determine the 
00378  *                                   minimal size for the text.
00379  *     text_extra_height (unsigned = 0)
00380  *                                   The extra height needed to determine the
00381  *                                   minimal size for the text.
00382  *     text_font_size (unsigned = 0) The font size, which needs to be used to 
00383  *                                   determine the minimal size for the text.
00384  *     text_font_style (font_style = "")  
00385  *                                   The font style, which needs to be used to
00386  *                                   determine the minimal size for the text.
00387  *
00388  *     state (section)               Every widget has one or more state sections.
00389  *                                   Note they aren't called state but state_xxx
00390  *                                   the exact names are listed per widget.
00391  * @end_table
00392  *
00393  */
00394 
00395     DBG_G_P << "Parsing resolution " 
00396         << window_width << ", " << window_height << '\n';
00397 }
00398 
00399 template<class T>
00400 void tcontrol_definition::load_resolutions(const config::child_list& resolution_list)
00401 {
00402 
00403     VALIDATE(!resolution_list.empty(), _("No resolution defined."));
00404     for(std::vector<config*>::const_iterator itor = resolution_list.begin();
00405             itor != resolution_list.end(); ++itor) {
00406 
00407         resolutions.push_back(new T(**itor));
00408     }
00409 }
00410 
00411 tstate_definition::tstate_definition(const config* cfg) :
00412     full_redraw(cfg ? utils::string_bool((*cfg)["full_redraw"]) : false),
00413     canvas()
00414 {
00415 /*WIKI
00416  * @page = GUIToolkitWML
00417  * @order = 1_widget
00418  *
00419  * == State ==
00420  *
00421  * Definition of a state. A state contains the info what to do in a state.
00422  * Atm this is rather focussed on the drawing part, might change later.
00423  * Keys: 
00424  * @start_table = config
00425  *     full_redraw (bool = false)      Does this state need a full redraw when
00426  *                                     it's being drawn? Normally only required
00427  *                                     if the widget is (partly) transparent.
00428  *     draw (section)                  Section with drawing directions for a canvas.
00429  * @end_table
00430  *
00431  */
00432 
00433     const config* draw = cfg ? cfg->child("draw") : 0;
00434 
00435     VALIDATE(draw, _("No state or draw section defined."));
00436 
00437     canvas.set_cfg(*draw);
00438 }
00439 
00440 /*WIKI
00441  * @page = GUIToolkitWML
00442  * @order = 1_widget
00443  *
00444  * = Example =
00445  *
00446  * FIXME add a example here.
00447  * 
00448  * = List of widgets =
00449  *
00450  * Below the list of available widgets.
00451  *
00452  */
00453 
00454 tbutton_definition::tbutton_definition(const config& cfg) :
00455     tcontrol_definition(cfg)
00456 {
00457     DBG_G_P << "Parsing button " << id << '\n';
00458 
00459     load_resolutions<tresolution>(cfg.get_children("resolution"));
00460 }
00461 
00462 tbutton_definition::tresolution::tresolution(const config& cfg) :
00463     tresolution_definition_(cfg)
00464 {
00465 /*WIKI
00466  * @page = GUIToolkitWML
00467  * @order = 1_widget_button
00468  *
00469  * == Button ==
00470  *
00471  * The definition of a normal push button.
00472  *
00473  * The following states exist:
00474  * * state_enabled, the button is enabled.
00475  * * state_disabled, the button is disabled.
00476  * * state_pressed, the left mouse button is down.
00477  * * state_focussed, the mouse is over the button.
00478  *
00479  */
00480 
00481     // Note the order should be the same as the enum tstate is button.hpp.
00482     state.push_back(tstate_definition(cfg.child("state_enabled")));
00483     state.push_back(tstate_definition(cfg.child("state_disabled")));
00484     state.push_back(tstate_definition(cfg.child("state_pressed")));
00485     state.push_back(tstate_definition(cfg.child("state_focussed")));
00486 }
00487 
00488 tlabel_definition::tlabel_definition(const config& cfg) :
00489     tcontrol_definition(cfg)
00490 {
00491     DBG_G_P << "Parsing label " << id << '\n';
00492 
00493     load_resolutions<tresolution>(cfg.get_children("resolution"));
00494 }
00495 
00496 
00497 tlabel_definition::tresolution::tresolution(const config& cfg) :
00498     tresolution_definition_(cfg)
00499 {
00500 /*WIKI
00501  * @page = GUIToolkitWML
00502  * @order = 1_widget_label
00503  *
00504  * == Label ==
00505  *
00506  * The definition of a normal label.
00507  * 
00508  * The following states exist:
00509  * * state_enabled, the label is enabled.
00510  * * state_disabled, the label is disabled.
00511  *
00512  */
00513 
00514     // Note the order should be the same as the enum tstate is label.hpp.
00515     state.push_back(tstate_definition(cfg.child("state_enabled")));
00516     state.push_back(tstate_definition(cfg.child("state_disabled")));
00517 }
00518 
00519 tlistbox_definition::tlistbox_definition(const config& cfg) :
00520     tcontrol_definition(cfg)
00521 {
00522     DBG_G_P << "Parsing listbox " << id << '\n';
00523 
00524     load_resolutions<tresolution>(cfg.get_children("resolution"));
00525 }
00526 
00527 tlistbox_definition::tresolution::tresolution(const config& cfg) :
00528     tresolution_definition_(cfg),
00529     scrollbar(0)
00530 
00531 {
00532 /*WIKI
00533  * @page = GUIToolkitWML
00534  * @order = 1_widget_listbox
00535  *
00536  * == Listbox ==
00537  *
00538  * The definition of a normal listbox. A listbox is multiwidget class which
00539  * means that it's build from multiple items.  The definition of a listbox
00540  * contains the definition of it's scrollbar. 
00541  *
00542  * The resolution for a text box also contains the following keys:
00543  * @start_table = config
00544  *     scrollbar (section)             A grid containing the widgets for the
00545  *                                     scrollbar. The scrollbar has some special
00546  *                                     widgets so it can make default behaviour
00547  *                                     for certain widgets.
00548  * @end_table
00549  *
00550  * @start_table = container
00551  *     [_begin] button                 Moves the position to the beginning of
00552  *                                     the list.
00553  *     [_line_up] button               Move the position one item up. (NOTE if
00554  *                                     too many items to move per item it might
00555  *                                     be more items.)
00556  *     [_half_page_up] button          Move the position half the number of the 
00557  *                                     visible items up. (See note at _line_up.)
00558  *     [_page_up] button               Move the position the number of visible
00559  *                                     items up. (See note at _line_up.)
00560  *
00561  *
00562  *     [_end] button                   Moves the position to the end of the
00563  *                                     list.
00564  *     [_line_down] button             Move the position one item down.(See note
00565  *                                     at _line_up.) 
00566  *     [_half_page_down] button        Move the position half the number of the 
00567  *                                     visible items down. (See note at _line_up.)
00568  *     [_page_down] button             Move the position the number of visible
00569  *                                     items down. (See note at _line_up.)
00570  *
00571  *     (_scrollbar) vertical_scrollbar This is the scrollbar so the user can
00572  *                                     scroll through the list.
00573  *
00574  * @end_table
00575  *
00576  * The following states exist:
00577  * * state_enabled, the listbox is enabled.
00578  * * state_disabled, the listbox is disabled.
00579  *
00580  */
00581 
00582     // Note the order should be the same as the enum tstate is listbox.hpp.
00583     state.push_back(tstate_definition(cfg.child("state_enabled")));
00584     state.push_back(tstate_definition(cfg.child("state_disabled")));
00585 
00586     const config* grid = cfg.child("scrollbar");
00587     VALIDATE(grid, _("No scrollbar defined."));
00588 
00589     scrollbar = new tbuilder_grid(*grid);
00590 }
00591 
00592 tpanel_definition::tpanel_definition(const config& cfg) : 
00593     tcontrol_definition(cfg)
00594 {
00595 
00596     DBG_G_P << "Parsing panel " << id << '\n';
00597 
00598     load_resolutions<tresolution>(cfg.get_children("resolution"));
00599 }
00600 
00601 tpanel_definition::tresolution::tresolution(const config& cfg) :
00602     tresolution_definition_(cfg),
00603     top_border(lexical_cast_default<unsigned>(cfg["top_border"])),
00604     bottom_border(lexical_cast_default<unsigned>(cfg["bottom_border"])),
00605     left_border(lexical_cast_default<unsigned>(cfg["left_border"])),
00606     right_border(lexical_cast_default<unsigned>(cfg["right_border"]))
00607 {
00608 /*WIKI 
00609  * @page = GUIToolkitWML
00610  * @order = 1_widget_panel
00611  *
00612  * == Panel ==
00613  *
00614  * The definition of a panel. A panel is a container hold other elements in it's
00615  * grid. A panel is always enabled and can't be disabled. Instead it uses the
00616  * states as layers to draw on.
00617  *
00618  * The resolution for a text box also contains the following keys:
00619  * @start_table = config
00620  *     top_border (unsigned = 0)     The size which isn't used for the client area.
00621  *     bottom_border (unsigned = 0)  The size which isn't used for the client area.
00622  *     left_border (unsigned = 0)    The size which isn't used for the client area.
00623  *     right_border (unsigned = 0)   The size which isn't used for the client area.
00624  * @end_table
00625  *
00626  * The following layers exist:
00627  * * background, the background of the panel.
00628  * * foreground, the foreground of the panel/
00629  */
00630 
00631     // The panel needs to know the order.
00632     state.push_back(tstate_definition(cfg.child("background")));
00633     state.push_back(tstate_definition(cfg.child("foreground")));
00634 }
00635 
00636 tspacer_definition::tspacer_definition(const config& cfg) :
00637     tcontrol_definition(cfg)
00638 {
00639     DBG_G_P << "Parsing spacer " << id << '\n';
00640 
00641     load_resolutions<tresolution>(cfg.get_children("resolution"));
00642 }
00643 
00644 
00645 tspacer_definition::tresolution::tresolution(const config& cfg) :
00646     tresolution_definition_(cfg)
00647 {
00648 /*WIKI
00649  * @page = GUIToolkitWML
00650  * @order = 1_widget_spacer
00651  *
00652  * == Spacer ==
00653  *
00654  * The definition of a normal spacer.
00655  *
00656  * A spacer has no states so nothing to load.
00657  * 
00658  */
00659 }
00660 
00661 ttext_box_definition::ttext_box_definition(const config& cfg) :
00662     tcontrol_definition(cfg)
00663 {
00664     DBG_G_P << "Parsing text_box " << id << '\n';
00665 
00666     load_resolutions<tresolution>(cfg.get_children("resolution"));
00667 }
00668 
00669 ttext_box_definition::tresolution::tresolution(const config& cfg) :
00670     tresolution_definition_(cfg),
00671     text_x_offset(cfg["text_x_offset"]),
00672     text_y_offset(cfg["text_y_offset"])
00673 {
00674 /*WIKI
00675  * @page = GUIToolkitWML
00676  * @order = 1_widget_text_box
00677  *
00678  * == Text box ==
00679  *
00680  * The definition of a text box.
00681  *
00682  * The resolution for a text box also contains the following keys:
00683  * @start_table = config
00684  *     text_x_offset (f_unsigned = "") The x offset of the text in the text
00685  *                                     box. This is needed for the code to 
00686  *                                     determine where in the text the mouse 
00687  *                                     clicks, so it can set the cursor
00688  *                                     properly.
00689  *     text_y_offset (f_unsigned = "") The y offset of the text in the text
00690  *                                     box.
00691  * @end_table
00692  *
00693  * The following states exist:
00694  * * state_enabled, the text box is enabled.
00695  * * state_disabled, the text box is disabled.
00696  * * state_focussed, the text box has the focus of the keyboard.
00697  *
00698  */
00699 
00700     // Note the order should be the same as the enum tstate is text_box.hpp.
00701     state.push_back(tstate_definition(cfg.child("state_enabled")));
00702     state.push_back(tstate_definition(cfg.child("state_disabled")));
00703     state.push_back(tstate_definition(cfg.child("state_focussed")));
00704 }
00705 
00706 ttoggle_button_definition::ttoggle_button_definition(const config& cfg) : 
00707     tcontrol_definition(cfg)
00708 {
00709     DBG_G_P << "Parsing toggle button " << id << '\n';
00710 
00711     load_resolutions<tresolution>(cfg.get_children("resolution"));
00712 }
00713 
00714 ttoggle_button_definition::tresolution::tresolution(const config& cfg) :
00715     tresolution_definition_(cfg)
00716 
00717 {
00718 /*WIKI
00719  * @page = GUIToolkitWML
00720  * @order = 1_widget_toggle_button
00721  *
00722  * == Toogle button ==
00723  *
00724  * The definition of a toggle button.
00725  *
00726  * The following states exist:
00727  * * state_enabled, the button is enabled and not selected.
00728  * * state_disabled, the button is disabled and not selected.
00729  * * state_focussed, the mouse is over the button and not selected.
00730  *
00731  * * state_enabled_selected, the button is enabled and selected.
00732  * * state_disabled_selected, the button is disabled and selected.
00733  * * state_focussed_selected, the mouse is over the button and selected.
00734  *
00735  */
00736 
00737     // Note the order should be the same as the enum tstate is toggle_button.hpp.
00738     state.push_back(tstate_definition(cfg.child("state_enabled")));
00739     state.push_back(tstate_definition(cfg.child("state_disabled")));
00740     state.push_back(tstate_definition(cfg.child("state_focussed")));
00741 
00742     state.push_back(tstate_definition(cfg.child("state_enabled_selected")));
00743     state.push_back(tstate_definition(cfg.child("state_disabled_selected")));
00744     state.push_back(tstate_definition(cfg.child("state_focussed_selected")));
00745 }
00746 
00747 ttooltip_definition::ttooltip_definition(const config& cfg) : 
00748     tcontrol_definition(cfg)
00749 {
00750     DBG_G_P << "Parsing tooltip " << id << '\n';
00751 
00752     load_resolutions<tresolution>(cfg.get_children("resolution"));
00753 }
00754 
00755 ttooltip_definition::tresolution::tresolution(const config& cfg) :
00756     tresolution_definition_(cfg)
00757 
00758 {
00759 /*WIKI
00760  * @page = GUIToolkitWML
00761  * @order = 1_widget_tooltip
00762  *
00763  * == Tooltip ==
00764  *
00765  * The definition of a tooltip.
00766  *
00767  * The following states exist:
00768  * * state_enabled, the tooltip has only one state, it's either shown or hidden.
00769  *
00770  */
00771 
00772     // Note only one state for a tooltip.
00773     state.push_back(tstate_definition(cfg.child("state_enabled")));
00774 }
00775 
00776 tvertical_scrollbar_definition::tvertical_scrollbar_definition(const config& cfg) : 
00777     tcontrol_definition(cfg)
00778 {
00779     DBG_G_P << "Parsing vertical scrollbar " << id << '\n';
00780 
00781     load_resolutions<tresolution>(cfg.get_children("resolution"));
00782 }
00783 
00784 tvertical_scrollbar_definition::tresolution::tresolution(const config& cfg) :
00785     tresolution_definition_(cfg),
00786     minimum_positioner_length(
00787         lexical_cast_default<unsigned>(cfg["minimum_positioner_length"])),
00788     top_offset(lexical_cast_default<unsigned>(cfg["top_offset"])),
00789     bottom_offset(lexical_cast_default<unsigned>(cfg["bottom_offset"]))
00790 {
00791 /*WIKI
00792  * @page = GUIToolkitWML
00793  * @order = 1_widget_vertical_scrollbar
00794  *
00795  * == Vertical scrollbar ==
00796  *
00797  * The definition of a vertical scrollbar. This class is most of the time not
00798  * used directly. Instead it's used to build other items with scrollbars.
00799  *
00800  * The resolution for a vertical scrollbar also contains the following keys:
00801  * @start_table = config
00802  *     minimum_positioner_length (unsigned)
00803  *                                     The minumum size the positioner is
00804  *                                     allowed to be. The engine needs to know
00805  *                                     this in order to calculate the best size
00806  *                                     for the positioner. There is no maximum
00807  *                                     size for the positioner it should be
00808  *                                     scaleable for the entire size. (Of course
00809  *                                     it is possible to file a FR if this is
00810  *                                     really wanted.)
00811  *     top_offset (unsigned = 0)       The number of pixels at the top which
00812  *                                     can't be used by the positioner.
00813  *     bottom_offset (unsigned = 0)    The number of pixels at the bottom which
00814  *                                     can't be used by the positioner.
00815  * @end_table
00816  *
00817  * The following states exist:
00818  * * state_enabled, the vertical scrollbar is enabled.
00819  * * state_disabled, the vertical scrollbar is disabled.
00820  * * state_pressed, the left mouse button is down on the positioner of the vertical scrollbar.
00821  * * state_focussed, the mouse is over the positioner of the vertical scrollbar.
00822  */
00823 
00824     VALIDATE(minimum_positioner_length, 
00825         missing_mandatory_wml_key("resolution", "minimum_positioner_length"));
00826 
00827     // Note the order should be the same as the enum tstate is scrollbar.hpp.
00828     state.push_back(tstate_definition(cfg.child("state_enabled")));
00829     state.push_back(tstate_definition(cfg.child("state_disabled")));
00830     state.push_back(tstate_definition(cfg.child("state_pressed")));
00831     state.push_back(tstate_definition(cfg.child("state_focussed")));
00832 }
00833 
00834 twindow_definition::twindow_definition(const config& cfg) : 
00835     tpanel_definition(cfg)
00836 {
00837 /*WIKI 
00838  * @page = GUIToolkitWML
00839  * @order = 1_widget_window
00840  *
00841  * == Window ==
00842  *
00843  * The definition of a window. A window is a kind of panel see the panel for
00844  * which fields exist
00845  *
00846  */
00847 
00848     DBG_G_P << "Parsing window " << id << '\n';
00849 }
00850 
00851 tresolution_definition_* get_control(const std::string& control_type, const std::string& definition)
00852 {
00853     const tgui_definition::tcontrol_definition_map::const_iterator  
00854         control_definition = current_gui->second.control_definition.find(control_type);
00855 
00856     assert(control_definition != current_gui->second.control_definition.end());
00857 
00858     std::map<std::string, tcontrol_definition*>::const_iterator 
00859         control = control_definition->second.find(definition);
00860 
00861     if(control == control_definition->second.end()) {
00862         LOG_G << "Control: type '" << control_type << "' definition '" 
00863             << definition << "' not found, falling back to 'default'.\n";
00864         control = control_definition->second.find("default");
00865         assert(control != control_definition->second.end());
00866     }
00867 
00868     for(std::vector<tresolution_definition_*>::const_iterator 
00869             itor = (*control->second).resolutions.begin(),
00870             end = (*control->second).resolutions.end();
00871             itor != end;
00872             ++itor) {
00873 
00874         if(settings::screen_width <= (**itor).window_width &&
00875                 settings::screen_height <= (**itor).window_height) {
00876 
00877             return *itor;
00878         } else if (itor == end - 1) {
00879             return *itor;
00880         }
00881     }
00882 
00883     assert(false);
00884 }
00885 
00886 std::vector<twindow_builder::tresolution>::const_iterator get_window_builder(const std::string& type)
00887 {
00888     std::map<std::string, twindow_builder>::const_iterator 
00889         window = current_gui->second.window_types.find(type);
00890 
00891     if(true) { // FIXME Test for default gui.
00892         assert(window != current_gui->second.window_types.end());
00893     } else {
00894         // FIXME Get the defintion in the default gui and do an assertion test.
00895     }
00896 
00897     for(std::vector<twindow_builder::tresolution>::const_iterator 
00898             itor = window->second.resolutions.begin(),
00899             end = window->second.resolutions.end();
00900             itor != end;
00901             ++itor) {
00902 
00903         if(settings::screen_width <= itor->window_width &&
00904                 settings::screen_height <= itor->window_height) {
00905 
00906             return itor;
00907         } else if (itor == end - 1) {
00908             return itor;
00909         }
00910     }
00911 
00912     assert(false);
00913 }
00914 
00915 } // namespace gui2

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs