Gridarta Editor
UndoModel.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2023 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.model.undo;
21 
22 import java.util.ArrayList;
23 import java.util.List;
31 import org.jetbrains.annotations.NotNull;
32 
40 public class UndoModel<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> {
41 
45  @NotNull
47 
51  @NotNull
53 
57  @NotNull
59 
64  @NotNull
65  private final List<UndoState<G, A, R>> undoStack = new ArrayList<>();
66 
72  private int undoStackIndex;
73 
78 
86  this.gameObjectFactory = gameObjectFactory;
87  this.gameObjectMatchers = gameObjectMatchers;
88  this.mapTransactionListener = mapTransactionListener;
89  }
90 
96  @NotNull
99  }
100 
106  private void addUndoState(@NotNull final UndoState<G, A, R> undoState) {
107  discardAllRedo();
108 
109  assert undoStackIndex == undoStack.size();
110  undoStack.add(undoState);
111  undoStackIndex = undoStack.size();
112  }
113 
118  public void trimToSize(final int maxUndoStates) {
119  while (undoStack.size() > maxUndoStates) {
120  if (canRedo()) { // prefer discarding redo over undo information
121  discardRedo();
122  } else {
123  discardUndo();
124  }
125  }
126  }
127 
133  public boolean canUndo() {
134  return undoStackIndex > 0;
135  }
136 
142  public boolean canRedo() {
143  return undoStackIndex < undoStack.size();
144  }
145 
150  public String undoName() {
151  if (undoStackIndex <= 0) {
152  throw new IllegalStateException("undo stack is empty");
153  }
154 
155  return undoStack.get(undoStackIndex - 1).getName();
156  }
157 
162  public String redoName() {
163  if (undoStackIndex >= undoStack.size()) {
164  throw new IllegalStateException("redo stack is empty");
165  }
166 
167  return undoStack.get(undoStackIndex).getName();
168  }
169 
175  @NotNull
177  if (undoStackIndex <= 0) {
178  throw new IllegalStateException("undo stack is empty");
179  }
180 
181  undoStackIndex--;
182  final UndoState<G, A, R> result = undoStack.get(undoStackIndex);
183  type = UndoType.UNDO;
184  return result;
185  }
186 
192  @NotNull
194  if (undoStackIndex >= undoStack.size()) {
195  throw new IllegalStateException("redo stack is empty");
196  }
197 
198  final UndoState<G, A, R> result = undoStack.get(undoStackIndex);
199  undoStackIndex++;
200  type = UndoType.REDO;
201  return result;
202  }
203 
208  public void finish(@NotNull final UndoState<G, A, R> undoState) {
209  switch (type) {
210  case NORMAL:
211  addUndoState(undoState);
212  break;
213 
214  case UNDO:
215  undoStack.set(undoStackIndex, undoState);
216  type = UndoType.NORMAL;
217  break;
218 
219  case REDO:
220  undoStack.set(undoStackIndex - 1, undoState);
221  type = UndoType.NORMAL;
222  break;
223  }
224  }
225 
229  public void finish() {
230  final int index;
231  switch (type) {
232  default:
233  case NORMAL:
234  return;
235 
236  case UNDO:
237  index = undoStackIndex;
238  break;
239 
240  case REDO:
241  index = undoStackIndex - 1;
242  break;
243  }
244 
245  final UndoState<G, A, R> prevUndoState = undoStack.get(index);
246  final String name = prevUndoState.getName();
247  final A mapArchObject = prevUndoState.getMapArchObject();
248  final UndoState<G, A, R> undoState = new UndoState<>(name, mapArchObject);
250  undoStack.set(index, undoState);
251  type = UndoType.NORMAL;
252  }
253 
257  private void discardAllRedo() {
258  while (undoStackIndex < undoStack.size()) {
259  discardRedo();
260  }
261  }
262 
266  private void discardRedo() {
267  assert !undoStack.isEmpty();
268  assert undoStackIndex < undoStack.size();
269  undoStack.remove(undoStack.size() - 1);
270  }
271 
275  private void discardUndo() {
276  assert !undoStack.isEmpty();
277  assert undoStackIndex > 0;
278  undoStack.remove(0);
279  undoStackIndex--;
280  }
281 
282 }
net.sf.gridarta.model.undo.UndoType.REDO
REDO
A redo operation is executing.
Definition: UndoType.java:41
name
name
Definition: ArchetypeTypeSetParserTest-ignoreDefaultAttribute1-result.txt:2
net.sf.gridarta.model.undo.UndoModel.type
UndoType type
The type for recording undo information.
Definition: UndoModel.java:77
net.sf.gridarta.model.gameobject.GameObjectFactory
Abstract factory for creating GameObject instances.
Definition: GameObjectFactory.java:31
net.sf.gridarta.model.undo.UndoModel.undoStackIndex
int undoStackIndex
Current index into undoStack.
Definition: UndoModel.java:72
net.sf.gridarta.model.undo.UndoState.getMapArchObject
A getMapArchObject()
Returns the map arch object before the operation started.
Definition: UndoState.java:107
net.sf.gridarta
Base package of all Gridarta classes.
net.sf.gridarta.model.undo.UndoModel.discardUndo
void discardUndo()
Discard one "undo" information.
Definition: UndoModel.java:275
net.sf.gridarta.model.undo.UndoState.setSavedSquares
void setSavedSquares(@NotNull final SavedSquares< G, A, R > savedSquares)
Records the affected map squares.
Definition: UndoState.java:81
net.sf.gridarta.model.mapmodel.MapTransactionListener
Interface for listeners listening on map transactions of MapModels.
Definition: MapTransactionListener.java:33
net.sf.gridarta.model.undo.UndoModel.undoStack
final List< UndoState< G, A, R > > undoStack
The undo stack.
Definition: UndoModel.java:65
net.sf
net.sf.gridarta.model.mapmodel
Definition: AboveFloorInsertionMode.java:20
net.sf.gridarta.model.archetype
Definition: AbstractArchetype.java:20
net.sf.gridarta.model.undo.UndoModel.redo
UndoState< G, A, R > redo()
Perform a "redo" operation.
Definition: UndoModel.java:193
net.sf.gridarta.model.gameobject.GameObject
Reflects a game object (object on a map).
Definition: GameObject.java:36
net.sf.gridarta.model.undo.UndoModel.addUndoState
void addUndoState(@NotNull final UndoState< G, A, R > undoState)
Add a new undo state to the undo stack.
Definition: UndoModel.java:106
net.sf.gridarta.model.undo.UndoModel.discardRedo
void discardRedo()
Discard one "redo" information.
Definition: UndoModel.java:266
net.sf.gridarta.model.mapmodel.SavedSquares
Records a set of changed map squares.
Definition: SavedSquares.java:41
net.sf.gridarta.model.undo.UndoModel.mapTransactionListener
final MapTransactionListener< G, A, R > mapTransactionListener
The stored MapTransactionListener.
Definition: UndoModel.java:58
net.sf.gridarta.model.gameobject
GameObjects are the objects based on Archetypes found on maps.
Definition: AbstractGameObject.java:20
net
net.sf.gridarta.model.undo.UndoModel.finish
void finish()
Finishes an undo or redo operation.
Definition: UndoModel.java:229
net.sf.gridarta.model.undo.UndoState.getName
String getName()
Return the name of the operation.
Definition: UndoState.java:71
net.sf.gridarta.model.match
Classes related to matching {GameObjects}, so called { net.sf.gridarta.model.match....
Definition: AndGameObjectMatcher.java:20
net.sf.gridarta.model.maparchobject.MapArchObject
Interface for MapArchObjects.
Definition: MapArchObject.java:40
net.sf.gridarta.model.match.GameObjectMatchers
Maintains GameObjectMatcher instances.
Definition: GameObjectMatchers.java:40
net.sf.gridarta.model.undo.UndoModel.canUndo
boolean canUndo()
Return whether an "undo" operation is possible.
Definition: UndoModel.java:133
net.sf.gridarta.model.undo.UndoModel.undoName
String undoName()
Return the "undo" operation name.
Definition: UndoModel.java:150
net.sf.gridarta.model.undo.UndoState
Holds information to undo/redo one edit operation.
Definition: UndoState.java:34
net.sf.gridarta.model.undo.UndoModel.gameObjectMatchers
final GameObjectMatchers gameObjectMatchers
The GameObjectMatchers to use.
Definition: UndoModel.java:52
net.sf.gridarta.model.undo.UndoModel.UndoModel
UndoModel(@NotNull final GameObjectFactory< G, A, R > gameObjectFactory, @NotNull final GameObjectMatchers gameObjectMatchers, @NotNull final MapTransactionListener< G, A, R > mapTransactionListener)
Creates a new instance.
Definition: UndoModel.java:85
net.sf.gridarta.model
net.sf.gridarta.model.archetype.Archetype
Reflects an Archetype.
Definition: Archetype.java:41
net.sf.gridarta.model.undo.UndoType
Represents the type of undo recording.
Definition: UndoType.java:26
net.sf.gridarta.model.undo.UndoModel.redoName
String redoName()
Return the "redo" operation name.
Definition: UndoModel.java:162
net.sf.gridarta.model.undo.UndoType.NORMAL
NORMAL
Normal operation: appends changes to undo stack.
Definition: UndoType.java:31
net.sf.gridarta.model.undo.UndoModel.getMapTransactionListener
MapTransactionListener< G, A, R > getMapTransactionListener()
Returns the MapTransactionListener that was passed to the constructor.
Definition: UndoModel.java:97
net.sf.gridarta.model.undo.UndoModel.trimToSize
void trimToSize(final int maxUndoStates)
Discard old undo information.
Definition: UndoModel.java:118
net.sf.gridarta.model.maparchobject
Definition: AbstractMapArchObject.java:20
net.sf.gridarta.model.undo.UndoModel
Maintains the undo state for one map control.
Definition: UndoModel.java:40
net.sf.gridarta.model.undo.UndoModel.undo
UndoState< G, A, R > undo()
Perform an "undo" operation.
Definition: UndoModel.java:176
net.sf.gridarta.model.undo.UndoModel.finish
void finish(@NotNull final UndoState< G, A, R > undoState)
Finishes an undo or redo operation.
Definition: UndoModel.java:208
net.sf.gridarta.model.undo.UndoType.UNDO
UNDO
An undo operation is executing.
Definition: UndoType.java:36
net.sf.gridarta.model.undo.UndoModel.canRedo
boolean canRedo()
Return whether a "redo" operation is possible.
Definition: UndoModel.java:142
net.sf.gridarta.model.undo.UndoModel.gameObjectFactory
final GameObjectFactory< G, A, R > gameObjectFactory
The GameObjectFactory to use.
Definition: UndoModel.java:46
net.sf.gridarta.model.undo.UndoModel.discardAllRedo
void discardAllRedo()
Discard all "redo" information.
Definition: UndoModel.java:257