Eclipse SUMO - Simulation of Urban MObility
GNEUndoList.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // FXUndoList is pretty dandy but some features are missing:
19 // - we cannot find out wether we have currently begun an undo-group and
20 // thus abort() is hard to use.
21 // - onUpd-methods do not disable undo/redo while in an undo-group
22 //
23 // GNEUndoList inherits from FXUndoList and patches some methods. these are
24 // prefixed with p_
25 /****************************************************************************/
27 #include <netedit/GNEViewNet.h>
28 
29 #include "GNEApplicationWindow.h"
30 #include "GNEUndoList.h"
31 
32 
33 // ===========================================================================
34 // FOX callback mapping
35 // ===========================================================================
36 FXDEFMAP(GNEUndoList) GNEUndoListMap[] = {
37  //FXMAPFUNC(SEL_COMMAND, FXUndoList::ID_REVERT, FXUndoList::onCmdRevert),
38  //FXMAPFUNC(SEL_COMMAND, FXUndoList::ID_UNDO, FXUndoList::onCmdUndo),
39  //FXMAPFUNC(SEL_COMMAND, FXUndoList::ID_REDO, FXUndoList::onCmdRedo),
40  //FXMAPFUNC(SEL_COMMAND, FXUndoList::ID_UNDO_ALL, FXUndoList::onCmdUndoAll),
41  //FXMAPFUNC(SEL_COMMAND, FXUndoList::ID_REDO_ALL, FXUndoList::onCmdRedoAll),
42  //
43  //FXMAPFUNC(SEL_UPDATE, FXUndoList::ID_UNDO_COUNT, FXUndoList::onUpdUndoCount),
44  //FXMAPFUNC(SEL_UPDATE, FXUndoList::ID_REDO_COUNT, FXUndoList::onUpdRedoCount),
45  //FXMAPFUNC(SEL_UPDATE, FXUndoList::ID_CLEAR, FXUndoList::onUpdClear),
46  //FXMAPFUNC(SEL_UPDATE, FXUndoList::ID_REVERT, FXUndoList::onUpdRevert),
47  FXMAPFUNC(SEL_UPDATE, FXUndoList::ID_UNDO_ALL, GNEUndoList::p_onUpdUndo),
48  FXMAPFUNC(SEL_UPDATE, FXUndoList::ID_REDO_ALL, GNEUndoList::p_onUpdRedo),
49  FXMAPFUNC(SEL_UPDATE, FXUndoList::ID_UNDO, GNEUndoList::p_onUpdUndo),
50  FXMAPFUNC(SEL_UPDATE, FXUndoList::ID_REDO, GNEUndoList::p_onUpdRedo)
51 };
52 
53 
54 // ===========================================================================
55 // FOX-declarations
56 // ===========================================================================
57 FXIMPLEMENT_ABSTRACT(GNEUndoList, FXUndoList, GNEUndoListMap, ARRAYNUMBER(GNEUndoListMap))
58 
59 
60 // ===========================================================================
61 // member method definitions
62 // ===========================================================================
63 
65  FXUndoList(),
66  myGNEApplicationWindowParent(parent) {
67 }
68 
69 
70 void
71 GNEUndoList::p_begin(const std::string& description) {
72  myCommandGroups.push(new CommandGroup(description));
73  begin(myCommandGroups.top());
74 }
75 
76 
77 void
79  myCommandGroups.pop();
80  // check if net has to be updated
83  }
84  end();
85 }
86 
87 
88 void
90  // disable updating of interval bar (check viewNet due #7252)
93  }
94  p_abort();
95  clear();
96  // enable updating of interval bar again (check viewNet due #7252)
99  }
100 }
101 
102 
103 void
105  while (hasCommandGroup()) {
106  myCommandGroups.top()->undo();
107  myCommandGroups.pop();
108  abort();
109  }
110 }
111 
112 
113 void
115  if (myCommandGroups.size() > 0) {
116  myCommandGroups.top()->undo();
117  myCommandGroups.pop();
118  abort();
119  }
120 }
121 
122 
123 void
125  WRITE_DEBUG("Calling GNEUndoList::undo()");
126  FXUndoList::undo();
127  // update specific controls
129 }
130 
131 
132 void
134  WRITE_DEBUG("Calling GNEUndoList::redo()");
135  FXUndoList::redo();
136  // update specific controls
138 }
139 
140 
141 void
143  if (cmd->trueChange()) {
144  add(cmd, true);
145  } else {
146  delete cmd;
147  }
148 }
149 
150 
151 int
153  if (myCommandGroups.size() > 0) {
154  return myCommandGroups.top()->size();
155  } else {
156  return 0;
157  }
158 }
159 
160 
161 long
162 GNEUndoList::p_onUpdUndo(FXObject* sender, FXSelector, void*) {
163  // first check if Undo Menu command or button has to be disabled
164  bool enable = canUndo() && !hasCommandGroup() && myGNEApplicationWindowParent->isUndoRedoEnabled().empty();
165  // cast button (see #6209)
166  FXButton* button = dynamic_cast<FXButton*>(sender);
167  // enable or disable depending of "enable" flag
168  if (button) {
169  // avoid unnnecesary enables/disables (due flickering)
170  if (enable && !button->isEnabled()) {
171  sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), nullptr);
172  button->update();
173  } else if (!enable && button->isEnabled()) {
174  sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
175  button->update();
176  }
177  } else {
178  sender->handle(this, enable ? FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE) : FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
179  }
180  // cast menu command
181  FXMenuCommand* menuCommand = dynamic_cast<FXMenuCommand*>(sender);
182  // only set caption on menu command item
183  if (menuCommand) {
184  // change caption of FXMenuCommand
185  FXString caption = undoName();
186  // set caption of FXmenuCommand edit/undo
188  caption = ("Cannot Undo in the middle of " + myGNEApplicationWindowParent->isUndoRedoEnabled()).c_str();
189  } else if (hasCommandGroup()) {
190  caption = ("Cannot Undo in the middle of " + myCommandGroups.top()->getDescription()).c_str();
191  } else if (!canUndo()) {
192  caption = "Undo";
193  }
194  menuCommand->handle(this, FXSEL(SEL_COMMAND, FXMenuCaption::ID_SETSTRINGVALUE), (void*)&caption);
195  menuCommand->update();
196  }
197  return 1;
198 }
199 
200 
201 long
202 GNEUndoList::p_onUpdRedo(FXObject* sender, FXSelector, void*) {
203  // first check if Redo Menu command or button has to be disabled
204  bool enable = canRedo() && !hasCommandGroup() && myGNEApplicationWindowParent->isUndoRedoEnabled().empty();
205  // cast button (see #6209)
206  FXButton* button = dynamic_cast<FXButton*>(sender);
207  // enable or disable depending of "enable" flag
208  if (button) {
209  // avoid unnnecesary enables/disables (due flickering)
210  if (enable && !button->isEnabled()) {
211  sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE), nullptr);
212  button->update();
213  } else if (!enable && button->isEnabled()) {
214  sender->handle(this, FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
215  button->update();
216  }
217  } else {
218  sender->handle(this, enable ? FXSEL(SEL_COMMAND, FXWindow::ID_ENABLE) : FXSEL(SEL_COMMAND, FXWindow::ID_DISABLE), nullptr);
219  }
220  // cast menu command
221  FXMenuCommand* menuCommand = dynamic_cast<FXMenuCommand*>(sender);
222  // only set caption on menu command item
223  if (menuCommand) {
224  // change caption of FXMenuCommand
225  FXString caption = redoName();
226  // set caption of FXmenuCommand edit/undo
228  caption = ("Cannot Redo in the middle of " + myGNEApplicationWindowParent->isUndoRedoEnabled()).c_str();
229  } else if (hasCommandGroup()) {
230  caption = ("Cannot Redo in the middle of " + myCommandGroups.top()->getDescription()).c_str();
231  } else if (!canRedo()) {
232  caption = "Redo";
233  }
234  menuCommand->handle(this, FXSEL(SEL_COMMAND, FXMenuCaption::ID_SETSTRINGVALUE), (void*)&caption);
235  menuCommand->update();
236  }
237  return 1;
238 }
239 
240 
241 bool
243  return myCommandGroups.size() != 0;
244 }
245 
246 
247 GNEUndoList::CommandGroup::CommandGroup(std::string description) :
248  myDescription(description) {
249 }
250 
251 
252 const std::string&
254  return myDescription;
255 }
256 
257 
258 FXString
260  return ("Undo " + myDescription).c_str();
261 }
262 
263 
264 FXString
266  return ("Redo " + myDescription).c_str();
267 }
FXDEFMAP(GNEUndoList) GNEUndoListMap[]
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:286
The main window of the Netedit.
void updateControls()
update control contents after undo/redo or recompute
GNEViewNet * getViewNet()
get pointer to viewNet
const std::string & isUndoRedoEnabled() const
check if undo-redo is enabled
the function-object for an editing operation (abstract base)
bool trueChange()
wether original and new value differ
class CommandGroup
Definition: GNEUndoList.h:104
FXString undoName() const
get undo Name
FXString redoName() const
get redo name
CommandGroup(std::string description)
Constructor.
const std::string & getDescription()
get description
bool hasCommandGroup() const
Check if undoList has command group.
void undo()
undo the last command group
void p_add(GNEChange_Attribute *cmd)
special method, avoid empty changes, always execute
GNEApplicationWindow *const myGNEApplicationWindowParent
Definition: GNEUndoList.h:127
void p_clear()
clears the undo list (implies abort)
Definition: GNEUndoList.cpp:89
void p_begin(const std::string &description)
Begin undo command sub-group. This begins a new group of commands that are treated as a single comman...
Definition: GNEUndoList.cpp:71
std::stack< CommandGroup * > myCommandGroups
Definition: GNEUndoList.h:124
void redo()
redo the last command group
int currentCommandGroupSize() const
get size of current CommandGroup
void p_end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
Definition: GNEUndoList.cpp:78
long p_onUpdUndo(FXObject *, FXSelector, void *)
long p_onUpdRedo(FXObject *, FXSelector, void *)
event after Redo
void p_abort()
reverts and discards ALL active command groups
void p_abortLastCommandGroup()
reverts last command group
void enableIntervalBarUpdate()
enable interval bar update
void disableIntervalBarUpdate()
enable interval bar update
GNEViewNetHelper::IntervalBar & getIntervalBar()
get interval bar
void updateViewNet() const
Mark the entire GNEViewNet to be repainted later.
Definition: GNEViewNet.cpp:318