b9064cf435860fc4b812c6e93c566845f8ed14bc
[fw/altos] / altosuilib / AltosUIMapCache.java
1 /*
2  * Copyright © 2010 Anthony Towns <aj@erisian.com.au>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 package org.altusmetrum.altosuilib_3;
19
20 import javax.swing.*;
21 import javax.imageio.ImageIO;
22 import java.awt.image.*;
23 import java.awt.*;
24 import java.io.*;
25 import java.net.*;
26
27 public class AltosUIMapCache implements AltosUIMapCacheListener {
28         static final int        success = 0;
29         static final int        loading = 1;
30         static final int        failed = 2;
31         static final int        bad_request = 3;
32         static final int        forbidden = 4;
33
34         int                     min_cache_size;         /* configured minimum cache size */
35         int                     cache_size;             /* current cache size */
36         int                     requested_cache_size;   /* cache size computed by application */
37
38         private Object          fetch_lock = new Object();
39         private Object          cache_lock = new Object();
40
41         AltosUIMapImage[]       images = new AltosUIMapImage[cache_size];
42
43         long                    used;
44
45         public void set_cache_size(int new_size) {
46
47                 requested_cache_size = new_size;
48
49                 if (new_size < min_cache_size)
50                         new_size = min_cache_size;
51
52                 if (new_size == cache_size)
53                         return;
54
55                 synchronized(cache_lock) {
56                         AltosUIMapImage[]       new_images = new AltosUIMapImage[new_size];
57
58                         for (int i = 0; i < cache_size; i++) {
59                                 if (i < new_size)
60                                         new_images[i] = images[i];
61                                 else if (images[i] != null)
62                                         images[i].flush();
63                         }
64                         images = new_images;
65                         cache_size = new_size;
66                 }
67         }
68
69         public Image get(AltosUIMapTile tile, AltosUIMapStore store, int width, int height) {
70                 int             oldest = -1;
71                 long            age = used;
72
73                 synchronized(cache_lock) {
74                         AltosUIMapImage image = null;
75                         for (int i = 0; i < cache_size; i++) {
76                                 image = images[i];
77
78                                 if (image == null) {
79                                         oldest = i;
80                                         break;
81                                 }
82                                 if (store.equals(image.store)) {
83                                         image.used = used++;
84                                         return image.image;
85                                 }
86                                 if (image.used < age) {
87                                         oldest = i;
88                                         age = image.used;
89                                 }
90                         }
91
92                         try {
93                                 image = new AltosUIMapImage(tile, store);
94                                 image.used = used++;
95                                 if (images[oldest] != null)
96                                         images[oldest].flush();
97
98                                 images[oldest] = image;
99
100                                 if (image.image == null)
101                                         tile.set_status(loading);
102                                 else
103                                         tile.set_status(success);
104
105                                 return image.image;
106                         } catch (IOException e) {
107                                 tile.set_status(failed);
108                                 return null;
109                         }
110                 }
111         }
112
113         public void map_cache_changed(int map_cache) {
114                 min_cache_size = map_cache;
115
116                 set_cache_size(requested_cache_size);
117         }
118
119         public void dispose() {
120                 AltosUIPreferences.unregister_map_cache_listener(this);
121
122                 for (int i = 0; i < cache_size; i++) {
123                         AltosUIMapImage image = images[i];
124
125                         if (image != null)
126                             image.flush();
127                 }
128         }
129
130         public AltosUIMapCache() {
131                 min_cache_size = AltosUIPreferences.map_cache();
132
133                 set_cache_size(0);
134
135                 AltosUIPreferences.register_map_cache_listener(this);
136         }
137 }