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-2015 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 
85  public UndoModel(@NotNull final GameObjectFactory<G, A, R> gameObjectFactory, @NotNull final GameObjectMatchers gameObjectMatchers, @NotNull final MapTransactionListener<G, A, R> mapTransactionListener) {
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);
249  undoState.setSavedSquares(new SavedSquares<>(gameObjectFactory, gameObjectMatchers));
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 }
final GameObjectMatchers gameObjectMatchers
The GameObjectMatchers to use.
Definition: UndoModel.java:52
String undoName()
Return the "undo" operation name.
Definition: UndoModel.java:150
Maintains the undo state for one map control.
Definition: UndoModel.java:40
This package contains classes related to matching GameObjects, so called GameObjectMatchers.
void setSavedSquares(@NotNull final SavedSquares< G, A, R > savedSquares)
Records the affected map squares.
Definition: UndoState.java:82
boolean canRedo()
Return whether a "redo" operation is possible.
Definition: UndoModel.java:142
REDO
A redo operation is executing.
Definition: UndoType.java:41
String getName()
Return the name of the operation.
Definition: UndoState.java:71
void finish(@NotNull final UndoState< G, A, R > undoState)
Finishes an undo or redo operation.
Definition: UndoModel.java:208
Holds information to undo/redo one edit operation.
Definition: UndoState.java:34
Represents the type of undo recording.
Definition: UndoType.java:26
Base package of all Gridarta classes.
NORMAL
Normal operation: appends changes to undo stack.
Definition: UndoType.java:31
Interface for listeners listening on map transactions of MapModels.
void discardRedo()
Discard one "redo" information.
Definition: UndoModel.java:266
Reflects a game object (object on a map).
Definition: GameObject.java:36
Abstract factory for creating GameObject instances.
boolean canUndo()
Return whether an "undo" operation is possible.
Definition: UndoModel.java:133
GameObjects are the objects based on Archetypes found on maps.
MapTransactionListener< G, A, R > getMapTransactionListener()
Returns the MapTransactionListener that was passed to the constructor.
Definition: UndoModel.java:97
int undoStackIndex
Current index into undoStack.
Definition: UndoModel.java:72
Maintains GameObjectMatcher instances.
final GameObjectFactory< G, A, R > gameObjectFactory
The GameObjectFactory to use.
Definition: UndoModel.java:46
UndoState< G, A, R > undo()
Perform an "undo" operation.
Definition: UndoModel.java:176
final MapTransactionListener< G, A, R > mapTransactionListener
The stored MapTransactionListener.
Definition: UndoModel.java:58
void discardUndo()
Discard one "undo" information.
Definition: UndoModel.java:275
String redoName()
Return the "redo" operation name.
Definition: UndoModel.java:162
void addUndoState(@NotNull final UndoState< G, A, R > undoState)
Add a new undo state to the undo stack.
Definition: UndoModel.java:106
UndoState< G, A, R > redo()
Perform a "redo" operation.
Definition: UndoModel.java:193
UNDO
An undo operation is executing.
Definition: UndoType.java:36
Records a set of changed map squares.
void finish()
Finishes an undo or redo operation.
Definition: UndoModel.java:229
void discardAllRedo()
Discard all "redo" information.
Definition: UndoModel.java:257
final List< UndoState< G, A, R > > undoStack
The undo stack.
Definition: UndoModel.java:65
A getMapArchObject()
Returns the map arch object before the operation started.
Definition: UndoState.java:109
void trimToSize(final int maxUndoStates)
Discard old undo information.
Definition: UndoModel.java:118
UndoType type
The type for recording undo information.
Definition: UndoModel.java:77
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