From: <chr...@us...> - 2006-08-27 14:26:05
|
Revision: 282 Author: christianhujer Date: 2006-08-27 07:25:53 -0700 (Sun, 27 Aug 2006) ViewCVS: http://svn.sourceforge.net/gridarta/?rev=282&view=rev Log Message: ----------- Removed manually linked lists for containers in ArchObjects. Modified Paths: -------------- trunk/daimonin/src/daieditor/arch/ArchObject.java trunk/daimonin/src/daieditor/arch/ArchObjectContainer.java trunk/daimonin/src/daieditor/arch/RecursiveArchObjectIterator.java trunk/daimonin/src/daieditor/map/MapSquare.java Removed Paths: ------------- trunk/daimonin/src/daieditor/arch/ArchObjectIterator.java Modified: trunk/daimonin/src/daieditor/arch/ArchObject.java =================================================================== --- trunk/daimonin/src/daieditor/arch/ArchObject.java 2006-08-27 12:22:46 UTC (rev 281) +++ trunk/daimonin/src/daieditor/arch/ArchObject.java 2006-08-27 14:25:53 UTC (rev 282) @@ -53,6 +53,7 @@ * @todo this class maybe could be split into 3 classes: AbstractArchObject as * abstract base class, DefArchObject for default arches and ArchObject for * normal arches. + * @todo this class is not always the best place for multipart object handling, see also {@link ArchObjectContainer} for issues about this */ public final class ArchObject /*extends NamedObject*/ extends ArchObjectContainer implements Cloneable, net.sf.gridarta.arch.ArchObject { @@ -104,7 +105,7 @@ * Data for multitile-arches. * Stays null for singlesquare-arches. */ - private MultiArchData multi; + @Nullable private MultiArchData multi; /** * Data for scripted events. @@ -132,10 +133,6 @@ */ private boolean artifact; - private ArchObject next; // to chain ArchObjects in maps - - private ArchObject prev; // same - /** * Container of this ArchObject. * There are two possibilities for the container: @@ -528,7 +525,7 @@ * @param node ArchObject to append */ public void insertBefore(final ArchObject node) { - add(prev, node, this); + getContainer().insertBefore(node, this); } /** @@ -536,7 +533,7 @@ * @param node ArchObject to append */ public void insertAfter(final ArchObject node) { - add(this, node, next); + getContainer().insertAfter(this, node); } /** {@inheritDoc} */ @@ -809,38 +806,6 @@ } } - /** - * Set Next link. - * @param arch Arch to point next to - */ - void setNext(final ArchObject arch) { - next = arch; - } - - /** - * Set Prev link. - * @param arch Arch to point prev to - */ - void setPrev(final ArchObject arch) { - prev = arch; - } - - /** - * Get Next link. - * @return next link - */ - ArchObject getNext() { - return next; - } - - /** - * Get Prev link. - * @return prev link - */ - ArchObject getPrev() { - return prev; - } - public int getDirection() { return direction; } @@ -1188,8 +1153,6 @@ final ArchObject clone = (ArchObject) super.clone(); clone.mapx = -1; clone.mapy = -1; - clone.next = null; - clone.prev = null; clone.container = null; return clone; } catch (final CloneNotSupportedException e) { Modified: trunk/daimonin/src/daieditor/arch/ArchObjectContainer.java =================================================================== --- trunk/daimonin/src/daieditor/arch/ArchObjectContainer.java 2006-08-27 12:22:46 UTC (rev 281) +++ trunk/daimonin/src/daieditor/arch/ArchObjectContainer.java 2006-08-27 14:25:53 UTC (rev 282) @@ -23,6 +23,11 @@ import daieditor.map.MapSquare; import java.util.Iterator; +import java.util.List; +import java.util.ArrayList; +import java.util.ListIterator; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; /** * Base class for classes that match contain ArchObjects as children. @@ -32,15 +37,16 @@ * <li>{@link daieditor.map.MapSquare} extends this class to list the tiles on a MapSquare.</li> * </ul> * @author <a href="mailto:ch...@ri...">Christian Hujer</a> + * @todo: In case of MapSquares, this class is most likely bogus regarding multipart objects. This needs to be fixed. */ public abstract class ArchObjectContainer implements Iterable<ArchObject> { - /** First object contained. */ - private ArchObject first; + /** + * The contents of this container. + * @note the order of this container is bottom to top. + */ + private List<ArchObject> contents = new ArrayList<ArchObject>(); - /** Last object contained. */ - private ArchObject last; - /** Iterable implementation for recursice traversal. */ private Iterable<ArchObject> recursive; @@ -57,13 +63,13 @@ recursive = new Iterable<ArchObject>() { /** {@inheritDoc} */ public Iterator<ArchObject> iterator() { - return new RecursiveArchObjectIterator(first); + return new RecursiveArchObjectIterator(ArchObjectContainer.this); } }; reverse = new Iterable<ArchObject>() { /** {@inheritDoc} */ public Iterator<ArchObject> iterator() { - return new ArchObjectIterator(last, false); + return new ReverseIterator(); } }; // Iterable<ArchObject> reverse } @@ -74,7 +80,7 @@ * The Iterator returned is transparent, that means modifying the iterator's collection actually modifies the unterlying ArchObjectContainer. */ public final Iterator<ArchObject> iterator() { - return new ArchObjectIterator(first); + return contents.iterator(); } /** @@ -100,7 +106,7 @@ * @return <code>true</code> if this square is empty, otherwise <code>false</code> */ public boolean isEmpty() { - return first == null; + return contents.isEmpty(); } /** @@ -109,7 +115,7 @@ * @return first object contained */ public final ArchObject getFirst() { - return first; + return contents.get(contents.size() - 1); } /** @@ -118,7 +124,7 @@ * @return last object contained */ public final ArchObject getLast() { - return last; + return contents.get(0); } /** @@ -126,35 +132,16 @@ * @param arch ArchObject to remove */ final void remove(final ArchObject arch) { - if (arch == first) { - first = arch.getNext(); - } - if (arch == last) { - last = arch.getPrev(); - } - if (arch.getNext() != null) { - arch.getNext().setPrev(arch.getPrev()); - } - if (arch.getPrev() != null) { - arch.getPrev().setNext(arch.getNext()); - } arch.setContainer(null); - arch.setNext(null); - arch.setPrev(null); - assert isListOkay() : "List in wrong order"; squareChanged(); } /** Remove all ArchObjects from this container. */ public final void removeAll() { - for (ArchObject arch : this) { + for (final ArchObject arch : contents) { arch.setContainer(null); - arch.setNext(null); - arch.setPrev(null); } - first = null; - last = null; - assert isListOkay() : "List in wrong order"; + contents.clear(); squareChanged(); } @@ -163,11 +150,12 @@ * @param arch item to move to top */ public final void moveTop(final ArchObject arch) { - getMapSquare().getModel().beginTransaction(); - while (last != arch) { - swap(arch, arch.getNext()); + final int oldIndex = contents.indexOf(arch); + if (oldIndex != contents.size() - 1) { + contents.remove(arch); + contents.add(arch); + squareChanged(); } - getMapSquare().getModel().endTransaction(); } /** @@ -175,7 +163,12 @@ * @param arch item to move up */ public final void moveUp(final ArchObject arch) { - swap(arch, arch.getNext()); + final int oldIndex = contents.indexOf(arch); + if (oldIndex < contents.size() - 1) { + contents.remove(arch); + contents.add(oldIndex + 1, arch); + squareChanged(); + } } /** @@ -183,7 +176,12 @@ * @param arch item to move down */ public final void moveDown(final ArchObject arch) { - swap(arch.getPrev(), arch); + final int oldIndex = contents.indexOf(arch); + if (oldIndex > 0) { + contents.remove(arch); + contents.add(oldIndex - 1, arch); + squareChanged(); + } } /** @@ -191,47 +189,15 @@ * @param arch item to move to bottom */ public final void moveBottom(final ArchObject arch) { - getMapSquare().getModel().beginTransaction(); - while (first != arch) { - swap(arch.getPrev(), arch); + final int oldIndex = contents.indexOf(arch); + if (oldIndex != 0) { + contents.remove(arch); + contents.add(0, arch); + squareChanged(); } - getMapSquare().getModel().endTransaction(); } /** - * Swap to ArchObjects, exchanging them with each other. - * If at least one of <var>a1</var> and <var>a2</var> is <code>null</code>, this method simply does nothing. - * @param a1 first ArchObject, maybe <code>null</code> - * @param a2 second ArchObject, maybe <code>null</code> - * @note as a precondition, a1 must be preceding a2 - */ - private void swap(final ArchObject a1, final ArchObject a2) { - if (a1 == null || a2 == null) { - return; - } - assert a1.getNext() == a2; - assert a2.getPrev() == a1; - a1.setNext(a2.getNext()); - a2.setPrev(a1.getPrev()); - if (a1.getPrev() != null) { - a1.getPrev().setNext(a2); - } - if (a2.getNext() != null) { - a2.getNext().setPrev(a1); - } - a1.setPrev(a2); - a2.setNext(a1); - if (first == a1) { - first = a2; - } - if (last == a2) { - last = a1; - } - assert isListOkay() : "List in wrong order"; - squareChanged(); - } - - /** * Get the X coordinate on the map. * @return X coordinate on map */ @@ -248,7 +214,9 @@ * @param arch the free yet unlinked <code>ArchObject</code> to be placed in the inventory */ public void addLast(final ArchObject arch) { - add(last, arch, null); + contents.add(0, arch); + arch.setContainer(this); + squareChanged(); } /** @@ -256,7 +224,9 @@ * @param arch the free yet unlinked <code>ArchObject</code> to be placed in the inventory */ public void addFirst(final ArchObject arch) { - add(null, arch, first); + contents.add(arch); + arch.setContainer(this); + squareChanged(); } /** @@ -265,7 +235,10 @@ * @param arch ArchObject to insert */ public void insertAfter(final ArchObject prev, final ArchObject arch) { - add(prev, arch, prev != null ? prev.getNext() : null); + final int insertIndex = contents.indexOf(prev); + contents.add(insertIndex, arch); + arch.setContainer(this); + squareChanged(); } /** @@ -274,36 +247,9 @@ * @param next next anchor */ public void insertBefore(final ArchObject arch, final ArchObject next) { - add(next != null ? next.getPrev() : null, arch, next); - } - - /** - * Add the given ArchObject in this Container. - * If you need to change add behaviour, override this method. - * @param prev previous anchor, <code>invLast</code> for addLast, <code>null</code> for addFirst - * @param arch ArchObject to add - * @param next next anchor, <code>null</code> for addLast, <code>invStart</code> for addFirst - * @note as a precondition, this method requires that <var>prev</var> and <var>next</var> are either null or linked to each other. - */ - protected void add(final ArchObject prev, final ArchObject arch, final ArchObject next) { - assert prev == null || prev.getNext() == next; - assert next == null || next.getPrev() == prev; - if (prev == null) { - first = arch; - } else { - prev.setNext(arch); - } - arch.setPrev(prev); - arch.setNext(next); - if (next == null) { - last = arch; - } else { - next.setPrev(arch); - } + final int insertIndex = contents.indexOf(next); + contents.add(insertIndex + 1, arch); arch.setContainer(this); - arch.setMapX(getMapX()); - arch.setMapY(getMapY()); - assert isListOkay() : "List in wrong order"; squareChanged(); } @@ -313,28 +259,15 @@ * @param newArch new ArchObject that replaces oldArch */ public void replace(final ArchObject oldArch, final ArchObject newArch) { - final ArchObject prev = oldArch.getPrev(); - final ArchObject next = oldArch.getNext(); - if (prev == null) { - first = newArch; - } else { - prev.setNext(newArch); - } - newArch.setPrev(prev); - newArch.setNext(next); - if (next == null) { - last = newArch; - } else { - next.setPrev(newArch); - } - newArch.setContainer(this); - newArch.setMapX(getMapX()); - newArch.setMapY(getMapY()); - oldArch.setPrev(null); - oldArch.setNext(null); + final int insertIndex = contents.indexOf(oldArch); + contents.remove(oldArch); + contents.add(newArch); oldArch.setContainer(null); - assert isListOkay() : "List in wrong order"; + newArch.setContainer(this); squareChanged(); + newArch.setMapX(getMapX()); // ??? + newArch.setMapY(getMapY()); // ??? + squareChanged(); } /** @@ -354,36 +287,11 @@ } } - /** - * Method that checks whether the linked lists are still in order. - * Usage: <code>assert isListOkay() : "List in wrong order";</code> - * Use this after list manipulation. - * @return <code>true</code> on success (list still in order) - * @throws AssertionError on failure (list disordered) - */ - private boolean isListOkay() throws AssertionError { - ArchObject next, prev = null; - for (ArchObject current = first; current != null; current = next) { - next = current.getNext(); - assert current.getPrev() == prev; - ((ArchObjectContainer) current).isListOkay(); - prev = current; - if (next == null) { - assert current == last; - } - } - // this looks strange, when is false going to be returned? - // quite simple: never. In the "false case", instead an AssertionError is thrown (asserts) by this method itself. - return true; - } - /** {@inheritDoc} */ @Override protected ArchObjectContainer clone() throws CloneNotSupportedException { try { final ArchObjectContainer clone = (ArchObjectContainer) super.clone(); clone.initIterables(); - clone.first = null; - clone.last = null; return clone; } catch (final CloneNotSupportedException e) { assert false; @@ -391,4 +299,21 @@ } } + /** ArchObjectIterator for iterating over this container in reverse order. */ + private class ReverseIterator implements Iterator<ArchObject> { + private ListIterator<ArchObject> delegate = contents.listIterator(contents.size()); + + public boolean hasNext() { + return delegate.hasPrevious(); + } + + public ArchObject next() { + return delegate.previous(); + } + + public void remove() { + delegate.remove(); + } + } // class ReverseIterator + } // interface ArchObjectContainer Deleted: trunk/daimonin/src/daieditor/arch/ArchObjectIterator.java =================================================================== --- trunk/daimonin/src/daieditor/arch/ArchObjectIterator.java 2006-08-27 12:22:46 UTC (rev 281) +++ trunk/daimonin/src/daieditor/arch/ArchObjectIterator.java 2006-08-27 14:25:53 UTC (rev 282) @@ -1,99 +0,0 @@ -/* - * Daimonin Java Editor. - * Copyright (C) 2000 Michael Toennies - * Copyright (C) 2001 Andreas Vogl - * - * (code based on: Gridder. 2D grid based level editor. (C) 2000 Pasi Keränen) - * - * 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., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -package daieditor.arch; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Iterator for ArchObjects. - * This class is only meant for usage during the transition from manually linked lists to encapslued Collections lists in arch handling. - * This Iterator is believed to be safe against concurrent modification. - * Therefore it is not fail-fast, it does not throw ConcurrentModificationException. - * The next link is future-fetched, which means that the invocation of {@link #next()} already prepares the next invocation of {@link #hasNext()} or {@link #next()}. - * This allows to safely perform manipulations on the current object, especially deletion, without loosing traversal. - * @author <a href="mailto:ch...@ri...">Christian Hujer</a> - */ -class ArchObjectIterator implements Iterator<ArchObject> { - -// /** Current ArchObject, used for {@link #remove()}. */ -// private ArchObject current; - - /** Traversal direction. */ - private final boolean forward; - - /** ArchObject for first iteration step. */ - private ArchObject next; - - /** - * Creates a new instance of ArchObjectIterator (forward iteration). - * @param first first ArchObject to start forward iteration on - */ - ArchObjectIterator(final ArchObject first) { - this(first, true); - } - - /** - * Creates a new instance of ArchObjectIterator. - * @param first first ArchObject to start iteration on - * @param forward <code>true</code> for forward iteration, <code>false</code> for backward iteration - */ - ArchObjectIterator(final ArchObject first, final boolean forward) { - next = first; - this.forward = forward; - } - - /** {@inheritDoc} */ - public boolean hasNext() { - return next != null; - } - - /** {@inheritDoc} */ - public ArchObject next() { - try { - return next; - } finally { - try { - next = forward ? next.getNext() : next.getPrev(); - } catch (final NullPointerException e) { - //noinspection ThrowFromFinallyBlock - throw new NoSuchElementException(); - } - } - } - - /** - * {@inheritDoc} - * @todo eventually, multitile-removal should go here. - */ - public void remove() { - throw new UnsupportedOperationException(); -// ArchObject prev = current.getPrevArch(); -// ArchObject next = current.getNextArch(); -// if (next != null) { next.setPrevArch(prev); } -// if (prev != null) { prev.setPrevArch(next); } - } - -} // class ArchObjectIterator Modified: trunk/daimonin/src/daieditor/arch/RecursiveArchObjectIterator.java =================================================================== --- trunk/daimonin/src/daieditor/arch/RecursiveArchObjectIterator.java 2006-08-27 12:22:46 UTC (rev 281) +++ trunk/daimonin/src/daieditor/arch/RecursiveArchObjectIterator.java 2006-08-27 14:25:53 UTC (rev 282) @@ -2,6 +2,10 @@ import java.util.Iterator; import java.util.NoSuchElementException; +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; +import java.util.EmptyStackException; /** * Iterator for recursively iterating over ArchObjectContainers. @@ -9,48 +13,49 @@ */ class RecursiveArchObjectIterator implements Iterator<ArchObject> { - /** The current iteration element. */ - private ArchObject current; + /** The Iterator stack. */ + private Stack<Iterator<ArchObject>> iteratorStack = new Stack<Iterator<ArchObject>>(); - /** The next iteration element. */ - private ArchObject next; + /** The current iterator. */ + private Iterator<ArchObject> current; /** * Create a recursive ArchObject Iterator. - * @param first ArchObjectContainer to start with + * @param container ArchObjectContainer to start with */ - RecursiveArchObjectIterator(final ArchObject first) { - next = first; + RecursiveArchObjectIterator(final ArchObjectContainer container) { + current = container.iterator(); } /** {@inheritDoc} */ public boolean hasNext() { - return next != null; + return current.hasNext(); } /** {@inheritDoc} */ public ArchObject next() { - current = next; - if (current == null) { - throw new NoSuchElementException(); - } - next = current.isEmpty() ? current.getNext() : current.getFirst(); - if (next == null && current.isInContainer()) { - final Object container = current.getContainer(); - if (container instanceof ArchObject) { - next = ((ArchObject) container).getNext(); + final ArchObject arch = current.next(); + try { + return arch; + } finally { + if (!arch.isEmpty()) { + iteratorStack.push(current); + current = arch.iterator(); + } else { + try { + while (!current.hasNext() ) { + current = iteratorStack.pop(); + } + } catch (final EmptyStackException e) { + /* ignore. */ + } } } - return current; } /** {@inheritDoc} */ public void remove() { - if (current == null) { - throw new IllegalStateException("remove() already invoked!"); - } current.remove(); - current = null; } } // class RecursiveArchObjectIterator Modified: trunk/daimonin/src/daieditor/map/MapSquare.java =================================================================== --- trunk/daimonin/src/daieditor/map/MapSquare.java 2006-08-27 12:22:46 UTC (rev 281) +++ trunk/daimonin/src/daieditor/map/MapSquare.java 2006-08-27 14:25:53 UTC (rev 282) @@ -24,8 +24,8 @@ package daieditor.map; -import daieditor.arch.ArchObject; import daieditor.arch.ArchObjectContainer; +import org.jetbrains.annotations.NotNull; /** * A single Map Square. @@ -37,7 +37,7 @@ public class MapSquare extends ArchObjectContainer { /** The MaoModel this square is associated with. */ - private final MapModel model; + @NotNull private final MapModel model; /** The X Coordinate of this map square within the model's grid. */ private final int x; @@ -51,7 +51,7 @@ * @param x X Coordinate of this map square within the model's grid * @param y Y Coordinate of this map square within the model's grid */ - MapSquare(final MapModel model, final int x, final int y) { + MapSquare(@NotNull final MapModel model, final int x, final int y) { this.model = model; this.x = x; this.y = y; @@ -61,30 +61,10 @@ * Get the MapModel. * @return MapModel */ - public MapModel getModel() { + @NotNull public MapModel getModel() { return model; } - /** - * {@inheritDoc} - * @todo This perhaps is the place to care about addition of multi-tile arches as well - */ - @Override protected void add(final ArchObject prev, final ArchObject arch, final ArchObject next) { -// // Pseudo-Code for adding a multihead at this place -// MultiHeadInfo info = getMultiHeadInfo(arch); -// if (!model.isValid(x + info.getX(), y + info.getY())) { -// return; -// } - super.add(prev, arch, next); - arch.setMapX(this.x); - arch.setMapY(this.y); -// // Pseudo-Code for adding a multihead at this place (continued) -// for (MultiHeadTileInfo tile : info) { -// MapSquare square = model.getMapSquare(x + tile.getX(), y + tile.getY()); -// square.super.add(square.getLast(), tile.createArch(arch), null); -// } - } - /** {@inheritDoc} */ @Override public final int getMapX() { return x; @@ -96,7 +76,7 @@ } /** {@inheritDoc} */ - @Override public final MapSquare getMapSquare() { + @Override @NotNull public final MapSquare getMapSquare() { return this; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |