Line data Source code
1 : /* Copyright (C) 2010 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "CommandProc.h"
21 :
22 : #include <cassert>
23 : #include <algorithm>
24 :
25 : //////////////////////////////////////////////////////////////////////////
26 :
27 0 : template<typename T> T next_it(T x) { T t = x; return ++t; }
28 :
29 0 : template<typename T> void delete_fn(T* v) { delete v; }
30 :
31 : //////////////////////////////////////////////////////////////////////////
32 :
33 : using namespace AtlasMessage;
34 :
35 : namespace AtlasMessage {
36 :
37 0 : CommandProc& GetCommandProc()
38 : {
39 0 : static CommandProc commandProc;
40 0 : return commandProc;
41 : }
42 :
43 0 : cmdHandlers& GetCmdHandlers()
44 : {
45 0 : static cmdHandlers h;
46 0 : return h;
47 : }
48 : }
49 :
50 :
51 0 : CommandProc::CommandProc()
52 : {
53 : // Start the list with a NULL, so m_CurrentCommand can point at
54 : // something even when the command stack is empty
55 0 : m_Commands.push_back(NULL);
56 :
57 0 : m_CurrentCommand = m_Commands.begin();
58 0 : }
59 :
60 0 : CommandProc::~CommandProc()
61 : {
62 : // Make sure Destroy has been called before now (to avoid
63 : // problems from the destruction order of static variables)
64 0 : ENSURE(!m_Commands.size());
65 0 : }
66 :
67 0 : void CommandProc::Destroy()
68 : {
69 0 : std::for_each(m_Commands.begin(), m_Commands.end(), delete_fn<Command>);
70 0 : m_Commands.clear();
71 0 : }
72 :
73 0 : void CommandProc::Submit(Command* cmd)
74 : {
75 : // If some commands have been undone at the time we insert this new one,
76 : // delete and remove them all.
77 0 : std::for_each(next_it(m_CurrentCommand), m_Commands.end(), delete_fn<Command>);
78 0 : m_Commands.erase(next_it(m_CurrentCommand), m_Commands.end());
79 0 : assert(next_it(m_CurrentCommand) == m_Commands.end());
80 :
81 0 : m_CurrentCommand = m_Commands.insert(next_it(m_CurrentCommand), cmd);
82 :
83 0 : (*m_CurrentCommand)->Do();
84 0 : }
85 :
86 0 : void CommandProc::Undo()
87 : {
88 0 : if (m_CurrentCommand != m_Commands.begin())
89 : {
90 0 : (*m_CurrentCommand)->Undo();
91 0 : --m_CurrentCommand;
92 : }
93 0 : }
94 :
95 0 : void CommandProc::Redo()
96 : {
97 0 : if (next_it(m_CurrentCommand) != m_Commands.end())
98 : {
99 0 : ++m_CurrentCommand;
100 0 : (*m_CurrentCommand)->Redo();
101 : }
102 0 : }
103 :
104 0 : void CommandProc::Merge()
105 : {
106 0 : if (m_CurrentCommand == m_Commands.begin())
107 : {
108 0 : debug_warn(L"Merge illogic: no commands");
109 0 : return;
110 : }
111 :
112 0 : if (next_it(m_CurrentCommand) != m_Commands.end())
113 : {
114 0 : debug_warn(L"Merge illogic: not at stack top");
115 0 : return;
116 : }
117 :
118 0 : cmdIt prev = m_CurrentCommand;
119 0 : --prev;
120 :
121 0 : if (prev == m_Commands.begin())
122 : {
123 0 : debug_warn(L"Merge illogic: only 1 command");
124 0 : return;
125 : }
126 :
127 0 : if ((*prev)->GetType() != (*m_CurrentCommand)->GetType())
128 : {
129 0 : const char* a = (*prev)->GetType();
130 0 : const char* b = (*m_CurrentCommand)->GetType();
131 0 : debug_printf("[incompatible: %s -> %s]\n", a, b);
132 0 : debug_warn(L"Merge illogic: incompatible command");
133 0 : return;
134 : }
135 :
136 0 : (*m_CurrentCommand)->Merge(*prev);
137 :
138 0 : delete *m_CurrentCommand;
139 0 : m_Commands.erase(m_CurrentCommand);
140 :
141 0 : m_CurrentCommand = prev;
142 : }
|