From: <aki...@us...> - 2008-07-22 18:45:19
|
Revision: 4386 http://gridarta.svn.sourceforge.net/gridarta/?rev=4386&view=rev Author: akirschbaum Date: 2008-07-22 18:45:23 +0000 (Tue, 22 Jul 2008) Log Message: ----------- Add more options to insertion tool. Modified Paths: -------------- trunk/crossfire/ChangeLog trunk/crossfire/src/cfeditor/CMainControl.java trunk/daimonin/ChangeLog trunk/daimonin/src/daieditor/CMainControl.java trunk/src/app/net/sf/gridarta/CopyBuffer.java trunk/src/app/net/sf/gridarta/MapImageCache.java trunk/src/app/net/sf/gridarta/floodfill/Floodfill.java trunk/src/app/net/sf/gridarta/gui/DefaultObjectChooser.java trunk/src/app/net/sf/gridarta/gui/MainActions.java trunk/src/app/net/sf/gridarta/gui/ObjectChooser.java trunk/src/app/net/sf/gridarta/gui/ReplaceDialog.java trunk/src/app/net/sf/gridarta/gui/ShiftProcessor.java trunk/src/app/net/sf/gridarta/gui/archetypechooser/ArchetypeChooserControl.java trunk/src/app/net/sf/gridarta/gui/map/tools/InsertionTool.java trunk/src/app/net/sf/gridarta/gui/map/tools/action.properties trunk/src/app/net/sf/gridarta/gui/map/tools/action_de.properties trunk/src/app/net/sf/gridarta/gui/map/tools/action_fr.properties trunk/src/app/net/sf/gridarta/gui/map/tools/action_sv.properties trunk/src/app/net/sf/gridarta/gui/pickmapchooser/PickmapChooserControl.java trunk/src/app/net/sf/gridarta/map/DefaultMapModel.java trunk/src/app/net/sf/gridarta/map/MapModel.java trunk/src/app/net/sf/gridarta/map/MapSquare.java Added Paths: ----------- trunk/src/app/net/sf/gridarta/map/InsertionMode.java Modified: trunk/crossfire/ChangeLog =================================================================== --- trunk/crossfire/ChangeLog 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/crossfire/ChangeLog 2008-07-22 18:45:23 UTC (rev 4386) @@ -1,3 +1,7 @@ +2008-07-22 Andreas Kirschbaum + + * Add more options to insertion tool. + 2008-07-18 Andreas Kirschbaum * Add more options to deletion tool. Modified: trunk/crossfire/src/cfeditor/CMainControl.java =================================================================== --- trunk/crossfire/src/cfeditor/CMainControl.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/crossfire/src/cfeditor/CMainControl.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -88,6 +88,7 @@ import net.sf.gridarta.io.IOUtils; import net.sf.gridarta.io.PathManager; import net.sf.gridarta.map.AutoValidator; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapControl; import net.sf.gridarta.map.MapModel; import net.sf.gridarta.map.validation.DefaultErrorCollector; @@ -287,7 +288,12 @@ log.fatal("GameObjectMatcher 'monster' does not exist"); throw new MissingResourceException("GameObjectMatcher 'monster' does not exist", null, null); } + final GameObjectMatcher belowFloorMatcher = gameObjectMatchers.getMatcher("below_floor"); + if (belowFloorMatcher == null) { + log.warn("GameObjectMatcher 'below_floor' does not exist"); + } DeletionTool.init(floorMatcher, wallMatcher, monsterMatcher); + InsertionMode.init(floorMatcher, wallMatcher, belowFloorMatcher); final GameObjectMatcher exitMatcher = gameObjectMatchers.getMatcher("exit"); if (exitMatcher == null) { log.fatal("GameObjectMatcher 'exit' does not exist"); Modified: trunk/daimonin/ChangeLog =================================================================== --- trunk/daimonin/ChangeLog 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/daimonin/ChangeLog 2008-07-22 18:45:23 UTC (rev 4386) @@ -1,3 +1,7 @@ +2008-07-22 Andreas Kirschbaum + + * Add more options to insertion tool. + 2008-07-18 Andreas Kirschbaum * Add more options to deletion tool. Modified: trunk/daimonin/src/daieditor/CMainControl.java =================================================================== --- trunk/daimonin/src/daieditor/CMainControl.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/daimonin/src/daieditor/CMainControl.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -95,6 +95,7 @@ import net.sf.gridarta.io.IOUtils; import net.sf.gridarta.io.PathManager; import net.sf.gridarta.map.AutoValidator; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapControl; import net.sf.gridarta.map.MapModel; import net.sf.gridarta.map.MapSquare; @@ -343,7 +344,12 @@ log.fatal("GameObjectMatcher 'monster' does not exist"); throw new MissingResourceException("GameObjectMatcher 'monster' does not exist", null, null); } + final GameObjectMatcher belowFloorMatcher = gameObjectMatchers.getMatcher("below_floor"); + if (belowFloorMatcher == null) { + log.warn("GameObjectMatcher 'below_floor' does not exist"); + } DeletionTool.init(floorMatcher, wallMatcher, monsterMatcher); + InsertionMode.init(floorMatcher, wallMatcher, belowFloorMatcher); final GameObjectMatcher exitMatcher = gameObjectMatchers.getMatcher("exit"); if (exitMatcher == null) { log.fatal("GameObjectMatcher 'exit' does not exist"); Modified: trunk/src/app/net/sf/gridarta/CopyBuffer.java =================================================================== --- trunk/src/app/net/sf/gridarta/CopyBuffer.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/CopyBuffer.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -29,6 +29,7 @@ import net.sf.gridarta.gameobject.GameObject; import net.sf.gridarta.gui.map.MapView; import net.sf.gridarta.gui.map.MapViewBasic; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapArchObject; import net.sf.gridarta.map.MapControl; import net.sf.gridarta.map.MapModel; @@ -158,7 +159,7 @@ if ((mode == Mode.DO_CUT || mode == Mode.DO_COPY) && gameObject.isHead() && !gameObject.isInContainer() && mainControl.isEditType(gameObject)) { // copy this gameObject final G clone = gameObject.createClone(posx - selRec.x, posy - selRec.y); - copyMapCtrl.getMapModel().addGameObjectToMap(clone, false); + copyMapCtrl.getMapModel().addGameObjectToMap(clone, InsertionMode.TOPMOST); } // delete the gameObject if we have a "cut" or "clear" command // again, arches that don't match the view settings are ignored @@ -199,7 +200,7 @@ if (mapControl.getMapModel().isPointValid(pos)) { for (final G gameObject : square) { if (!gameObject.isMulti()) { - mapControl.getMapModel().addCopyToMap(gameObject, pos, true, false); + mapControl.getMapModel().addCopyToMap(gameObject, pos, true, InsertionMode.TOPMOST); } } } @@ -211,7 +212,7 @@ if (mapControl.getMapModel().isPointValid(pos)) { for (final G gameObject : square) { if (gameObject.isMulti()) { - mapControl.getMapModel().addCopyToMap(gameObject, pos, true, false); + mapControl.getMapModel().addCopyToMap(gameObject, pos, true, InsertionMode.TOPMOST); } } } @@ -222,13 +223,12 @@ /** * Executing the Fill command. * @param mapView the map view to fill on - * @param fillBelow if true, the filling content is placed *below* the - * existing map + * @param insertionMode the insertion mode to use * @param seed map view of the random objects or <code>null</code> to use * the currently selected Archetype. * @param density the fill density in percent; -1 to disable */ - public void fill(final MapView<G, A, R, V> mapView, final boolean fillBelow, final MapView<G, A, R, V> seed, final int density) { + public void fill(final MapView<G, A, R, V> mapView, final InsertionMode insertionMode, final MapView<G, A, R, V> seed, final int density) { if (mapView.getView().getMapGrid().getSelectedRec() == null) { return; // should actually never happen } @@ -249,7 +249,7 @@ continue; } final G gameObject = archList.get(MainControl.rnd.nextInt(archList.size())); - mapView.getMapControl().getMapModel().addCopyToMap(gameObject, p, false, fillBelow); + mapView.getMapControl().getMapModel().addCopyToMap(gameObject, p, false, insertionMode); } mapView.getMapControl().getMapModel().endTransaction(); } Modified: trunk/src/app/net/sf/gridarta/MapImageCache.java =================================================================== --- trunk/src/app/net/sf/gridarta/MapImageCache.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/MapImageCache.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -135,7 +135,7 @@ * @param mapFile the map file to return the icon image for * @return the icon image */ - @NotNull + @Nullable public ImageIcon getOrCreateIcon(@NotNull final File mapFile) { final ImageIcon cachedIcon = lookupCache(mapFile, Type.ICON); if (cachedIcon != null || mapFile.isDirectory()) { Modified: trunk/src/app/net/sf/gridarta/floodfill/Floodfill.java =================================================================== --- trunk/src/app/net/sf/gridarta/floodfill/Floodfill.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/floodfill/Floodfill.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -25,6 +25,7 @@ import net.sf.gridarta.Size2D; import net.sf.gridarta.gameobject.Archetype; import net.sf.gridarta.gameobject.GameObject; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapArchObject; import net.sf.gridarta.map.MapControl; import net.sf.gridarta.map.MapModel; @@ -86,7 +87,7 @@ if (mapControl.getMapModel().isPointValid(p) && mapModel.getMapSquare(p).isEmpty()) { area[p.x][p.y] = WAS_EMPTY; final G gameObject = archList.get(MainControl.rnd.nextInt(archList.size())); - mapControl.getMapModel().addCopyToMap(gameObject, p, false, false); + mapControl.getMapModel().addCopyToMap(gameObject, p, false, InsertionMode.TOPMOST); try { if (area[p.x - 1][p.y] == NOT_LOOKED_AT) { area[p.x - 1][p.y] = BORDER; Modified: trunk/src/app/net/sf/gridarta/gui/DefaultObjectChooser.java =================================================================== --- trunk/src/app/net/sf/gridarta/gui/DefaultObjectChooser.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/DefaultObjectChooser.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -37,6 +37,7 @@ import net.sf.gridarta.gui.pickmapchooser.PickmapChooserControl; import net.sf.gridarta.gui.pickmapchooser.PickmapChooserListener; import net.sf.gridarta.gui.selectedsquare.SelectedSquareView; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapArchObject; import net.sf.gridarta.map.MapModel; import net.sf.japi.swing.ActionFactory; @@ -152,8 +153,8 @@ /** {@inheritDoc} */ @Nullable - public G insertSelectedObject(@NotNull final MapModel<G, A, R> mapModel, @NotNull final Point pos, final boolean allowMany) { - return pickmapActive ? pickmapChooserControl.insertSelectedObject(mapModel, pos, allowMany) : archetypeChooserControl.insertSelectedArchetype(mapModel, pos, allowMany); + public G insertSelectedObject(@NotNull final MapModel<G, A, R> mapModel, @NotNull final Point pos, final boolean allowMany, final InsertionMode insertionMode) { + return pickmapActive ? pickmapChooserControl.insertSelectedObject(mapModel, pos, allowMany, insertionMode) : archetypeChooserControl.insertSelectedArchetype(mapModel, pos, allowMany, insertionMode); } /** {@inheritDoc} */ Modified: trunk/src/app/net/sf/gridarta/gui/MainActions.java =================================================================== --- trunk/src/app/net/sf/gridarta/gui/MainActions.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/MainActions.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -43,6 +43,7 @@ import net.sf.gridarta.gui.map.MapView; import net.sf.gridarta.gui.map.MapViewBasic; import net.sf.gridarta.gui.pickmapchooser.PickmapChooserControl; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapArchObject; import net.sf.gridarta.map.MapControl; import net.sf.gridarta.map.MapModel; @@ -448,7 +449,7 @@ public void fillAbove() { final MapView<G, A, R, V> mapView = getFillAboveEnabled(); if (mapView != null) { - fillWanted(mapView, false); + fillWanted(mapView, InsertionMode.TOPMOST); } } @@ -456,25 +457,24 @@ public void fillBelow() { final MapView<G, A, R, V> mapView = getFillBelowEnabled(); if (mapView != null) { - fillWanted(mapView, true); + fillWanted(mapView, InsertionMode.BOTTOMMOST); } } /** * "Fill" was selected from the Edit menu. * @param mapView the map view to fill - * @param fillBelow true if "Fill Below" was activated, false if "Fill - * Above" + * @param insertionMode the insertion mode to use */ - private void fillWanted(@NotNull final MapView<G, A, R, V> mapView, final boolean fillBelow) { - mainControl.getCopyBuffer().fill(mapView, fillBelow, null, -1); + private void fillWanted(@NotNull final MapView<G, A, R, V> mapView, final InsertionMode insertionMode) { + mainControl.getCopyBuffer().fill(mapView, insertionMode, null, -1); } /** "Random fill above" was selected from the Edit menu. */ public void randFillAbove() { final MapView<G, A, R, V> mapView = getRandFillAboveEnabled(); if (mapView != null) { - fillRandomWanted(mapView, false); + fillRandomWanted(mapView, InsertionMode.TOPMOST); } } @@ -482,18 +482,19 @@ public void randFillBelow() { final MapView<G, A, R, V> mapView = getRandFillBelowEnabled(); if (mapView != null) { - fillRandomWanted(mapView, true); + fillRandomWanted(mapView, InsertionMode.BOTTOMMOST); } } /** * "RandomFill" was selected from the Edit menu. * @param mapView the map view to fill - * @param fillBelow true if "Fill Below" was activated, false if "Fill - * Above" + * @param insertionMode the insertion mode to use */ - private void fillRandomWanted(@NotNull final MapView<G, A, R, V> mapView, final boolean fillBelow) { - final StringBuilder title = new StringBuilder(fillBelow ? "Random fill below " : "Random fill above "); + private void fillRandomWanted(@NotNull final MapView<G, A, R, V> mapView, final InsertionMode insertionMode) { + final StringBuilder title = new StringBuilder("Random fill "); + title.append(insertionMode); + title.append(" "); final G arch = objectChooser.getObjectChooserHighlight(); MapControl<G, A, R, V> pickmap = null; @@ -531,7 +532,7 @@ if (rand < 1 || rand > 100) { JOptionPane.showMessageDialog(mainControl.getMainView(), "The fill density must be between 1-100.", "Illegal Value.", JOptionPane.ERROR_MESSAGE); } else { - mainControl.getCopyBuffer().fill(mapView, fillBelow, pickmap == null ? null : pickmap.getMapViewFrame(), rand); + mainControl.getCopyBuffer().fill(mapView, insertionMode, pickmap == null ? null : pickmap.getMapViewFrame(), rand); break; } } Modified: trunk/src/app/net/sf/gridarta/gui/ObjectChooser.java =================================================================== --- trunk/src/app/net/sf/gridarta/gui/ObjectChooser.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/ObjectChooser.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -24,6 +24,7 @@ import javax.swing.JMenu; import net.sf.gridarta.gameobject.Archetype; import net.sf.gridarta.gameobject.GameObject; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapArchObject; import net.sf.gridarta.map.MapModel; import org.jetbrains.annotations.NotNull; @@ -95,11 +96,12 @@ * @param pos The location to add to. * @param allowMany Whether to allow multiple copies of the inserted game * object. + * @param insertionMode the insertion mode to use * @return The inserted game object, or <code>null</code> if nothing was * inserted. */ @Nullable - G insertSelectedObject(@NotNull final MapModel<G, A, R> mapModel, @NotNull Point pos, boolean allowMany); + G insertSelectedObject(@NotNull final MapModel<G, A, R> mapModel, @NotNull Point pos, boolean allowMany, InsertionMode insertionMode); /** * Sets the pickmap folders menu to manage. Modified: trunk/src/app/net/sf/gridarta/gui/ReplaceDialog.java =================================================================== --- trunk/src/app/net/sf/gridarta/gui/ReplaceDialog.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/ReplaceDialog.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -43,6 +43,7 @@ import net.sf.gridarta.gameobject.GameObject; import net.sf.gridarta.gui.map.MapView; import net.sf.gridarta.gui.map.MapViewBasic; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapArchObject; import net.sf.gridarta.map.MapControl; import net.sf.gridarta.map.MapSquare; @@ -364,7 +365,7 @@ // insert replacement object if (randomArch.isMulti()) { // multi's cannot be inserted properly, so we just put them ontop - mapControl.getMapModel().insertArchetype(randomArch.getArchetypeName(), new Point(square.getMapX(), square.getMapY()), false, false, false); + mapControl.getMapModel().insertArchetype(randomArch.getArchetypeName(), new Point(square.getMapX(), square.getMapY()), false, false, InsertionMode.TOPMOST); // TODO: if from pickmap it could have special attributes -> copy them } else { Modified: trunk/src/app/net/sf/gridarta/gui/ShiftProcessor.java =================================================================== --- trunk/src/app/net/sf/gridarta/gui/ShiftProcessor.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/ShiftProcessor.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -30,6 +30,7 @@ import net.sf.gridarta.gui.map.MapCursor; import net.sf.gridarta.gui.map.MapGrid; import net.sf.gridarta.gui.map.MapView; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapArchObject; import net.sf.gridarta.map.MapModel; import org.jetbrains.annotations.NotNull; @@ -265,7 +266,7 @@ // [prevPos] = [pos] for (final G gameObject : mapModel.getMapSquare(pos)) { if (gameObject.isHead() && !gameObject.isInContainer() && mainControl.isEditType(gameObject)) { - mapModel.addGameObjectToMap(gameObject.createClone(prevPos.x, prevPos.y), false); + mapModel.addGameObjectToMap(gameObject.createClone(prevPos.x, prevPos.y), InsertionMode.TOPMOST); gameObjectsToDelete.add(gameObject); } } @@ -275,7 +276,7 @@ // [prevPos] = [startGameObjects] for (final G gameObject : startGameObjects) { assert gameObject.isHead() && !gameObject.isInContainer() && mainControl.isEditType(gameObject); - mapModel.addGameObjectToMap(gameObject.createClone(prevPos.x, prevPos.y), false); + mapModel.addGameObjectToMap(gameObject.createClone(prevPos.x, prevPos.y), InsertionMode.TOPMOST); } startGameObjects.clear(); } else { @@ -295,7 +296,7 @@ // [prevPos] = [startGameObjects] for (final G gameObject : startGameObjects) { assert gameObject.isHead() && !gameObject.isInContainer() && mainControl.isEditType(gameObject); - mapModel.addGameObjectToMap(gameObject.createClone(prevPos.x, prevPos.y), false); + mapModel.addGameObjectToMap(gameObject.createClone(prevPos.x, prevPos.y), InsertionMode.TOPMOST); } startGameObjects.clear(); } Modified: trunk/src/app/net/sf/gridarta/gui/archetypechooser/ArchetypeChooserControl.java =================================================================== --- trunk/src/app/net/sf/gridarta/gui/archetypechooser/ArchetypeChooserControl.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/archetypechooser/ArchetypeChooserControl.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -41,6 +41,7 @@ import net.sf.gridarta.gameobject.Archetype; import net.sf.gridarta.gameobject.GameObject; import net.sf.gridarta.gui.map.MapViewBasic; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapArchObject; import net.sf.gridarta.map.MapModel; import org.jetbrains.annotations.NotNull; @@ -343,12 +344,13 @@ * @param pos the location to add to * @param allowMany whether to allow multiple copies of the inserted game * object + * @param insertionMode the insertion mode to use * @return the inserted game object, or <code>null</code> if nothing was * inserted */ @Nullable - public G insertSelectedArchetype(final MapModel<G, A, R> mapModel, final Point pos, final boolean allowMany) { - return selectedArch == null ? null : mapModel.insertArchetype(selectedArch.getArchetypeName(), pos, allowMany, true, false); + public G insertSelectedArchetype(final MapModel<G, A, R> mapModel, final Point pos, final boolean allowMany, final InsertionMode insertionMode) { + return selectedArch == null ? null : mapModel.insertArchetype(selectedArch.getArchetypeName(), pos, allowMany, true, insertionMode); } } // class ArchetypeChooserControl Modified: trunk/src/app/net/sf/gridarta/gui/map/tools/InsertionTool.java =================================================================== --- trunk/src/app/net/sf/gridarta/gui/map/tools/InsertionTool.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/map/tools/InsertionTool.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -20,7 +20,10 @@ package net.sf.gridarta.gui.map.tools; import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; import java.awt.Point; +import javax.swing.JComboBox; import javax.swing.JPanel; import net.sf.gridarta.gameobject.Archetype; import net.sf.gridarta.gameobject.GameObject; @@ -29,10 +32,11 @@ import net.sf.gridarta.gui.map.MapViewBasic; import net.sf.gridarta.gui.map.event.MouseOpEvent; import net.sf.gridarta.gui.selectedsquare.SelectedSquareView; +import net.sf.gridarta.gui.undo.SwingUtils; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapArchObject; import net.sf.gridarta.map.MapControl; import net.sf.japi.swing.ActionFactory; -import net.sf.japi.swing.ToggleAction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,13 +47,39 @@ */ public class InsertionTool<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>, V extends MapViewBasic<G, A, R, V>> extends BasicAbstractTool<G, A, R, V> { + /** + * Index into {@link #modeComboBox}: guess insertion location. + */ + private static final int MODE_AUTO = 0; + + /** + * Index into {@link #modeComboBox}: insert topmost. + */ + private static final int MODE_TOPMOST = 1; + + /** + * Index into {@link #modeComboBox}: insert above floor. + */ + private static final int MODE_ABOVE_FLOOR = 2; + + /** + * Index into {@link #modeComboBox}: insert below floor. + */ + private static final int MODE_BELOW_FLOOR = 3; + + /** + * Index into {@link #modeComboBox}: insert bottommost. + */ + private static final int MODE_BOTTOMMOST = 4; + /** Action Factory. */ @NotNull private static final ActionFactory ACTION_FACTORY = ActionFactory.getFactory("net.sf.gridarta.gui.map.tools"); - /** The ToggleAction for toggling the insertBelow status. */ - @SuppressWarnings({"UnusedDeclaration"}) - private final ToggleAction insertBelowAction = (ToggleAction) ACTION_FACTORY.createToggle(true, "insertBelow", this); + /** + * The {@link JComboBox} for selecting the insertion mode. + */ + private final JComboBox modeComboBox = createModeComboBox(); /** The main control. */ @NotNull @@ -59,9 +89,6 @@ @NotNull private final ObjectChooser<G, A, R> objectChooser; - /** The position for insertion. */ - private boolean insertBelow; - /** * Create a BasicAbstractTool. * @param selectedSquareView the selected square view @@ -118,7 +145,33 @@ mapControl.insertMapArchToPickmap(p); insertedObject = null; } else { - insertedObject = objectChooser.insertSelectedObject(mapControl.getMapModel(), p, isPressed); + final int modeIndex = modeComboBox.getSelectedIndex(); + final InsertionMode insertionMode; + switch (modeIndex) { + case MODE_AUTO: + insertionMode = InsertionMode.AUTO; + break; + + case MODE_TOPMOST: + insertionMode = InsertionMode.TOPMOST; + break; + + case MODE_ABOVE_FLOOR: + insertionMode = InsertionMode.ABOVE_FLOOR; + break; + + case MODE_BELOW_FLOOR: + insertionMode = InsertionMode.BELOW_FLOOR; + break; + + case MODE_BOTTOMMOST: + insertionMode = InsertionMode.BOTTOMMOST; + break; + + default: + throw new AssertionError(); + } + insertedObject = objectChooser.insertSelectedObject(mapControl.getMapModel(), p, isPressed || modeIndex == MODE_AUTO, insertionMode); } mapControl.getMapModel().endTransaction(); selectedSquareView.setSelectedGameObject(insertedObject); @@ -128,26 +181,41 @@ @Override @Nullable public Component createOptionsView() { - final JPanel optionsPanel = new JPanel(); - // commented to hide it because currently inserting below doesn't work. - //optionsPanel.add(insertBelowAction.createCheckBox()); - return optionsPanel; - } + final JPanel panel = new JPanel(); + panel.setLayout(new GridBagLayout()); - /** - * Returns the position for insertion. - * @return the position for insertion. - */ - public boolean isInsertBelow() { - return insertBelow; + final GridBagConstraints gbcLabel = new GridBagConstraints(); + gbcLabel.anchor = GridBagConstraints.EAST; + + final GridBagConstraints gbcComboBox = new GridBagConstraints(); + gbcComboBox.fill = GridBagConstraints.HORIZONTAL; + gbcComboBox.weightx = 1; + gbcComboBox.gridwidth = GridBagConstraints.REMAINDER; + + final GridBagConstraints gbcCheckBox = new GridBagConstraints(); + gbcCheckBox.fill = GridBagConstraints.HORIZONTAL; + gbcCheckBox.gridwidth = GridBagConstraints.REMAINDER; + + panel.add(SwingUtils.createLabel("insertionTool.mode", modeComboBox), gbcLabel); + panel.add(modeComboBox, gbcComboBox); + return panel; } /** - * Sets the position for insertion. - * @param insertBelow the position for insertion. + * Create a {@link JComboBox} for selecting the scope to delete. + * @return the combo box */ - public void setInsertBelow(final boolean insertBelow) { - this.insertBelow = insertBelow; + private static JComboBox createModeComboBox() { + final String[] options = new String[] { + ACTION_FACTORY.getString("insertionTool.mode.auto"), + ACTION_FACTORY.getString("insertionTool.mode.topmost"), + ACTION_FACTORY.getString("insertionTool.mode.aboveFloor"), + ACTION_FACTORY.getString("insertionTool.mode.belowFloor"), + ACTION_FACTORY.getString("insertionTool.mode.bottommost"), + }; + final JComboBox comboBox = new JComboBox(options); + comboBox.setToolTipText(ACTION_FACTORY.getString("insertionTool.mode.shortdescription")); + return comboBox; } } // class InsertionTool Modified: trunk/src/app/net/sf/gridarta/gui/map/tools/action.properties =================================================================== --- trunk/src/app/net/sf/gridarta/gui/map/tools/action.properties 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/map/tools/action.properties 2008-07-22 18:45:23 UTC (rev 4386) @@ -22,10 +22,9 @@ deletion.icon=misc/Delete16 deletion.shortdescription=Delete objects. insertion.icon=misc/Insert16 -insertion.shortdescription=Insert topmost objects. +insertion.shortdescription=Insert objects. void.icon=misc/Void16 void.shortdescription=Do nothing (makes selected mouse button inactive). -insertBelow.text=Insert below left=left middle=middle right=right @@ -52,3 +51,11 @@ deletionToolExceptionsIgnoreFloors.shortdescription=Prevents floors from being deleted. deletionToolExceptionsIgnoreMonsters.text=ignore monsters deletionToolExceptionsIgnoreMonsters.shortdescription=Prevents monsters from being deleted. + +insertionTool.mode.text=Mode: +insertionTool.mode.shortdescription=<html>Selects the insertion mode:<br>auto=guess insertion point depending on object type<br>topmost=insert above existing objects<br>above floor=insert right above floor<br>below floor=insert right below floor<br>bottom=insert below existing objects +insertionTool.mode.auto=auto +insertionTool.mode.topmost=topmost +insertionTool.mode.aboveFloor=above floor +insertionTool.mode.belowFloor=below floor +insertionTool.mode.bottommost=bottommost Modified: trunk/src/app/net/sf/gridarta/gui/map/tools/action_de.properties =================================================================== --- trunk/src/app/net/sf/gridarta/gui/map/tools/action_de.properties 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/map/tools/action_de.properties 2008-07-22 18:45:23 UTC (rev 4386) @@ -19,9 +19,8 @@ selection.shortdescription=Kartenbereich ausw\xE4hlen. deletion.shortdescription=L\xF6schen von Objekten. -insertion.shortdescription=Objekte oben einf\xFCgen. +insertion.shortdescription=Objekte einf\xFCgen. void.shortdescription=Nichts (deaktiviert die Maustaste). -insertBelow.text=Unten einf\xFCgen left=links middle=mitte right=rechts @@ -48,3 +47,11 @@ deletionToolExceptionsIgnoreFloors.shortdescription=Verhindert das L\xF6schen vom Boden. deletionToolExceptionsIgnoreMonsters.text=Monster ignorieren deletionToolExceptionsIgnoreMonsters.shortdescription=Verhindert das L\xF6schen von Monstern. + +insertionTool.mode.text=Modus: +insertionTool.mode.shortdescription=<html>W\xE4hlt den Einf\xFCgemodus:<br>automatisch=abh\xE4ngig vom eingef\xFCgten Objekt<br>oben=als oberstes Objekt einf\xFCgen<br>\xFCber Boden=direkt \xFCber Boden einf\xFCgen<br>unter Boden=direkt unter Boden einf\xFCgen<br>unten=als unterstes Objekt einf\xFCgen +insertionTool.mode.auto=auto +insertionTool.mode.topmost=oben +insertionTool.mode.aboveFloor=\xFCber Boden +insertionTool.mode.belowFloor=unter Boden +insertionTool.mode.bottommost=unten Modified: trunk/src/app/net/sf/gridarta/gui/map/tools/action_fr.properties =================================================================== --- trunk/src/app/net/sf/gridarta/gui/map/tools/action_fr.properties 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/map/tools/action_fr.properties 2008-07-22 18:45:23 UTC (rev 4386) @@ -21,7 +21,6 @@ #deletion.shortdescription= #insertion.shortdescription= #void.shortdescription= -#insertBelow.text= #left= #middle= #right= @@ -48,3 +47,11 @@ #deletionToolExceptionsIgnoreFloors.shortdescription= #deletionToolExceptionsIgnoreMonsters.text= #deletionToolExceptionsIgnoreMonsters.shortdescription= + +#insertionTool.mode.text= +#insertionTool.mode.shortdescription= +#insertionTool.mode.auto=auto +#insertionTool.mode.topmost= +#insertionTool.mode.aboveFloor= +#insertionTool.mode.belowFloor= +#insertionTool.mode.bottommost= Modified: trunk/src/app/net/sf/gridarta/gui/map/tools/action_sv.properties =================================================================== --- trunk/src/app/net/sf/gridarta/gui/map/tools/action_sv.properties 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/map/tools/action_sv.properties 2008-07-22 18:45:23 UTC (rev 4386) @@ -21,7 +21,6 @@ #deletion.shortdescription= #insertion.shortdescription= #void.shortdescription= -#insertBelow.text= #left= #middle= #right= @@ -48,3 +47,11 @@ #deletionToolExceptionsIgnoreFloors.shortdescription= #deletionToolExceptionsIgnoreMonsters.text= #deletionToolExceptionsIgnoreMonsters.shortdescription= + +#insertionTool.mode.text= +#insertionTool.mode.shortdescription= +#insertionTool.mode.auto=auto +#insertionTool.mode.topmost= +#insertionTool.mode.aboveFloor= +#insertionTool.mode.belowFloor= +#insertionTool.mode.bottommost= Modified: trunk/src/app/net/sf/gridarta/gui/pickmapchooser/PickmapChooserControl.java =================================================================== --- trunk/src/app/net/sf/gridarta/gui/pickmapchooser/PickmapChooserControl.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/gui/pickmapchooser/PickmapChooserControl.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -38,6 +38,7 @@ import net.sf.gridarta.gui.map.MapViewBasic; import net.sf.gridarta.gui.newmap.NewMapDialogFactory; import net.sf.gridarta.map.DefaultMapControl; +import net.sf.gridarta.map.InsertionMode; import net.sf.gridarta.map.MapArchObject; import net.sf.gridarta.map.MapControl; import net.sf.gridarta.map.MapControlListener; @@ -394,13 +395,14 @@ * @param pos the location to add to * @param allowMany whether to allow multiple copies of the inserted game * object + * @param insertionMode the insertion mode to use * @return the inserted game object, or <code>null</code> if nothing was * inserted */ @Nullable - public G insertSelectedObject(final MapModel<G, A, R> mapModel, final Point pos, final boolean allowMany) { + public G insertSelectedObject(final MapModel<G, A, R> mapModel, final Point pos, final boolean allowMany, final InsertionMode insertionMode) { final G gameObject = getSelection(); - return gameObject == null ? null : mapModel.insertGameObject(gameObject, pos, allowMany); + return gameObject == null ? null : mapModel.insertGameObject(gameObject, pos, allowMany, insertionMode); } } // class PickmapChooserControl Modified: trunk/src/app/net/sf/gridarta/map/DefaultMapModel.java =================================================================== --- trunk/src/app/net/sf/gridarta/map/DefaultMapModel.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/map/DefaultMapModel.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -191,7 +191,7 @@ if (objects != null) { for (final G gameObject : objects) { if (!gameObject.isInContainer()) { // only map arches.... - addGameObjectToMap(gameObject, false); + addGameObjectToMap(gameObject, InsertionMode.TOPMOST); } } } @@ -634,7 +634,7 @@ // put arch on the map if (templateGameObject.isArchetype()) { - newGameObject = insertArchetype(templateGameObject.getArchetypeName(), pos, true, join, false); + newGameObject = insertArchetype(templateGameObject.getArchetypeName(), pos, true, join, InsertionMode.TOPMOST); if (newGameObject == null) { return null; } @@ -642,7 +642,7 @@ // insert the given 'templateGameObject' (multis not allowed here yet - sorry) if (!templateGameObject.isMulti()) { newGameObject = templateGameObject.createClone(pos.x, pos.y); - addGameObjectToMap(newGameObject, false); + addGameObjectToMap(newGameObject, InsertionMode.TOPMOST); } else { return null; // tried to insert multi (probably from pickmap) } @@ -683,7 +683,7 @@ /** {@inheritDoc} */ @Nullable - public G insertArchetype(@Nullable final String archetypeName, @NotNull final Point pos, final boolean allowDouble, final boolean join, final boolean insertBelow) { + public G insertArchetype(@Nullable final String archetypeName, @NotNull final Point pos, final boolean allowDouble, final boolean join, final InsertionMode insertionMode) { if (archetypeName == null || archetypeName.length() == 0 || !isPointValid(pos)) { return null; } @@ -720,14 +720,6 @@ final int mapx = pos.x + part.getMultiX(); final int mapy = pos.y + part.getMultiY(); - part.setMapX(mapx); - part.setMapY(mapy); - if (insertBelow) { - mapGrid[mapx][mapy].addFirst(part); - } else { - mapGrid[mapx][mapy].addLast(part); - } - final Integer direction = archetypeChooserControl.getCurrentDirection(); if (direction != null) { part.setDirection(direction); @@ -735,6 +727,10 @@ } part.postParseGameObject(mapControl.getActiveEditType()); part.setObjectFace(); + + part.setMapX(mapx); + part.setMapY(mapy); + insertionMode.insert(part, mapGrid[mapx][mapy]); } for (final G invObject : archetype) { @@ -746,7 +742,7 @@ /** {@inheritDoc} */ @Nullable - public G insertGameObject(@NotNull final G gameObject, @NotNull final Point pos, final boolean allowMany) { + public G insertGameObject(@NotNull final G gameObject, @NotNull final Point pos, final boolean allowMany, final InsertionMode insertionMode) { if (!allowMany) { // check if there is already an arch of that kind for (final G t : getMapSquare(pos)) { @@ -760,14 +756,14 @@ if (!gameObject.isMulti()) { // insert single tile from pickmap final G newObject = gameObject.createClone(pos.x, pos.y); - addGameObjectToMap(newObject, false); + addGameObjectToMap(newObject, insertionMode); return newObject; } // insert multi tile from pickmap: final G newarchHead = gameObject.getHead(); // first insert default arch from archlist - final G newObject = insertArchetype(newarchHead.getArchetypeName(), pos, allowMany, false, false); + final G newObject = insertArchetype(newarchHead.getArchetypeName(), pos, allowMany, false, insertionMode); if (newObject != null) { newObject.setObjectText(newarchHead.getObjectText()); newObject.setObjName(newarchHead.getObjName()); @@ -778,7 +774,7 @@ } /** {@inheritDoc} */ - public void addGameObjectToMap(final G gameObject, final boolean insertBelow) { + public void addGameObjectToMap(final G gameObject, final InsertionMode insertionMode) { gameObject.setObjectFace(); final int mapx = gameObject.getMapX(); @@ -791,12 +787,7 @@ return; } - if (insertBelow) { - mapGrid[mapx][mapy].addFirst(gameObject); - } else { - mapGrid[mapx][mapy].addLast(gameObject); - } - + insertionMode.insert(gameObject, mapGrid[mapx][mapy]); gameObject.updateEditType(mapControl.getActiveEditType()); } @@ -854,9 +845,9 @@ } // class MapSquareIterator /** {@inheritDoc} */ - public void addCopyToMap(final G gameObject, final Point pos, final boolean allowDouble, final boolean fillBelow) { + public void addCopyToMap(final G gameObject, final Point pos, final boolean allowDouble, final InsertionMode insertionMode) { if (gameObject.isArchetype()) { - insertArchetype(gameObject.getArchetypeName(), pos, allowDouble, false, fillBelow); + insertArchetype(gameObject.getArchetypeName(), pos, allowDouble, false, insertionMode); } else { final G newGameObject = gameObject.createMultiClone(pos.x, pos.y); for (G tmp = newGameObject; tmp != null; tmp = tmp.getMultiNext()) { @@ -866,9 +857,9 @@ } } - addGameObjectToMap(newGameObject, fillBelow); + addGameObjectToMap(newGameObject, insertionMode); for (G tmp = newGameObject.getMultiNext(); tmp != null; tmp = tmp.getMultiNext()) { - addGameObjectToMap(tmp, fillBelow); + addGameObjectToMap(tmp, insertionMode); tmp.postParseGameObject(mapControl.getActiveEditType()); } } @@ -892,7 +883,7 @@ } } - addCopyToMap(newarch2, pos, true, false); + addCopyToMap(newarch2, pos, true, InsertionMode.TOPMOST); } } // class DefaultMapModel Added: trunk/src/app/net/sf/gridarta/map/InsertionMode.java =================================================================== --- trunk/src/app/net/sf/gridarta/map/InsertionMode.java (rev 0) +++ trunk/src/app/net/sf/gridarta/map/InsertionMode.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -0,0 +1,231 @@ +/* + * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games. + * Copyright (C) 2000-2007 The Gridarta Developers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package net.sf.gridarta.map; + +import net.sf.gridarta.gameobject.Archetype; +import net.sf.gridarta.gameobject.GameObject; +import net.sf.gridarta.gameobject.match.GameObjectMatcher; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Insertion modes. + * @todo make replacement of multi-part objects work + * @author Andreas Kirschbaum + */ +public enum InsertionMode { + + /** + * Automatically guess the insertion position. May replace rather than + * insert the object. + */ + AUTO { + + /** {@inheritDoc} */ + public <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> void insert(@NotNull final G gameObject, @NotNull final MapSquare<G, A, R> mapSquare) { + if (floorGameObjectMatcher != null && floorGameObjectMatcher.isMatching(gameObject)) { + replaceFloor(gameObject, mapSquare, mapSquare.getLast(floorGameObjectMatcher)); + } else if (wallGameObjectMatcher != null && wallGameObjectMatcher.isMatching(gameObject)) { + replaceWall(gameObject, mapSquare, mapSquare.getLast(wallGameObjectMatcher)); + } else if (belowFloorGameObjectMatcher != null && belowFloorGameObjectMatcher.isMatching(gameObject)) { + mapSquare.addFirst(gameObject); + } else { + mapSquare.addLast(gameObject); + } + } + + /** {@inheritDoc} */ + public String toString() { + return "auto"; + } + }, + + /** + * Insert topmost. + */ + TOPMOST { + + /** {@inheritDoc} */ + public <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> void insert(@NotNull final G gameObject, @NotNull final MapSquare<G, A, R> mapSquare) { + mapSquare.addLast(gameObject); + } + + /** {@inheritDoc} */ + public String toString() { + return "topmost"; + } + + }, + + /** + * Insert right above the topmost floor tile. Inserts bottommost if no + * floor tile exists. + */ + ABOVE_FLOOR { + + /** {@inheritDoc} */ + public <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> void insert(@NotNull final G gameObject, @NotNull final MapSquare<G, A, R> mapSquare) { + if (floorGameObjectMatcher == null) { + mapSquare.addFirst(gameObject); + return; + } + + final G lastFloor = mapSquare.getLast(floorGameObjectMatcher); + if (lastFloor == null) { + mapSquare.addFirst(gameObject); + return; + } + + mapSquare.insertBefore(gameObject, lastFloor); + } + + /** {@inheritDoc} */ + public String toString() { + return "above floor"; + } + + }, + + /** + * Insert right below the bottommost floor tile. Inserts bottommost if no + * floor tile exists. + */ + BELOW_FLOOR { + + /** {@inheritDoc} */ + public <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> void insert(@NotNull final G gameObject, @NotNull final MapSquare<G, A, R> mapSquare) { + if (floorGameObjectMatcher == null) { + mapSquare.addFirst(gameObject); + return; + } + final G firstFloor = mapSquare.getFirst(floorGameObjectMatcher); + if (firstFloor == null) { + mapSquare.addFirst(gameObject); + return; + } + + mapSquare.insertAfter(firstFloor, gameObject); + } + + /** {@inheritDoc} */ + public String toString() { + return "below floor"; + } + + }, + + /** + * Insert bottommost. + */ + BOTTOMMOST { + + /** {@inheritDoc} */ + public <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> void insert(@NotNull final G gameObject, @NotNull final MapSquare<G, A, R> mapSquare) { + mapSquare.addFirst(gameObject); + } + + /** {@inheritDoc} */ + public String toString() { + return "bottommost"; + } + + }; + + /** + * A {@link GameObjectMatcher} matching floor game objects. + */ + @Nullable + private static GameObjectMatcher floorGameObjectMatcher = null; + + /** + * A {@link GameObjectMatcher} matching wall game objects. + */ + @Nullable + private static GameObjectMatcher wallGameObjectMatcher = null; + + /** + * A {@link GameObjectMatcher} matching monster game objects. + */ + @Nullable + private static GameObjectMatcher belowFloorGameObjectMatcher = null; + + /** + * Initializes the class. + * @param floorGameObjectMatcher the floor matcher to use + * @param wallGameObjectMatcher the wall matcher to use + * @param belowFloorGameObjectMatcher the game object to insert below the + * floor + */ + public static void init(@Nullable final GameObjectMatcher floorGameObjectMatcher, @Nullable final GameObjectMatcher wallGameObjectMatcher, @Nullable final GameObjectMatcher belowFloorGameObjectMatcher) { + InsertionMode.floorGameObjectMatcher = floorGameObjectMatcher; + InsertionMode.wallGameObjectMatcher = wallGameObjectMatcher; + InsertionMode.belowFloorGameObjectMatcher = belowFloorGameObjectMatcher; + } + + /** + * Inserts a {@link GameObject} into a {@link MapSquare}. + * @param gameObject the game object to insert + * @param mapSquare the map square to modify + */ + public abstract <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> void insert(@NotNull final G gameObject, @NotNull final MapSquare<G, A, R> mapSquare); + + /** + * Replace a floor game object. + * @param gameObject the game object to insert with + * @param mapSquare the map square to modify + * @param lastFloor the last floor game object within + * <code>mapSquare</code> + */ + private static <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> void replaceFloor(final G gameObject, final MapSquare<G, A, R> mapSquare, final G lastFloor) { + // floor exists ==> replace it + if (lastFloor != null && !lastFloor.isMulti()) { + mapSquare.replace(lastFloor, gameObject); + return; + } + + // "below floor" objects exist ==> insert afterwards + if (belowFloorGameObjectMatcher != null) { + final G lastBelowFloor = mapSquare.getLastOfLeadingSpan(belowFloorGameObjectMatcher); + if (lastBelowFloor != null) { + mapSquare.insertAfter(lastBelowFloor, gameObject); + return; + } + } + + // fallback ==> insert bottommost + mapSquare.addFirst(gameObject); + } + + /** + * Replace a wall game object. + * @param gameObject the game object to insert with + * @param mapSquare the map square to modify + * @param lastWall the last wall game object within + * <code>mapSquare</code> + */ + private static <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> void replaceWall(final G gameObject, final MapSquare<G, A, R> mapSquare, final G lastWall) { + if (lastWall != null && !lastWall.isMulti()) { + mapSquare.replace(lastWall, gameObject); + } else { + mapSquare.addLast(gameObject); + } + } + +} // enum InsertionMode Property changes on: trunk/src/app/net/sf/gridarta/map/InsertionMode.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:eol-style + LF Modified: trunk/src/app/net/sf/gridarta/map/MapModel.java =================================================================== --- trunk/src/app/net/sf/gridarta/map/MapModel.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/map/MapModel.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -302,11 +302,10 @@ * <var>gameObject</var> is a new and unlinked object. * @param gameObject The new GameObject with set destination coordinates to * be linked onto the map. - * @param insertBelow <code>true</code> to insert at top, <code>false</code> - * for below + * @param insertionMode the insertion mode to use * @todo verify <code>insertBelow</code> documentation */ - void addGameObjectToMap(G gameObject, boolean insertBelow); + void addGameObjectToMap(G gameObject, InsertionMode insertionMode); /** * Return the current state of this object. @@ -332,8 +331,7 @@ * inserted per square * @param join if set, auto-joining is supported; autojoining is only done * if enabled in the main control - * @param insertBelow true: new arch is inserted on top, false: new arch is - * inserted below + * @param insertionMode the insertion mode to use * @return The head of the inserted object or <code>null</code> if for some * reason no object could be inserted. * @todo discuss whether this method really belongs to a map model, as @@ -343,18 +341,19 @@ * than returning <code>null</code>. */ @Nullable - G insertArchetype(@Nullable String archetypeName, @NotNull Point pos, boolean allowDouble, boolean join, boolean insertBelow); + G insertArchetype(@Nullable String archetypeName, @NotNull Point pos, boolean allowDouble, boolean join, final InsertionMode insertionMode); /** * Adds a {@link GameObject} to the map. * @param gameObject the game object to insert * @param pos the insert-location on this map * @param allowMany whether duplicates are allowed + * @param insertionMode the insertion mode to use * @return the inserted game object or <code>null</code> if nothing was * inserted */ @Nullable - G insertGameObject(@NotNull G gameObject, @NotNull Point pos, boolean allowMany); + G insertGameObject(@NotNull G gameObject, @NotNull Point pos, boolean allowMany, final InsertionMode insertionMode); /** * Checks whether an GameObject (multi-arch) would still fit on this map. @@ -440,10 +439,9 @@ * @param pos position to add GameObject at * @param allowDouble <code>true</code> for allowing similar GameObjects on * the same square, <code>false</code> to disallow - * @param fillBelow <code>true</code> if the GameObject should be added - * below all others, <code>false</code> for above + * @param insertionMode the insertion mode to use */ - void addCopyToMap(G gameObject, Point pos, boolean allowDouble, boolean fillBelow); + void addCopyToMap(G gameObject, Point pos, boolean allowDouble, InsertionMode insertionMode); /** * This method is only called for pickmaps. Take the currently highlighted Modified: trunk/src/app/net/sf/gridarta/map/MapSquare.java =================================================================== --- trunk/src/app/net/sf/gridarta/map/MapSquare.java 2008-07-22 18:37:53 UTC (rev 4385) +++ trunk/src/app/net/sf/gridarta/map/MapSquare.java 2008-07-22 18:45:23 UTC (rev 4386) @@ -117,6 +117,22 @@ } /** + * Returns the last occurrence of a matching game object. + * @param gameObjectMatcher the matcher to use + * @return the last match, or <code>null</code> if no such game object + * exists + */ + @Nullable + public G getLast(@NotNull final GameObjectMatcher gameObjectMatcher) { + for (final G gameObject : reverse()) { + if (gameObjectMatcher.isMatching(gameObject)) { + return gameObject; + } + } + return null; + } + + /** * Returns the game object after the last occurrence of a matching game * object. * @param gameObjectMatcher the matcher to use @@ -136,6 +152,22 @@ } /** + * Returns the first occurrence of a matching game object. + * @param gameObjectMatcher the matcher to use + * @return the first match, or <code>null</code> if no such game object + * exists + */ + @Nullable + public G getFirst(@NotNull final GameObjectMatcher gameObjectMatcher) { + for (final G gameObject : this) { + if (gameObjectMatcher.isMatching(gameObject)) { + return gameObject; + } + } + return null; + } + + /** * Returns the game object before the first occurrence of a matching game * object. * @param gameObjectMatcher the matcher to use @@ -153,4 +185,24 @@ } return null; } + + /** + * Returns the last game object of the initial segment of matching game + * objects. + * @param gameObjectMatcher the matcher to use + * @return the result or <code>null</code> if the first game object does + * not match <code>gameObjectMatcher</code> + */ + @Nullable + public G getLastOfLeadingSpan(@NotNull final GameObjectMatcher gameObjectMatcher) { + @Nullable G result = null; + for (final G tmp : this) { + if (!gameObjectMatcher.isMatching(tmp)) { + break; + } + result = tmp; + } + return result; + } + } // class MapSquare This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |