Merge the undo and redo stacks into a single class.

This is just the first step in upgrading undo_list, and there are not
many benefits yet.  Future steps will add functionality to the class
(right now it is just a wrapper) and improve the interface (the
current interface was chosen to minimize the changes needed to
existing code).
This commit is contained in:
J. Tyne 2012-11-21 16:56:24 +00:00
parent ee23d7a632
commit 90e214a901
11 changed files with 55 additions and 23 deletions

View File

@ -20,6 +20,7 @@
#include "move.hpp"
#include "undo.hpp"
#include "vision.hpp"
#include "../game_display.hpp"

View File

@ -23,10 +23,9 @@
struct map_location;
class replay;
class undo_list;
class unit;
#include "undo.hpp"
#include "../unit_map.hpp"
#include <vector>

View File

@ -76,7 +76,44 @@ struct undo_action {
bool is_recruit() const { return type == RECRUIT; }
};
typedef std::vector<undo_action> undo_list;
/// Class to store the actions that a player can undo and redo.
class undo_list {
public:
undo_list() :
undos_(), redos_()
{}
~undo_list() {}
void clear() { undos_.clear(); }
bool empty() const { return undos_.empty(); }
const undo_action & back() const { return undos_.back(); }
void push_back(const undo_action & action) { undos_.push_back(action); }
void pop_back() { undos_.pop_back(); }
// apply_shroud_changes() needs to step through undos_.
// (Will be removed once apply_shroud_changes() is made a member function.)
typedef std::vector<undo_action>::const_iterator iterator;
iterator begin() const { return undos_.begin(); }
iterator end() const { return undos_.end(); }
void clear_redo() { redos_.clear(); }
bool empty_redo() const { return redos_.empty(); }
const undo_action & back_redo() const { return redos_.back(); }
void push_back_redo(const undo_action & action) { redos_.push_back(action); }
void pop_back_redo() { redos_.pop_back(); }
private: // functions
/// Copying the undo list is probably an error, so it is not implemented.
undo_list(const undo_list &);
/// Assigning the undo list is probably an error, so it is not implemented.
undo_list & operator=(const undo_list &);
private: // data
std::vector<undo_action> undos_;
std::vector<undo_action> redos_;
};
/**
* Function to apply pending shroud changes in the undo stack.

View File

@ -136,7 +136,7 @@ gui::dialog_button_action::RESULT delete_recall_unit::button_pressed(int menu_se
recall_list.erase(dismissed_unit);
//clear the redo stack to avoid duplication of dismissals
resources::redo_stack->clear();
resources::undo_stack->clear_redo();
return gui::DELETE_ITEM;
} else {
return gui::CONTINUE_DIALOG;
@ -867,7 +867,7 @@ bool menu_handler::do_recruit(const std::string &name, int side_num,
//MP_COUNTDOWN grant time bonus for recruiting
current_team.set_action_bonus_count(1 + current_team.action_bonus_count());
resources::redo_stack->clear();
resources::undo_stack->clear_redo();
assert(new_unit.type());
resources::undo_stack->push_back(undo_action(new_unit, loc, recruited_from, undo_action::RECRUIT));
@ -1088,7 +1088,7 @@ bool menu_handler::do_recall(const unit& un, int side_num, const map_location& r
clear_undo_stack(side_num);
}
resources::redo_stack->clear();
resources::undo_stack->clear_redo();
gui_->redraw_minimap();
gui_->invalidate_game_status();
gui_->invalidate(recall_location);
@ -1203,7 +1203,7 @@ void menu_handler::undo(int side_num)
resources::whiteboard->on_gamestate_change();
}
recorder.undo();
resources::redo_stack->push_back(action);
resources::undo_stack->push_back_redo(action);
gui_->invalidate_unit();
gui_->invalidate_game_status();
@ -1213,7 +1213,7 @@ void menu_handler::undo(int side_num)
void menu_handler::redo(int side_num)
{
if(resources::redo_stack->empty())
if ( resources::undo_stack->empty_redo() )
return;
const events::command_disabler disable_commands;
@ -1221,8 +1221,8 @@ void menu_handler::redo(int side_num)
// Get the action to undo. (This will be placed on the undo stack, but
// only if the redo is successful.)
undo_action action = resources::redo_stack->back();
resources::redo_stack->pop_back();
undo_action action = resources::undo_stack->back_redo();
resources::undo_stack->pop_back_redo();
if (action.is_dismiss()) {
if(!current_team.persistent()) {

View File

@ -809,7 +809,7 @@ size_t mouse_handler::move_unit_along_route(const std::vector<map_location> & st
if(moves == 0)
return 0;
resources::redo_stack->clear();
resources::undo_stack->clear_redo();
if ( interrupted && moves + 1 < steps.size() ) {
// reselect the unit (for "press t to continue")
@ -1018,7 +1018,7 @@ void mouse_handler::attack_enemy_(const map_location& att_loc
//may fire event and modify things
apply_shroud_changes(*resources::undo_stack, side_num_);
resources::undo_stack->clear();
resources::redo_stack->clear();
resources::undo_stack->clear_redo();
unit_map::iterator attacker = find_unit(attacker_loc);
if(attacker == units_.end()

View File

@ -105,7 +105,6 @@ play_controller::play_controller(const config& level, game_state& state_of_game,
map_(game_config, level),
units_(),
undo_stack_(),
redo_stack_(),
whiteboard_manager_(),
xp_mod_(level["experience_modifier"].to_int(100)),
loading_game_(level["playing_team"].empty() == false),
@ -133,7 +132,6 @@ play_controller::play_controller(const config& level, game_state& state_of_game,
resources::controller = this;
resources::tod_manager = &tod_manager_;
resources::undo_stack = &undo_stack_;
resources::redo_stack = &redo_stack_;
resources::persist = &persist_;
persist_.start_transaction();
@ -881,7 +879,7 @@ bool play_controller::can_execute_command(hotkey::HOTKEY_COMMAND command, int in
return network::nconnections() > 0;
case hotkey::HOTKEY_REDO:
return !linger_ && !redo_stack_.empty() && !events::commands_disabled && !browse_;
return !linger_ && !undo_stack_.empty_redo() && !events::commands_disabled && !browse_;
case hotkey::HOTKEY_UNDO:
return !linger_ && !undo_stack_.empty() && !events::commands_disabled && !browse_;

View File

@ -220,7 +220,6 @@ protected:
gamemap map_;
unit_map units_;
undo_list undo_stack_;
undo_list redo_stack_;
//whiteboard manager
boost::scoped_ptr<wb::manager> whiteboard_manager_;

View File

@ -30,7 +30,6 @@ namespace resources
::tod_manager *tod_manager = NULL;
pathfind::manager *tunnels = NULL;
wb::manager *whiteboard = NULL;
std::vector<undo_action> *undo_stack = NULL;
std::vector<undo_action> *redo_stack = NULL;
undo_list *undo_stack = NULL;
persist_manager *persist = NULL;
}

View File

@ -28,7 +28,7 @@ class team;
class tod_manager;
class unit_map;
class persist_manager;
struct undo_action;
class undo_list;
namespace soundsource { class manager; }
@ -50,8 +50,7 @@ namespace resources
extern tod_manager *tod_manager;
extern pathfind::manager *tunnels;
extern wb::manager *whiteboard;
extern std::vector<undo_action> *undo_stack;
extern std::vector<undo_action> *redo_stack;
extern undo_list *undo_stack;
extern persist_manager *persist;
}

View File

@ -1083,7 +1083,7 @@ void manager::clear_undo()
{
apply_shroud_changes(*resources::undo_stack, viewer_side());
resources::undo_stack->clear();
resources::redo_stack->clear();
resources::undo_stack->clear_redo();
}
void manager::options_dlg()

View File

@ -183,7 +183,7 @@ public:
/** Determines whether or not the undo_stack should be cleared.
* @todo Only when there are networked allies and we have set a preferences option */
bool should_clear_undo() const {return true;}
/** Updates shroud and clears the undo_stack and redo_stack. */
/** Updates shroud and clears the undo_stack. */
void clear_undo();
/** Displays the whiteboard options dialog. */