From: <chr...@us...> - 2006-08-02 21:46:47
|
Revision: 243 Author: christianhujer Date: 2006-08-02 14:46:32 -0700 (Wed, 02 Aug 2006) ViewCVS: http://svn.sourceforge.net/gridarta/?rev=243&view=rev Log Message: ----------- Improved MapModel and DefaultMapModel: * Moved documentation from implementation to interface. * Documented future plans, e.g. deprecated symbols planned to be removed. * Added several @Nullable and @NotNull annotations. * Removed unused positioning parameters from deleteMapArch methods. Modified Paths: -------------- trunk/daimonin/src/daieditor/CMainControl.java trunk/daimonin/src/daieditor/CopyBuffer.java trunk/daimonin/src/daieditor/gui/map/MapCursorControl.java trunk/daimonin/src/daieditor/gui/map/tools/DeletionTool.java trunk/daimonin/src/daieditor/map/DefaultMapModel.java trunk/daimonin/src/daieditor/map/MapArchObject.java trunk/daimonin/src/daieditor/map/MapControl.java trunk/daimonin/src/daieditor/map/MapModel.java Modified: trunk/daimonin/src/daieditor/CMainControl.java =================================================================== --- trunk/daimonin/src/daieditor/CMainControl.java 2006-08-02 21:45:26 UTC (rev 242) +++ trunk/daimonin/src/daieditor/CMainControl.java 2006-08-02 21:46:32 UTC (rev 243) @@ -805,7 +805,7 @@ } public void deleteMapArch(final ArchObject arch, final int mapx, final int mapy, final boolean refreshMap) { - currentMap.deleteMapArch(arch, mapx, mapy, refreshMap); + currentMap.deleteMapArch(arch, refreshMap); } /** Modified: trunk/daimonin/src/daieditor/CopyBuffer.java =================================================================== --- trunk/daimonin/src/daieditor/CopyBuffer.java 2006-08-02 21:45:26 UTC (rev 242) +++ trunk/daimonin/src/daieditor/CopyBuffer.java 2006-08-02 21:46:32 UTC (rev 243) @@ -173,7 +173,7 @@ // above the head (we would miss to copy them otherwise). if (mode == Mode.DO_CLEAR || !arch.isMulti() || arch.getMultiRefCount() > 0 || arch.getMapMultiHead() != null && arch.getMultiRefX() >= 0 && arch.getMultiRefY() >= 0) { - mapControl.deleteMapArch(arch, posx, posy, false); + mapControl.deleteMapArch(arch, false); } } } Modified: trunk/daimonin/src/daieditor/gui/map/MapCursorControl.java =================================================================== --- trunk/daimonin/src/daieditor/gui/map/MapCursorControl.java 2006-08-02 21:45:26 UTC (rev 242) +++ trunk/daimonin/src/daieditor/gui/map/MapCursorControl.java 2006-08-02 21:46:32 UTC (rev 243) @@ -126,7 +126,7 @@ if (arch != null) { final Point pos = mapCursor.getLocation(); assert pos != null; - mapControl.deleteMapArch(arch, pos.x, pos.y, true); + mapControl.deleteMapArch(arch, true); } } } Modified: trunk/daimonin/src/daieditor/gui/map/tools/DeletionTool.java =================================================================== --- trunk/daimonin/src/daieditor/gui/map/tools/DeletionTool.java 2006-08-02 21:45:26 UTC (rev 242) +++ trunk/daimonin/src/daieditor/gui/map/tools/DeletionTool.java 2006-08-02 21:46:32 UTC (rev 243) @@ -72,7 +72,7 @@ } } if (delArch != null) { - mapControl.deleteMapArch(delArch, mapLoc.x, mapLoc.y, false); + mapControl.deleteMapArch(delArch, false); } } Modified: trunk/daimonin/src/daieditor/map/DefaultMapModel.java =================================================================== --- trunk/daimonin/src/daieditor/map/DefaultMapModel.java 2006-08-02 21:45:26 UTC (rev 242) +++ trunk/daimonin/src/daieditor/map/DefaultMapModel.java 2006-08-02 21:46:32 UTC (rev 243) @@ -41,6 +41,7 @@ import net.sf.japi.swing.ActionFactory; import static net.sf.japi.swing.ActionFactory.getFactory; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; /** * The level model that represents a level. @@ -67,7 +68,10 @@ /** The registered event listeners. */ private EventListenerList listenerList = new EventListenerList(); - /** The Map Arch Object with the meta information about the map. */ + /** + * The MapArchObject with the meta information about the map. + * The model knows the MapArchObject because one of them has to know the other for updating the size in case a map is resized. + */ private final MapArchObject mapArch; /** @@ -82,11 +86,17 @@ /** Flag that indicates if the level has been changed since last save. */ private boolean levelChanged = false; - /** CMainControl. */ - private final CMainControl mainControl; + /** + * The CMainControl used for various operations. + * @deprecated it's not a good idea to require the MapModel implementation to know such a heavy-weight strongly UI-related glue class like {@link CMainControl}. + */ + @Deprecated private final CMainControl mainControl; - /** The MapControl that controls this MapModel. */ - private final MapControl mapControl; + /** + * The MapControl that controls this MapModel. + * @deprecated it's not a good idea to require the MapModel implementation to know such a heavy-weight strongly UI-related glue class like {@link CMapControl}. + */ + @Deprecated private final MapControl mapControl; /** The transaction depth. */ private int transactionDepth; @@ -112,9 +122,17 @@ /** Iterator for iterating over all squares of a model. */ private class MapSquareIterator implements Iterator<MapSquare> { - /** Index of current map square. */ + /** + * Index of current map square. + * The point is used as single value index to a two dimensional array. + * That works fine because the two dimensional array is a rectangular array. + */ private int point; + private MapSquareIterator() { + assert isRectangular(); + } + /** {@inheritDoc} */ public void remove() { throw new UnsupportedOperationException(); @@ -138,27 +156,41 @@ } // class MapSquareIterator + /** + * This method checks whether the map is rectangular. + * A map always MUST be rectangular, this method can be used for assertions regarding this assumption. + * The check for rectangularity is a check whether the array dimensions of {@link #mapGrid} match the size specified in {@link #mapSize}. + * @return <code>true</code> if the map is rectangular, otherwise <code>false</code>. + */ + private boolean isRectangular() { + final int width = mapSize.getWidth(); + final int height = mapSize.getHeight(); + if (mapGrid.length != height) { + return false; + } + for (int y = 0; y < height; y++) { + if (mapGrid[y].length != width) { + return false; + } + } + return true; + } + /** {@inheritDoc} */ public Iterator<MapSquare> iterator() { return new MapSquareIterator(); } - /** - * Get the map square at a given point. - * @param p Point to get map square at - * @return Map Square at <var>p</var> - * @throws ArrayIndexOutOfBoundsException in case the coordinates are outside the map - */ + /** {@inheritDoc} */ public MapSquare getMapSquare(final Point p) throws ArrayIndexOutOfBoundsException { return mapGrid[p.x][p.y]; } /** - * Get the currently selected map square. - * XXX: This method should be moved to the view. - * @return currently selected map square + * {@inheritDoc} + * @todo This method should be moved to the view. */ - @Nullable public MapSquare getMouseRightPosObject() { + @Deprecated @Nullable public MapSquare getMouseRightPosObject() { final Point p = mapControl.getMapCursor().getLocation(); return p == null ? null : mapGrid[p.x][p.y]; } @@ -180,7 +212,7 @@ } /** - * Reset the level changed flag to false. + * {@inheritDoc} * @todo it's not a good idea to use the mapViewFrame here */ public void resetLevelChangedFlag() { @@ -196,7 +228,7 @@ } /** - * Set the level changed flag to true. + * {@inheritDoc} * @todo it's not a good idea to use the mapViewFrame here */ public void setLevelChangedFlag() { @@ -217,19 +249,10 @@ } } - /** - * Return whether the level has changed since it was last saved or not. - * @return <code>true</code> if level has changed, <code>false</code> if - * not. - */ public boolean isLevelChanged() { return levelChanged; } - /** - * Return the map size of this level. - * @return map size of this level - */ public Size2D getMapSize() { return mapSize; } @@ -378,15 +401,7 @@ } } - /** - * Link an existing arch to the map. Including multi tile arches. This - * function allows to insert any given arch (can be non-default). Make sure - * that the given 'arch' is a new and unlinked object. - * @param arch the new arch to be linked onto the map. (Dest. - * coordinates must be set (arch.mapx/y)!) - * @param insertBelow true: new arch is inserted on top, false: new arch - * is inserted below - */ + /** {@inheritDoc} */ public void addArchObjectToMap(final ArchObject arch, final boolean insertBelow) { // Make sure this arch has the proper edit_type if (arch.getEditType() == IGUIConstants.TILE_EDIT_NONE) { @@ -422,20 +437,8 @@ setLevelChangedFlag(); // the map has been modified } - /** - * Delete an existing arch from the map. (If the specified arch doesn't - * exist, nothing happens.) (This includes deletion of multiparts and - * inventory.) - * <p/> - * XXX This method looks extremely strange. We have xx and yy and the arch, - * yet we look whether the arch is on the current square! Probably this - * method is not just bogus but also not neccessary. - * @param arch Arch to be removed - * @param pos location of the arch to be removed - * @param refreshMap If true, mapview is redrawn after deletion. Keep in - * mind: drawing consumes time! - */ - public void deleteMapArch(final ArchObject arch, final Point pos, final boolean refreshMap) { + /** {@inheritDoc} */ + public void deleteMapArch(final ArchObject arch, final boolean refreshMap) { // Okay, it's in an inventory then arch.remove(); setLevelChangedFlag(); // the map has been modified @@ -444,7 +447,10 @@ } } - /** Clear this map. */ + /** {@inheritDoc} + * This implementation is very safe by recreating every single MapSquare as new empty square with the trade-off of some strain of the garbage-collector. + * An alternative implemenation would manually clean every existing MapSquare but that probably wouldn't really be faster until we have reusage of ArchObject instances similar to J2EE. + */ public void clearMap() { for (int x = 0; x < mapSize.getWidth(); x++) { for (int y = 0; y < mapSize.getHeight(); y++) { @@ -453,30 +459,17 @@ } } - /** - * Returns the Map Arch Object with the meta information about the map. - * @return the Map Arch Object with the meta information about the map. - */ + /** {@inheritDoc} */ public MapArchObject getMapArch() { return mapArch; } - /** - * Check whether the given coordinate is within map bounds. - * @param pos the coordinates to check - * @return true=the given coordinates are within map bounds - */ + /** {@inheritDoc} */ public boolean isPointValid(@Nullable final Point pos) { return pos != null && pos.x >= 0 && pos.y >= 0 && pos.x < mapSize.getWidth() && pos.y < mapSize.getHeight(); } - /** - * Searching for a valid exit at the highlighted map-spot. (This can be a - * teleporter, exit, pit etc.) selected Arch - this method should NOT - * retrieve that data itself. - * @param hspot Point to get exit at - * @return ArchObject exit-arch if existent, otherwise null - */ + /** {@inheritDoc} */ @Nullable public ArchObject getExit(@Nullable final Point hspot) { if (hspot == null) { return null; // out of map @@ -490,17 +483,17 @@ } /** - * Check if objects get cut off if the map was resized to the given bounds. + * Check if no objects get cut off if the map was resized to the given bounds so cutoff is safe. * @param newSize the new level size - * @return true if objects would be cut off + * @return true if no objects would be cut off */ - public boolean isCutoffUnsafe(final Size2D newSize) { + public boolean isCutoffSafe(@NotNull final Size2D newSize) { if (mapSize.getWidth() > newSize.getWidth()) { // search the right stripe (as far as being cut off) for (int x = newSize.getWidth(); x < mapSize.getWidth(); x++) { for (int y = 0; y < mapSize.getHeight(); y++) { if (!mapGrid[x][y].isEmpty()) { - return true; + return false; } } } @@ -511,22 +504,17 @@ for (int y = newSize.getHeight(); y < mapSize.getHeight(); y++) { for (int x = 0; x < mapSize.getWidth(); x++) { if (!mapGrid[x][y].isEmpty()) { - return true; + return false; } } } } - return false; + return true; } - /** - * Resize this map to the new size. If any bounds are smaller than before, - * the map gets cut on the right and bottom side. Accordingly, new space is - * attached to right and bottom. - * @param newSize new map size - */ - public void resizeMap(final Size2D newSize) { + /** {@inheritDoc} */ + public void resizeMap(@NotNull final Size2D newSize) { if (newSize.equals(mapSize)) { return; } @@ -540,8 +528,8 @@ for (int x = newSize.getWidth(); x < mapSize.getWidth(); x++) { for (int y = 0; y < mapSize.getHeight(); y++) { // for every map square: delete all arches on it - for (ArchObject node : mapGrid[x][y]) { - deleteMapArch(node, new Point(x, y), false); // delete previous one + for (final ArchObject node : mapGrid[x][y]) { + deleteMapArch(node, false); // delete previous one } } } @@ -554,8 +542,8 @@ for (int y = newSize.getHeight(); y < mapSize.getHeight(); y++) { for (int x = 0; x < mapSize.getWidth(); x++) { // for every map square: delete all arches on it - for (ArchObject node : mapGrid[x][y]) { - deleteMapArch(node, new Point(x, y), false); // delete previous one + for (final ArchObject node : mapGrid[x][y]) { + deleteMapArch(node, false); // delete previous one } } } Modified: trunk/daimonin/src/daieditor/map/MapArchObject.java =================================================================== --- trunk/daimonin/src/daieditor/map/MapArchObject.java 2006-08-02 21:45:26 UTC (rev 242) +++ trunk/daimonin/src/daieditor/map/MapArchObject.java 2006-08-02 21:46:32 UTC (rev 243) @@ -29,6 +29,8 @@ import java.io.BufferedWriter; import java.io.IOException; import net.sf.gridarta.Size2D; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * MapArchObject contains the specific meta data about a map that is stored in @@ -56,7 +58,7 @@ * Map size. * @fixme this is redundant with {@link DefaultMapModel}. */ - private Size2D mapSize = new Size2D(1, 1); + @NotNull private Size2D mapSize = new Size2D(1, 1); /** Default enter coordinates (usage not recommended). */ private int enterX, enterY; @@ -186,11 +188,7 @@ * Set map size. * @param mapSize new map size */ - public void setMapSize(final Size2D mapSize) { - if (mapSize == null) { - throw new IllegalArgumentException("No map size set"); - } - + public void setMapSize(@NotNull final Size2D mapSize) { this.mapSize = mapSize; } @@ -203,7 +201,7 @@ mapSize = new Size2D(Math.max(mapSize.getWidth(), width), Math.max(mapSize.getHeight(), height)); } - public Size2D getMapSize() { + @NotNull public Size2D getMapSize() { return mapSize; } @@ -315,7 +313,7 @@ return tilePaths[n]; } - public void setTilePath(final int n, final String tilePath) { + public void setTilePath(final int n, @Nullable final String tilePath) { tilePaths[n] = tilePath; } @@ -403,7 +401,7 @@ * Append 'text' to the map text. * @param text string to add */ - public void addText(final String text) { + public void addText(@NotNull final String text) { msgText.append(text); } @@ -413,7 +411,7 @@ } /** @return the maptext */ - public String getText() { + public @NotNull String getText() { return msgText.toString(); } @@ -426,7 +424,7 @@ * @return true if reading the MapArchObject succeeded with sane results, * otherwise false */ - public boolean parseMapArch(final BufferedReader reader, final String fname) { + public boolean parseMapArch(@NotNull final BufferedReader reader, @NotNull final String fname) { filename = fname; // store file name boolean archflag = false; // flag for arch<->end int width = 0; @@ -571,7 +569,7 @@ * @param s the attribute line to be parsed * @return attribute value, zero if value not readable */ - private static int getLineValue(final String s) { + private static int getLineValue(@NotNull final String s) { try { if (s.lastIndexOf(" ") > 0) { return Integer.valueOf(s.substring(s.lastIndexOf(" ") + 1)); @@ -587,7 +585,7 @@ * @param stream <code>BufferedWriter</code> to the mapfile * @throws IOException an I/O error occured during writing to the file */ - public void writeMapArch(final BufferedWriter stream) throws IOException { + public void writeMapArch(@NotNull final BufferedWriter stream) throws IOException { stream.append("arch map\n"); if (name.length() > 0) { Modified: trunk/daimonin/src/daieditor/map/MapControl.java =================================================================== --- trunk/daimonin/src/daieditor/map/MapControl.java 2006-08-02 21:45:26 UTC (rev 242) +++ trunk/daimonin/src/daieditor/map/MapControl.java 2006-08-02 21:46:32 UTC (rev 243) @@ -233,8 +233,8 @@ mapModel.addArchObjectToMap(arch, false); } - public void deleteMapArch(final ArchObject arch, final int mapx, final int mapy, final boolean refreshMap) { - mapModel.deleteMapArch(arch, new Point(mapx, mapy), refreshMap); + public void deleteMapArch(final ArchObject arch, final boolean refreshMap) { + mapModel.deleteMapArch(arch, refreshMap); } /** @@ -339,7 +339,7 @@ } public boolean checkResizeMap(final Size2D size) { - return mapModel.isCutoffUnsafe(size); + return mapModel.isCutoffSafe(size); } public String getMapFileName() { Modified: trunk/daimonin/src/daieditor/map/MapModel.java =================================================================== --- trunk/daimonin/src/daieditor/map/MapModel.java 2006-08-02 21:45:26 UTC (rev 242) +++ trunk/daimonin/src/daieditor/map/MapModel.java 2006-08-02 21:46:32 UTC (rev 243) @@ -5,9 +5,17 @@ import java.util.Iterator; import net.sf.gridarta.Size2D; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; /** * Interface for MapModels. + * <h2>Transaction System</h2> + * The purpose of the transaction system in MapModel is to allow several subsequent changes to the model to be collected as a single big change before the registered listeners (usually the user interface) gets notified. + * This prevents the user interface from performing hundrets of updates when a single one would be enough. + * <p /> + * It is not the purpose of the transaction system to provide real transactions (ACID). + * Queries to the MapModel during an ongoing transaction will reflect the intermediate state. + * And there is no rollback. * @author <a href="mailto:ch...@ri...">Christian Hujer</a> */ public interface MapModel extends Iterable<MapSquare> { @@ -23,15 +31,36 @@ */ MapSquare getMapSquare(Point p) throws ArrayIndexOutOfBoundsException; - // TODO Remove this method - @Nullable MapSquare getMouseRightPosObject(); + /** + * Get the currently selected map square. + * @return currently selected map square + * @deprecated this method requires MapModel implementations to know their views + */ + @Deprecated @Nullable MapSquare getMouseRightPosObject(); + /** + * Reset the level changed flag to false. + * @todo this probably belongs to CMapControl instead + */ void resetLevelChangedFlag(); + /** + * Set the level changed flag to true. + * @todo this probably belongs to CMapControl instead + */ void setLevelChangedFlag(); + /** + * Return whether the level has changed since it was last saved or not. + * @return <code>true</code> if level has changed, <code>false</code> if not. + * @todo this probably belongs to CMapControl instead + */ boolean isLevelChanged(); + /** + * Return the map size of this level. + * @return map size of this level + */ Size2D getMapSize(); /** @@ -79,21 +108,68 @@ */ boolean insertArchToMap(ArchObject newarch, String archname, ArchObject next, Point pos); + /** + * Link an existing arch to the map. Including multi tile arches. This + * function allows to insert any given arch (can be non-default). Make sure + * that the given 'arch' is a new and unlinked object. + * @param arch the new arch to be linked onto the map. (Dest. + * coordinates must be set (arch.mapx/y)!) + * @param insertBelow true: new arch is inserted on top, false: new arch + * is inserted below + */ void addArchObjectToMap(ArchObject arch, boolean insertBelow); - void deleteMapArch(ArchObject arch, Point pos, boolean refreshMap); + /** + * Delete an existing arch from the map. (If the specified arch doesn't + * exist, nothing happens.) (This includes deletion of multiparts and + * inventory.) + * @param arch Arch to be removed + * @param refreshMap If true, mapview is redrawn after deletion. + * @todo eventually remove this method as arch has its own remove() method and refreshMap is controlled via the transaction system. + */ + void deleteMapArch(ArchObject arch, boolean refreshMap); + /** + * Clear this map. + */ void clearMap(); + /** + * Returns the Map Arch Object with the meta information about the map. + * @return the Map Arch Object with the meta information about the map + */ MapArchObject getMapArch(); + /** + * Check whether the given coordinate is within map bounds. + * @param pos the coordinates to check + * @return <code>true</code> if the given coordinates are on the map, otherwise <code>false</code> (also returns <code>false</code> if <code><var>pos</var> == null</code>) + */ boolean isPointValid(@Nullable Point pos); + /** + * Get the first exit on the MapSquare described by <var>hspot</var>. + * Possible exits include teleporters, exits and pits. + * @param hspot Point to get exit at + * @return first exit found or <code>null</code> if no exit was found + * @todo move this method somewhere else because the model should not know about arch types + */ @Nullable ArchObject getExit(@Nullable Point hspot); - boolean isCutoffUnsafe(Size2D newSize); + /** + * Check if no objects get cut off if the map was resized to the given bounds so cutoff is safe. + * @param newSize the new level size + * @return true if no objects would be cut off + */ + boolean isCutoffSafe(@NotNull Size2D newSize); - void resizeMap(Size2D newSize); + /** + * Resize this map to the new size. + * If any bounds are smaller than before, the map gets cut on the right and bottom side. + * Accordingly, new space is attached to right and bottom. + * @param newSize new map size + */ + void resizeMap(@NotNull Size2D newSize); /** * Returns the MapControl that controls this MapModel. @@ -105,13 +181,13 @@ * Register a map listener. * @param listener MapListener to register */ - void addMapModelListener(MapModelListener listener); + void addMapModelListener(@NotNull MapModelListener listener); /** * Unregister a map listener. * @param listener MapListener to unregsiter */ - void removeMapModelListener(MapModelListener listener); + void removeMapModelListener(@NotNull MapModelListener listener); /** * Method to notify the model that a map square was changed. @@ -119,7 +195,7 @@ * The model then notifies the registered listeners of the changes. * @param square MapSquare that has changed */ - void squareChanged(MapSquare square); + void squareChanged(@NotNull MapSquare square); /** * Start a new transaction. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |