Gridarta Editor
MainActions.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.mainactions;
21 
22 import java.awt.Point;
23 import java.awt.Rectangle;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.IdentityHashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import javax.swing.Action;
31 import javax.swing.JFrame;
64 import net.sf.gridarta.utils.Size2D;
65 import net.sf.japi.swing.action.ActionMethod;
66 import org.jetbrains.annotations.NotNull;
67 import org.jetbrains.annotations.Nullable;
68 
73 public class MainActions<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> implements EditorAction, MapViewManagerListener<G, A, R> {
74 
78  @NotNull
80 
84  @NotNull
86 
90  @NotNull
91  private final JFrame parent;
92 
96  @NotNull
98 
102  @NotNull
104 
108  @NotNull
110 
114  @NotNull
116 
120  @Nullable
121  private Action aClear;
122 
126  @Nullable
127  private Action aCut;
128 
132  @Nullable
133  private Action aCopy;
134 
138  @Nullable
139  private Action aShiftNorth;
140 
144  @Nullable
145  private Action aShiftNorthEast;
146 
150  @Nullable
151  private Action aShiftEast;
152 
156  @Nullable
157  private Action aShiftSouthEast;
158 
162  @Nullable
163  private Action aShiftSouth;
164 
168  @Nullable
169  private Action aShiftSouthWest;
170 
174  @Nullable
175  private Action aShiftWest;
176 
180  @Nullable
181  private Action aShiftNorthWest;
182 
186  @Nullable
187  private Action aPaste;
188 
192  @Nullable
193  private Action aPasteTiled;
194 
198  @Nullable
199  private Action aFind;
200 
204  @Nullable
205  private Action aFindNext;
206 
210  @Nullable
211  private Action aFindPrev;
212 
216  @Nullable
217  private Action aReplace;
218 
222  @Nullable
223  private Action aFillAuto;
224 
228  @Nullable
229  private Action aFillAbove;
230 
234  @Nullable
235  private Action aFillBelow;
236 
240  @Nullable
241  private Action aRandFillAuto;
242 
246  @Nullable
247  private Action aRandFillAbove;
248 
252  @Nullable
253  private Action aRandFillBelow;
254 
258  @Nullable
259  private Action aFloodFill;
260 
264  @Nullable
265  private Action aMassChange;
266 
270  @Nullable
271  private Action aSelectAll;
272 
276  @Nullable
277  private Action aInvertSelection;
278 
282  @Nullable
283  private Action aExpandEmptySelection;
284 
288  @Nullable
289  private Action aTileStretchingSet;
290 
294  @Nullable
295  private Action aTileStretchingClear;
296 
300  @Nullable
301  private Action aTileStretchingIncrease;
302 
306  @Nullable
307  private Action aTileStretchingDecrease;
308 
312  @NotNull
314 
318  @NotNull
320 
324  @NotNull
326 
330  @Nullable
332 
336  @Nullable
338 
342  @NotNull
344 
345  @Override
346  public void mapGridChanged(@NotNull final MapGridEvent e) {
347  refreshMenus(); // selection state may have changed
348  }
349 
350  @Override
351  public void mapGridResized(@NotNull final MapGridEvent e) {
352  // ignore
353  }
354 
355  };
356 
369  public MainActions(@NotNull final FindDialogManager<G, A, R> findDialogManager, @NotNull final ReplaceDialogManager<G, A, R> replaceDialogManager, @NotNull final JFrame parent, @NotNull final MapViewSettings mapViewSettings, @NotNull final ArchetypeSet<G, A, R> archetypeSet, @NotNull final CopyBuffer<G, A, R> copyBuffer, @NotNull final ObjectChooser<G, A, R> objectChooser, @NotNull final MapManager<G, A, R> mapManager, @NotNull final InsertionModeSet<G, A, R> insertionModeSet) {
370  this.findDialogManager = findDialogManager;
371  this.replaceDialogManager = replaceDialogManager;
372  this.parent = parent;
373  this.mapViewSettings = mapViewSettings;
374  this.copyBuffer = copyBuffer;
375  this.objectChooser = objectChooser;
376  this.insertionModeSet = insertionModeSet;
377 
378  mapManager.addMapManagerListener(newMapManagerListener());
379  currentMapControl = mapManager.getCurrentMap();
380 
381  archetypeSet.addArchetypeSetListener(this::refreshMenus);
382  copyBuffer.addMapModelListener(newMapModelListener());
383  }
384 
390  @NotNull
392  return new MapManagerListener<G, A, R>() {
393 
394  @Override
395  public void currentMapChanged(@Nullable final MapControl<G, A, R> mapControl) {
396  currentMapControl = mapControl;
397  refreshMenus();
398  }
399 
400  @Override
401  public void mapCreated(@NotNull final MapControl<G, A, R> mapControl, final boolean interactive) {
402  // ignore: a current map changed event will be generated
403  }
404 
405  @Override
406  public void mapClosing(@NotNull final MapControl<G, A, R> mapControl) {
407  // ignore: a current map changed event will be generated
408  }
409 
410  @Override
411  public void mapClosed(@NotNull final MapControl<G, A, R> mapControl) {
412  // ignore: a current map changed event will be generated
413  }
414 
415  };
416  }
417 
423  @NotNull
425  return new MapModelListener<G, A, R>() {
426 
427  @Override
428  public void mapSizeChanged(@NotNull final Size2D newSize) {
429  // ignore
430  }
431 
432  @Override
433  public void mapSquaresChanged(@NotNull final Set<MapSquare<G, A, R>> mapSquares) {
434  refreshMenus();
435  }
436 
437  @Override
438  public void mapObjectsChanged(@NotNull final Set<G> gameObjects, @NotNull final Set<G> transientGameObjects) {
439  // ignore
440  }
441 
442  @Override
443  public void errorsChanged(@NotNull final ErrorCollector<G, A, R> errors) {
444  // ignore
445  }
446 
447  @Override
448  public void mapFileChanged(@Nullable final MapFile oldMapFile) {
449  // ignore
450  }
451 
452  @Override
453  public void modifiedChanged() {
454  // ignore
455  }
456 
457  };
458  }
459 
463  private void refreshMenus() {
464  if (aClear != null) {
465  //noinspection ConstantConditions
466  aClear.setEnabled(doClear(false));
467  }
468  if (aCut != null) {
469  //noinspection ConstantConditions
470  aCut.setEnabled(doCut(false));
471  }
472  if (aCopy != null) {
473  //noinspection ConstantConditions
474  aCopy.setEnabled(doCopy(false));
475  }
476  if (aPaste != null) {
477  //noinspection ConstantConditions
478  aPaste.setEnabled(doPaste(false));
479  }
480  if (aPasteTiled != null) {
481  //noinspection ConstantConditions
482  aPasteTiled.setEnabled(doPasteTiled(false));
483  }
484  if (aShiftNorth != null) {
485  //noinspection ConstantConditions
486  aShiftNorth.setEnabled(doShift(false, Direction.NORTH));
487  }
488  if (aShiftNorthEast != null) {
489  //noinspection ConstantConditions
490  aShiftNorthEast.setEnabled(doShift(false, Direction.NORTH_EAST));
491  }
492  if (aShiftEast != null) {
493  //noinspection ConstantConditions
494  aShiftEast.setEnabled(doShift(false, Direction.EAST));
495  }
496  if (aShiftSouthEast != null) {
497  //noinspection ConstantConditions
498  aShiftSouthEast.setEnabled(doShift(false, Direction.SOUTH_EAST));
499  }
500  if (aShiftSouth != null) {
501  //noinspection ConstantConditions
502  aShiftSouth.setEnabled(doShift(false, Direction.SOUTH));
503  }
504  if (aShiftSouthWest != null) {
505  //noinspection ConstantConditions
506  aShiftSouthWest.setEnabled(doShift(false, Direction.SOUTH_WEST));
507  }
508  if (aShiftWest != null) {
509  //noinspection ConstantConditions
510  aShiftWest.setEnabled(doShift(false, Direction.WEST));
511  }
512  if (aShiftNorthWest != null) {
513  //noinspection ConstantConditions
514  aShiftNorthWest.setEnabled(doShift(false, Direction.NORTH_WEST));
515  }
516  if (aFind != null) {
517  //noinspection ConstantConditions
518  aFind.setEnabled(doFind(false));
519  }
520  if (aFindNext != null) {
521  //noinspection ConstantConditions
522  aFindNext.setEnabled(doFindNext(false));
523  }
524  if (aFindPrev != null) {
525  //noinspection ConstantConditions
526  aFindPrev.setEnabled(doFindPrev(false));
527  }
528  if (aReplace != null) {
529  //noinspection ConstantConditions
530  aReplace.setEnabled(doReplace(false));
531  }
532  if (aFillAuto != null) {
533  //noinspection ConstantConditions
534  aFillAuto.setEnabled(doFillAuto(false));
535  }
536  if (aFillAbove != null) {
537  //noinspection ConstantConditions
538  aFillAbove.setEnabled(doFillAbove(false));
539  }
540  if (aFillBelow != null) {
541  //noinspection ConstantConditions
542  aFillBelow.setEnabled(doFillBelow(false));
543  }
544  if (aRandFillAuto != null) {
545  //noinspection ConstantConditions
546  aRandFillAuto.setEnabled(doRandFillAuto(false));
547  }
548  if (aRandFillAbove != null) {
549  //noinspection ConstantConditions
550  aRandFillAbove.setEnabled(doRandFillAbove(false));
551  }
552  if (aRandFillBelow != null) {
553  //noinspection ConstantConditions
554  aRandFillBelow.setEnabled(doRandFillBelow(false));
555  }
556  if (aFloodFill != null) {
557  //noinspection ConstantConditions
558  aFloodFill.setEnabled(doFloodFill(false));
559  }
560  if (aMassChange != null) {
561  //noinspection ConstantConditions
562  aMassChange.setEnabled(doMassChange(false));
563  }
564  if (aSelectAll != null) {
565  //noinspection ConstantConditions
566  aSelectAll.setEnabled(doSelectAll(false));
567  }
568  if (aInvertSelection != null) {
569  //noinspection ConstantConditions
570  aInvertSelection.setEnabled(doInvertSelection(false));
571  }
572  if (aExpandEmptySelection != null) {
573  //noinspection ConstantConditions
574  aExpandEmptySelection.setEnabled(doExpandEmptySelection(false));
575  }
576  if (aTileStretchingSet != null) {
577  //noinspection ConstantConditions
578  aTileStretchingSet.setEnabled(doTileStretchingChangeSet(false));
579  }
580  if (aTileStretchingClear != null) {
581  //noinspection ConstantConditions
582  aTileStretchingClear.setEnabled(doTileStretchingChange(false, 0, true));
583  }
584  if (aTileStretchingIncrease != null) {
585  //noinspection ConstantConditions
586  aTileStretchingIncrease.setEnabled(doTileStretchingChange(false, 1, false));
587  }
588  if (aTileStretchingDecrease != null) {
589  //noinspection ConstantConditions
590  aTileStretchingDecrease.setEnabled(doTileStretchingChange(false, -1, false));
591  }
592  }
593 
597  @ActionMethod
598  public void clear() {
599  doClear(true);
600  }
601 
605  @ActionMethod
606  public void cut() {
607  doCut(true);
608  }
609 
613  @ActionMethod
614  public void copy() {
615  doCopy(true);
616  }
617 
621  @ActionMethod
622  public void paste() {
623  doPaste(true);
624  }
625 
629  @ActionMethod
630  public void pasteTiled() {
631  doPasteTiled(true);
632  }
633 
637  @ActionMethod
638  public void shiftNorth() {
639  doShift(true, Direction.NORTH);
640  }
641 
645  @ActionMethod
646  public void shiftNorthEast() {
648  }
649 
653  @ActionMethod
654  public void shiftEast() {
655  doShift(true, Direction.EAST);
656  }
657 
661  @ActionMethod
662  public void shiftSouthEast() {
664  }
665 
669  @ActionMethod
670  public void shiftSouth() {
671  doShift(true, Direction.SOUTH);
672  }
673 
677  @ActionMethod
678  public void shiftSouthWest() {
680  }
681 
685  @ActionMethod
686  public void shiftWest() {
687  doShift(true, Direction.WEST);
688  }
689 
693  @ActionMethod
694  public void shiftNorthWest() {
696  }
697 
701  @ActionMethod
702  public void find() {
703  doFind(true);
704  }
705 
709  @ActionMethod
710  public void findNext() {
711  doFindNext(true);
712  }
713 
717  @ActionMethod
718  public void findPrev() {
719  doFindPrev(true);
720  }
721 
725  @ActionMethod
726  public void replace() {
727  doReplace(true);
728  }
729 
733  @ActionMethod
734  public void fillAuto() {
735  doFillAuto(true);
736  }
737 
741  @ActionMethod
742  public void fillAbove() {
743  doFillAbove(true);
744  }
745 
749  @ActionMethod
750  public void fillBelow() {
751  doFillBelow(true);
752  }
753 
757  @ActionMethod
758  public void randFillAuto() {
759  doRandFillAuto(true);
760  }
761 
765  @ActionMethod
766  public void randFillAbove() {
767  doRandFillAbove(true);
768  }
769 
773  @ActionMethod
774  public void randFillBelow() {
775  doRandFillBelow(true);
776  }
777 
781  @ActionMethod
782  public void floodFill() {
783  doFloodFill(true);
784  }
785 
789  @ActionMethod
790  public void massChange() {
791  doMassChange(true);
792  }
793 
797  @ActionMethod
798  public void selectAll() {
799  doSelectAll(true);
800  }
801 
805  @ActionMethod
806  public void invertSelection() {
807  doInvertSelection(true);
808  }
809 
814  @ActionMethod
815  public void expandEmptySelection() {
817  }
818 
823  @ActionMethod
824  public void tileStretchingSet() {
826  }
827 
832  @ActionMethod
833  public void tileStretchingClear() {
834  doTileStretchingChange(true, 0, true);
835  }
836 
841  @ActionMethod
842  public void tileStretchingIncrease() {
843  doTileStretchingChange(true, 1, false);
844  }
845 
850  @ActionMethod
851  public void tileStretchingDecrease() {
852  doTileStretchingChange(true, -1, false);
853  }
854 
859  @Nullable
861  return currentMapView != null && currentMapView.getMapGrid().getSelectedRec() != null ? currentMapView : null;
862  }
863 
869  private boolean doFind(final boolean performAction) {
870  final MapView<G, A, R> mapView = currentMapView;
871  if (mapView == null) {
872  return false;
873  }
874 
875  if (performAction) {
876  findDialogManager.showDialog(mapView);
877  }
878 
879  return true;
880  }
881 
887  private boolean doFindNext(final boolean performAction) {
888  final MapView<G, A, R> mapView = currentMapView;
889  return mapView != null && findDialogManager.findNext(mapView, performAction);
890  }
891 
897  private boolean doFindPrev(final boolean performAction) {
898  final MapView<G, A, R> mapView = currentMapView;
899  return mapView != null && findDialogManager.findPrev(mapView, performAction);
900  }
901 
907  private boolean doReplace(final boolean performAction) {
908  final MapView<G, A, R> mapView = currentMapView;
909  if (mapView == null) {
910  return false;
911  }
912 
913  if (performAction) {
914  replaceDialogManager.showDialog(mapView);
915  }
916 
917  return true;
918  }
919 
925  private boolean doClear(final boolean performAction) {
926  final MapView<G, A, R> mapView = currentMapView;
927  if (mapView == null) {
928  return false;
929  }
930 
931  final Rectangle selectedRec = mapView.getMapGrid().getSelectedRec();
932  if (selectedRec == null) {
933  return false;
934  }
935 
936  if (performAction) {
937  copyBuffer.clear(mapView, selectedRec);
938  }
939 
940  return true;
941  }
942 
948  private boolean doCut(final boolean performAction) {
949  final MapView<G, A, R> mapView = currentMapView;
950  if (mapView == null) {
951  return false;
952  }
953 
954  final Rectangle selectedRec = mapView.getMapGrid().getSelectedRec();
955  if (selectedRec == null) {
956  return false;
957  }
958 
959  if (performAction) {
960  copyBuffer.cut(mapView, selectedRec);
961  }
962 
963  return true;
964  }
965 
971  private boolean doCopy(final boolean performAction) {
972  final MapView<G, A, R> mapView = currentMapView;
973  if (mapView == null) {
974  return false;
975  }
976 
977  final Rectangle selectedRec = mapView.getMapGrid().getSelectedRec();
978  if (selectedRec == null) {
979  return false;
980  }
981 
982  if (performAction) {
983  copyBuffer.copy(mapView, selectedRec);
984  }
985 
986  return true;
987  }
988 
994  private boolean doPaste(final boolean performAction) {
995  final MapView<G, A, R> mapView = currentMapView;
996  if (mapView == null) {
997  return false;
998  }
999 
1000  final Point startLocation = mapView.getMapCursor().getLocation();
1001  if (copyBuffer.isEmpty()) {
1002  return false;
1003  }
1004 
1005  if (performAction) {
1006  copyBuffer.paste(mapView, startLocation);
1007  }
1008 
1009  return true;
1010  }
1011 
1017  private boolean doPasteTiled(final boolean performAction) {
1018  final MapView<G, A, R> mapView = currentMapView;
1019  if (mapView == null) {
1020  return false;
1021  }
1022 
1023  if (copyBuffer.isEmpty()) {
1024  return false;
1025  }
1026 
1027  final List<MapSquare<G, A, R>> selectedSquares = mapView.getSelectedSquares();
1028  if (selectedSquares.isEmpty()) {
1029  return false;
1030  }
1031 
1032  final MapGrid mapGrid = mapView.getMapGrid();
1033  final Rectangle selectedRec = mapGrid.getSelectedRec();
1034  if (selectedRec == null) {
1035  return false;
1036  }
1037 
1038  if (performAction) {
1039  final Point cursorLocation = mapView.getMapCursor().getLocation();
1040  copyBuffer.pasteTiled(mapView, selectedSquares, cursorLocation);
1041  }
1042 
1043  return true;
1044  }
1045 
1052  private boolean doShift(final boolean performAction, @NotNull final Direction direction) {
1053  final MapControl<G, A, R> mapControl = currentMapControl;
1054  if (mapControl == null) {
1055  return false;
1056  }
1057 
1058  final MapView<G, A, R> mapView = currentMapView;
1059  if (mapView == null) {
1060  return false;
1061  }
1062 
1063  final ShiftProcessor<G, A, R> shiftProcessor = new ShiftProcessor<>(mapViewSettings, mapView, mapControl.getMapModel(), insertionModeSet);
1064  if (!shiftProcessor.canShift(direction)) {
1065  return false;
1066  }
1067 
1068  if (performAction) {
1069  shiftProcessor.shift(direction);
1070  }
1071 
1072  return true;
1073  }
1074 
1080  private boolean doFillAuto(final boolean performAction) {
1081  final MapView<G, A, R> mapView = getSelection();
1082  if (mapView == null) {
1083  return false;
1084  }
1085 
1086  if (performAction) {
1087  fill(mapView, insertionModeSet.getAutoInsertionMode());
1088  }
1089 
1090  return true;
1091  }
1092 
1098  private boolean doFillAbove(final boolean performAction) {
1099  final MapView<G, A, R> mapView = getSelection();
1100  if (mapView == null) {
1101  return false;
1102  }
1103 
1104  if (performAction) {
1105  fill(mapView, insertionModeSet.getTopmostInsertionMode());
1106  }
1107 
1108  return true;
1109  }
1110 
1116  private boolean doFillBelow(final boolean performAction) {
1117  final MapView<G, A, R> mapView = getSelection();
1118  if (mapView == null) {
1119  return false;
1120  }
1121 
1122  if (performAction) {
1123  fill(mapView, insertionModeSet.getBottommostInsertionMode());
1124  }
1125 
1126  return true;
1127  }
1128 
1134  private boolean doRandFillAuto(final boolean performAction) {
1135  final MapView<G, A, R> mapView = getSelection();
1136  if (mapView == null) {
1137  return false;
1138  }
1139 
1140  if (performAction) {
1141  fillRandom(mapView, insertionModeSet.getAutoInsertionMode());
1142  }
1143 
1144  return true;
1145  }
1146 
1152  private boolean doRandFillAbove(final boolean performAction) {
1153  final MapView<G, A, R> mapView = getSelection();
1154  if (mapView == null) {
1155  return false;
1156  }
1157 
1158  if (performAction) {
1159  fillRandom(mapView, insertionModeSet.getTopmostInsertionMode());
1160  }
1161 
1162  return true;
1163  }
1164 
1170  private boolean doRandFillBelow(final boolean performAction) {
1171  final MapView<G, A, R> mapView = getSelection();
1172  if (mapView == null) {
1173  return false;
1174  }
1175 
1176  if (performAction) {
1177  fillRandom(mapView, insertionModeSet.getBottommostInsertionMode());
1178  }
1179 
1180  return true;
1181  }
1182 
1188  private boolean doFloodFill(final boolean performAction) {
1189  final MapView<G, A, R> mapView = currentMapView;
1190  if (mapView == null) {
1191  return false;
1192  }
1193 
1194  final Point mapCursorLocation = mapView.getMapCursor().getLocation();
1195  if (performAction) {
1196  FillUtils.floodFill(mapView.getMapControl().getMapModel(), mapCursorLocation, objectChooser.getSelections(), insertionModeSet);
1197  }
1198 
1199  return true;
1200  }
1201 
1207  private boolean doMassChange(final boolean performAction) {
1208  final MapView<G, A, R> mapView = getSelection();
1209  if (mapView == null) {
1210  return false;
1211  }
1212 
1213  if (performAction) {
1214  if (!massChangeDialog.showMassChangeDialog(parent)) {
1215  return false;
1216  }
1217 
1218  final String[] archNames = massChangeDialog.getArchNames();
1219  final String[] names = massChangeDialog.getNames();
1220  final Integer[] layers = massChangeDialog.getLayers();
1221  final Integer[] subLayers = massChangeDialog.getSubLayers();
1222  final String changes = massChangeDialog.getChanges();
1223 
1224  final Collection<MatchCriteria<G, A, R>> matchCriteriaArch = new ArrayList<>(archNames.length);
1225  for (final String archName : archNames) {
1226  matchCriteriaArch.add(new ArchetypeNameMatchCriteria<>(archName));
1227  }
1228 
1229  final Collection<MatchCriteria<G, A, R>> matchCriteriaName = new ArrayList<>(names.length);
1230  for (final String name : names) {
1231  matchCriteriaName.add(new ObjectNameMatchCriteria<>(name));
1232  }
1233 
1234  final MapModel<G, A, R> mapModel = mapView.getMapControl().getMapModel();
1235 
1236  mapModel.beginTransaction("Mass change"); // TODO; I18N/L10N
1237  try {
1238  for (final MapSquare<G, A, R> mapSquare : mapView.getSelectedSquares()) {
1239  for (final GameObject<G, A, R> gameObject : mapSquare) {
1240  boolean doModify = false;
1241 
1242  if (matchCriteriaArch.isEmpty() && matchCriteriaName.isEmpty()) {
1243  doModify = true;
1244  }
1245 
1246  for (final MatchCriteria<G, A, R> matchCriteria : matchCriteriaArch) {
1247  if (matchCriteria.matches(gameObject.getHead())) {
1248  doModify = true;
1249  break;
1250  }
1251  }
1252 
1253  for (final MatchCriteria<G, A, R> matchCriteria : matchCriteriaName) {
1254  if (!matchCriteria.matches(gameObject.getHead())) {
1255  doModify = true;
1256  break;
1257  }
1258  }
1259 
1260  if (!doModify) {
1261  continue;
1262  }
1263 
1264  gameObject.applyMassChange(layers, subLayers, changes);
1265  }
1266  }
1267  } finally {
1268  mapModel.endTransaction();
1269  }
1270  }
1271 
1272  return true;
1273  }
1274 
1280  private boolean doSelectAll(final boolean performAction) {
1281  if (currentMapView == null) {
1282  return false;
1283  }
1284 
1285  if (performAction) {
1286  currentMapView.getMapGrid().selectAll();
1287  }
1288 
1289  return true;
1290  }
1291 
1297  private boolean doInvertSelection(final boolean performAction) {
1298  if (currentMapView == null) {
1299  return false;
1300  }
1301 
1302  if (performAction) {
1303  currentMapView.getMapGrid().invertSelection();
1304  }
1305 
1306  return true;
1307  }
1308 
1314  private boolean doExpandEmptySelection(final boolean performAction) {
1315  final MapView<G, A, R> mapView = getSelection();
1316  if (mapView == null) {
1317  return false;
1318  }
1319 
1320  boolean foundEmptySelectedSquare = false;
1321  final List<MapSquare<G, A, R>> selectedSquares = mapView.getSelectedSquares();
1322  for (final MapSquare<G, A, R> selectedSquare : selectedSquares) {
1323  if (selectedSquare.isEmpty()) {
1324  foundEmptySelectedSquare = true;
1325  break;
1326  }
1327  }
1328  if (!foundEmptySelectedSquare) {
1329  return false;
1330  }
1331 
1332  if (performAction) {
1333  final Map<MapSquare<G, A, R>, Void> newSelection = new IdentityHashMap<>();
1334  Map<MapSquare<G, A, R>, Void> todo = new IdentityHashMap<>();
1335  for (final MapSquare<G, A, R> mapSquare : selectedSquares) {
1336  todo.put(mapSquare, null);
1337  newSelection.put(mapSquare, null);
1338  }
1339  final MapModel<G, A, R> mapModel = mapView.getMapControl().getMapModel();
1340  final MapArchObject<A> mapArchObject = mapModel.getMapArchObject();
1341  final Point point = new Point();
1342  while (!todo.isEmpty()) {
1343  final Map<MapSquare<G, A, R>, Void> tmp = new IdentityHashMap<>();
1344  for (final MapSquare<G, A, R> mapSquare : todo.keySet()) {
1345  for (int dy = -1; dy <= 1; dy++) {
1346  for (int dx = -1; dx <= 1; dx++) {
1347  if (dx != 0 || dy != 0) {
1348  mapSquare.getMapLocation(point, dx, dy);
1349  if (mapArchObject.isPointValid(point)) {
1350  final MapSquare<G, A, R> newMapSquare = mapModel.getMapSquare(point);
1351  if (newMapSquare.isEmpty() && !newSelection.containsKey(newMapSquare)) {
1352  tmp.put(newMapSquare, null);
1353  newSelection.put(newMapSquare, null);
1354  }
1355  }
1356  }
1357  }
1358  }
1359  }
1360  todo = tmp;
1361  }
1362  final MapGrid mapGrid = mapView.getMapGrid();
1363  mapGrid.beginTransaction();
1364  try {
1365  mapGrid.unSelect();
1366  for (final MapSquare<G, A, R> mapSquare : newSelection.keySet()) {
1367  mapSquare.getMapLocation(point);
1368  mapGrid.select(point, SelectionMode.ADD);
1369  }
1370  } finally {
1371  mapGrid.endTransaction();
1372  }
1373  }
1374 
1375  return true;
1376  }
1377 
1383  private boolean doTileStretchingChangeSet(final boolean performAction) {
1384  final MapView<G, A, R> mapView = getSelection();
1385  if (mapView == null) {
1386  return false;
1387  }
1388 
1389  if (performAction) {
1390  if (!tileStretchingDialog.showTileStretchingDialog(parent)) {
1391  return false;
1392  }
1393 
1394  final int heightValue = tileStretchingDialog.getHeightValue();
1395  final Integer[] subLayers = tileStretchingDialog.getSubLayers();
1396  final boolean isAbsolute = tileStretchingDialog.isTileStretchingAbsolute();
1397  tileStretching(mapView, heightValue, isAbsolute, subLayers);
1398  }
1399 
1400  return true;
1401  }
1402 
1410  private boolean doTileStretchingChange(final boolean performAction, final int heightValue, final boolean isAbsolute) {
1411  final MapView<G, A, R> mapView = getSelection();
1412  if (mapView == null) {
1413  return false;
1414  }
1415 
1416  if (performAction) {
1417  tileStretching(mapView, heightValue, isAbsolute, null);
1418  }
1419 
1420  return true;
1421  }
1422 
1428  private void fill(@NotNull final MapView<G, A, R> mapView, @NotNull final InsertionMode<G, A, R> insertionMode) {
1429  FillUtils.fill(mapView.getMapControl().getMapModel(), mapView.getSelectedSquares(), insertionMode, objectChooser.getSelections(), -1, false);
1430  }
1431 
1437  private void fillRandom(@NotNull final MapView<G, A, R> mapView, @NotNull final InsertionMode<G, A, R> insertionMode) {
1438  if (!randomFillDialog.showRandomFillDialog(parent)) {
1439  return;
1440  }
1441 
1442  final int fillDensity = randomFillDialog.getFillDensity();
1443  final boolean noAdjacent = randomFillDialog.isRandomFillSkipAdjacentSquares();
1444  FillUtils.fill(mapView.getMapControl().getMapModel(), mapView.getSelectedSquares(), insertionMode, objectChooser.getSelections(), fillDensity, noAdjacent);
1445  }
1446 
1455  private void tileStretching(@NotNull final MapView<G, A, R> mapView, final int heightValue, final boolean isAbsolute, @Nullable final Integer[] subLayers) {
1456  final MapModel<G, A, R> mapModel = mapView.getMapControl().getMapModel();
1457 
1458  mapModel.beginTransaction("Tile stretching"); // TODO; I18N/L10N
1459  try {
1460  for (final MapSquare<G, A, R> mapSquare : mapView.getSelectedSquares()) {
1461  for (final GameObject<G, A, R> gameObject : mapSquare) {
1462  gameObject.updateTileStretch(heightValue, isAbsolute, subLayers);
1463  }
1464  }
1465  } finally {
1466  mapModel.endTransaction();
1467  }
1468  }
1469 
1470  @Override
1471  public void setAction(@NotNull final Action action, @NotNull final String name) {
1472  if (name.equals("clear")) {
1473  aClear = action;
1474  } else if (name.equals("cut")) {
1475  aCut = action;
1476  } else if (name.equals("copy")) {
1477  aCopy = action;
1478  } else if (name.equals("paste")) {
1479  aPaste = action;
1480  } else if (name.equals("pasteTiled")) {
1481  aPasteTiled = action;
1482  } else if (name.equals("shiftNorth")) {
1483  aShiftNorth = action;
1484  } else if (name.equals("shiftNorthEast")) {
1485  aShiftNorthEast = action;
1486  } else if (name.equals("shiftEast")) {
1487  aShiftEast = action;
1488  } else if (name.equals("shiftSouthEast")) {
1489  aShiftSouthEast = action;
1490  } else if (name.equals("shiftSouth")) {
1491  aShiftSouth = action;
1492  } else if (name.equals("shiftSouthWest")) {
1493  aShiftSouthWest = action;
1494  } else if (name.equals("shiftWest")) {
1495  aShiftWest = action;
1496  } else if (name.equals("shiftNorthWest")) {
1497  aShiftNorthWest = action;
1498  } else if (name.equals("find")) {
1499  aFind = action;
1500  } else if (name.equals("findNext")) {
1501  aFindNext = action;
1502  } else if (name.equals("findPrev")) {
1503  aFindPrev = action;
1504  } else if (name.equals("replace")) {
1505  aReplace = action;
1506  } else if (name.equals("fillAuto")) {
1507  aFillAuto = action;
1508  } else if (name.equals("fillAbove")) {
1509  aFillAbove = action;
1510  } else if (name.equals("fillBelow")) {
1511  aFillBelow = action;
1512  } else if (name.equals("randFillAuto")) {
1513  aRandFillAuto = action;
1514  } else if (name.equals("randFillAbove")) {
1515  aRandFillAbove = action;
1516  } else if (name.equals("randFillBelow")) {
1517  aRandFillBelow = action;
1518  } else if (name.equals("floodFill")) {
1519  aFloodFill = action;
1520  } else if (name.equals("massChange")) {
1521  aMassChange = action;
1522  } else if (name.equals("selectAll")) {
1523  aSelectAll = action;
1524  } else if (name.equals("invertSelection")) {
1525  aInvertSelection = action;
1526  } else if (name.equals("expandEmptySelection")) {
1527  aExpandEmptySelection = action;
1528  } else if (name.equals("tileStretchingSet")) {
1529  aTileStretchingSet = action;
1530  } else if (name.equals("tileStretchingClear")) {
1531  aTileStretchingClear = action;
1532  } else if (name.equals("tileStretchingIncrease")) {
1533  aTileStretchingIncrease = action;
1534  } else if (name.equals("tileStretchingDecrease")) {
1535  aTileStretchingDecrease = action;
1536  } else {
1537  throw new IllegalArgumentException();
1538  }
1539  refreshMenus();
1540  }
1541 
1542  @Override
1543  public void activeMapViewChanged(@Nullable final MapView<G, A, R> mapView) {
1544  currentMapView = mapView;
1545  refreshMenus();
1546  }
1547 
1548  @Override
1549  public void mapViewCreated(@NotNull final MapView<G, A, R> mapView) {
1550  mapView.getMapGrid().addMapGridListener(mapGridListener);
1551  }
1552 
1553  @Override
1554  public void mapViewClosing(@NotNull final MapView<G, A, R> mapView) {
1555  mapView.getMapGrid().removeMapGridListener(mapGridListener);
1556  }
1557 
1558 }
void replace()
"Replace" was selected from the Edit menu.
void shiftNorthWest()
"Shift North West" was selected from the Edit menu.
void massChange()
"Mass change" was selected from the Edit menu.
Action aCopy
Action called for "copy".
boolean doReplace(final boolean performAction)
Executes the "replace" action.
boolean doPaste(final boolean performAction)
Executes the "paste" action.
void shiftSouthWest()
"Shift South West" was selected from the Edit menu.
Rectangle getSelectedRec()
Returns the smallest rectangle containing selection.
Definition: MapGrid.java:514
void tileStretchingIncrease()
Invoked when the user wants to increase tile stretching on the selected map squares.
MapModelListener< G, A, R > newMapModelListener()
Creates a new MapModelListener that refreshes the actions when the map contents change.
InsertionMode< G, A, R > getAutoInsertionMode()
Returns the "auto" insertion mode.
List< MapSquare< G, A, R > > getSelectedSquares()
Returns the selected squares.
boolean isPointValid(@Nullable Point pos)
Checks whether the given coordinate is within map bounds.
Displays a dialog asking for parameters for the "mass change" function.
String [] getArchNames()
Returns the arch names to affect.
A MapModel reflects the data of a map.
Definition: MapModel.java:75
A MapManager manages all opened maps.
Definition: MapManager.java:37
MapView< G, A, R > currentMapView
The last known active map view, or.
boolean doSelectAll(final boolean performAction)
Executes the "select all" action.
Graphical User Interface of Gridarta.
boolean isTileStretchingAbsolute()
Action method for "absolute" action.
boolean doPasteTiled(final boolean performAction)
Executes the "paste tiled" action.
Action aClear
Action called for "clear".
Integer [] getSubLayers()
Returns the sub-layers to affect.
Action aFillBelow
Action called for "fill below".
Creates and displays the find dialog.
Action aExpandEmptySelection
Action called for "grow empty selection".
boolean isEmpty()
Check whether this square is empty.
void mapViewClosing(@NotNull final MapView< G, A, R > mapView)
This event handler is called when a map view is to be closed.
This package contains the framework for validating maps.
Action aShiftSouthWest
Action called for "shift south west".
boolean showMassChangeDialog(@NotNull final Component parent)
Displays the mass change dialog.
void endTransaction()
End a transaction.
boolean doRandFillAbove(final boolean performAction)
Executes the "rand fill above" action.
boolean doFindPrev(final boolean performAction)
Executes the "find prev" action.
MapGrid getMapGrid()
Returns the MapGrid of this view.
Action aRandFillAuto
Action called for "random fill".
boolean doCut(final boolean performAction)
Executes the "cut" action.
void clear(@NotNull final MapView< G, A, R > mapView, @NotNull final Rectangle selectedRec)
Executing the Clear command.
Action aShiftSouth
Action called for "shift south".
final InsertionModeSet< G, A, R > insertionModeSet
The InsertionModeSet to use.
boolean findNext(@NotNull final MapView< G, A, R > mapView, final boolean performAction)
Executes the "find next" action.
MapManagerListener< G, A, R > newMapManagerListener()
Creates a new MapManagerListener that refreshes the actions when the current map changes.
Interface for listeners listening on MapModel events.
Action aInvertSelection
Action called for "invert selection".
MapView< G, A, R > getSelection()
Determine if the current map has a selection.
Action aShiftSouthEast
Action called for "shift south east".
boolean doClear(final boolean performAction)
Executes the "clear" action.
MainActions(@NotNull final FindDialogManager< G, A, R > findDialogManager, @NotNull final ReplaceDialogManager< G, A, R > replaceDialogManager, @NotNull final JFrame parent, @NotNull final MapViewSettings mapViewSettings, @NotNull final ArchetypeSet< G, A, R > archetypeSet, @NotNull final CopyBuffer< G, A, R > copyBuffer, @NotNull final ObjectChooser< G, A, R > objectChooser, @NotNull final MapManager< G, A, R > mapManager, @NotNull final InsertionModeSet< G, A, R > insertionModeSet)
Create a new instance.
final MapViewSettings mapViewSettings
The map view settings instance.
void paste()
"Paste" was selected from the Edit menu.
boolean showRandomFillDialog(@NotNull final Component parent)
Displays the random fill dialog.
final ObjectChooser< G, A, R > objectChooser
The ObjectChooser instance to use.
void shiftEast()
"Shift East" was selected from the Edit menu.
Integer [] getLayers()
Returns the layers to affect.
void clear()
"Clear" was selected from the Edit menu.
void cut(@NotNull final MapView< G, A, R > mapView, @NotNull final Rectangle selectedRec)
Executing the Cut command.
boolean doTileStretchingChange(final boolean performAction, final int heightValue, final boolean isAbsolute)
Executes one of the "tile stretching clear/increase/decrease" actions.
MapControl< G, A, R > getMapControl()
Return the controller of this view.
void selectAll()
Invoked when the user wants to select all squares from a map.
Action aRandFillAbove
Action called for "random fill above".
void shiftSouth()
"Shift South" was selected from the Edit menu.
boolean doExpandEmptySelection(final boolean performAction)
Executes the "expand empty selection" action.
void unSelect()
Clears all selection and pre-selection flags from the grid.
Definition: MapGrid.java:263
boolean doFindNext(final boolean performAction)
Executes the "find next" action.
boolean doShift(final boolean performAction, @NotNull final Direction direction)
Executes the "shift" action.
boolean isEmpty()
Returns whether this copy buffer contains any game objects.
Point getLocation()
Get position of cursor.
Definition: MapCursor.java:226
MapModel< G, A, R > getMapModel()
Returns the map model.
void shiftNorthEast()
"Shift North East" was selected from the Edit menu.
boolean canShift(@NotNull final Direction dir)
Check whether shifting is possible.
Base package of all Gridarta classes.
void pasteTiled(@NotNull final MapView< G, A, R > mapView, @NotNull final Iterable< MapSquare< G, A, R >> selectedSquares, @NotNull final Point origin)
Executing the Paste Tiled command.
Action aCut
Action called for "cut".
void fillRandom(@NotNull final MapView< G, A, R > mapView, @NotNull final InsertionMode< G, A, R > insertionMode)
"RandomFill" was selected from the Edit menu.
Reflects a game object (object on a map).
Definition: GameObject.java:36
Action aPaste
Action called for "paste".
boolean doFillAuto(final boolean performAction)
Executes the "fill auto" action.
Interface for listeners listening to MapGridEvents.
void fillAbove()
"Fill above" was selected from the Edit menu.
Action aSelectAll
Action called for "select all".
A global editor action.
Interface for listeners listening to MapManager changes.
final MapGridListener mapGridListener
The map grid listener used to detect map grid changes.
void tileStretchingDecrease()
Invoked when the user wants to decrease tile stretching on the selected map squares.
InsertionMode< G, A, R > getBottommostInsertionMode()
Returns the "bottommost" insertion mode.
boolean doCopy(final boolean performAction)
Executes the "copy" action.
Displays a dialog asking for parameters for the "tile stretching set" function.
final FindDialogManager< G, A, R > findDialogManager
The find dialog manager to use.
void activeMapViewChanged(@Nullable final MapView< G, A, R > mapView)
This event handler is called when the current map view has changed.
boolean isRandomFillSkipAdjacentSquares()
Action method for "skip adjacent squares" action.
Container for settings that affect the rendering of maps.
MapSquare< G, A, R > getMapSquare(@NotNull Point pos)
Get the square at a specified location.
boolean doMassChange(final boolean performAction)
Executes the "mass change" actions.
InsertionMode< G, A, R > getTopmostInsertionMode()
Returns the "topmost" insertion mode.
void findPrev()
"Find previous" was selected from the Edit menu.
GameObjects are the objects based on Archetypes found on maps.
final ReplaceDialogManager< G, A, R > replaceDialogManager
The replace dialog manager to use.
void randFillAuto()
"Random fill" was selected from the Edit menu.
Action aFillAbove
Action called for "fill above".
Interface for listeners interested in events related to MapViewManager instances. ...
String [] getNames()
Returns the object names to affect.
boolean doFloodFill(final boolean performAction)
Executes the "flood fill" action.
boolean showTileStretchingDialog(@NotNull final Component parent)
Displays the tile stretching dialog.
Action aTileStretchingClear
Action called for "tile stretching -> clear Z".
2D-Grid containing flags for selection, pre-selection, cursor, warnings and errors.
Definition: MapGrid.java:45
void shiftNorth()
"Shift North" was selected from the Edit menu.
void expandEmptySelection()
Invoked when the user wants to expand the selection of empty map squares to surrounding empty map squ...
Action aFindNext
Action called for "find next".
void showDialog(@NotNull final MapView< G, A, R > mapView)
Displays the replace dialog.
final CopyBuffer< G, A, R > copyBuffer
The copy buffer instance.
void floodFill()
"Flood fill" was selected from the Edit menu.
void cut()
"Cut" was selected from the Edit menu.
List<? extends BaseObject< G, A, R, ?> > getSelections()
Returns the selected arches in the left-side panel.
void tileStretching(@NotNull final MapView< G, A, R > mapView, final int heightValue, final boolean isAbsolute, @Nullable final Integer[] subLayers)
Performs one of the "tile stretching" actions.
Base classes for rendering maps.
Displays a dialog asking for parameters for the "random fill" function.
void fill(@NotNull final MapView< G, A, R > mapView, @NotNull final InsertionMode< G, A, R > insertionMode)
"Fill" was selected from the Edit menu.
Action aTileStretchingDecrease
Action called for "tile stretching -> decrease Z".
void beginTransaction()
Starts a new transaction.
Definition: MapGrid.java:756
Action aShiftWest
Action called for "shift west".
void showDialog(@NotNull final MapView< G, A, R > mapView)
Displays the replace dialog.
Action aMassChange
Action called for "mass change".
boolean doTileStretchingChangeSet(final boolean performAction)
Executes one of the "tile stretching" actions.
final RandomFillDialog randomFillDialog
The RandomFillDialog instance.
void randFillBelow()
"Random fill below" was selected from the Edit menu.
void mapViewCreated(@NotNull final MapView< G, A, R > mapView)
This event handler is called when a map view was created.
void randFillAbove()
"Random fill above" was selected from the Edit menu.
Action aFloodFill
Action called for "flood fill".
Encapsulates actions and related functions.
A MatchCriteria that matches by object name.
A getMapArchObject()
Returns the Map Arch Object with the meta information about the map.
boolean doFind(final boolean performAction)
Executes the "find" action.
void refreshMenus()
Enable/disable menu entries based on the current state.
boolean doFillBelow(final boolean performAction)
Executes the "fill below" action.
void shiftSouthEast()
"Shift South East" was selected from the Edit menu.
void select(@NotNull final Point pos, @NotNull final SelectionMode selectionMode)
Selects or deselects a single square.
Definition: MapGrid.java:408
Action aShiftEast
Action called for "shift east".
MapCursor< G, A, R > getMapCursor()
Returns the MapCursor of this view.
void endTransaction()
Ends a transaction.
Definition: MapGrid.java:776
void shiftWest()
"Shift West" was selected from the Edit menu.
String getChanges()
Returns the actual changes to apply.
Currently nothing more than a marker interface for unification.
Definition: MapControl.java:35
Action aTileStretchingSet
Action called for "tile stretching -> set Z".
void fillBelow()
"Fill below" was selected from the Edit menu.
Action aPasteTiled
Action called for "paste tiled".
A map view consists of a map grid and a map cursor, and is attached to a map control.
Definition: MapView.java:43
void shift(@NotNull final Direction dir)
Shift the map contents by one square.
void setAction(@NotNull final Action action, @NotNull final String name)
Sets the Action instance for this editor action.
Action aFindPrev
Action called for "find prev".
void tileStretchingClear()
Invoked when the user wants to clear tile stretching on the selected map squares. ...
Action aShiftNorthWest
Action called for "shift north west".
final TileStretchingDialog tileStretchingDialog
The TileStretchingDialog instance.
Action aTileStretchingIncrease
Action called for "tile stretching -> increase Z".
An interface for classes that collect errors.
ADD
All squares that are preselected get selected.
Action aFillAuto
Action called for "fill".
Action aRandFillBelow
Action called for "random fill below".
void pasteTiled()
"Paste Tiled" was selected from the Edit menu.
Utility class implementing fill operations on map instances.
Definition: FillUtils.java:43
boolean doInvertSelection(final boolean performAction)
Executes the "invert selection" action.
Interface that captures similarities between different ArchetypeSet implementations.
Modes that describe how squares get selected.
Action aFind
Action called for "find".
void findNext()
"Find next" was selected from the Edit menu.
Common base interface for ObjectChoosers.
void beginTransaction(@NotNull String name)
Starts a new transaction.
final JFrame parent
The parent component for dialog windows.
void invertSelection()
Invoked when the user wants to invert all selected squares from a map.
A MatchCriteria that matches by archetype name.
void find()
"Find" was selected from the Edit menu.
Action aReplace
Action called for "replace".
void copy()
"Copy" was selected from the Edit menu.
Action aShiftNorth
Action called for "shift north".
Criteria for game object matchers.
Common base implementation of CopyBuffer.
Definition: CopyBuffer.java:52
void fillAuto()
"Fill" was selected from the Edit menu.
void paste(@NotNull final MapView< G, A, R > mapView, @NotNull final Point startLocation)
Executing the Paste command.
MapControl< G, A, R > currentMapControl
The last known active map, or.
boolean doFillAbove(final boolean performAction)
Executes the "fill above" action.
The location of a map file with a map directory.
Definition: MapFile.java:31
boolean doRandFillAuto(final boolean performAction)
Executes the "rand fill auto" action.
Integer [] getSubLayers()
Returns the sub-layers to affect.
Performs a "shift" operation in a map: shift all selected squares into the given direction.
Action aShiftNorthEast
Action called for "shift north east".
void tileStretchingSet()
Invoked when the user wants to set tile stretching on the selected map squares.
int getFillDensity()
Returns the fill density.
boolean doRandFillBelow(final boolean performAction)
Executes the "rand fill below" action.
The class Size2D represents a 2d rectangular area.
Definition: Size2D.java:30
This event is created by MapGrid.
boolean findPrev(@NotNull final MapView< G, A, R > mapView, final boolean performAction)
Executes the "find next" action.
final MassChangeDialog massChangeDialog
The MassChangeDialog instance.
void copy(@NotNull final MapView< G, A, R > mapView, @NotNull final Rectangle selectedRec)
Executing the Copy command.