1 // Copyright (C) 2006-2016 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "commands.hxx"
21 #include "guiContext.hxx"
23 #include "Catalog.hxx"
24 #include "RuntimeSALOME.hxx"
27 #include "YacsTrace.hxx"
33 using namespace YACS::HMI;
35 int Invocator::_ctr = 0;
40 _normalReverse = true;
43 //! the command is executed a first time after its registration for undo redo, then on redo
45 * Execute may induce subcommands to be registered during its execution.
46 * Subcommands must be deleted before redo, to be recreated by redo.
47 * CommandDestroy is a special case, where subcommands are registered before Execute, and
48 * undo action calls executeSubOnly instead of reverse. Subcommands pf CommandDestroy must
51 bool Command::execute()
53 if ( !GuiContext::getCurrent() || !GuiContext::getCurrent()->getInvoc() )
56 bool commandInProgress = !GuiContext::getCurrent()->getInvoc()->isSpecialReverse();
57 if (commandInProgress)
58 GuiContext::getCurrent()->getInvoc()->_commandsInProgress.push_back(this);
61 if (GuiContext::getCurrent()->getInvoc()->_isRedo && _normalReverse)
63 for (int i=0; i<_subCommands.size(); i++)
64 delete _subCommands[i];
68 if (ret) GuiContext::getCurrent()->setNotSaved(true);
70 if (commandInProgress)
71 GuiContext::getCurrent()->getInvoc()->_commandsInProgress.pop_back();
75 //! Reverse action: undo
76 /*! Recursive reverse of sub commands then local action
77 * @param isNormal: true for ordinary command, false for command Destroy
79 bool Command::reverse(bool isNormal)
82 if (! _subCommands.empty())
84 for (int i=0; i<_subCommands.size(); i++)
86 ret =_subCommands[i]->reverse(isNormal);
92 if (isNormal) // true for all commands but commandDestroy
95 ret = localExecute(); // subCommand of command Destroy
100 //! execute only sub commands in a reverse action
102 * for undo of commandDestroy, only sub commands of commandDestroy must be executed,
103 * via subcommand->reverse(false)
105 bool Command::executeSubOnly()
108 if (! _subCommands.empty())
110 for (int i=0; i<_subCommands.size(); i++)
112 ret =_subCommands[i]->reverse(false);
119 std::string Command::dump()
121 return "=== generic command dump ===";
124 std::string Command::recursiveDump(int level)
127 for (int i=0; i<level; i++) prefix += " ";
128 string ret = prefix + dump() + "\n";
129 for (int i=0; i<_subCommands.size(); i++)
130 ret += _subCommands[i]->recursiveDump(level+1);
134 void Command::addSubCommand(Command* command)
136 _subCommands.push_back(command);
143 Invocator::Invocator()
145 _commandsDone.clear();
146 _commandsUndone.clear();
147 _commandsInProgress.clear();
150 _specialReverse = false;
151 _undoCata = new YACS::ENGINE::Catalog("undoCata");
152 YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime();
153 _undoProc= runTime->createProc("undoProc");
156 void Invocator::add(Command* command)
158 DEBTRACE("Invocator::add");
161 if (GuiContext::getCurrent()->getInvoc()->isSpecialReverse())
166 if (_commandsInProgress.empty())
168 _commandsDone.push_back(command); // --- to do after execute ok
169 _commandsUndone.clear(); // --- undone stack is no more relevant
173 DEBTRACE("addSubCommand");
174 _commandsInProgress.back()->addSubCommand(command);
178 bool Invocator::undo()
180 DEBTRACE("Invocator::undo");
185 ret1 << "_commandsDone" << endl;
186 for (int i=0; i<_commandsDone.size(); i++)
187 ret1 << i << _commandsDone[i]->recursiveDump(2);
188 DEBTRACE(ret1.str());
190 ret2 << "_commandsUndone" << endl;
191 for (int i=0; i<_commandsUndone.size(); i++)
192 ret2 << i << _commandsUndone[i]->recursiveDump(2);
193 DEBTRACE(ret2.str());
196 if (! _commandsDone.empty())
198 bool isNormal = _commandsDone.back()->isNormalReverse();
199 _specialReverse = !isNormal;
202 ret = _commandsDone.back()->reverse(isNormal);
204 ret = _commandsDone.back()->executeSubOnly();
206 _commandsUndone.push_back(_commandsDone.back());
207 _commandsDone.pop_back();
208 _specialReverse = false;
213 ret1 << "_commandsDone" << endl;
214 for (int i=0; i<_commandsDone.size(); i++)
215 ret1 << i << _commandsDone[i]->recursiveDump(2);
216 DEBTRACE(ret1.str());
218 ret2 << "_commandsUndone" << endl;
219 for (int i=0; i<_commandsUndone.size(); i++)
220 ret2 << i << _commandsUndone[i]->recursiveDump(2);
221 DEBTRACE(ret2.str());
227 bool Invocator::redo()
229 DEBTRACE("Invocator::redo");
234 ret1 << "_commandsDone" << endl;
235 for (int i=0; i<_commandsDone.size(); i++)
236 ret1 << i << _commandsDone[i]->recursiveDump(2);
237 DEBTRACE(ret1.str());
239 ret2 << "_commandsUndone" << endl;
240 for (int i=0; i<_commandsUndone.size(); i++)
241 ret2 << i << _commandsUndone[i]->recursiveDump(2);
242 DEBTRACE(ret2.str());
245 if (! _commandsUndone.empty())
248 ret = _commandsUndone.back()->execute();
250 _commandsDone.push_back(_commandsUndone.back());
251 _commandsUndone.pop_back();
256 ret1 << "_commandsDone" << endl;
257 for (int i=0; i<_commandsDone.size(); i++)
258 ret1 << i << _commandsDone[i]->recursiveDump(2);
259 DEBTRACE(ret1.str());
261 ret2 << "_commandsUndone" << endl;
262 for (int i=0; i<_commandsUndone.size(); i++)
263 ret2 << i << _commandsUndone[i]->recursiveDump(2);
264 DEBTRACE(ret2.str());
270 std::list<std::string> Invocator::getDone()
272 list<string> listDone;
274 for (int i=0; i<_commandsDone.size(); i++)
275 listDone.push_back(_commandsDone[i]->recursiveDump());
279 std::list<std::string> Invocator::getUndone()
281 list<string> listUndone;
283 for (int i=0; i<_commandsUndone.size(); i++)
284 listUndone.push_back(_commandsUndone[i]->recursiveDump());