This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
/** @file | |
* @brief undo redo command class | |
* @author S.F. (Satoshi Fujiwara) | |
*/ | |
#include <stack> | |
namespace sf { | |
namespace model { | |
struct command_manager; | |
struct command_interface | |
{ | |
virtual ~command_interface(){}; | |
virtual const bool can_undo() const throw() = 0; | |
virtual const bool can_redo() const throw() = 0; | |
virtual const bool is_terminate() const throw() = 0; | |
virtual void undo() = 0; | |
virtual void redo() = 0; | |
virtual void execute() = 0; | |
virtual const std::wstring& name() const throw() = 0; | |
}; | |
struct abstract_command : public command_interface | |
{ | |
abstract_command(const bool terminate) | |
: m_terminate(terminate){} | |
abstract_command(const abstract_command& src) | |
: m_terminate(src.m_terminate) {} | |
virtual ~abstract_command(){}; | |
virtual const bool is_terminate() const throw() {return m_terminate;} | |
virtual void execute() {redo();} | |
virtual const std::wstring& name() const throw() = 0; | |
protected: | |
bool m_terminate; | |
}; | |
struct command : public abstract_command | |
{ | |
typedef boost::function<void () > func_type; | |
command(const std::wstring& command_name,const func_type& exec_func,const func_type& undo_func,const bool term = true) | |
: abstract_command(term),m_name(command_name),m_undo_func(undo_func),m_exec_func(exec_func),m_terminate(term) | |
{ | |
//m_undo_func = undo_func; | |
//m_exec_func = exec_func; | |
//m_terminate = term; | |
}; | |
command(const std::wstring& command_name,const func_type& exec_func,const bool term = true) | |
: abstract_command(term),m_name(command_name),m_exec_func(exec_func),m_terminate(term) | |
{ | |
//m_exec_func = exec_func; | |
//m_terminate = term; | |
}; | |
~command(){}; | |
const bool can_undo() const throw() | |
{ | |
return !m_undo_func.empty(); | |
}; | |
const bool can_redo() const throw() | |
{ | |
return !m_exec_func.empty(); | |
}; | |
const bool is_terminate() const throw() { return m_terminate;}; | |
void undo(){m_undo_func();}; | |
void redo(){m_exec_func();}; | |
void execute(){m_exec_func();}; | |
const std::wstring& name() const throw() {return m_name;} | |
private: | |
func_type m_undo_func; | |
func_type m_exec_func; | |
bool m_terminate; | |
std::wstring m_name; | |
static void null_func(){}; | |
}; | |
struct command_manager | |
{ | |
typedef boost::function<void (command_manager&)> changed_evt_func; | |
typedef boost::ptr_deque<sf::model::command_interface> container_type; | |
command_manager(){}; | |
~command_manager(){}; | |
void add(command_interface* exec_command) | |
{ | |
if(exec_command->can_undo()) | |
{ | |
m_redo.clear(); | |
m_undo.push_front(exec_command); | |
m_func(*this); | |
} | |
} | |
void undo() | |
{ | |
bool term_ = false; | |
while(!term_ && !m_undo.empty()) | |
{ | |
// (_T("undo() size: %d \n"),m_undo.size()); | |
m_undo.front().undo(); | |
term_ = m_undo.front().is_terminate(); | |
m_redo.push_front(m_undo.pop_front().release()); | |
// m_undo.pop_front(); | |
} | |
if(!m_func.empty()) | |
{ | |
m_func(*this); | |
} | |
} | |
void redo() | |
{ | |
bool term_ = false; | |
while(!term_ && !m_redo.empty()) | |
{ | |
m_redo.front().redo(); | |
term_ = m_redo.front().is_terminate(); | |
m_undo.push_front(m_redo.pop_front().release()); | |
// m_redo.pop_front(); | |
} | |
if(!m_func.empty()) | |
{ | |
m_func(*this); | |
} | |
} | |
void clear() | |
{ | |
m_undo.clear(); | |
m_redo.clear(); | |
if(!m_func.empty()) | |
{ | |
m_func(*this); | |
} | |
} | |
const container_type& undo_buf() const throw() {return m_undo;} | |
const container_type& redo_buf() const throw() {return m_redo;} | |
const bool is_undo(){return !m_undo.empty();}; | |
const bool is_redo(){return !m_undo.empty();}; | |
void event_func(const changed_evt_func& func){m_func = func;}; | |
private: | |
changed_evt_func m_func; | |
container_type m_undo; | |
container_type m_redo; | |
}; | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment