Split wml_menu_item and wmi_container into their own source files.

They are now under the game_events subdirectory.
This commit is contained in:
JaMiT 2013-10-26 22:30:40 -05:00
parent 2064b0c847
commit 1f77cb1fc3
14 changed files with 586 additions and 437 deletions

View file

@ -236,8 +236,12 @@
<Unit filename="../../src/game_events/entity_location.hpp" />
<Unit filename="../../src/game_events/handlers.cpp" />
<Unit filename="../../src/game_events/handlers.hpp" />
<Unit filename="../../src/game_events/menu_item.cpp" />
<Unit filename="../../src/game_events/menu_item.hpp" />
<Unit filename="../../src/game_events/pump.cpp" />
<Unit filename="../../src/game_events/pump.hpp" />
<Unit filename="../../src/game_events/wmi_container.cpp" />
<Unit filename="../../src/game_events/wmi_container.hpp" />
<Unit filename="../../src/game_preferences.cpp" />
<Unit filename="../../src/game_preferences.hpp" />
<Unit filename="../../src/game_preferences_display.cpp" />

View file

@ -329,8 +329,12 @@
<Unit filename="..\..\src\game_events\entity_location.hpp" />
<Unit filename="..\..\src\game_events\handlers.cpp" />
<Unit filename="..\..\src\game_events\handlers.hpp" />
<Unit filename="..\..\src\game_events\menu_item.cpp" />
<Unit filename="..\..\src\game_events\menu_item.hpp" />
<Unit filename="..\..\src\game_events\pump.cpp" />
<Unit filename="..\..\src\game_events\pump.hpp" />
<Unit filename="..\..\src\game_events\wmi_container.cpp" />
<Unit filename="..\..\src\game_events\wmi_container.hpp" />
<Unit filename="..\..\src\game_instance.cpp" />
<Unit filename="..\..\src\game_instance.hpp" />
<Unit filename="..\..\src\game_preferences.cpp" />

View file

@ -3499,8 +3499,12 @@
<File Name="../../src/game_events/entity_location.hpp"/>
<File Name="../../src/game_events/handlers.cpp"/>
<File Name="../../src/game_events/handlers.hpp"/>
<File Name="../../src/game_events/menu_item.cpp"/>
<File Name="../../src/game_events/menu_item.hpp"/>
<File Name="../../src/game_events/pump.cpp"/>
<File Name="../../src/game_events/pump.hpp"/>
<File Name="../../src/game_events/wmi_container.cpp"/>
<File Name="../../src/game_events/wmi_container.hpp"/>
</VirtualDirectory>
<VirtualDirectory Name="gui">
<VirtualDirectory Name="lib">

View file

@ -698,7 +698,9 @@ set(wesnoth-main_SRC
game_events/conditional_wml.cpp
game_events/entity_location.cpp
game_events/handlers.cpp
game_events/menu_item.cpp
game_events/pump.cpp
game_events/wmi_container.cpp
game_instance.cpp
game_preferences.cpp
game_preferences_display.cpp

View file

@ -265,7 +265,9 @@ wesnoth_sources = Split("""
game_events/conditional_wml.cpp
game_events/entity_location.cpp
game_events/handlers.cpp
game_events/menu_item.cpp
game_events/pump.cpp
game_events/wmi_container.cpp
game_instance.cpp
game_preferences.cpp
gamestatus.cpp

View file

@ -18,10 +18,11 @@
* excluding conditional action WML.
*/
#include "global.hpp"
#include "../global.hpp"
#include "action_wml.hpp"
#include "conditional_wml.hpp"
#include "handlers.hpp"
#include "menu_item.hpp"
#include "pump.hpp"
#include "../actions/create.hpp"

View file

@ -18,8 +18,9 @@
* (Typically, handlers are defined by [event] tags.)
*/
#include "global.hpp"
#include "../global.hpp"
#include "handlers.hpp"
#include "menu_item.hpp"
#include "pump.hpp"
#include "../formula_string_utils.hpp"

View file

@ -0,0 +1,183 @@
/*
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
* @file
* Definitions for a class that implements WML-defined (right-click) menu items.
*/
#include "../global.hpp"
#include "menu_item.hpp"
#include "conditional_wml.hpp"
#include "handlers.hpp"
#include "../game_config.hpp"
#include "../gamestatus.hpp"
#include "../log.hpp"
#include "../resources.hpp"
#include "../terrain_filter.hpp"
static lg::log_domain log_engine("engine");
#define ERR_NG LOG_STREAM(err, log_engine)
wml_menu_item::wml_menu_item(const std::string& id, const config* cfg) :
item_id_(id),
event_name_("menu item" + (id.empty() ? "" : ' ' + id)),
image_(),
description_(),
needs_select_(false),
show_if_(vconfig::empty_vconfig()),
filter_location_(vconfig::empty_vconfig()),
command_(),
default_hotkey_(),
use_hotkey_(true),
use_wml_menu_(true)
{
if(cfg != NULL) {
image_ = (*cfg)["image"].str();
description_ = (*cfg)["description"];
needs_select_ = (*cfg)["needs_select"].to_bool();
// use_hotkey is already a name of a member of this class.
const config::attribute_value & use_hotkey_attribute_value = (*cfg)["use_hotkey"];
if(use_hotkey_attribute_value.str() == "only" )
{
use_hotkey_ = true;
use_wml_menu_ = false;
}
else
{
use_hotkey_ = use_hotkey_attribute_value.to_bool(true);
use_wml_menu_ = true;
}
if (const config &c = cfg->child("show_if")) show_if_ = vconfig(c, true);
if (const config &c = cfg->child("filter_location")) filter_location_ = vconfig(c, true);
if (const config &c = cfg->child("command")) command_ = c;
if (const config &c = cfg->child("default_hotkey")) default_hotkey_ = c;
}
}
/**
* The image associated with this menu item.
* The returned string will not be empty; a default will be supplied if needed.
*/
const std::string & wml_menu_item::image() const
{
// Default the image?
return image_.empty() ? game_config::images::wml_menu : image_;
}
/**
* Returns whether or not *this is applicable given the context.
* Assumes game variables x1, y1, and unit have been set.
* @param[in] hex The hex where the menu will appear.
*/
bool wml_menu_item::can_show(const map_location & hex) const
{
// Failing the [show_if] tag means no show.
if ( !show_if_.empty() && !game_events::conditional_passed(show_if_) )
return false;
// Failing the [fiter_location] tag means no show.
if ( !filter_location_.empty() &&
!terrain_filter(filter_location_, *resources::units)(hex) )
return false;
// Failing to have a required selection means no show.
if ( needs_select_ && !resources::gamedata->last_selected.valid() )
return false;
// Passed all tests.
return true;
}
/**
* Writes *this to the provided config.
*/
void wml_menu_item::to_config(config & cfg) const
{
cfg["id"] = item_id_;
cfg["image"] = image_;
cfg["description"] = description_;
cfg["needs_select"] = needs_select_;
if ( use_hotkey_ && use_wml_menu_ )
cfg["use_hotkey"] = true;
if ( use_hotkey_ && !use_wml_menu_ )
cfg["use_hotkey"] = "only";
if ( !use_hotkey_ && use_wml_menu_ )
cfg["use_hotkey"] = false;
if ( !use_hotkey_ && !use_wml_menu_ )
{
ERR_NG << "Bad data: wml_menu_item with both use_wml_menu and use_hotkey set to false is not supposed to be possible.";
cfg["use_hotkey"] = false;
}
if ( !show_if_.empty() )
cfg.add_child("show_if", show_if_.get_config());
if ( !filter_location_.empty() )
cfg.add_child("filter_location", filter_location_.get_config());
if ( !command_.empty() )
cfg.add_child("command", command_);
if ( !default_hotkey_.empty() )
cfg.add_child("default_hotkey", default_hotkey_);
}
/**
* Updates *this based on @a vcfg.
*/
void wml_menu_item::update(const vconfig & vcfg)
{
if ( vcfg.has_attribute("image") )
image_ = vcfg["image"].str();
if ( vcfg.has_attribute("description") )
description_ = vcfg["description"].t_str();
if ( vcfg.has_attribute("needs_select") )
needs_select_ = vcfg["needs_select"].to_bool();
if ( const vconfig & child = vcfg.child("show_if") ) {
show_if_ = child;
show_if_.make_safe();
}
if ( const vconfig & child = vcfg.child("filter_location") ) {
filter_location_ = child;
filter_location_.make_safe();
}
if ( const vconfig & child = vcfg.child("default_hotkey") ) {
default_hotkey_ = child.get_parsed_config();
}
if ( vcfg.has_attribute("use_hotkey") ) {
const config::attribute_value & use_hotkey_attribute_value = vcfg["use_hotkey"];
if(use_hotkey_attribute_value.str() == "only")
{
use_hotkey_ = true;
use_wml_menu_ = false;
}
else
{
use_hotkey_ = use_hotkey_attribute_value.to_bool(true);
use_wml_menu_ = true;
}
}
if ( const vconfig & cmd = vcfg.child("command") ) {
const bool delayed = cmd["delayed_variable_substitution"].to_bool(true);
game_events::add_wmi_change(item_id_, delayed ? cmd.get_config() : cmd.get_parsed_config());
}
}

View file

@ -0,0 +1,92 @@
/*
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
* @file
* Declarations for a class that implements WML-defined (right-click) menu items.
*/
#ifndef GAME_EVENTS_MENU_ITEM_HPP_INCLUDED
#define GAME_EVENTS_MENU_ITEM_HPP_INCLUDED
#include "../config.hpp"
#include "../tstring.hpp"
#include "../variable.hpp"
struct map_location;
class wml_menu_item
{
public:
explicit wml_menu_item(const std::string& id, const config* cfg=NULL);
/// The identification of this item.
const std::string & id() const { return item_id_; }
/// The WML actions specified within this item.
const config & command() const { return command_; }
/// The text to display in the menu for this item.
const t_string & description() const { return description_; }
/// The name of the event to fire when this item is chosen.
const std::string & event_name() const { return event_name_; }
/// The image associated with this menu item.
const std::string & image() const;
/// If true, then the preceeding "select" event needs to be stored in the replay.
bool needs_select() const { return needs_select_; }
/// Config object containing the default hotkey.
const config & default_hotkey() const { return default_hotkey_; }
/// If true, allow using a hotkey to trigger this item.
bool use_hotkey() const { return use_hotkey_; }
/// If true, allow using the menu to trigger this item.
bool use_wml_menu() const { return use_wml_menu_; }
/// Returns whether or not *this is applicable given the context.
bool can_show(const map_location & hex) const;
/// Change the actions associated with this item.
/// (Internal bookkeeping only; the caller must still update the event handlers.)
void set_command(const config & cfg) { command_ = cfg; }
/// Writes *this to the provided config.
void to_config(config & cfg) const;
/// Updates *this based on @a vcfg.
void update(const vconfig & vcfg);
private:
/// The id of this menu item.
const std::string item_id_;
/// The name of this item's event(s); based on the item's id.
const std::string event_name_;
/// The image to display in the menu next to this item's description.
std::string image_;
/// The text to display in the menu for this item.
t_string description_;
/// Whether or not this event says it makes use of the last selected unit.
bool needs_select_;
/// A condition that must hold in order for this menu item to be visible.
/// (An empty condition always holds.)
vconfig show_if_; // When used, we need a vconfig instead of a config.
/// A location filter to be applied to the hex where the menu is invoked.
/// (An empty filter always passes.)
vconfig filter_location_; // When used, we need a vconfig instead of a config.
/// Actions to take when this item is chosen.
config command_;
/// Config object containing the default hotkey.
config default_hotkey_;
/// If true, allow using a hotkey to trigger this item.
bool use_hotkey_;
/// If true, allow using the menu to trigger this item.
bool use_wml_menu_;
};
#endif // GAME_EVENTS_MENU_ITEM_HPP_INCLUDED

View file

@ -0,0 +1,185 @@
/*
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
* @file
* Definitions for a container for wml_menu_item.
*/
#include "../global.hpp"
#include "wmi_container.hpp"
#include "handlers.hpp"
#include "menu_item.hpp"
#include "../config.hpp"
#include "../hotkeys.hpp"
#include "../log.hpp"
#include "../play_controller.hpp"
#include <boost/foreach.hpp>
static lg::log_domain log_engine("engine");
#define WRN_NG LOG_STREAM(warn, log_engine)
#define LOG_NG LOG_STREAM(info, log_engine)
wmi_container::wmi_container()
: wml_menu_items_()
{}
wmi_container::wmi_container(const wmi_container& container)
: wml_menu_items_()
{
copy(container.wml_menu_items_);
}
/**
* Performs a deep copy, replacing our current contents.
* Used by assignment and the copy constructor.
*/
void wmi_container::copy(const map_t & source)
{
// Safety measure.
if ( &source == &wml_menu_items_ )
return;
// Free up the old memory.
clear_wmi();
const map_t::const_iterator source_end = source.end();
for ( map_t::const_iterator itor = source.begin(); itor != source_end; ++itor )
// Deep copy.
wml_menu_items_[itor->first] = new wml_menu_item(*(itor->second));
}
void wmi_container::clear_wmi()
{
const map_t::iterator i_end = wml_menu_items_.end();
for ( map_t::iterator i = wml_menu_items_.begin(); i != i_end; ++i ) {
// Release the wml_menu_item.
delete i->second;
}
wml_menu_items_.clear();
}
/** Erases the item pointed to by @a pos. */
void wmi_container::erase(const iterator & pos)
{
const map_t::iterator & iter = pos.get(key());
// Release the wml_menu_item.
delete iter->second;
// Remove the now-defunct pointer from the map.
wml_menu_items_.erase(iter);
}
/** Erases the item with id @a key. */
wmi_container::size_type wmi_container::erase(const std::string & key)
{
// Locate the item to erase.
iterator pos = find(key);
if ( pos == end() )
// No such item.
return 0;
// Pass the buck.
erase(pos);
return 1; // Erased one item.
}
/**
* Returns an item with the given id.
* If one does not already exist, one will be created.
*/
wml_menu_item & wmi_container::get_item(const std::string& id)
{
// Try to insert a dummy value. This combines looking for an existing
// entry with insertion.
// the static cast fixes http://connect.microsoft.com/VisualStudio/feedback/details/520043/
// c++11's nullptr would be a better solution as soon as we support it.
map_t::iterator add_it = wml_menu_items_.insert(map_t::value_type(id, static_cast<wml_menu_item *>(NULL))).first;
// If we ended up with a dummy value, create an entry for it.
if ( add_it->second == NULL )
add_it->second = new wml_menu_item(id);
// Return the item.
return *add_it->second;
}
/**
* Initializes the implicit event handlers for inlined [command]s.
*/
void wmi_container::init_handlers() const
{
int wmi_count = 0;
// Loop through each menu item.
BOOST_FOREACH( const wml_menu_item & wmi, *this ) {
// If this menu item has a [command], add a handler for it.
const config & wmi_command = wmi.command();
if ( !wmi_command.empty() ) {
game_events::add_event_handler(wmi_command, true);
if ( wmi.use_hotkey() ) {
// Applying default hotkeys here currently does not work because
// the hotkeys are reset by play_controler::init_managers() ->
// display_manager::display_manager, which is called after this.
// The result is that default wml hotkeys will be ignored if wml
// hotkeys are set to default in the preferences menu. (They are
// still reapplied if set_menu_item is called again, for example
// by starting a new campaign.) Since it isn't that important
// I'll just leave it for now.
hotkey::add_wml_hotkey(play_controller::wml_menu_hotkey_prefix + wmi.id(), wmi.description(), wmi.default_hotkey());
}
}
// Count the menu items (for the diagnostic message).
++wmi_count;
}
// Diagnostic:
if ( wmi_count > 0 ) {
LOG_NG << wmi_count << " WML menu items found, loaded." << std::endl;
}
}
void wmi_container::to_config(config& cfg)
{
// Loop through our items.
for ( const_iterator j = begin(), wmi_end = end(); j != wmi_end; ++j )
// Add this item as a child of cfg.
j->to_config(cfg.add_child("menu_item"));
}
void wmi_container::set_menu_items(const config& cfg)
{
clear_wmi();
BOOST_FOREACH(const config &item, cfg.child_range("menu_item"))
{
if(!item.has_attribute("id")){ continue; }
std::string id = item["id"];
wml_menu_item*& mref = wml_menu_items_[id];
if(mref == NULL) {
mref = new wml_menu_item(id, &item);
} else {
WRN_NG << "duplicate menu item (" << id << ") while loading from config\n";
}
}
}

View file

@ -0,0 +1,97 @@
/*
Copyright (C) 2003 - 2013 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
* @file
* Declarations for a container for wml_menu_item.
*/
#ifndef GAME_EVENTS_WMI_CONTAINER_HPP_INCLUDED
#define GAME_EVENTS_WMI_CONTAINER_HPP_INCLUDED
#include "iterator.hpp"
#include <map>
class config;
class wml_menu_item;
/// A container of wml_menu_item.
class wmi_container{
/// The underlying storage type.
typedef std::map<std::string, wml_menu_item*> map_t;
/// The key for interaction with our iterators.
struct key {
/// Instructions for converting a map_t iterator to a wml_menu_item.
static const wml_menu_item & eval(const map_t::const_iterator & iter)
{ return *iter->second; }
};
public:
// Typedefs required of a container:
typedef wml_menu_item value_type;
typedef wml_menu_item * pointer;
typedef wml_menu_item & reference;
typedef const wml_menu_item & const_reference;
typedef map_t::difference_type difference_type;
typedef map_t::size_type size_type;
typedef util::iterator_extend <value_type, map_t, key, key> iterator;
typedef util::const_iterator_extend<value_type, map_t, key, key> const_iterator;
public:
wmi_container();
wmi_container(const wmi_container& container);
~wmi_container() { clear_wmi(); }
/// Assignment operator to support deep copies.
wmi_container & operator=(const wmi_container & that)
{ copy(that.wml_menu_items_); return *this; }
void clear_wmi();
/// Returns true if *this contains no data.
bool empty() const { return wml_menu_items_.empty(); }
/// Erases the item pointed to by @a pos.
void erase(const iterator & pos);
/// Erases the item with id @a key.
size_type erase(const std::string & key);
/// Initializes the implicit event handlers for inlined [command]s.
void init_handlers() const;
void to_config(config& cfg);
void set_menu_items(const config& cfg);
iterator find(const std::string & id) { return iterator(wml_menu_items_.find(id)); }
const_iterator find(const std::string & id) const { return const_iterator(wml_menu_items_.find(id)); }
/// Returns an item with the given id.
wml_menu_item & get_item(const std::string& id);
// Iteration support:
iterator begin() { return iterator(wml_menu_items_.begin()); }
iterator end() { return iterator(wml_menu_items_.end()); }
const_iterator begin() const { return const_iterator(wml_menu_items_.begin()); }
const_iterator end() const { return const_iterator(wml_menu_items_.end()); }
private:
/// Performs a deep copy, replacing our current contents.
void copy(const map_t & source);
private: // data
map_t wml_menu_items_;
};
#endif // GAME_EVENTS_WMI_CONTAINER_HPP_INCLUDED

View file

@ -23,26 +23,23 @@
#include "actions/create.hpp"
#include "filesystem.hpp"
#include "formula_string_utils.hpp"
#include "game_config.hpp"
#include "game_events/conditional_wml.hpp"
#include "game_events/handlers.hpp"
#include "game_preferences.hpp"
#include "gettext.hpp"
#include "hotkeys.hpp"
#include "log.hpp"
#include "play_controller.hpp"
#include "map.hpp"
#include "replay.hpp"
#include "resources.hpp"
#include "serialization/binary_or_text.hpp"
#include "statistics.hpp"
#include "team.hpp"
#include "terrain_filter.hpp"
#include "unit.hpp"
#include "unit_id.hpp"
#include "wesconfig.h"
#include "wml_exception.hpp"
#include "formula_string_utils.hpp"
#include "map.hpp"
#include "variable.hpp"
#include "pathfind/pathfind.hpp"
#include "whiteboard/side_actions.hpp"
#include "sound.hpp"
@ -76,304 +73,6 @@ static lg::log_domain log_enginerefac("enginerefac");
const std::string DEFAULT_DIFFICULTY("NORMAL");
wml_menu_item::wml_menu_item(const std::string& id, const config* cfg) :
item_id_(id),
event_name_("menu item" + (id.empty() ? "" : ' ' + id)),
image_(),
description_(),
needs_select_(false),
show_if_(vconfig::empty_vconfig()),
filter_location_(vconfig::empty_vconfig()),
command_(),
default_hotkey_(),
use_hotkey_(true),
use_wml_menu_(true)
{
if(cfg != NULL) {
image_ = (*cfg)["image"].str();
description_ = (*cfg)["description"];
needs_select_ = (*cfg)["needs_select"].to_bool();
// use_hotkey is already a name of a member of this class.
const config::attribute_value & use_hotkey_attribute_value = (*cfg)["use_hotkey"];
if(use_hotkey_attribute_value.str() == "only" )
{
use_hotkey_ = true;
use_wml_menu_ = false;
}
else
{
use_hotkey_ = use_hotkey_attribute_value.to_bool(true);
use_wml_menu_ = true;
}
if (const config &c = cfg->child("show_if")) show_if_ = vconfig(c, true);
if (const config &c = cfg->child("filter_location")) filter_location_ = vconfig(c, true);
if (const config &c = cfg->child("command")) command_ = c;
if (const config &c = cfg->child("default_hotkey")) default_hotkey_ = c;
}
}
/**
* The image associated with this menu item.
* The returned string will not be empty; a default will be supplied if needed.
*/
const std::string & wml_menu_item::image() const
{
// Default the image?
return image_.empty() ? game_config::images::wml_menu : image_;
}
/**
* Returns whether or not *this is applicable given the context.
* Assumes game variables x1, y1, and unit have been set.
* @param[in] hex The hex where the menu will appear.
*/
bool wml_menu_item::can_show(const map_location & hex) const
{
// Failing the [show_if] tag means no show.
if ( !show_if_.empty() && !game_events::conditional_passed(show_if_) )
return false;
// Failing the [fiter_location] tag means no show.
if ( !filter_location_.empty() &&
!terrain_filter(filter_location_, *resources::units)(hex) )
return false;
// Failing to have a required selection means no show.
if ( needs_select_ && !resources::gamedata->last_selected.valid() )
return false;
// Passed all tests.
return true;
}
/**
* Writes *this to the provided config.
*/
void wml_menu_item::to_config(config & cfg) const
{
cfg["id"] = item_id_;
cfg["image"] = image_;
cfg["description"] = description_;
cfg["needs_select"] = needs_select_;
if ( use_hotkey_ && use_wml_menu_ )
cfg["use_hotkey"] = true;
if ( use_hotkey_ && !use_wml_menu_ )
cfg["use_hotkey"] = "only";
if ( !use_hotkey_ && use_wml_menu_ )
cfg["use_hotkey"] = false;
if ( !use_hotkey_ && !use_wml_menu_ )
{
ERR_NG << "Bad data: wml_menu_item with both use_wml_menu and use_hotkey set to false is not supposed to be possible.";
cfg["use_hotkey"] = false;
}
if ( !show_if_.empty() )
cfg.add_child("show_if", show_if_.get_config());
if ( !filter_location_.empty() )
cfg.add_child("filter_location", filter_location_.get_config());
if ( !command_.empty() )
cfg.add_child("command", command_);
if ( !default_hotkey_.empty() )
cfg.add_child("default_hotkey", default_hotkey_);
}
/**
* Updates *this based on @a vcfg.
*/
void wml_menu_item::update(const vconfig & vcfg)
{
if ( vcfg.has_attribute("image") )
image_ = vcfg["image"].str();
if ( vcfg.has_attribute("description") )
description_ = vcfg["description"].t_str();
if ( vcfg.has_attribute("needs_select") )
needs_select_ = vcfg["needs_select"].to_bool();
if ( const vconfig & child = vcfg.child("show_if") ) {
show_if_ = child;
show_if_.make_safe();
}
if ( const vconfig & child = vcfg.child("filter_location") ) {
filter_location_ = child;
filter_location_.make_safe();
}
if ( const vconfig & child = vcfg.child("default_hotkey") ) {
default_hotkey_ = child.get_parsed_config();
}
if ( vcfg.has_attribute("use_hotkey") ) {
const config::attribute_value & use_hotkey_attribute_value = vcfg["use_hotkey"];
if(use_hotkey_attribute_value.str() == "only")
{
use_hotkey_ = true;
use_wml_menu_ = false;
}
else
{
use_hotkey_ = use_hotkey_attribute_value.to_bool(true);
use_wml_menu_ = true;
}
}
if ( const vconfig & cmd = vcfg.child("command") ) {
const bool delayed = cmd["delayed_variable_substitution"].to_bool(true);
game_events::add_wmi_change(item_id_, delayed ? cmd.get_config() : cmd.get_parsed_config());
}
}
wmi_container::wmi_container()
: wml_menu_items_()
{}
wmi_container::wmi_container(const wmi_container& container)
: wml_menu_items_()
{
copy(container.wml_menu_items_);
}
/**
* Performs a deep copy, replacing our current contents.
* Used by assignment and the copy constructor.
*/
void wmi_container::copy(const map_t & source)
{
// Safety measure.
if ( &source == &wml_menu_items_ )
return;
// Free up the old memory.
clear_wmi();
const map_t::const_iterator source_end = source.end();
for ( map_t::const_iterator itor = source.begin(); itor != source_end; ++itor )
// Deep copy.
wml_menu_items_[itor->first] = new wml_menu_item(*(itor->second));
}
void wmi_container::clear_wmi()
{
const map_t::iterator i_end = wml_menu_items_.end();
for ( map_t::iterator i = wml_menu_items_.begin(); i != i_end; ++i ) {
// Release the wml_menu_item.
delete i->second;
}
wml_menu_items_.clear();
}
/** Erases the item pointed to by @a pos. */
void wmi_container::erase(const iterator & pos)
{
const map_t::iterator & iter = pos.get(key());
// Release the wml_menu_item.
delete iter->second;
// Remove the now-defunct pointer from the map.
wml_menu_items_.erase(iter);
}
/** Erases the item with id @a key. */
wmi_container::size_type wmi_container::erase(const std::string & key)
{
// Locate the item to erase.
iterator pos = find(key);
if ( pos == end() )
// No such item.
return 0;
// Pass the buck.
erase(pos);
return 1; // Erased one item.
}
/**
* Returns an item with the given id.
* If one does not already exist, one will be created.
*/
wml_menu_item & wmi_container::get_item(const std::string& id)
{
// Try to insert a dummy value. This combines looking for an existing
// entry with insertion.
// the static cast fixes http://connect.microsoft.com/VisualStudio/feedback/details/520043/
// c++11's nullptr would be a better solution as soon as we support it.
map_t::iterator add_it = wml_menu_items_.insert(map_t::value_type(id, static_cast<wml_menu_item *>(NULL))).first;
// If we ended up with a dummy value, create an entry for it.
if ( add_it->second == NULL )
add_it->second = new wml_menu_item(id);
// Return the item.
return *add_it->second;
}
/**
* Initializes the implicit event handlers for inlined [command]s.
*/
void wmi_container::init_handlers() const
{
int wmi_count = 0;
// Loop through each menu item.
BOOST_FOREACH( const wml_menu_item & wmi, *this ) {
// If this menu item has a [command], add a handler for it.
const config & wmi_command = wmi.command();
if ( !wmi_command.empty() ) {
game_events::add_event_handler(wmi_command, true);
if ( wmi.use_hotkey() ) {
// Applying default hotkeys here currently does not work because
// the hotkeys are reset by play_controler::init_managers() ->
// display_manager::display_manager, which is called after this.
// The result is that default wml hotkeys will be ignored if wml
// hotkeys are set to default in the preferences menu. (They are
// still reapplied if set_menu_item is called again, for example
// by starting a new campaign.) Since it isn't that important
// I'll just leave it for now.
hotkey::add_wml_hotkey(play_controller::wml_menu_hotkey_prefix + wmi.id(), wmi.description(), wmi.default_hotkey());
}
}
// Count the menu items (for the diagnostic message).
++wmi_count;
}
// Diagnostic:
if ( wmi_count > 0 ) {
LOG_NG << wmi_count << " WML menu items found, loaded." << std::endl;
}
}
void wmi_container::to_config(config& cfg)
{
// Loop through our items.
for ( const_iterator j = begin(), wmi_end = end(); j != wmi_end; ++j )
// Add this item as a child of cfg.
j->to_config(cfg.add_child("menu_item"));
}
void wmi_container::set_menu_items(const config& cfg)
{
clear_wmi();
BOOST_FOREACH(const config &item, cfg.child_range("menu_item"))
{
if(!item.has_attribute("id")){ continue; }
std::string id = item["id"];
wml_menu_item*& mref = wml_menu_items_[id];
if(mref == NULL) {
mref = new wml_menu_item(id, &item);
} else {
WRN_NG << "duplicate menu item (" << id << ") while loading from config\n";
}
}
}
carryover::carryover(const config& side)
: add_(side["add"].to_bool())
, color_(side["color"])

View file

@ -19,13 +19,11 @@
#include "config.hpp"
#include "game_end_exceptions.hpp"
#include "iterator.hpp"
#include "game_events/wmi_container.hpp"
#include "map_location.hpp"
#include "mp_game_settings.hpp"
#include "random.hpp"
#include "simple_rng.hpp"
#include "tstring.hpp"
#include "variable.hpp"
#include <boost/shared_ptr.hpp>
@ -33,6 +31,7 @@ class config_writer;
class game_display;
class gamemap;
class scoped_wml_variable;
class t_string;
class team;
class unit_map;
@ -53,132 +52,6 @@ typedef boost::shared_ptr<team_builder> team_builder_ptr;
extern const std::string DEFAULT_DIFFICULTY;
class wml_menu_item
{
public:
explicit wml_menu_item(const std::string& id, const config* cfg=NULL);
/// The identification of this item.
const std::string & id() const { return item_id_; }
/// The WML actions specified within this item.
const config & command() const { return command_; }
/// The text to display in the menu for this item.
const t_string & description() const { return description_; }
/// The name of the event to fire when this item is chosen.
const std::string & event_name() const { return event_name_; }
/// The image associated with this menu item.
const std::string & image() const;
/// If true, then the preceeding "select" event needs to be stored in the replay.
bool needs_select() const { return needs_select_; }
/// Config object containing the default hotkey.
const config & default_hotkey() const { return default_hotkey_; }
/// If true, allow using a hotkey to trigger this item.
bool use_hotkey() const { return use_hotkey_; }
/// If true, allow using the menu to trigger this item.
bool use_wml_menu() const { return use_wml_menu_; }
/// Returns whether or not *this is applicable given the context.
bool can_show(const map_location & hex) const;
/// Change the actions associated with this item.
/// (Internal bookkeeping only; the caller must still update the event handlers.)
void set_command(const config & cfg) { command_ = cfg; }
/// Writes *this to the provided config.
void to_config(config & cfg) const;
/// Updates *this based on @a vcfg.
void update(const vconfig & vcfg);
private:
/// The id of this menu item.
const std::string item_id_;
/// The name of this item's event(s); based on the item's id.
const std::string event_name_;
/// The image to display in the menu next to this item's description.
std::string image_;
/// The text to display in the menu for this item.
t_string description_;
/// Whether or not this event says it makes use of the last selected unit.
bool needs_select_;
/// A condition that must hold in order for this menu item to be visible.
/// (An empty condition always holds.)
vconfig show_if_; // When used, we need a vconfig instead of a config.
/// A location filter to be applied to the hex where the menu is invoked.
/// (An empty filter always passes.)
vconfig filter_location_; // When used, we need a vconfig instead of a config.
/// Actions to take when this item is chosen.
config command_;
/// Config object containing the default hotkey.
config default_hotkey_;
/// If true, allow using a hotkey to trigger this item.
bool use_hotkey_;
/// If true, allow using the menu to trigger this item.
bool use_wml_menu_;
};
/// A container of wml_menu_item.
class wmi_container{
/// The underlying storage type.
typedef std::map<std::string, wml_menu_item*> map_t;
/// The key for interaction with our iterators.
struct key {
/// Instructions for converting a map_t iterator to a wml_menu_item.
static const wml_menu_item & eval(const map_t::const_iterator & iter)
{ return *iter->second; }
};
public:
// Typedefs required of a container:
typedef wml_menu_item value_type;
typedef wml_menu_item * pointer;
typedef wml_menu_item & reference;
typedef const wml_menu_item & const_reference;
typedef map_t::difference_type difference_type;
typedef map_t::size_type size_type;
typedef util::iterator_extend <value_type, map_t, key, key> iterator;
typedef util::const_iterator_extend<value_type, map_t, key, key> const_iterator;
public:
wmi_container();
wmi_container(const wmi_container& container);
~wmi_container() { clear_wmi(); }
/// Assignment operator to support deep copies.
wmi_container & operator=(const wmi_container & that)
{ copy(that.wml_menu_items_); return *this; }
void clear_wmi();
/// Returns true if *this contains no data.
bool empty() const { return wml_menu_items_.empty(); }
/// Erases the item pointed to by @a pos.
void erase(const iterator & pos);
/// Erases the item with id @a key.
size_type erase(const std::string & key);
/// Initializes the implicit event handlers for inlined [command]s.
void init_handlers() const;
void to_config(config& cfg);
void set_menu_items(const config& cfg);
iterator find(const std::string & id) { return iterator(wml_menu_items_.find(id)); }
const_iterator find(const std::string & id) const { return const_iterator(wml_menu_items_.find(id)); }
/// Returns an item with the given id.
wml_menu_item & get_item(const std::string& id);
// Iteration support:
iterator begin() { return iterator(wml_menu_items_.begin()); }
iterator end() { return iterator(wml_menu_items_.end()); }
const_iterator begin() const { return const_iterator(wml_menu_items_.begin()); }
const_iterator end() const { return const_iterator(wml_menu_items_.end()); }
private:
/// Performs a deep copy, replacing our current contents.
void copy(const map_t & source);
private: // data
map_t wml_menu_items_;
};
class carryover{
public:
carryover()

View file

@ -19,13 +19,17 @@
*/
#include "play_controller.hpp"
#include "actions/create.hpp"
#include "actions/heal.hpp"
#include "actions/undo.hpp"
#include "actions/vision.hpp"
#include "dialogs.hpp"
#include "formula_string_utils.hpp"
#include "game_events/handlers.hpp"
#include "game_events/menu_item.hpp"
#include "game_events/pump.hpp"
#include "game_preferences.hpp"
#include "gettext.hpp"
#include "halo.hpp"
#include "loadscreen.hpp"
@ -40,9 +44,7 @@
#include "replay.hpp"
#include "soundsource.hpp"
#include "tooltips.hpp"
#include "game_preferences.hpp"
#include "wml_exception.hpp"
#include "formula_string_utils.hpp"
#include "ai/manager.hpp"
#include "ai/testing.hpp"
#include "whiteboard/manager.hpp"