1 /*******************************************************************************
2 * Copyright (c) 2012 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.maps.tile;
14 import java.awt.Image;
15 import java.lang.ref.SoftReference;
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.List;
22 * @author Tuukka Lehtonen
24 public class TileCache implements ITileListener {
26 public static class LevelCache {
28 * Allow collection of tile images when under memory pressure.
30 private Map<TileKey, SoftReference<Image>> cache = new HashMap<TileKey, SoftReference<Image>>();
32 public Image get(TileKey key) {
33 SoftReference<Image> ref = cache.get(key);
39 public void put(TileKey key, Image value) {
40 cache.put(key, new SoftReference<Image>(value));
43 public void remove(TileKey key) {
48 private final ITileJobQueue job;
49 private Map<Integer, LevelCache> levels = new HashMap<Integer, LevelCache>();
50 private List<ITileListener> tileListeners = new ArrayList<ITileListener>();
52 public TileCache(ITileJobQueue job) {
56 public void addTileListener(ITileListener l) {
60 public void removeTileListener(ITileListener l) {
61 tileListeners.remove(l);
64 private LevelCache getLevel(int l, boolean create) {
65 synchronized (levels) {
66 LevelCache level = levels.get(l);
67 if (level == null && create) {
68 level = new LevelCache();
77 * @return <code>null</code> to signify that the requested tile was not
78 * cached and a background request has been scheduled for the tile.
80 public Image get(final TileKey key) {
81 LevelCache level = getLevel(key.getLevel(), true);
82 Image image = level.get(key);
84 job.addJob(key, this);
90 * Take a peek into the cache to see if there is an image readily available
91 * for the requested tile.
93 * @param key the key of the requested tile
94 * @return <code>null</code> if there was no image in the cache
96 public Image peek(final TileKey key) {
97 LevelCache level = getLevel(key.getLevel(), false);
100 synchronized (level) {
101 return level.get(key);
106 * Flush the specified tile from the cache.
110 public synchronized void flush(final TileKey key) {
111 LevelCache level = getLevel(key.getLevel(), false);
113 synchronized (level) {
120 * Removes queries from the job queue that do not pass the specified filter.
122 public void filterJobQueue(IFilter<TileKey> filter) {
123 job.filterQueries(filter);
127 public void tileCanceled(TileKey key) {
128 for (ITileListener l : tileListeners) {
134 public void tileFailed(TileKey key, Throwable e) {
135 for (ITileListener l : tileListeners) {
136 l.tileFailed(key, e);
141 public void tileUpdated(TileKey key, Image image) {
142 LevelCache level = getLevel(key.getLevel(), true);
143 synchronized (level) {
144 level.put(key, image);
147 for (ITileListener l : tileListeners) {
148 l.tileUpdated(key, image);