terrain_type::terrain_type(const config& cfg) : icon_image_(cfg["icon_image"]), minimap_image_(cfg["symbol_image"]), minimap_image_overlay_(), editor_image_(cfg["editor_image"].empty() ? "terrain/" + minimap_image_ + ".png" : "terrain/" + cfg["editor_image"].str() + ".png"), id_(cfg["id"]), name_(cfg["name"].t_str()), editor_name_(cfg["editor_name"].t_str()), description_(cfg["description"].t_str()), help_topic_text_(cfg["help_topic_text"].t_str()), number_(t_translation::read_terrain_code(cfg["string"])), mvt_type_(), vision_type_(), def_type_(), union_type_(), height_adjust_(cfg["unit_height_adjust"]), height_adjust_set_(!cfg["unit_height_adjust"].empty()), submerge_(cfg["submerge"].to_double()), submerge_set_(!cfg["submerge"].empty()), light_modification_(cfg["light"]), max_light_(cfg["max_light"].to_int(light_modification_)), min_light_(cfg["min_light"].to_int(light_modification_)), heals_(cfg["heals"]), income_description_(), income_description_ally_(), income_description_enemy_(), income_description_own_(), editor_group_(cfg["editor_group"]), village_(cfg["gives_income"].to_bool()), castle_(cfg["recruit_onto"].to_bool()), keep_(cfg["recruit_from"].to_bool()), overlay_(number_.base == t_translation::NO_LAYER), combined_(false), editor_default_base_(t_translation::read_terrain_code(cfg["default_base"])), hide_help_(cfg["hide_help"].to_bool(false)), hide_in_editor_(cfg["hidden"].to_bool(false)) { /** * @todo reenable these validations. The problem is that all MP * scenarios/campaigns share the same namespace and one rogue scenario * can avoid the player to create a MP game. So every scenario/campaign * should get its own namespace to be safe. */ #if 0 VALIDATE(number_ != t_translation::NONE_TERRAIN, missing_mandatory_wml_key("terrain_type", "string")); VALIDATE(!minimap_image_.empty(), missing_mandatory_wml_key("terrain_type", "symbol_image", "string", t_translation::write_terrain_code(number_))); VALIDATE(!name_.empty(), missing_mandatory_wml_key("terrain_type", "name", "string", t_translation::write_terrain_code(number_))); #endif if(editor_image_.empty()) { editor_image_ = "terrain/" + minimap_image_ + ".png"; } if(hide_in_editor_) { editor_image_ = ""; } mvt_type_.push_back(number_); def_type_.push_back(number_); vision_type_.push_back(number_); const t_translation::ter_list& alias = t_translation::read_list(cfg["aliasof"]); if(!alias.empty()) { mvt_type_ = alias; vision_type_ = alias; def_type_ = alias; } const t_translation::ter_list& mvt_alias = t_translation::read_list(cfg["mvt_alias"]); if(!mvt_alias.empty()) { mvt_type_ = mvt_alias; } const t_translation::ter_list& def_alias = t_translation::read_list(cfg["def_alias"]); if(!def_alias.empty()) { def_type_ = def_alias; } const t_translation::ter_list& vision_alias = t_translation::read_list(cfg["vision_alias"]); if(!vision_alias.empty()) { vision_type_ = vision_alias; } union_type_ = mvt_type_; union_type_.insert( union_type_.end(), def_type_.begin(), def_type_.end() ); union_type_.insert( union_type_.end(), vision_type_.begin(), vision_type_.end() ); // remove + and - union_type_.erase(std::remove(union_type_.begin(), union_type_.end(), t_translation::MINUS), union_type_.end()); union_type_.erase(std::remove(union_type_.begin(), union_type_.end(), t_translation::PLUS), union_type_.end()); // remove doubles std::sort(union_type_.begin(),union_type_.end()); union_type_.erase(std::unique(union_type_.begin(), union_type_.end()), union_type_.end()); //mouse over message are only shown on villages if(village_) { income_description_ = cfg["income_description"]; if(income_description_ == "") { income_description_ = _("Village"); } income_description_ally_ = cfg["income_description_ally"]; if(income_description_ally_ == "") { income_description_ally_ = _("Allied village"); } income_description_enemy_ = cfg["income_description_enemy"]; if(income_description_enemy_ == "") { income_description_enemy_ = _("Enemy village"); } income_description_own_ = cfg["income_description_own"]; if(income_description_own_ == "") { income_description_own_ = _("Owned village"); } } }
twindow_builder::tresolution::ttip::ttip(const config& cfg, const std::string& tagname) : id(cfg["id"]) { VALIDATE(!id.empty(), missing_mandatory_wml_key("[window][resolution][" + tagname + "]", "id")); }
/*WIKI * @begin{tag}{name="tip"}{min="0"}{max="-1"} * @begin{table}{config} * source & t_string & & Author * text & t_string & & Text of the tip. * @end{table} * @end{tag}{name="tip"} * @end{parent}{name="gui/"} */ const std::string& tgui_definition::read(const config& cfg) { id = cfg["id"].str(); description = cfg["description"]; VALIDATE(!id.empty(), missing_mandatory_wml_key("gui", "id")); VALIDATE(!description.empty(), missing_mandatory_wml_key("gui", "description")); DBG_GUI_P << "Parsing gui " << id << '\n'; /***** Control definitions *****/ for(auto & widget_type : registred_widget_type()) { widget_type.second(*this, widget_type.first, cfg, nullptr); } /***** Window types *****/ for(const auto & w : cfg.child_range("window")) { std::pair<std::string, twindow_builder> child; child.first = child.second.read(w); window_types.insert(child); } if(id == "default") { // The default gui needs to define all window types since we're the // fallback in case another gui doesn't define the window type. for(std::vector<std::string>::const_iterator itor = registered_window_types().begin(); itor != registered_window_types().end(); ++itor) { const std::string error_msg( "Window not defined in WML: '" + *itor + "'. Perhaps a mismatch between data and source versions." " Try --data-dir <trunk-dir>"); VALIDATE(window_types.find(*itor) != window_types.end(), error_msg); } } /***** settings *****/ /** * @todo Regarding sounds: * Need to evaluate but probably we want the widget definition be able to: * - Override the default (and clear it). This will allow toggle buttons in * a * listbox to sound like a toggle panel. * - Override the default and above per instance of the widget, some buttons * can give a different sound. */ const config& settings = cfg.child("settings"); popup_show_delay_ = settings["popup_show_delay"]; popup_show_time_ = settings["popup_show_time"]; help_show_time_ = settings["help_show_time"]; double_click_time_ = settings["double_click_time"]; repeat_button_repeat_time_ = settings["repeat_button_repeat_time"]; VALIDATE(double_click_time_, missing_mandatory_wml_key("settings", "double_click_time")); sound_button_click_ = settings["sound_button_click"].str(); sound_toggle_button_click_ = settings["sound_toggle_button_click"].str(); sound_toggle_panel_click_ = settings["sound_toggle_panel_click"].str(); sound_slider_adjust_ = settings["sound_slider_adjust"].str(); has_helptip_message_ = settings["has_helptip_message"]; VALIDATE(!has_helptip_message_.empty(), missing_mandatory_wml_key("[settings]", "has_helptip_message")); tips_ = tips::load(cfg); return id; }
/*WIKI * @page = GUIToolkitWML * @order = 1_window * @begin{parent}{name=gui/window/} * == Resolution == * @begin{tag}{name="resolution"}{min="0"}{max="-1"} * @begin{table}{config} * window_width & unsigned & 0 & Width of the application window. $ * window_height & unsigned & 0 & Height of the application window. $ * * * automatic_placement & bool & true & * Automatically calculate the best size for the window and place it. If * automatically placed ''vertical_placement'' and ''horizontal_placement'' * can be used to modify the final placement. If not automatically placed * the ''width'' and ''height'' are mandatory. $ * * * x & f_unsigned & 0 & X coordinate of the window to show. $ * y & f_unsigned & 0 & Y coordinate of the window to show. $ * width & f_unsigned & 0 & Width of the window to show. $ * height & f_unsigned & 0 & Height of the window to show. $ * * reevaluate_best_size & f_bool & false & * The foo $ * * functions & function & "" & * The function definitions s available for the formula fields in window. $ * * vertical_placement & v_align & "" & * The vertical placement of the window. $ * * horizontal_placement & h_align & "" & * The horizontal placement of the window. $ * * * maximum_width & unsigned & 0 & * The maximum width of the window (only used for automatic placement). $ * * maximum_height & unsigned & 0 & * The maximum height of the window (only used for automatic placement). $ * * * click_dismiss & bool & false & * Does the window need click dismiss behavior? Click dismiss behavior * means that any mouse click will close the dialog. Note certain widgets * will automatically disable this behavior since they need to process the * clicks as well, for example buttons do need a click and a misclick on * button shouldn't close the dialog. NOTE with some widgets this behavior * depends on their contents (like scrolling labels) so the behavior might * get changed depending on the data in the dialog. NOTE the default * behavior might be changed since it will be disabled when can't be used * due to widgets which use the mouse, including buttons, so it might be * wise to set the behavior explicitly when not wanted and no mouse using * widgets are available. This means enter, escape or an external source * needs to be used to close the dialog (which is valid). $ * * * definition & string & "default" & * Definition of the window which we want to show. $ * * * linked_group & sections & [] & A group of linked widget sections. $ * * * tooltip & section & & * Information regarding the tooltip for this window. $ * * helptip & section & & * Information regarding the helptip for this window. $ * * * grid & grid & & The grid with the widgets to show. $ * @end{table} * @begin{tag}{name="linked_group"}{min=0}{max=-1} * A linked_group section has the following fields: * @begin{table}{config} * id & string & & The unique id of the group (unique in this * window). $ * fixed_width & bool & false & Should widget in this group have the same * width. $ * fixed_height & bool & false & Should widget in this group have the same * height. $ * @end{table} * @end{tag}{name="linked_group"} * A linked group needs to have at least one size fixed. * @begin{tag}{name="tooltip"}{min=0}{max=1} * A tooltip and helptip section have the following field: * @begin{table}{config} * id & string & & The id of the tip to show. * Note more fields will probably be added later on. * @end{table}{config} * @end{tag}{name=tooltip} * @begin{tag}{name="foreground"}{min=0}{max=1} * @end{tag}{name="foreground"} * @begin{tag}{name="background"}{min=0}{max=1} * @end{tag}{name="background"} * @end{tag}{name="resolution"} * @end{parent}{name=gui/window/} * @begin{parent}{name=gui/window/resolution/} * @begin{tag}{name="helptip"}{min=0}{max=1}{super="gui/window/resolution/tooltip"} * @end{tag}{name="helptip"} * @end{parent}{name=gui/window/resolution/} */ twindow_builder::tresolution::tresolution(const config& cfg) : window_width(cfg["window_width"]) , window_height(cfg["window_height"]) , automatic_placement(cfg["automatic_placement"].to_bool(true)) , x(cfg["x"]) , y(cfg["y"]) , width(cfg["width"]) , height(cfg["height"]) , reevaluate_best_size(cfg["reevaluate_best_size"]) , functions() , vertical_placement(implementation::get_v_align(cfg["vertical_placement"])) , horizontal_placement( implementation::get_h_align(cfg["horizontal_placement"])) , maximum_width(cfg["maximum_width"]) , maximum_height(cfg["maximum_height"]) , click_dismiss(cfg["click_dismiss"].to_bool()) , definition(cfg["definition"]) , linked_groups() , tooltip(cfg.child_or_empty("tooltip"), "tooltip") , helptip(cfg.child_or_empty("helptip"), "helptip") , grid(0) { if(!cfg["functions"].empty()) { game_logic::formula(cfg["functions"], &functions).evaluate(); } const config& c = cfg.child("grid"); VALIDATE(c, _("No grid defined.")); grid = std::make_shared<tbuilder_grid>(tbuilder_grid(c)); if(!automatic_placement) { VALIDATE(width.has_formula() || width(), missing_mandatory_wml_key("resolution", "width")); VALIDATE(height.has_formula() || height(), missing_mandatory_wml_key("resolution", "height")); } DBG_GUI_P << "Window builder: parsing resolution " << window_width << ',' << window_height << '\n'; if(definition.empty()) { definition = "default"; } for(const auto & lg : cfg.child_range("linked_group")) { tlinked_group linked_group; linked_group.id = lg["id"].str(); linked_group.fixed_width = lg["fixed_width"].to_bool(); linked_group.fixed_height = lg["fixed_height"].to_bool(); VALIDATE(!linked_group.id.empty(), missing_mandatory_wml_key("linked_group", "id")); if(!(linked_group.fixed_width || linked_group.fixed_height)) { utils::string_map symbols; symbols["id"] = linked_group.id; t_string msg = vgettext("Linked '$id' group needs a 'fixed_width' or " "'fixed_height' key.", symbols); FAIL(msg); } linked_groups.push_back(linked_group); } }
tslider_definition::tresolution::tresolution(const config& cfg) : tresolution_definition_(cfg) , minimum_positioner_length(cfg["minimum_positioner_length"]) , maximum_positioner_length(cfg["maximum_positioner_length"]) , left_offset(cfg["left_offset"]) , right_offset(cfg["right_offset"]) { /*WIKI * @page = GUIWidgetDefinitionWML * @order = 1_slider * * == Slider == * * @macro = slider_description * * @begin{parent}{name="gui/"} * @begin{tag}{name="slider_definition"}{min=0}{max=-1}{super="generic/widget_definition"} * @begin{tag}{name="resolution"}{min=0}{max=-1}{super="generic/widget_definition/resolution"} * @begin{table}{config} * minimum_positioner_length & unsigned & & * The minimum size the positioner is * allowed to be. The engine needs to know * this in order to calculate the best size * for the positioner. $ * maximum_positioner_length & unsigned & 0 & * The maximum size the positioner is * allowed to be. If minimum and maximum are * the same value the positioner is fixed * size. If the maximum is 0 (and the * minimum not) there's no maximum. $ * left_offset & unsigned & 0 & The number of pixels at the left side * which can't be used by the positioner. $ * right_offset & unsigned & 0 & The number of pixels at the right side * which can't be used by the positioner. $ * @end{table} * * The following states exist: * * state_enabled, the slider is enabled. * * state_disabled, the slider is disabled. * * state_pressed, the left mouse button is down on the positioner of the * slider. * * state_focussed, the mouse is over the positioner of the slider. * @begin{tag}{name="state_enabled"}{min=0}{max=1}{super="generic/state"} * @end{tag}{name="state_enabled"} * @begin{tag}{name="state_disabled"}{min=0}{max=1}{super="generic/state"} * @end{tag}{name="state_disabled"} * @begin{tag}{name="state_pressed"}{min=0}{max=1}{super="generic/state"} * @end{tag}{name="state_pressed"} * @begin{tag}{name="state_focussed"}{min=0}{max=1}{super="generic/state"} * @end{tag}{name="state_focussed"} * @end{tag}{name="resolution"} * @end{tag}{name="slider_definition"} * @end{parent}{name="gui/"} */ VALIDATE(minimum_positioner_length , missing_mandatory_wml_key( "resolution" , "minimum_positioner_length")); // Note the order should be the same as the enum tstate is slider.hpp. state.push_back(tstate_definition(cfg.child("state_enabled"))); state.push_back(tstate_definition(cfg.child("state_disabled"))); state.push_back(tstate_definition(cfg.child("state_pressed"))); state.push_back(tstate_definition(cfg.child("state_focussed"))); }