Gridarta Editor
ShiftProcessor.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.gui.misc;
21 
22 import java.awt.Point;
23 import java.awt.Rectangle;
24 import java.util.Collection;
25 import java.util.LinkedList;
26 import java.util.List;
37 import net.sf.gridarta.utils.Size2D;
38 import org.jetbrains.annotations.NotNull;
39 import org.jetbrains.annotations.Nullable;
40 
46 public class ShiftProcessor<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> {
47 
51  @NotNull
53 
57  @NotNull
58  private final MapView<G, A, R> mapView;
59 
63  @NotNull
64  private final MapModel<G, A, R> mapModel;
65 
69  @NotNull
71 
75  @Nullable
76  private MapGrid mapGrid;
77 
81  @Nullable
82  private Rectangle selRec;
83 
87  private int dx;
88 
92  private int dy;
93 
102  this.mapViewSettings = mapViewSettings;
103  this.mapView = mapView;
104  this.mapModel = mapModel;
105  this.insertionModeSet = insertionModeSet;
106  }
107 
113  public boolean canShift(@NotNull final Direction dir) {
116  if (selRec == null) {
117  return false;
118  }
119 
120  assert mapGrid != null;
121  final Size2D size = mapGrid.getSize();
122 
123  dx = dir.getDx();
124  dy = dir.getDy();
125  if (dx < 0) {
126  assert selRec != null;
127  if (selRec.x + dx < 0) {
128  return false;
129  }
130  } else if (dx > 0) {
131  assert selRec != null;
132  if (selRec.x + selRec.width + dx > size.getWidth()) {
133  return false;
134  }
135  }
136 
137  if (dy < 0) {
138  assert selRec != null;
139  if (selRec.y + dy < 0) {
140  return false;
141  }
142  } else if (dy > 0) {
143  assert selRec != null;
144  if (selRec.y + selRec.height + dy > size.getHeight()) {
145  return false;
146  }
147  }
148 
149  return true;
150  }
151 
157  public void shift(@NotNull final Direction dir) {
158  if (canShift(dir)) {
159  final Point pos = new Point();
160  mapModel.beginTransaction("Shift");
161  try {
163  try {
164  switch (dir) {
165  case NORTH:
166  for (int x = selRec.x; x < selRec.x + selRec.width; x++) {
167  pos.x = x;
168  pos.y = selRec.y;
169  shift(pos, selRec.height);
170  }
171  break;
172 
173  case EAST:
174  for (int y = selRec.y; y < selRec.y + selRec.height; y++) {
175  pos.x = selRec.x + selRec.width - 1;
176  pos.y = y;
177  shift(pos, selRec.width);
178  }
179  break;
180 
181  case SOUTH:
182  for (int x = selRec.x; x < selRec.x + selRec.width; x++) {
183  pos.x = x;
184  pos.y = selRec.y + selRec.height - 1;
185  shift(pos, selRec.height);
186  }
187  break;
188 
189  case WEST:
190  for (int y = selRec.y; y < selRec.y + selRec.height; y++) {
191  pos.x = selRec.x;
192  pos.y = y;
193  shift(pos, selRec.width);
194  }
195  break;
196 
197  case NORTH_EAST:
198  for (int x = selRec.x; x < selRec.x + selRec.width; x++) {
199  pos.x = x;
200  pos.y = selRec.y;
201  shift(pos, Math.min(x - selRec.x + 1, selRec.height));
202  }
203  for (int y = selRec.y + 1; y < selRec.y + selRec.height; y++) {
204  pos.x = selRec.x + selRec.width - 1;
205  pos.y = y;
206  shift(pos, Math.min(selRec.y + selRec.height - y, selRec.width));
207  }
208  break;
209 
210  case SOUTH_EAST:
211  for (int x = selRec.x; x < selRec.x + selRec.width; x++) {
212  pos.x = x;
213  pos.y = selRec.y + selRec.height - 1;
214  shift(pos, Math.min(x - selRec.x + 1, selRec.height));
215  }
216  for (int y = selRec.y + selRec.height - 2; y >= selRec.y; y--) {
217  pos.x = selRec.x + selRec.width - 1;
218  pos.y = y;
219  shift(pos, Math.min(y - selRec.y + 1, selRec.width));
220  }
221  break;
222 
223  case SOUTH_WEST:
224  for (int y = selRec.y; y < selRec.y + selRec.height; y++) {
225  pos.x = selRec.x;
226  pos.y = y;
227  shift(pos, Math.min(y - selRec.y + 1, selRec.width));
228  }
229  for (int x = selRec.x + 1; x < selRec.x + selRec.width; x++) {
230  pos.x = x;
231  pos.y = selRec.y + selRec.height - 1;
232  shift(pos, Math.min(selRec.x + selRec.width - x, selRec.height));
233  }
234  break;
235 
236  case NORTH_WEST:
237  for (int y = selRec.y + selRec.height - 1; y >= selRec.y; y--) {
238  pos.x = selRec.x;
239  pos.y = y;
240  shift(pos, Math.min(selRec.y + selRec.height - y, selRec.width));
241  }
242  for (int x = selRec.x + 1; x < selRec.x + selRec.width; x++) {
243  pos.x = x;
244  pos.y = selRec.y;
245  shift(pos, Math.min(selRec.x + selRec.width - x, selRec.height));
246  }
247  break;
248 
249  default:
250  throw new IllegalArgumentException("unsupported direction: " + dir);
251  }
252  } finally {
254  }
255  } finally {
257  }
258  }
259 
260  mapGrid = null;
261  selRec = null;
262  dx = 0;
263  dy = 0;
264  }
265 
271  private void shift(final Point pos, final int len) {
272  final Point prevPos = new Point(pos.x + dx, pos.y + dy);
273  final Point startPos = new Point();
274  assert mapGrid != null;
275  final boolean startSelection = (mapGrid.getFlags(prevPos) & MapGrid.GRID_FLAG_SELECTION) > 0;
276  assert !startSelection;
277  boolean isStart = true;
278  final Collection<G> startGameObjects = new LinkedList<>();
279  final List<GameObject<G, A, R>> gameObjectsToDelete = new LinkedList<>();
280  final Collection<G> gameObjectsToInsert = new LinkedList<>();
281  for (int i = 0; i < len; i++) {
282  assert mapGrid != null;
283  final boolean thisSelection = (mapGrid.getFlags(pos) & MapGrid.GRID_FLAG_SELECTION) > 0;
284  assert mapGrid != null;
285  mapGrid.select(prevPos, thisSelection ? SelectionMode.ADD : SelectionMode.SUB);
286  gameObjectsToInsert.clear();
287  if (thisSelection) {
288  if (isStart) {
289  isStart = false;
290  startPos.setLocation(prevPos);
291  // [startGameObjects] = [prevPos]
292  assert startGameObjects.isEmpty();
293  for (final G gameObject : mapModel.getMapSquare(prevPos)) {
294  if (gameObject.isHead() && !gameObject.isInContainer() && mapViewSettings.isEditType(gameObject)) {
295  startGameObjects.add(gameObject);
296  gameObjectsToDelete.add(gameObject);
297  }
298  }
299  }
300  // [prevPos] = [pos]
301  for (final G gameObject : mapModel.getMapSquare(pos)) {
302  if (gameObject.isHead() && !gameObject.isInContainer() && mapViewSettings.isEditType(gameObject)) {
303  gameObjectsToInsert.add(gameObject);
304  gameObjectsToDelete.add(gameObject);
305  }
306  }
307  } else {
308  if (isStart) {
309  // ignore
310  } else {
311  isStart = true;
312  // [prevPos] = [startGameObjects]
313  gameObjectsToInsert.addAll(startGameObjects);
314  startGameObjects.clear();
315  }
316  }
317 
318  insertAllAndClear(gameObjectsToInsert, prevPos);
319 
320  while (!gameObjectsToDelete.isEmpty()) {
321  gameObjectsToDelete.remove(0).remove();
322  }
323 
324  prevPos.setLocation(pos);
325  pos.x -= dx;
326  pos.y -= dy;
327  }
328  if (!isStart) {
329  // [prevPos] = [startGameObjects]
330  insertAllAndClear(startGameObjects, prevPos);
331  }
332  assert startGameObjects.isEmpty();
333  assert mapGrid != null;
334  mapGrid.select(prevPos, startSelection ? SelectionMode.ADD : SelectionMode.SUB);
335  }
336 
343  private void insertAllAndClear(@NotNull final Collection<G> gameObjects, @NotNull final Point point) {
344  for (final G gameObject : gameObjects) {
345  assert gameObject.isHead() && !gameObject.isInContainer() && mapViewSettings.isEditType(gameObject);
346  mapModel.insertBaseObject(gameObject, point, true, false, insertionModeSet.getTopmostInsertionMode());
347  }
348  gameObjects.clear();
349  }
350 
351 }
net.sf.gridarta.model.mapmodel.InsertionModeSet.getTopmostInsertionMode
InsertionMode getTopmostInsertionMode()
Returns the "topmost" insertion mode.
Definition: InsertionModeSet.java:98
net.sf.gridarta.utils.Size2D.getWidth
int getWidth()
Returns the width of the area.
Definition: Size2D.java:96
net.sf.gridarta.model.direction.Direction
A direction.
Definition: Direction.java:28
net.sf.gridarta.model.mapmodel.MapModel
A MapModel reflects the data of a map.
Definition: MapModel.java:75
net.sf.gridarta.model.mapgrid.MapGrid.getFlags
int getFlags(final int x, final int y)
Returns the flags of a square.
Definition: MapGrid.java:476
net.sf.gridarta.model.mapgrid.MapGrid.endTransaction
void endTransaction()
Ends a transaction.
Definition: MapGrid.java:776
net.sf.gridarta.gui.map.mapview.MapView.getMapGrid
MapGrid getMapGrid()
Returns the MapGrid of this view.
net.sf.gridarta.model.mapmodel.InsertionModeSet
A set of InsertionModes.
Definition: InsertionModeSet.java:33
net.sf.gridarta.model.mapmodel.MapModel.insertBaseObject
G insertBaseObject(@NotNull BaseObject< G, A, R, ?> baseObject, @NotNull Point pos, boolean allowMany, boolean join, @NotNull InsertionMode insertionMode)
Inserts a BaseObject to a map.
net.sf.gridarta.gui.misc.ShiftProcessor.mapViewSettings
final MapViewSettings mapViewSettings
The map view settings instance.
Definition: ShiftProcessor.java:52
net.sf.gridarta
Base package of all Gridarta classes.
net.sf.gridarta.model.mapmodel.MapModel.endTransaction
void endTransaction()
End a transaction.
net.sf.gridarta.model.mapgrid.MapGrid.GRID_FLAG_SELECTION
static final int GRID_FLAG_SELECTION
Selection - marks all selected squares.
Definition: MapGrid.java:98
net.sf.gridarta.model.mapviewsettings
Definition: AbstractMapViewSettings.java:20
net.sf
net.sf.gridarta.model.mapmodel.MapModel.beginTransaction
void beginTransaction(@NotNull String name)
Starts a new transaction.
net.sf.gridarta.gui.misc.ShiftProcessor.shift
void shift(final Point pos, final int len)
Shifts one row.
Definition: ShiftProcessor.java:271
net.sf.gridarta.model.mapmodel
Definition: AboveFloorInsertionMode.java:20
net.sf.gridarta.model.mapgrid.SelectionMode.SUB
SUB
All squares that are preselected get unselected.
Definition: SelectionMode.java:36
net.sf.gridarta.model.mapgrid.MapGrid.getSelectedRec
Rectangle getSelectedRec()
Returns the smallest rectangle containing selection.
Definition: MapGrid.java:514
net.sf.gridarta.model.archetype
Definition: AbstractArchetype.java:20
net.sf.gridarta.gui.misc.ShiftProcessor.insertionModeSet
final InsertionModeSet< G, A, R > insertionModeSet
The InsertionModeSet to use.
Definition: ShiftProcessor.java:70
net.sf.gridarta.model.gameobject.GameObject
Reflects a game object (object on a map).
Definition: GameObject.java:36
net.sf.gridarta.model.mapviewsettings.MapViewSettings
Container for settings that affect the rendering of maps.
Definition: MapViewSettings.java:30
net.sf.gridarta.gui
Graphical User Interface of Gridarta.
net.sf.gridarta.gui.misc.ShiftProcessor.mapModel
final MapModel< G, A, R > mapModel
The map model to operate on.
Definition: ShiftProcessor.java:64
net.sf.gridarta.model.mapgrid.MapGrid.beginTransaction
void beginTransaction()
Starts a new transaction.
Definition: MapGrid.java:756
net.sf.gridarta.gui.misc.ShiftProcessor.mapView
final MapView< G, A, R > mapView
The map view to operate on.
Definition: ShiftProcessor.java:58
net.sf.gridarta.gui.misc.ShiftProcessor.dy
int dy
The y offset to shift.
Definition: ShiftProcessor.java:92
net.sf.gridarta.model.gameobject
GameObjects are the objects based on Archetypes found on maps.
Definition: AbstractGameObject.java:20
net
net.sf.gridarta.utils.Size2D.getHeight
int getHeight()
Returns the height of the area.
Definition: Size2D.java:104
net.sf.gridarta.gui.misc.ShiftProcessor.ShiftProcessor
ShiftProcessor(@NotNull final MapViewSettings mapViewSettings, @NotNull final MapView< G, A, R > mapView, @NotNull final MapModel< G, A, R > mapModel, @NotNull final InsertionModeSet< G, A, R > insertionModeSet)
Creates a new instance.
Definition: ShiftProcessor.java:101
net.sf.gridarta.gui.misc.ShiftProcessor.shift
void shift(@NotNull final Direction dir)
Shifts the map contents by one square.
Definition: ShiftProcessor.java:157
net.sf.gridarta.model.mapgrid.MapGrid.getSize
Size2D getSize()
Returns size of grid.
Definition: MapGrid.java:504
net.sf.gridarta.model.maparchobject.MapArchObject
Interface for MapArchObjects.
Definition: MapArchObject.java:40
net.sf.gridarta.model.mapviewsettings.MapViewSettings.isEditType
boolean isEditType(int editType)
Get information on the current state of edit type.
net.sf.gridarta.gui.misc.ShiftProcessor.selRec
Rectangle selRec
The selection rectangle to operate on.
Definition: ShiftProcessor.java:82
net.sf.gridarta.gui.map.mapview
Definition: AbstractMapView.java:20
net.sf.gridarta.gui.map.mapview.MapView
A map view consists of a map grid and a map cursor, and is attached to a map control.
Definition: MapView.java:43
net.sf.gridarta.model.mapgrid.SelectionMode
Modes that describe how squares get selected.
Definition: SelectionMode.java:26
net.sf.gridarta.model.mapgrid.MapGrid.select
void select(@NotNull final Point pos, @NotNull final SelectionMode selectionMode)
Selects or deselects a single square.
Definition: MapGrid.java:408
net.sf.gridarta.gui.misc.ShiftProcessor.dx
int dx
The x offset to shift.
Definition: ShiftProcessor.java:87
net.sf.gridarta.gui.misc.ShiftProcessor.mapGrid
MapGrid mapGrid
The map grid to operate on.
Definition: ShiftProcessor.java:76
net.sf.gridarta.model.mapgrid.MapGrid
2D-Grid containing flags for selection, pre-selection, cursor, warnings and errors.
Definition: MapGrid.java:46
net.sf.gridarta.model.mapgrid.SelectionMode.ADD
ADD
All squares that are preselected get selected.
Definition: SelectionMode.java:31
net.sf.gridarta.model.mapmodel.MapModel.getMapSquare
MapSquare< G, A, R > getMapSquare(@NotNull Point pos)
Get the square at a specified location.
net.sf.gridarta.model.mapgrid
Definition: MapGrid.java:20
net.sf.gridarta.model
net.sf.gridarta.model.archetype.Archetype
Reflects an Archetype.
Definition: Archetype.java:41
net.sf.gridarta.gui.map
Base classes for rendering maps.
Definition: AbstractPerMapDialogManager.java:20
net.sf.gridarta.model.maparchobject
Definition: AbstractMapArchObject.java:20
net.sf.gridarta.gui.misc.ShiftProcessor
Performs a "shift" operation in a map: shift all selected squares into the given direction.
Definition: ShiftProcessor.java:46
net.sf.gridarta.gui.misc.ShiftProcessor.insertAllAndClear
void insertAllAndClear(@NotNull final Collection< G > gameObjects, @NotNull final Point point)
Inserts a collection of GameObjects into the map and clears the list.
Definition: ShiftProcessor.java:343
net.sf.gridarta.gui.misc.ShiftProcessor.canShift
boolean canShift(@NotNull final Direction dir)
Checks whether shifting is possible.
Definition: ShiftProcessor.java:113
net.sf.gridarta.utils.Size2D
The class Size2D represents a 2d rectangular area.
Definition: Size2D.java:30
net.sf.gridarta.utils
Definition: ActionBuilderUtils.java:20
net.sf.gridarta.model.direction
Definition: Direction.java:20