source: josm/trunk/src/org/openstreetmap/josm/gui/mappaint/MapImage.java@ 6711

Last change on this file since 6711 was 6711, checked in by bastiK, 10 years ago

closes #6797 - clear disabled image cache, when image loading is finished

  • Property svn:eol-style set to native
File size: 6.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.mappaint;
3
4import static org.openstreetmap.josm.tools.Utils.equal;
5
6import java.awt.Image;
7import java.awt.Rectangle;
8import java.awt.image.BufferedImage;
9
10import javax.swing.ImageIcon;
11
12import org.openstreetmap.josm.Main;
13import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.BoxProvider;
14import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.BoxProviderResult;
15import org.openstreetmap.josm.gui.util.GuiHelper;
16import org.openstreetmap.josm.tools.ImageProvider;
17import org.openstreetmap.josm.tools.ImageProvider.ImageCallback;
18import org.openstreetmap.josm.tools.Utils;
19
20public class MapImage {
21
22 private static final int MAX_SIZE = 48;
23
24 /**
25 * ImageIcon can change while the image is loading.
26 */
27 private BufferedImage img;
28
29 /**
30 * The 5 following fields are only used to check for equality.
31 */
32 public int alpha = 255;
33 public String name;
34 public StyleSource source;
35 public int width = -1;
36 public int height = -1;
37
38 private boolean temporary;
39 private Image disabledImgCache;
40
41 public MapImage(String name, StyleSource source) {
42 this.name = name;
43 this.source = source;
44 }
45
46 public Image getDisabled() {
47 if (disabledImgCache != null)
48 return disabledImgCache;
49 if (img == null)
50 getImage(); // fix #7498 ?
51 disabledImgCache = GuiHelper.getDisabledImage(img);
52 return disabledImgCache;
53 }
54
55 public BufferedImage getImage() {
56 if (img != null)
57 return img;
58 temporary = false;
59 new ImageProvider(name)
60 .setDirs(MapPaintStyles.getIconSourceDirs(source))
61 .setId("mappaint."+source.getPrefName())
62 .setArchive(source.zipIcons)
63 .setInArchiveDir(source.getZipEntryDirName())
64 .setWidth(width)
65 .setHeight(height)
66 .setOptional(true)
67 .getInBackground(new ImageCallback() {
68 @Override
69 public void finished(ImageIcon result) {
70 synchronized (MapImage.this) {
71 if (result == null) {
72 ImageIcon noIcon = MapPaintStyles.getNoIcon_Icon(source);
73 img = noIcon == null ? null : (BufferedImage) noIcon.getImage();
74 } else {
75 img = (BufferedImage) result.getImage();
76 }
77 if (temporary) {
78 disabledImgCache = null;
79 Main.map.mapView.preferenceChanged(null); // otherwise repaint is ignored, because layer hasn't changed
80 Main.map.mapView.repaint();
81 }
82 temporary = false;
83 }
84 }
85 }
86 );
87 synchronized (this) {
88 if (img == null) {
89 img = (BufferedImage) ImageProvider.get("clock").getImage();
90 temporary = true;
91 }
92 }
93 return img;
94 }
95
96 public int getWidth() {
97 return getImage().getWidth(null);
98 }
99
100 public int getHeight() {
101 return getImage().getHeight(null);
102 }
103
104 public float getAlphaFloat() {
105 return Utils.color_int2float(alpha);
106 }
107
108 /**
109 * Returns true, if image is not completely loaded and getImage() returns a temporary image.
110 */
111 public boolean isTemporary() {
112 return temporary;
113 }
114
115 protected class MapImageBoxProvider implements BoxProvider {
116 @Override
117 public BoxProviderResult get() {
118 return new BoxProviderResult(box(), temporary);
119 }
120
121 private Rectangle box() {
122 int w = getWidth(), h = getHeight();
123 if (mustRescale(getImage())) {
124 w = 16;
125 h = 16;
126 }
127 return new Rectangle(-w/2, -h/2, w, h);
128 }
129
130 private MapImage getParent() {
131 return MapImage.this;
132 }
133
134 @Override
135 public int hashCode() {
136 return MapImage.this.hashCode();
137 }
138
139 @Override
140 public boolean equals(Object obj) {
141 if (!(obj instanceof BoxProvider))
142 return false;
143 if (obj instanceof MapImageBoxProvider) {
144 MapImageBoxProvider other = (MapImageBoxProvider) obj;
145 return MapImage.this.equals(other.getParent());
146 } else if (temporary) {
147 return false;
148 } else {
149 final BoxProvider other = (BoxProvider) obj;
150 BoxProviderResult resultOther = other.get();
151 if (resultOther.isTemporary()) return false;
152 return box().equals(resultOther.getBox());
153 }
154 }
155 }
156
157 public BoxProvider getBoxProvider() {
158 return new MapImageBoxProvider();
159 }
160
161 /**
162 * Returns the really displayed node icon for this {@code MapImage}.
163 * @param disabled {@code} true to request disabled version, {@code false} for the standard version
164 * @return The scaled down version to 16x16 pixels if the image height and width exceeds 48 pixels and no size has been explicitely specified
165 * @since 6174
166 */
167 public Image getDisplayedNodeIcon(boolean disabled) {
168 final Image image = disabled ? getDisabled() : getImage();
169 // Scale down large (.svg) images to 16x16 pixels if no size is explicitely specified
170 if (mustRescale(image)) {
171 return ImageProvider.createBoundedImage(image, 16);
172 } else {
173 return image;
174 }
175 }
176
177 private boolean mustRescale(Image image) {
178 return ((width == -1 && image.getWidth(null) > MAX_SIZE)
179 && (height == -1 && image.getHeight(null) > MAX_SIZE));
180 }
181
182 @Override
183 public boolean equals(Object obj) {
184 if (obj == null || getClass() != obj.getClass())
185 return false;
186 final MapImage other = (MapImage) obj;
187 // img changes when image is fully loaded and can't be used for equality check.
188 return alpha == other.alpha &&
189 equal(name, other.name) &&
190 equal(source, other.source) &&
191 width == other.width &&
192 height == other.height;
193 }
194
195 @Override
196 public int hashCode() {
197 int hash = 7;
198 hash = 67 * hash + alpha;
199 hash = 67 * hash + name.hashCode();
200 hash = 67 * hash + source.hashCode();
201 hash = 67 * hash + width;
202 hash = 67 * hash + height;
203 return hash;
204 }
205
206 @Override
207 public String toString() {
208 return name;
209 }
210}
Note: See TracBrowser for help on using the repository browser.