Gridarta Editor
MapImageCache.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2015 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.gui.mapimagecache;
21 
22 import java.awt.Image;
23 import java.io.File;
24 import java.io.IOException;
25 import java.lang.ref.SoftReference;
26 import java.util.Collection;
27 import java.util.EnumMap;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.concurrent.CopyOnWriteArrayList;
43 import org.jetbrains.annotations.NotNull;
44 import org.jetbrains.annotations.Nullable;
45 
54 public class MapImageCache<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> {
55 
59  private static final int ICON_WIDTH = 48;
60 
64  private static final int ICON_HEIGHT = 23;
65 
69  private static final int PREVIEW_SCALE = 8;
70 
74  @NotNull
76 
80  @NotNull
82 
86  @NotNull
87  private final Collection<MapImageCacheListener<G, A, R>> listenerList = new CopyOnWriteArrayList<>();
88 
93  @NotNull
94  private final Map<ImageType, MapImageCacheEntry> entries = new EnumMap<>(ImageType.class);
95 
100  @NotNull
101  private final Map<MapControl<G, A, R>, SoftReference<MapRenderer>> mapRendererReferences = new HashMap<>();
102 
108 
109  @Override
110  public void saved(@NotNull final DefaultMapControl<G, A, R> mapControl) {
111  final MapFile mapFile = mapControl.getMapModel().getMapFile();
112  assert mapFile != null;
113  final File file = mapFile.getFile();
114  updateCaches(file, mapControl, ImageType.ICON);
115  updateCaches(file, mapControl, ImageType.PREVIEW);
116  }
117 
118  };
119 
131  public MapImageCache(@NotNull final MapManager<G, A, R> mapManager, @NotNull final Image defaultIcon, @NotNull final Image defaultPreview, @NotNull final RendererFactory<G, A, R> rendererFactory, @NotNull final CacheFiles cacheFiles) {
132  this.mapManager = mapManager;
133  this.rendererFactory = rendererFactory;
134  entries.put(ImageType.ICON, new MapImageCacheEntry(cacheFiles, defaultIcon, ImageType.ICON.toString()));
135  entries.put(ImageType.PREVIEW, new MapImageCacheEntry(cacheFiles, defaultPreview, ImageType.PREVIEW.toString()));
136 
137  final MapManagerListener<G, A, R> mapManagerListener = new MapManagerListener<G, A, R>() {
138 
139  @Override
140  public void currentMapChanged(@Nullable final MapControl<G, A, R> mapControl) {
141  // ignore
142  }
143 
144  @Override
145  public void mapCreated(@NotNull final MapControl<G, A, R> mapControl, final boolean interactive) {
146  mapControl.addMapControlListener(mapControlListener);
147  }
148 
149  @Override
150  public void mapClosing(@NotNull final MapControl<G, A, R> mapControl) {
151  // ignore
152  }
153 
159  @Override
160  public void mapClosed(@NotNull final MapControl<G, A, R> mapControl) {
161  mapControl.addMapControlListener(mapControlListener);
162  mapRendererReferences.remove(mapControl);
163  }
164 
165  };
166  mapManager.addMapManagerListener(mapManagerListener);
167  }
168 
173  public void flush(@NotNull final File mapFile) {
174  for (final ImageType imageType : ImageType.values()) {
175  entries.get(imageType).flush(mapFile);
176  }
177  }
178 
185  @Nullable
186  public Image getIcon(@NotNull final File mapFile) {
187  return entries.get(ImageType.ICON).lookupCache(mapFile);
188  }
189 
197  @Nullable
198  public Image getOrCreateIcon(@NotNull final File mapFile) {
199  return getOrCreate(mapFile, ImageType.ICON);
200  }
201 
208  @NotNull
209  public Image getOrCreateIcon(@NotNull final MapControl<G, A, R> mapControl) {
210  return getOrCreate(mapControl, ImageType.ICON);
211  }
212 
219  @Nullable
220  public Image getPreview(@NotNull final File mapFile) {
221  return entries.get(ImageType.PREVIEW).lookupCache(mapFile);
222  }
223 
231  @Nullable
232  public Image getOrCreatePreview(@NotNull final File mapFile) {
233  return getOrCreate(mapFile, ImageType.PREVIEW);
234  }
235 
242  @NotNull
243  public Image getOrCreatePreview(@NotNull final MapControl<G, A, R> mapControl) {
244  return getOrCreate(mapControl, ImageType.PREVIEW);
245  }
246 
254  @Nullable
255  private Image updateCaches(@NotNull final File mapFile, final ImageType imageType) {
256  try {
257  final MapControl<G, A, R> mapControl = mapManager.openMapFile(mapFile, false);
258  try {
259  return updateCaches(mapFile, mapControl, imageType);
260  } finally {
261  mapManager.release(mapControl);
262  }
263  } catch (final IOException ignored) {
264  // ignore: do not update cached images
265  }
266 
267  return entries.get(imageType).getDefaultImage();
268  }
269 
279  @NotNull
280  private Image updateCaches(@Nullable final File mapFile, @NotNull final MapControl<G, A, R> mapControl, final ImageType imageType) {
281  final Image image;
282  //noinspection ErrorNotRethrown
283  try {
284  image = getRenderer(mapControl).getFullImage();
285  } catch (final OutOfMemoryError ignored) {
286  return entries.get(imageType).getDefaultImage();
287  }
288  final Image[] images = new Image[2];
289  images[0] = entries.get(ImageType.ICON).scaleImage(mapFile, image, ICON_WIDTH, ICON_HEIGHT);
290  images[1] = entries.get(ImageType.PREVIEW).scaleImage(mapFile, image, (image.getWidth(null) + PREVIEW_SCALE - 1) / PREVIEW_SCALE, (image.getHeight(null) + PREVIEW_SCALE - 1) / PREVIEW_SCALE);
291 
292  if (mapFile != null) {
293  for (final MapImageCacheListener<G, A, R> listener : listenerList) {
294  listener.iconChanged(mapControl);
295  }
296  }
297 
298  return images[imageType == ImageType.ICON ? 0 : 1];
299  }
300 
307  @NotNull
308  private MapRenderer getRenderer(@NotNull final MapControl<G, A, R> mapControl) {
309  final SoftReference<MapRenderer> mapRendererReference = mapRendererReferences.get(mapControl);
310  final MapRenderer tmpMapRenderer = mapRendererReference == null ? null : mapRendererReference.get();
311  final MapRenderer mapRenderer;
312  if (tmpMapRenderer == null) {
313  mapRenderer = rendererFactory.newSimpleMapRenderer(mapControl.getMapModel());
314  mapRendererReferences.put(mapControl, new SoftReference<>(mapRenderer));
315  } else {
316  mapRenderer = tmpMapRenderer;
317  }
318  return mapRenderer;
319  }
320 
325  public void addMapImageCacheListener(@NotNull final MapImageCacheListener<G, A, R> listener) {
326  listenerList.add(listener);
327  }
328 
333  public void removeMapImageCacheListener(@NotNull final MapImageCacheListener<G, A, R> listener) {
334  listenerList.remove(listener);
335  }
336 
344  @NotNull
345  private Image getOrCreate(@NotNull final MapControl<G, A, R> mapControl, @NotNull final ImageType imageType) {
346  final MapFile mapFile = mapControl.getMapModel().getMapFile();
347  if (mapFile != null) {
348  final Image image = entries.get(imageType).lookupCache(mapFile.getFile());
349  if (image != null) {
350  return image;
351  }
352  }
353 
354  return updateCaches(mapFile == null ? null : mapFile.getFile(), mapControl, imageType);
355  }
356 
365  @Nullable
366  private Image getOrCreate(@NotNull final File mapFile, @NotNull final ImageType imageType) {
367  if (mapFile.isDirectory()) {
368  return null;
369  }
370 
371  final Image image = entries.get(imageType).lookupCache(mapFile);
372  return image == null ? updateCaches(mapFile, imageType) : image;
373  }
374 
375 }
net.sf.gridarta.model.mapmanager
Definition: AbstractMapManager.java:20
net.sf.gridarta.gui.mapimagecache.MapImageCache.entries
final Map< ImageType, MapImageCacheEntry > entries
Definition: MapImageCache.java:94
net.sf.gridarta.model.mapmanager.MapManager
Definition: MapManager.java:37
net.sf.gridarta.gui.mapimagecache.MapImageCache.getOrCreateIcon
Image getOrCreateIcon(@NotNull final MapControl< G, A, R > mapControl)
Definition: MapImageCache.java:209
net.sf.gridarta
net.sf.gridarta.gui.mapimagecache.MapImageCache.getOrCreatePreview
Image getOrCreatePreview(@NotNull final MapControl< G, A, R > mapControl)
Definition: MapImageCache.java:243
net.sf
net.sf.gridarta.model.mapmanager.MapManagerListener
Definition: MapManagerListener.java:42
net.sf.gridarta.gui.map.renderer.RendererFactory.newSimpleMapRenderer
MapRenderer newSimpleMapRenderer(@NotNull MapModel< G, A, R > mapModel)
net.sf.gridarta.model.mapmodel
Definition: AboveFloorInsertionMode.java:20
net.sf.gridarta.gui.mapimagecache.MapImageCache.mapRendererReferences
final Map< MapControl< G, A, R >, SoftReference< MapRenderer > > mapRendererReferences
Definition: MapImageCache.java:101
net.sf.gridarta.gui.map.renderer
Definition: AbstractIsoMapRenderer.java:20
net.sf.gridarta.model.mapmanager.MapManager.addMapManagerListener
void addMapManagerListener(@NotNull MapManagerListener< G, A, R > listener)
net.sf.gridarta.model.archetype
Definition: AbstractArchetype.java:20
net.sf.gridarta.model.gameobject.GameObject
Definition: GameObject.java:36
net.sf.gridarta.model.mapcontrol
Definition: DefaultMapControl.java:20
net.sf.gridarta.gui.mapimagecache.MapImageCache.ICON_HEIGHT
static final int ICON_HEIGHT
Definition: MapImageCache.java:64
net.sf.gridarta.gui.mapimagecache.ImageType.PREVIEW
PREVIEW
Definition: ImageType.java:36
net.sf.gridarta.gui
net.sf.gridarta.gui.mapimagecache.MapImageCache.getOrCreate
Image getOrCreate(@NotNull final File mapFile, @NotNull final ImageType imageType)
Definition: MapImageCache.java:366
net.sf.gridarta.gui.mapimagecache.MapImageCache.getIcon
Image getIcon(@NotNull final File mapFile)
Definition: MapImageCache.java:186
net.sf.gridarta.gui.mapimagecache.MapImageCache
Definition: MapImageCache.java:54
net.sf.gridarta.model.gameobject
Definition: AbstractGameObject.java:20
net
net.sf.gridarta.gui.mapimagecache.MapImageCache.getOrCreateIcon
Image getOrCreateIcon(@NotNull final File mapFile)
Definition: MapImageCache.java:198
net.sf.gridarta.gui.mapimagecache.MapImageCache.removeMapImageCacheListener
void removeMapImageCacheListener(@NotNull final MapImageCacheListener< G, A, R > listener)
Definition: MapImageCache.java:333
net.sf.gridarta.gui.mapimagecache.MapImageCache.rendererFactory
final RendererFactory< G, A, R > rendererFactory
Definition: MapImageCache.java:81
net.sf.gridarta.gui.mapimagecache.MapImageCache.flush
void flush(@NotNull final File mapFile)
Definition: MapImageCache.java:173
net.sf.gridarta.gui.mapimagecache.MapImageCache.mapControlListener
final MapControlListener< G, A, R > mapControlListener
Definition: MapImageCache.java:107
net.sf.gridarta.gui.mapimagecache.MapImageCache.listenerList
final Collection< MapImageCacheListener< G, A, R > > listenerList
Definition: MapImageCache.java:87
net.sf.gridarta.model.maparchobject.MapArchObject
Definition: MapArchObject.java:40
net.sf.gridarta.gui.mapimagecache.MapImageCache.updateCaches
Image updateCaches(@NotNull final File mapFile, final ImageType imageType)
Definition: MapImageCache.java:255
net.sf.gridarta.gui.mapimagecache.MapImageCache.getOrCreatePreview
Image getOrCreatePreview(@NotNull final File mapFile)
Definition: MapImageCache.java:232
net.sf.gridarta.model.mapmodel.MapFile.getFile
File getFile()
Definition: MapFile.java:102
net.sf.gridarta.model.mapmanager.MapManager.openMapFile
MapControl< G, A, R > openMapFile(@NotNull MapFile mapFile, boolean interactive)
net.sf.gridarta.gui.mapimagecache.MapImageCacheListener< G, A, R >
net.sf.gridarta.gui.mapimagecache.MapImageCache.MapImageCache
MapImageCache(@NotNull final MapManager< G, A, R > mapManager, @NotNull final Image defaultIcon, @NotNull final Image defaultPreview, @NotNull final RendererFactory< G, A, R > rendererFactory, @NotNull final CacheFiles cacheFiles)
Definition: MapImageCache.java:131
net.sf.gridarta.gui.mapimagecache.MapImageCache.addMapImageCacheListener
void addMapImageCacheListener(@NotNull final MapImageCacheListener< G, A, R > listener)
Definition: MapImageCache.java:325
net.sf.gridarta.gui.mapimagecache.MapImageCache.mapManager
final MapManager< G, A, R > mapManager
Definition: MapImageCache.java:75
net.sf.gridarta.model.mapmodel.MapFile
Definition: MapFile.java:31
net.sf.gridarta.model.io
Definition: AbstractArchetypeParser.java:20
net.sf.gridarta.gui.mapimagecache.MapImageCache.PREVIEW_SCALE
static final int PREVIEW_SCALE
Definition: MapImageCache.java:69
net.sf.gridarta.model.mapmanager.MapManager.release
void release(@NotNull MapControl< G, A, R > mapControl)
net.sf.gridarta.gui.mapimagecache.ImageType
Definition: ImageType.java:26
net.sf.gridarta.gui.mapimagecache.MapImageCache.getRenderer
MapRenderer getRenderer(@NotNull final MapControl< G, A, R > mapControl)
Definition: MapImageCache.java:308
net.sf.gridarta.gui.mapimagecache.MapImageCache.getPreview
Image getPreview(@NotNull final File mapFile)
Definition: MapImageCache.java:220
net.sf.gridarta.model
net.sf.gridarta.model.archetype.Archetype
Definition: Archetype.java:41
net.sf.gridarta.gui.mapimagecache.MapImageCache.getOrCreate
Image getOrCreate(@NotNull final MapControl< G, A, R > mapControl, @NotNull final ImageType imageType)
Definition: MapImageCache.java:345
net.sf.gridarta.gui.mapimagecache.MapImageCache.ICON_WIDTH
static final int ICON_WIDTH
Definition: MapImageCache.java:59
net.sf.gridarta.gui.map.renderer.RendererFactory
Definition: RendererFactory.java:33
net.sf.gridarta.gui.map
Definition: AbstractPerMapDialogManager.java:20
net.sf.gridarta.gui.mapimagecache.MapImageCacheEntry
Definition: MapImageCacheEntry.java:42
net.sf.gridarta.model.mapcontrol.MapControl
Definition: MapControl.java:35
net.sf.gridarta.model.mapcontrol.MapControlListener
Definition: MapControlListener.java:33
net.sf.gridarta.gui.mapimagecache.ImageType.ICON
ICON
Definition: ImageType.java:31
net.sf.gridarta.model.maparchobject
Definition: AbstractMapArchObject.java:20
net.sf.gridarta.gui.map.renderer.MapRenderer.getFullImage
BufferedImage getFullImage()
net.sf.gridarta.model.io.CacheFiles
Definition: CacheFiles.java:30
net.sf.gridarta.gui.mapimagecache.MapImageCache.updateCaches
Image updateCaches(@Nullable final File mapFile, @NotNull final MapControl< G, A, R > mapControl, final ImageType imageType)
Definition: MapImageCache.java:280
net.sf.gridarta.model.mapcontrol.DefaultMapControl
Definition: DefaultMapControl.java:44
net.sf.gridarta.gui.map.renderer.MapRenderer
Definition: MapRenderer.java:36