Gridarta Editor
DeletionTool.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.gui.panel.tools;
21 
22 import java.awt.Component;
23 import java.awt.Container;
24 import java.awt.GridBagConstraints;
25 import java.awt.GridBagLayout;
26 import java.awt.Point;
27 import java.util.Collection;
28 import java.util.HashSet;
29 import javax.swing.JComboBox;
30 import javax.swing.JPanel;
45 import net.sf.japi.swing.action.ActionBuilder;
46 import net.sf.japi.swing.action.ActionBuilderFactory;
47 import net.sf.japi.swing.action.ActionMethod;
48 import net.sf.japi.swing.action.ToggleAction;
49 import org.jetbrains.annotations.NotNull;
50 import org.jetbrains.annotations.Nullable;
51 
56 public class DeletionTool<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> extends BasicAbstractTool<G, A, R> {
57 
61  private static final int DELETE_TOPMOST = 0;
62 
66  private static final int DELETE_ALL = 1;
67 
71  private static final int DELETE_BOTTOMMOST = 2;
72 
76  private static final int SCOPE_SQUARE = 0;
77 
81  private static final int SCOPE_ABOVE_FLOOR = 1;
82 
86  private static final int SCOPE_BELOW_FLOOR = 2;
87 
92  private static final int SCOPE_SELECTED_OBJECT = 3;
93 
97  private static final int SCOPE_WALL = 4;
98 
102  private static final int SCOPE_FLOOR = 5;
103 
107  @NotNull
108  private static final ActionBuilder ACTION_BUILDER = ActionBuilderFactory.getInstance().getActionBuilder("net.sf.gridarta.gui.panel.tools");
109 
113  @NotNull
115 
119  @Nullable
121 
125  @Nullable
127 
131  @Nullable
133 
137  @NotNull
139 
143  @NotNull
145 
149  @NotNull
150  private final ToggleAction ignoreWallsAction = (ToggleAction) ACTION_BUILDER.createToggle(true, "deletionToolExceptionsIgnoreWalls", this);
151 
155  @NotNull
156  private final ToggleAction ignoreFloorsAction = (ToggleAction) ACTION_BUILDER.createToggle(true, "deletionToolExceptionsIgnoreFloors", this);
157 
161  @NotNull
162  private final ToggleAction ignoreMonstersAction = (ToggleAction) ACTION_BUILDER.createToggle(true, "deletionToolExceptionsIgnoreMonsters", this);
163 
168 
173 
178 
182  @NotNull
183  private final JComboBox<?> deleteComboBox = createDeleteComboBox();
184 
188  @NotNull
189  private final JComboBox<?> scopeComboBox = createScopeComboBox();
190 
200  public DeletionTool(@NotNull final MapViewSettings mapViewSettings, @NotNull final ObjectChooser<G, A, R> objectChooser, @NotNull final PickmapSettings pickmapSettings, @Nullable final GameObjectMatcher floorGameObjectMatcher, @Nullable final GameObjectMatcher wallGameObjectMatcher, @Nullable final GameObjectMatcher monsterGameObjectMatcher) {
201  super("deletion");
202  this.mapViewSettings = mapViewSettings;
203  this.objectChooser = objectChooser;
204  this.pickmapSettings = pickmapSettings;
205  this.floorGameObjectMatcher = floorGameObjectMatcher;
206  this.wallGameObjectMatcher = wallGameObjectMatcher;
207  this.monsterGameObjectMatcher = monsterGameObjectMatcher;
208  }
209 
210  @Override
211  public void pressed(@NotNull final MouseOpEvent<G, A, R> e) {
212  final Point mapLoc = e.getMapLocation();
213  final MapCursor<G, A, R> mapCursor = e.getMapCursor();
214  final MapControl<G, A, R> mapControl = e.getMapControl();
215  mapCursor.setLocationSafe(mapLoc);
216  if (mapLoc != null) {
217  // delete the topmost arch (matching the view settings) on that square and redraw the map
218  deleteArch(mapLoc, mapControl);
219  }
220  }
221 
222  @Override
223  public void released(@NotNull final MouseOpEvent<G, A, R> e) {
224 
225  }
226 
227  @Override
228  public void clicked(@NotNull final MouseOpEvent<G, A, R> e) {
229  }
230 
231  @Override
232  public void dragged(@NotNull final MouseOpEvent<G, A, R> e) {
233  final Point mapLoc = e.getMapLocation();
234  final MapCursor<G, A, R> mapCursor = e.getMapCursor();
235  final MapControl<G, A, R> mapControl = e.getMapControl();
236  if (mapCursor.setLocationSafe(mapLoc)) {
237  // delete the topmost arch (matching the view settings) on that square and redraw the map
238  deleteArch(mapLoc, mapControl);
239  }
240  }
241 
242  @Override
243  public void moved(@NotNull final MouseOpEvent<G, A, R> e) {
244  }
245 
252  private void deleteArch(@NotNull final Point mapLoc, @NotNull final MapControl<G, A, R> mapControl) {
253  if (mapControl.isPickmap() && pickmapSettings.isLocked()) {
254  return;
255  }
256 
257  final MapSquare<G, A, R> mapSquare = mapControl.getMapModel().getMapSquare(mapLoc);
258  final int scopeType = scopeComboBox.getSelectedIndex();
259  final int deleteType = deleteComboBox.getSelectedIndex();
260 
261  @Nullable final GameObject<G, A, R> start;
262  @Nullable final GameObject<G, A, R> end;
263  switch (scopeType) {
264  case SCOPE_SQUARE:
265  start = mapSquare.getFirst();
266  end = mapSquare.getLast();
267  break;
268 
269  case SCOPE_ABOVE_FLOOR:
270  start = floorGameObjectMatcher == null ? null : mapSquare.getAfterLast(floorGameObjectMatcher);
271  end = mapSquare.getLast();
272  break;
273 
274  case SCOPE_BELOW_FLOOR:
275  start = mapSquare.getFirst();
276  end = floorGameObjectMatcher == null ? null : mapSquare.getBeforeFirst(floorGameObjectMatcher);
277  break;
278 
280  start = mapSquare.getFirst();
281  end = mapSquare.getLast();
282  break;
283 
284  case SCOPE_WALL:
285  start = mapSquare.getFirst();
286  end = mapSquare.getLast();
287  break;
288 
289  case SCOPE_FLOOR:
290  start = mapSquare.getFirst();
291  end = mapSquare.getLast();
292  break;
293 
294  default:
295  return;
296  }
297  if (start == null || end == null) {
298  return;
299  }
300  final Collection<G> gameObjectsToDelete = new HashSet<>();
301  boolean foundFirst = false;
302  final GameObject<G, A, R> start2 = deleteType == DELETE_TOPMOST ? end : start;
303  final GameObject<G, A, R> end2 = deleteType == DELETE_TOPMOST ? start : end;
304  for (final GameObject<G, A, R> gameObject : deleteType == DELETE_TOPMOST ? mapSquare.reverse() : mapSquare) {
305  if (gameObject == start2) {
306  foundFirst = true;
307  }
308  if (foundFirst) {
309  final G head = gameObject.getHead();
310  if (mapViewSettings.isEditType(head)) {
311  boolean insert = false;
312  switch (scopeType) {
313  case SCOPE_SQUARE:
314  case SCOPE_ABOVE_FLOOR:
315  case SCOPE_BELOW_FLOOR:
316  insert = true;
317  break;
318 
320  if (objectChooser.isMatching(head)) {
321  insert = true;
322  }
323  break;
324 
325  case SCOPE_WALL:
326  if (wallGameObjectMatcher != null && wallGameObjectMatcher.isMatching(head)) {
327  insert = true;
328  }
329  break;
330 
331  case SCOPE_FLOOR:
332  if (floorGameObjectMatcher != null && floorGameObjectMatcher.isMatching(head)) {
333  insert = true;
334  }
335  break;
336  }
337  if (insert) {
338  if (deletionToolExceptionsIgnoreWalls && wallGameObjectMatcher != null && wallGameObjectMatcher.isMatching(head)) {
339  // ignore
340  } else if (deletionToolExceptionsIgnoreFloors && floorGameObjectMatcher != null && floorGameObjectMatcher.isMatching(head)) {
341  // ignore
342  } else if (deletionToolExceptionsIgnoreMonsters && monsterGameObjectMatcher != null && monsterGameObjectMatcher.isMatching(head)) {
343  // ignore
344  } else {
345  gameObjectsToDelete.add(head);
346  if (deleteType != DELETE_ALL) {
347  break;
348  }
349  }
350  }
351  }
352  if (gameObject == end2) {
353  break;
354  }
355  }
356  }
357  if (!gameObjectsToDelete.isEmpty()) {
358  final MapModel<G, A, R> mapModel = mapSquare.getMapModel();
359  mapModel.beginTransaction("Delete Object");
360  try {
361  for (final G gameObjectToDelete : gameObjectsToDelete) {
362  mapModel.removeGameObject(gameObjectToDelete, mapViewSettings.isAutojoin());
363  }
364  } finally {
365  mapModel.endTransaction();
366  }
367  }
368  }
369 
370  @Nullable
371  @Override
372  public Component createOptionsView() {
373  final Container panel = new JPanel();
374  panel.setLayout(new GridBagLayout());
375 
376  final GridBagConstraints gbcLabel = new GridBagConstraints();
377  gbcLabel.anchor = GridBagConstraints.EAST;
378 
379  final GridBagConstraints gbcComboBox = new GridBagConstraints();
380  gbcComboBox.fill = GridBagConstraints.HORIZONTAL;
381  gbcComboBox.weightx = 1.0;
382  gbcComboBox.gridwidth = GridBagConstraints.REMAINDER;
383 
384  final GridBagConstraints gbcCheckBox = new GridBagConstraints();
385  gbcCheckBox.fill = GridBagConstraints.HORIZONTAL;
386  gbcCheckBox.gridwidth = GridBagConstraints.REMAINDER;
387 
388  panel.add(SwingUtils.createLabel("deletionTool.delete", deleteComboBox), gbcLabel);
389  panel.add(deleteComboBox, gbcComboBox);
390 
391  panel.add(SwingUtils.createLabel("deletionTool.scope", scopeComboBox), gbcLabel);
392  panel.add(scopeComboBox, gbcComboBox);
393 
394  panel.add(ignoreWallsAction.createCheckBox(), gbcCheckBox);
395  panel.add(ignoreFloorsAction.createCheckBox(), gbcCheckBox);
396  panel.add(ignoreMonstersAction.createCheckBox(), gbcCheckBox);
397  return panel;
398  }
399 
404  @NotNull
405  private static JComboBox<?> createDeleteComboBox() {
406  final String[] options = { ActionBuilderUtils.getString(ACTION_BUILDER, "deletionTool.delete.top"), ActionBuilderUtils.getString(ACTION_BUILDER, "deletionTool.delete.all"), ActionBuilderUtils.getString(ACTION_BUILDER, "deletionTool.delete.bottom"), };
407  final JComboBox<?> comboBox = new JComboBox<>(options);
408  comboBox.setToolTipText(ActionBuilderUtils.getString(ACTION_BUILDER, "deletionTool.delete.shortdescription"));
409  return comboBox;
410  }
411 
416  @NotNull
417  private static JComboBox<?> createScopeComboBox() {
418  final String[] options = { ActionBuilderUtils.getString(ACTION_BUILDER, "deletionTool.scope.square"), ActionBuilderUtils.getString(ACTION_BUILDER, "deletionTool.scope.aboveFloor"), ActionBuilderUtils.getString(ACTION_BUILDER, "deletionTool.scope.belowFloor"), ActionBuilderUtils.getString(ACTION_BUILDER, "deletionTool.scope.selectedObject"), ActionBuilderUtils.getString(ACTION_BUILDER, "deletionTool.scope.wall"), ActionBuilderUtils.getString(ACTION_BUILDER, "deletionTool.scope.floor"), };
419  final JComboBox<?> comboBox = new JComboBox<>(options);
420  comboBox.setToolTipText(ActionBuilderUtils.getString(ACTION_BUILDER, "deletionTool.scope.shortdescription"));
421  return comboBox;
422  }
423 
428  @ActionMethod
431  }
432 
438  @ActionMethod
439  public void setDeletionToolExceptionsIgnoreWalls(final boolean deletionToolExceptionsIgnoreWalls) {
440  this.deletionToolExceptionsIgnoreWalls = deletionToolExceptionsIgnoreWalls;
441  }
442 
447  @ActionMethod
450  }
451 
457  @ActionMethod
458  public void setDeletionToolExceptionsIgnoreFloors(final boolean deletionToolExceptionsIgnoreFloors) {
459  this.deletionToolExceptionsIgnoreFloors = deletionToolExceptionsIgnoreFloors;
460  }
461 
466  @ActionMethod
469  }
470 
476  @ActionMethod
477  public void setDeletionToolExceptionsIgnoreMonsters(final boolean deletionToolExceptionsIgnoreMonsters) {
478  this.deletionToolExceptionsIgnoreMonsters = deletionToolExceptionsIgnoreMonsters;
479  }
480 
481 }
final JComboBox<?> deleteComboBox
The JComboBox for selecting the objects to delete.
T getHead()
Return the head part of a multi-part object.
Base class for the default provided tools.
final JComboBox<?> scopeComboBox
The JComboBox for selecting the scope to delete.
final GameObjectMatcher monsterGameObjectMatcher
A GameObjectMatcher matching monster game objects.
boolean deletionToolExceptionsIgnoreMonsters
Whether "ignore monsters" is enabled.
final PickmapSettings pickmapSettings
The PickmapSettings to use.
Iterable< G > reverse()
Return an object that is the reverse representation.
void dragged(@NotNull final MouseOpEvent< G, A, R > e)
boolean isDeletionToolExceptionsIgnoreWalls()
Returns whether walls should not be deleted.
A MapModel reflects the data of a map.
Definition: MapModel.java:75
boolean isAutojoin()
Returns whether "autojoin" is enabled.
Graphical User Interface of Gridarta.
void pressed(@NotNull final MouseOpEvent< G, A, R > e)
Interface for classes that match GameObjects.
This package contains classes related to matching GameObjects, so called GameObjectMatchers.
boolean isMatching(@NotNull G gameObject)
Returns whether the current selection matches a given game object.
MapModel< G, A, R > getMapModel()
Returns the MapModel this map square is part of.
Definition: MapSquare.java:99
void endTransaction()
End a transaction.
static JComboBox<?> createDeleteComboBox()
Create a JComboBox for selecting the objects to delete.
void removeGameObject(@NotNull G gameObject, boolean join)
Delete an existing GameObject from the map.
final MapViewSettings mapViewSettings
The map view settings instance.
boolean isEditType(int editType)
Get information on the current state of edit type.
MapCursor provides methods to move and drag on map.
Definition: MapCursor.java:57
void released(@NotNull final MouseOpEvent< G, A, R > e)
void setDeletionToolExceptionsIgnoreFloors(final boolean deletionToolExceptionsIgnoreFloors)
Sets whether floors should not be deleted.
G getAfterLast(@NotNull final GameObjectMatcher gameObjectMatcher)
Returns the game object after the last occurrence of a matching game object.
Definition: MapSquare.java:208
static final int DELETE_TOPMOST
Index into deleteComboBox: delete topmost object.
boolean deletionToolExceptionsIgnoreFloors
Whether "ignore floors" is enabled.
Utility class for Swing related functions.
Definition: SwingUtils.java:37
boolean setLocationSafe(@Nullable final Point p)
Move cursor to a new location.
Definition: MapCursor.java:254
static String getString(@NotNull final ActionBuilder actionBuilder, @NotNull final String key, @NotNull final String defaultValue)
Returns the value of a key.
boolean isDeletionToolExceptionsIgnoreMonsters()
Returns whether monsters should not be deleted.
Base package of all Gridarta classes.
boolean isDeletionToolExceptionsIgnoreFloors()
Returns whether floors should not be deleted.
Reflects a game object (object on a map).
Definition: GameObject.java:36
static final int DELETE_BOTTOMMOST
Index into deleteComboBox: delete bottommost object.
final ToggleAction ignoreWallsAction
The action for "ignore walls".
Container for settings that affect the rendering of maps.
MapSquare< G, A, R > getMapSquare(@NotNull Point pos)
Get the square at a specified location.
GameObjects are the objects based on Archetypes found on maps.
static final ActionBuilder ACTION_BUILDER
Action Builder.
static final int SCOPE_ABOVE_FLOOR
Index into scopeComboBox: delete all objects above floors.
G getFirst(@NotNull final GameObjectMatcher gameObjectMatcher)
Returns the first occurrence of a matching game object.
Definition: MapSquare.java:226
G getBeforeFirst(@NotNull final GameObjectMatcher gameObjectMatcher)
Returns the game object before the first occurrence of a matching game object.
Definition: MapSquare.java:244
Base classes for rendering maps.
static final int SCOPE_WALL
Index into scopeComboBox: delete all wall objects.
static JComboBox<?> createScopeComboBox()
Create a JComboBox for selecting the scope to delete.
static final int SCOPE_BELOW_FLOOR
Index into scopeComboBox: delete all objects below floors.
final GameObjectMatcher floorGameObjectMatcher
A GameObjectMatcher matching floor game objects.
Utility class for ActionBuilder related functions.
boolean deletionToolExceptionsIgnoreWalls
Whether "ignore walls" is enabled.
void deleteArch(@NotNull final Point mapLoc, @NotNull final MapControl< G, A, R > mapControl)
Delete an arch.
static final int DELETE_ALL
Index into deleteComboBox: delete all objects.
void clicked(@NotNull final MouseOpEvent< G, A, R > e)
final ToggleAction ignoreMonstersAction
The action for "ignore monsters".
Currently nothing more than a marker interface for unification.
Definition: MapControl.java:35
A MouseOpEvent is an event triggered for a MouseOpListener.
final ObjectChooser< G, A, R > objectChooser
The ObjectChooser to use.
static Component createLabel(@NotNull final String key, @Nullable final Component component)
Create a javax.swing.JLabel instance.
Definition: SwingUtils.java:58
boolean isLocked()
Returns whether pickmaps are immutable.
final ToggleAction ignoreFloorsAction
The action for "ignore floors".
void moved(@NotNull final MouseOpEvent< G, A, R > e)
static final int SCOPE_FLOOR
Index into scopeComboBox: delete all floor objects.
Common base interface for ObjectChoosers.
void beginTransaction(@NotNull String name)
Starts a new transaction.
void setDeletionToolExceptionsIgnoreWalls(final boolean deletionToolExceptionsIgnoreWalls)
Sets whether walls should not be deleted.
static final int SCOPE_SELECTED_OBJECT
Index into scopeComboBox: delete all objects matching the object chooser.
G getLast(@NotNull final GameObjectMatcher gameObjectMatcher)
Returns the last occurrence of a matching game object.
Definition: MapSquare.java:190
static final int SCOPE_SQUARE
Index into scopeComboBox: delete all objects.
DeletionTool(@NotNull final MapViewSettings mapViewSettings, @NotNull final ObjectChooser< G, A, R > objectChooser, @NotNull final PickmapSettings pickmapSettings, @Nullable final GameObjectMatcher floorGameObjectMatcher, @Nullable final GameObjectMatcher wallGameObjectMatcher, @Nullable final GameObjectMatcher monsterGameObjectMatcher)
Create a DeletionTool.
final GameObjectMatcher wallGameObjectMatcher
A GameObjectMatcher matching wall game objects.
void setDeletionToolExceptionsIgnoreMonsters(final boolean deletionToolExceptionsIgnoreMonsters)
Sets whether monsters should not be deleted.
boolean isMatching(@NotNull GameObject<?, ?, ?> gameObject)
Matches an GameObject.
Container for settings that affect pickmaps.