From: <aki...@us...> - 2007-09-07 21:23:33
|
Revision: 2889 http://gridarta.svn.sourceforge.net/gridarta/?rev=2889&view=rev Author: akirschbaum Date: 2007-09-07 14:23:36 -0700 (Fri, 07 Sep 2007) Log Message: ----------- Add map validator module. Modified Paths: -------------- trunk/crossfire/ChangeLog trunk/crossfire/src/cfeditor/CMainControl.java trunk/crossfire/src/cfeditor/CMapViewBasic.java trunk/crossfire/src/cfeditor/IGUIConstants.java trunk/crossfire/src/cfeditor/MainActions.java trunk/crossfire/src/cfeditor/action.properties trunk/crossfire/src/cfeditor/gui/map/DefaultLevelRenderer.java trunk/crossfire/src/cfeditor/map/MapControl.java trunk/crossfire/src/cfeditor/messages.properties trunk/crossfire/src/cfeditor/messages_de.properties trunk/crossfire/src/cfeditor/messages_fr.properties trunk/crossfire/src/cfeditor/messages_sv.properties Added Paths: ----------- trunk/crossfire/resource/system/warning.png Modified: trunk/crossfire/ChangeLog =================================================================== --- trunk/crossfire/ChangeLog 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/ChangeLog 2007-09-07 21:23:36 UTC (rev 2889) @@ -1,3 +1,10 @@ +2007-09-07 Andreas Kirschbaum + + * Add map validator module. For now the following is checked: + - a connected object must not be pickable + - a connected object must not be in an inventory + - the map difficulty must be positive + 2007-09-05 Andreas Kirschbaum * Fix part of #1555837 (Doesn't support new move_type system): add Added: trunk/crossfire/resource/system/warning.png =================================================================== (Binary files differ) Property changes on: trunk/crossfire/resource/system/warning.png ___________________________________________________________________ Name: svn:mime-type + image/png Modified: trunk/crossfire/src/cfeditor/CMainControl.java =================================================================== --- trunk/crossfire/src/cfeditor/CMainControl.java 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/src/cfeditor/CMainControl.java 2007-09-07 21:23:36 UTC (rev 2889) @@ -35,7 +35,12 @@ import cfeditor.map.MapControl; import cfeditor.script.ScriptController; import cfeditor.spells.Spells; +import java.awt.Image; import java.awt.Point; +import java.awt.Toolkit; +import java.awt.image.FilteredImageSource; +import java.awt.image.ImageFilter; +import java.awt.image.ImageProducer; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -62,7 +67,14 @@ import net.sf.gridarta.gui.RecentManager; import net.sf.gridarta.gui.map.MapView; import net.sf.gridarta.gui.undo.UndoControl; +import net.sf.gridarta.map.MapModel; import net.sf.gridarta.map.MapType; +import net.sf.gridarta.map.validation.DefaultErrorCollector; +import net.sf.gridarta.map.validation.DelegatingMapValidator; +import net.sf.gridarta.map.validation.ErrorCollector; +import net.sf.gridarta.map.validation.checks.ConnectedInsideContainerChecker; +import net.sf.gridarta.map.validation.checks.ConnectedPickableChecker; +import net.sf.gridarta.map.validation.checks.MapDifficultyChecker; import net.sf.gridarta.textedit.scripteditor.ScriptEditControl; import net.sf.japi.swing.ActionFactory; import net.sf.japi.swing.ActionMethod; @@ -143,6 +155,8 @@ private static ImageIcon emptyTileIcon; + private static ImageIcon warningSquareIcon; + private static ImageIcon nofaceTileIcon; private static ImageIcon noarchTileIcon; @@ -185,6 +199,9 @@ /** The list of archtype-data (loaded from "types.xml"). */ private CFArchTypeList typeList = null; + /** The map validators. */ + private final DelegatingMapValidator validators; + private final MapCursorControl mapCursorControl; /** The map manager. */ @@ -256,9 +273,24 @@ } treasureListTree = new CFTreasureListTree(archetypeSet); recentManager.initRecent(); + validators = createMapValidators(); } /** + * Initializes the map validators. + * @return A MapValidator that delegates to other map validators. + */ + private static DelegatingMapValidator createMapValidators() { + final DelegatingMapValidator mapValidators = new DelegatingMapValidator(); + mapValidators.add( + new ConnectedInsideContainerChecker(), + new ConnectedPickableChecker(), + new MapDifficultyChecker() + ); + return mapValidators; + } + + /** * Get the static instance of CMainControl. * @return static instance of this class */ @@ -333,6 +365,19 @@ } /** + * Check a map. + * @param map map to check + * @todo that's not nice here. Instead there should be an error model and error listeners. + */ + public void validateMap(final MapModel<GameObject, MapArchObject, Archetype> map) { + final ErrorCollector errorCollector = new DefaultErrorCollector(); + validators.validateAll(map, errorCollector); + for (final MapViewIFrame mapViewIFrame : ((MapControl) map.getMapControl()).getMapViewFrames()) { + mapViewIFrame.getView().setErrors(errorCollector); + } + } + + /** * Runs the garbage collection. */ @SuppressWarnings({"InstanceMethodNamingConvention"}) @@ -842,6 +887,10 @@ return nofaceTileIcon; } + public static ImageIcon getWarningSquareIcon() { + return warningSquareIcon; + } + public static ImageIcon getNoarchTileIcon() { return noarchTileIcon; } @@ -860,12 +909,23 @@ mapCursorIcon = GUIUtils.getSysIcon(IGUIConstants.TILE_CURSOR); emptyTileIcon = GUIUtils.getSysIcon(IGUIConstants.TILE_EMPTY); unknownTileIcon = GUIUtils.getSysIcon(IGUIConstants.TILE_UNKNOWN); + warningSquareIcon = createWarningSquareIcon(); nofaceTileIcon = GUIUtils.getSysIcon(IGUIConstants.TILE_NOFACE); noarchTileIcon = GUIUtils.getSysIcon(IGUIConstants.TILE_NOARCH); defaultIcon = GUIUtils.getSysIcon(IGUIConstants.DEFAULT_ICON); defaultPreview = GUIUtils.getSysIcon(IGUIConstants.DEFAULT_PREVIEW); } + private static ImageIcon createWarningSquareIcon() { + final ImageFilter alphaFilter = FaceObjects.ALPHA_FILTER; + final ImageIcon sysIcon = GUIUtils.getSysIcon(IGUIConstants.TILE_WARNING); + final Image image = sysIcon.getImage(); + final ImageProducer source = image.getSource(); + final FilteredImageSource producer = new FilteredImageSource(source, alphaFilter); + final Image image2 = Toolkit.getDefaultToolkit().createImage(producer); + return new ImageIcon(image2); + } + /** {@inheritDoc} */ public void handleThrowable(final Throwable t) { mainView.handleThrowable(t); Modified: trunk/crossfire/src/cfeditor/CMapViewBasic.java =================================================================== --- trunk/crossfire/src/cfeditor/CMapViewBasic.java 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/src/cfeditor/CMapViewBasic.java 2007-09-07 21:23:36 UTC (rev 2889) @@ -33,6 +33,8 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import javax.imageio.ImageIO; import javax.swing.JViewport; import net.sf.gridarta.gui.map.MapCursor; @@ -43,6 +45,8 @@ import net.sf.gridarta.map.MapModel; import net.sf.gridarta.map.MapModelEvent; import net.sf.gridarta.map.MapSquare; +import net.sf.gridarta.map.validation.ErrorCollector; +import net.sf.gridarta.map.validation.ValidationError; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -85,6 +89,12 @@ /** The tile palette renderer. */ private final DefaultLevelRenderer renderer; + /** The MapSquares that are known to contain errors. */ + private final Map<MapSquare<GameObject, MapArchObject, Archetype>, ValidationError> erraneousMapSquares = new HashMap<MapSquare<GameObject, MapArchObject, Archetype>, ValidationError>(); + + /** The ArchObjects that are known to contain errors. */ + private final Map<GameObject, ValidationError> erraneousArchObjects = new HashMap<GameObject, ValidationError>(); + @NotNull private final MapUserListener mapUserListener; /** @@ -124,6 +134,8 @@ if (!mapControl.isPickmap()) { renderer.addMouseMotionListener(mainControl.getMainView().getStatusBar()); } + renderer.setErraneousMapSquares(erraneousMapSquares); + renderer.setErraneousArchObjects(erraneousArchObjects); renderer.setFocusable(true); setFocusable(true); } @@ -233,6 +245,27 @@ } /** {@inheritDoc} */ + public void setErrors(final ErrorCollector errors) { + erraneousMapSquares.clear(); + erraneousArchObjects.clear(); + mapGrid.clearErrors(); + for (final ValidationError<GameObject, MapArchObject, Archetype> validationError : errors.getErrors()) { + final MapSquare<GameObject, MapArchObject, Archetype> mapSquare = validationError.getMapSquare(); + final GameObject archObject = validationError.getGameObject(); + if (mapSquare != null) { + erraneousMapSquares.put(mapSquare, validationError); + mapGrid.setError(mapSquare.getMapX(), mapSquare.getMapY()); + } + if (archObject != null) { + erraneousArchObjects.put(archObject, validationError); + final GameObject topContainer = archObject.getTopContainer(); + mapGrid.setError(topContainer.getMapX(), topContainer.getMapY()); + } + } + renderer.repaint(); + } + + /** {@inheritDoc} */ public void mapCursorChangedPos(@NotNull final MapCursorEvent e) { final MapCursor mapCursor = e.getSource(); if (mapCursor.isActive()) { Modified: trunk/crossfire/src/cfeditor/IGUIConstants.java =================================================================== --- trunk/crossfire/src/cfeditor/IGUIConstants.java 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/src/cfeditor/IGUIConstants.java 2007-09-07 21:23:36 UTC (rev 2889) @@ -122,6 +122,8 @@ String TILE_UNKNOWN = "unknown.png"; + String TILE_WARNING = "warning.png"; + String TILE_NOFACE = "noface.png"; String TILE_NOARCH = "noarch.png"; Modified: trunk/crossfire/src/cfeditor/MainActions.java =================================================================== --- trunk/crossfire/src/cfeditor/MainActions.java 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/src/cfeditor/MainActions.java 2007-09-07 21:23:36 UTC (rev 2889) @@ -34,6 +34,7 @@ import net.sf.gridarta.gui.map.MapGridEvent; import net.sf.gridarta.gui.map.MapGridListener; import net.sf.gridarta.gui.map.MapView; +import net.sf.gridarta.map.MapModel; import net.sf.gridarta.map.MapModelEvent; import net.sf.gridarta.map.MapModelListener; import net.sf.japi.swing.ActionFactory; @@ -92,7 +93,15 @@ /** Action called for "reload faces". */ private final Action aReloadFaces = ACTION_FACTORY.createAction(true, "reloadFaces", this); + /** Action called for "validate map". */ + private final Action aValidateMap = ACTION_FACTORY.createAction(true, "validateMap", this); + /** + * The last known active map, or <code>null</code> if no map is active. + */ + @Nullable private MapControl currentMap; + + /** * The last known active map view, or <code>null</code> if no map is * active. */ @@ -105,7 +114,8 @@ /* {@inheritDoc} */ public void currentMapChanged(@Nullable final MapControl mapControl) { - // ignore: a current map view changed event will be generated + currentMap = mapControl; + refreshMenus(); } /* {@inheritDoc} */ @@ -219,6 +229,7 @@ public MainActions(@NotNull final CMainControl mainControl) { this.mainControl = mainControl; mainControl.addMainControlListener(mainControlListener); + currentMap = mainControl.getCurrentMap(); currentMapView = mainControl.getCurrentMapView(); } @@ -248,6 +259,7 @@ aSelectAll.setEnabled(getSelectAllEnabled() != null); aCollectArches.setEnabled(!mainControl.getArchetypeSet().isLoadedFromArchive()); aReloadFaces.setEnabled(!mainControl.getArchetypeSet().isLoadedFromArchive()); + aValidateMap.setEnabled(getValidateMapEnabled() != null); } /** "Clear" was selected from the Edit menu. */ @@ -409,6 +421,14 @@ mainControl.reloadFaces(); } + /** Invoked when "validate map" was selected. */ + @ActionMethod public void validateMap() { + final MapModel<GameObject, MapArchObject, Archetype> mapModel = getValidateMapEnabled(); + if (mapModel != null) { + mainControl.validateMap(mapModel); + } + } + /** * Determine if "clear" is enabled. * @return the map view to clear if "clear" is enabled, or @@ -509,6 +529,16 @@ } /** + * Determine if "validate map" is enabled. + * @return The map model to check if "validate map" is enabled, or + * <code>null</code> otherwise. + */ + private MapModel<GameObject, MapArchObject, Archetype> getValidateMapEnabled() { + final MapControl mapControl = currentMap; + return mapControl == null ? null : mapControl.getMapModel(); + } + + /** * Determine if the current map has a selection. * @return the map view if a selection exists, or <code>null</code> * otherwise Modified: trunk/crossfire/src/cfeditor/action.properties =================================================================== --- trunk/crossfire/src/cfeditor/action.properties 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/src/cfeditor/action.properties 2007-09-07 21:23:36 UTC (rev 2889) @@ -34,7 +34,7 @@ cursor.menu=moveCursor - selectTile startStopDrag addToSelection subFromSelection releaseDrag - insertArch deleteArch - selectArchAbove selectArchBelow - archAttributes #pickmaps.menu: See gridarta resources.menu=collectArches - viewTreasurelists -tools.menu=gc +tools.menu=validateMap - gc analyze.menu= view.menu=- showMonster showExit showBackground showDoor showWall showEquipment showTreasure showConnected resetView - prevWindow nextWindow plugins.menu=- editPlugins - savePlugins exportPluginAs importPlugin Modified: trunk/crossfire/src/cfeditor/gui/map/DefaultLevelRenderer.java =================================================================== --- trunk/crossfire/src/cfeditor/gui/map/DefaultLevelRenderer.java 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/src/cfeditor/gui/map/DefaultLevelRenderer.java 2007-09-07 21:23:36 UTC (rev 2889) @@ -29,7 +29,9 @@ import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; +import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; +import java.util.Map; import net.sf.gridarta.Size2D; import net.sf.gridarta.gui.map.MapGrid; import net.sf.gridarta.gui.map.MapGridEvent; @@ -38,6 +40,7 @@ import net.sf.gridarta.map.MapModelEvent; import net.sf.gridarta.map.MapModelListener; import net.sf.gridarta.map.MapSquare; +import net.sf.gridarta.map.validation.ValidationError; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -67,6 +70,9 @@ /** Used to avoid creation millions of points. */ private final Point tmpPoint = new Point(); + /** The MapSquares that are known to contain errors. */ + private Map<MapSquare<GameObject, MapArchObject, Archetype>, ValidationError> erraneousMapSquares; + /** * The map model listener to track changes in {@link #mapModel}. */ @@ -147,6 +153,7 @@ mapSize = mapModel.getMapSize(); this.mapGrid = mapGrid; + setToolTipText("dummy"); setFocusable(true); borderOffset.setLocation(borderSize, borderSize); @@ -170,6 +177,26 @@ } /** {@inheritDoc} */ + @Nullable @Override public String getToolTipText(final MouseEvent event) { + final Point mapLocation = getTileLocationAt(event.getPoint(), tmpPoint); + if (mapLocation == null) { + return null; + } + if (mapGrid.hasError(mapLocation)) { + final MapSquare<GameObject, MapArchObject, Archetype> mapSquare = mapModel.getMapSquare(mapLocation); + + if (erraneousMapSquares.containsKey(mapSquare)) { + final ValidationError error = erraneousMapSquares.get(mapSquare); + return error.getMessage(); + } else { + return null; + } + } else { + return null; + } + } + + /** {@inheritDoc} */ @NotNull public BufferedImage getFullImage() { final int viewWidth = 32 * mapSize.getWidth(); final int viewHeight = 32 * mapSize.getHeight(); @@ -253,6 +280,9 @@ if ((gridFlags & MapGrid.GRID_FLAG_CURSOR) != 0) { CMainControl.getMapCursorIcon().paintIcon(this, grfx, borderOffset.x + point.x * 32, borderOffset.y + point.y * 32); } + if ((gridFlags & MapGrid.GRID_FLAG_ERROR) != 0) { + CMainControl.getWarningSquareIcon().paintIcon(this, grfx, borderOffset.x + point.x * 32, borderOffset.y + point.y * 32); + } } /** @@ -400,6 +430,22 @@ protected abstract void updateAll(); /** + * Sets the ArchObjects that are known to contain errors. + * @param erraneousArchObjects the ArchObjects that are known to contain errors + */ + public void setErraneousArchObjects(final Map<GameObject, ValidationError> erraneousArchObjects) { + //XXX: save erraneousArchObjects + } + + /** + * Sets the MapSquares that are known to contain errors. + * @param erraneousMapSquares the MapSquares that are known to contain errors + */ + public void setErraneousMapSquares(final Map<MapSquare<GameObject, MapArchObject, Archetype>, ValidationError> erraneousMapSquares) { + this.erraneousMapSquares = erraneousMapSquares; + } + + /** * Returns whether the map grid is rendered. * * @return <code>true</code> if the map grid is rendered, otherwise Modified: trunk/crossfire/src/cfeditor/map/MapControl.java =================================================================== --- trunk/crossfire/src/cfeditor/map/MapControl.java 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/src/cfeditor/map/MapControl.java 2007-09-07 21:23:36 UTC (rev 2889) @@ -414,6 +414,14 @@ } /** + * Get the List of all views. + * @return the last used view + */ + public List<MapViewIFrame> getMapViewFrames() { + return mapViewIFrames; + } + + /** * Close a view of this level. * @param mapViewIFrame the view to be closed */ Modified: trunk/crossfire/src/cfeditor/messages.properties =================================================================== --- trunk/crossfire/src/cfeditor/messages.properties 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/src/cfeditor/messages.properties 2007-09-07 21:23:36 UTC (rev 2889) @@ -274,6 +274,10 @@ tools.text=Tools tools.mnemonic=T +validateMap.text=Check map +validateMap.mnemonic=M +validateMap.shortdescription=Run map checker + gc.text=Run Garbage Collection gc.mnemonic=G Modified: trunk/crossfire/src/cfeditor/messages_de.properties =================================================================== --- trunk/crossfire/src/cfeditor/messages_de.properties 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/src/cfeditor/messages_de.properties 2007-09-07 21:23:36 UTC (rev 2889) @@ -241,6 +241,10 @@ tools.text=Werkzeuge tools.mnemonic=W +validateMap.text=Karte pr\xFCfen +validateMap.mnemonic=K +validateMap.shortdescription=Karte auf Fehler pr\xFCfen + gc.text=Starte Garbage Collection gc.mnemonic=G Modified: trunk/crossfire/src/cfeditor/messages_fr.properties =================================================================== --- trunk/crossfire/src/cfeditor/messages_fr.properties 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/src/cfeditor/messages_fr.properties 2007-09-07 21:23:36 UTC (rev 2889) @@ -242,6 +242,10 @@ tools.text=Outils tools.mnemonic=O +#validateMap.text= +#validateMap.mnemonic= +#validateMap.shortdescription= + gc.text=Garbage Collection gc.mnemonic=G Modified: trunk/crossfire/src/cfeditor/messages_sv.properties =================================================================== --- trunk/crossfire/src/cfeditor/messages_sv.properties 2007-09-07 21:11:41 UTC (rev 2888) +++ trunk/crossfire/src/cfeditor/messages_sv.properties 2007-09-07 21:23:36 UTC (rev 2889) @@ -240,6 +240,10 @@ tools.text=Verktyg tools.mnemonic=T +validateMap.text=Validera karta +validateMap.mnemonic=V +validateMap.shortdescription=K\xF6r kartvalideraren + gc.text=G\xF6r garbage collection gc.mnemonic=G This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |