Adapt wmi_container to use smart pointers.

This may make it possible to remove the explicit buffering of
WML menu item changes, but that is for a future commit.
This commit is contained in:
JaMiT 2013-11-10 12:38:47 -06:00
parent 93be97c278
commit 7341d0190b
4 changed files with 36 additions and 38 deletions

View file

@ -52,6 +52,15 @@ wmi_container::wmi_container(const wmi_container& container)
copy(container.wml_menu_items_);
}
/**
* Destructor.
* Default implementation, but defined here because this function needs to be
* able to see wml_menu_item's destructor.
*/
wmi_container::~wmi_container()
{
}
/**
* Performs a deep copy, replacing our current contents.
@ -64,23 +73,12 @@ void wmi_container::copy(const map_t & source)
return;
// Free up the old memory.
clear_wmi();
wml_menu_items_.clear();
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();
wml_menu_items_[itor->first].reset(new wml_menu_item(*(itor->second)));
}
/** Erases the item with id @a key. */
@ -99,9 +97,7 @@ wmi_container::size_type wmi_container::erase(const std::string & id)
remove_wmi_change(id);
remove_event_handler(id);
// Release the wml_menu_item.
delete iter->second;
// Remove the now-defunct pointer from the map.
// Remove the item from the map.
wml_menu_items_.erase(iter);
return 1; // Erased one item.
@ -182,14 +178,11 @@ 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;
map_t::iterator add_it = wml_menu_items_.insert(map_t::value_type(id, item_ptr())).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);
if ( !add_it->second )
add_it->second.reset(new wml_menu_item(id));
// Return the item.
return *add_it->second;
@ -202,7 +195,7 @@ wml_menu_item & wmi_container::get_item(const std::string& id)
* @param[out] descriptions Menu item text will be pushed onto @descriptions (in the same order as @a items).
*/
void wmi_container::get_items(const map_location& hex,
std::vector<const wml_menu_item *> & items,
std::vector<boost::shared_ptr<const wml_menu_item> > & items,
std::vector<std::string> & descriptions) const
{
size_t item_count = 0;
@ -276,15 +269,15 @@ void wmi_container::set_item(const std::string& id, const vconfig& menu_item)
*/
void wmi_container::set_menu_items(const config& cfg)
{
clear_wmi();
wml_menu_items_.clear();
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);
item_ptr & mref = wml_menu_items_[id];
if ( !mref ) {
mref.reset(new wml_menu_item(id, &item));
} else {
WRN_NG << "duplicate menu item (" << id << ") while loading from config\n";
}

View file

@ -22,6 +22,8 @@
#include "iterator.hpp"
#include <boost/shared_ptr.hpp>
#include <map>
#include <vector>
@ -38,7 +40,7 @@ class wml_menu_item;
/// A container of wml_menu_item.
class wmi_container{
/// Pointers to our elements.
typedef wml_menu_item * item_ptr;
typedef boost::shared_ptr<wml_menu_item> item_ptr;
/// The underlying storage type.
typedef std::map<std::string, item_ptr> map_t;
/// The key for interaction with our iterators.
@ -64,13 +66,12 @@ public:
public:
wmi_container();
wmi_container(const wmi_container& container);
~wmi_container() { clear_wmi(); }
~wmi_container();
/// 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 with the provided @a id.
@ -82,7 +83,7 @@ public:
bool fire_item(const std::string & id, const map_location & hex) const;
/// Returns the menu items that can be shown for the given location.
void get_items(const map_location& hex,
std::vector<const wml_menu_item *> & items,
std::vector<boost::shared_ptr<const wml_menu_item> > & items,
std::vector<std::string> & descriptions) const;
/// Initializes the implicit event handlers for inlined [command]s.
void init_handlers() const;

View file

@ -812,7 +812,7 @@ bool play_controller::execute_command(const hotkey::hotkey_command& cmd, int ind
// Load the game by throwing load_game_exception
throw game::load_game_exception(savenames_[i],false,false,false,"");
} else if (i < wml_commands_.size() && wml_commands_[i] != NULL) {
} else if ( i < wml_commands_.size() && wml_commands_[i] ) {
wml_commands_[i]->fire_event(mouse_handler_.get_last_hex());
return true;
}
@ -834,7 +834,7 @@ bool play_controller::can_execute_command(const hotkey::hotkey_command& cmd, int
if(index >= 0) {
unsigned i = static_cast<unsigned>(index);
if((i < savenames_.size() && !savenames_[i].empty())
|| (i < wml_commands_.size() && wml_commands_[i] != NULL)) {
|| (i < wml_commands_.size() && wml_commands_[i])) {
return true;
}
}
@ -1184,9 +1184,9 @@ void play_controller::expand_wml_commands(std::vector<std::string>& items)
// End the "for" loop.
break;
}
// Pad the commands with NULL (keeps the indices of items and
// Pad the commands with null pointers (keeps the indices of items and
// wml_commands_ synced).
wml_commands_.push_back(NULL);
wml_commands_.push_back(const_item_ptr());
}
}
@ -1270,8 +1270,8 @@ bool play_controller::in_context_menu(hotkey::HOTKEY_COMMAND command) const
std::string play_controller::get_action_image(hotkey::HOTKEY_COMMAND command, int index) const
{
if(index >= 0 && index < static_cast<int>(wml_commands_.size())) {
const game_events::wml_menu_item* const wmi = wml_commands_[index];
if(wmi != NULL) {
const const_item_ptr wmi = wml_commands_[index];
if ( wmi ) {
return wmi->image();
}
}

View file

@ -27,6 +27,7 @@
#include "gamestatus.hpp"
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
class game_display;
class game_state;
@ -259,6 +260,9 @@ protected:
void update_gui_to_player(const int team_index, const bool observe = false);
private:
/// A smart pointer used when retrieving menu items.
typedef boost::shared_ptr<const game_events::wml_menu_item> const_item_ptr;
void init(CVideo &video);
// Expand AUTOSAVES in the menu items, setting the real savenames.
void expand_autosaves(std::vector<std::string>& items);
@ -266,7 +270,7 @@ private:
std::vector<std::string> savenames_;
void expand_wml_commands(std::vector<std::string>& items);
std::vector<const game_events::wml_menu_item *> wml_commands_;
std::vector<const_item_ptr> wml_commands_;
bool victory_when_enemies_defeated_;
bool remove_from_carryover_on_leaders_loss_;