source: josm/trunk/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java@ 5390

Last change on this file since 5390 was 5390, checked in by bastiK, 12 years ago

use individual imagery icons in layer list

  • Property svn:eol-style set to native
File size: 10.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.layer;
3
4import static org.openstreetmap.josm.tools.I18n.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6import static org.openstreetmap.josm.tools.I18n.trc;
7
8import java.awt.Color;
9import java.awt.Component;
10import java.awt.Font;
11import java.awt.Graphics;
12import java.awt.Toolkit;
13import java.awt.event.ActionEvent;
14import java.awt.image.BufferedImage;
15import java.awt.image.BufferedImageOp;
16import java.awt.image.ConvolveOp;
17import java.awt.image.Kernel;
18import java.util.List;
19
20import javax.swing.AbstractAction;
21import javax.swing.Icon;
22import javax.swing.JCheckBoxMenuItem;
23import javax.swing.JComponent;
24import javax.swing.JMenu;
25import javax.swing.JMenuItem;
26import javax.swing.JPopupMenu;
27import javax.swing.JSeparator;
28import javax.swing.SwingUtilities;
29
30import org.openstreetmap.josm.Main;
31import org.openstreetmap.josm.actions.ImageryAdjustAction;
32import org.openstreetmap.josm.data.ProjectionBounds;
33import org.openstreetmap.josm.data.coor.EastNorth;
34import org.openstreetmap.josm.data.imagery.ImageryInfo;
35import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
36import org.openstreetmap.josm.data.imagery.OffsetBookmark;
37import org.openstreetmap.josm.data.preferences.IntegerProperty;
38import org.openstreetmap.josm.gui.MenuScroller;
39import org.openstreetmap.josm.io.imagery.OffsetServer;
40import org.openstreetmap.josm.io.imagery.OsmosnimkiOffsetServer;
41import org.openstreetmap.josm.tools.ImageProvider;
42
43public abstract class ImageryLayer extends Layer {
44
45 public static final IntegerProperty PROP_FADE_AMOUNT = new IntegerProperty("imagery.fade_amount", 0);
46 public static final IntegerProperty PROP_SHARPEN_LEVEL = new IntegerProperty("imagery.sharpen_level", 0);
47
48 public static Color getFadeColor() {
49 return Main.pref.getColor(marktr("Imagery fade"), Color.white);
50 }
51
52 public static Color getFadeColorWithAlpha() {
53 Color c = getFadeColor();
54 return new Color(c.getRed(),c.getGreen(),c.getBlue(),PROP_FADE_AMOUNT.get()*255/100);
55 }
56
57 public static void setFadeColor(Color color) {
58 Main.pref.putColor(marktr("Imagery fade"), color);
59 }
60
61 protected final ImageryInfo info;
62
63 protected Icon icon;
64
65 protected double dx = 0.0;
66 protected double dy = 0.0;
67
68 protected int sharpenLevel;
69
70 protected boolean offsetServerSupported;
71 protected boolean offsetServerUsed;
72 protected OffsetServerThread offsetServerThread;
73
74 protected OffsetServerThread createoffsetServerThread() {
75 return new OffsetServerThread(new OsmosnimkiOffsetServer(
76 OsmosnimkiOffsetServer.PROP_SERVER_URL.get()));
77 }
78
79 public ImageryLayer(ImageryInfo info) {
80 super(info.getName());
81 this.info = info;
82 if (info.getIcon() != null) {
83 icon = new ImageProvider(info.getIcon()).setOptional(true).
84 setMaxHeight(ICON_SIZE).setMaxWidth(ICON_SIZE).get();
85 if (icon == null) {
86 icon = ImageProvider.get("imagery_small");
87 }
88 }
89 this.sharpenLevel = PROP_SHARPEN_LEVEL.get();
90 if (OffsetServer.PROP_SERVER_ENABLED.get()) {
91 offsetServerThread = createoffsetServerThread();
92 offsetServerThread.start();
93 }
94 }
95
96 public double getPPD(){
97 if (Main.map == null || Main.map.mapView == null) return Main.getProjection().getDefaultZoomInPPD();
98 ProjectionBounds bounds = Main.map.mapView.getProjectionBounds();
99 return Main.map.mapView.getWidth() / (bounds.maxEast - bounds.minEast);
100 }
101
102 public double getDx() {
103 return dx;
104 }
105
106 public double getDy() {
107 return dy;
108 }
109
110 public void setOffset(double dx, double dy) {
111 this.dx = dx;
112 this.dy = dy;
113 }
114
115 public void displace(double dx, double dy) {
116 setOffset(this.dx += dx, this.dy += dy);
117 }
118
119 public ImageryInfo getInfo() {
120 return info;
121 }
122
123 @Override
124 public Icon getIcon() {
125 return icon;
126 }
127
128 @Override
129 public boolean isMergable(Layer other) {
130 return false;
131 }
132
133 @Override
134 public void mergeFrom(Layer from) {
135 }
136
137 @Override
138 public Object getInfoComponent() {
139 return getToolTipText();
140 }
141
142 public static ImageryLayer create(ImageryInfo info) {
143 if (info.getImageryType() == ImageryType.WMS || info.getImageryType() == ImageryType.HTML)
144 return new WMSLayer(info);
145 else if (info.getImageryType() == ImageryType.TMS || info.getImageryType() == ImageryType.BING || info.getImageryType() == ImageryType.SCANEX)
146 return new TMSLayer(info);
147 else throw new AssertionError();
148 }
149
150 class ApplyOffsetAction extends AbstractAction {
151 private OffsetBookmark b;
152 ApplyOffsetAction(OffsetBookmark b) {
153 super(b.name);
154 this.b = b;
155 }
156
157 @Override
158 public void actionPerformed(ActionEvent ev) {
159 setOffset(b.dx, b.dy);
160 enableOffsetServer(false);
161 Main.main.menu.imageryMenu.refreshOffsetMenu();
162 Main.map.repaint();
163 }
164 }
165
166 public class OffsetAction extends AbstractAction implements LayerAction {
167 @Override
168 public void actionPerformed(ActionEvent e) {
169 }
170
171 @Override
172 public Component createMenuComponent() {
173 return getOffsetMenuItem();
174 }
175
176 @Override
177 public boolean supportLayers(List<Layer> layers) {
178 return false;
179 }
180 }
181
182 ImageryAdjustAction adjustAction = new ImageryAdjustAction(this);
183 AbstractAction useServerOffsetAction = new AbstractAction(tr("(use server offset)")) {
184 @Override
185 public void actionPerformed(ActionEvent e) {
186 enableOffsetServer(true);
187 }
188 };
189
190 public void enableOffsetServer(boolean enable) {
191 offsetServerUsed = enable;
192 if (offsetServerUsed && !offsetServerThread.isAlive()) {
193 offsetServerThread = createoffsetServerThread();
194 offsetServerThread.start();
195 }
196 }
197
198 public JMenuItem getOffsetMenuItem() {
199 JMenu subMenu = new JMenu(trc("layer", "Offset"));
200 subMenu.setIcon(ImageProvider.get("mapmode", "adjustimg"));
201 return (JMenuItem)getOffsetMenuItem(subMenu);
202 }
203
204 public JComponent getOffsetMenuItem(JComponent subMenu) {
205 JMenuItem adjustMenuItem = new JMenuItem(adjustAction);
206 if (OffsetBookmark.allBookmarks.isEmpty() && !offsetServerSupported) return adjustMenuItem;
207
208 subMenu.add(adjustMenuItem);
209 if (offsetServerSupported) {
210 JCheckBoxMenuItem item = new JCheckBoxMenuItem(useServerOffsetAction);
211 if (offsetServerUsed) {
212 item.setSelected(true);
213 }
214 subMenu.add(item);
215 }
216 subMenu.add(new JSeparator());
217 boolean hasBookmarks = false;
218 int menuItemHeight = 0;
219 for (OffsetBookmark b : OffsetBookmark.allBookmarks) {
220 if (!b.isUsable(this)) {
221 continue;
222 }
223 JCheckBoxMenuItem item = new JCheckBoxMenuItem(new ApplyOffsetAction(b));
224 if (b.dx == dx && b.dy == dy && !offsetServerUsed) {
225 item.setSelected(true);
226 }
227 subMenu.add(item);
228 menuItemHeight = item.getPreferredSize().height;
229 hasBookmarks = true;
230 }
231 if (menuItemHeight > 0) {
232 int scrollcount = (Toolkit.getDefaultToolkit().getScreenSize().height / menuItemHeight) - 1;
233 if (subMenu instanceof JMenu) {
234 MenuScroller.setScrollerFor((JMenu) subMenu, scrollcount);
235 } else if (subMenu instanceof JPopupMenu) {
236 MenuScroller.setScrollerFor((JPopupMenu)subMenu, scrollcount);
237 }
238 }
239 return (hasBookmarks || offsetServerSupported) ? subMenu : adjustMenuItem;
240 }
241
242 public BufferedImage sharpenImage(BufferedImage img) {
243 if (sharpenLevel <= 0) return img;
244 int width = img.getWidth(null);
245 int height = img.getHeight(null);
246 BufferedImage tmp = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
247 tmp.getGraphics().drawImage(img, 0, 0, null);
248 Kernel kernel;
249 if (sharpenLevel == 1) {
250 kernel = new Kernel(3, 3, new float[] { -0.25f, -0.5f, -0.25f, -0.5f, 4, -0.5f, -0.25f, -0.5f, -0.25f});
251 } else {
252 kernel = new Kernel(3, 3, new float[] { -0.5f, -1, -0.5f, -1, 7, -1, -0.5f, -1, -0.5f});
253 }
254 BufferedImageOp op = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
255 return op.filter(tmp, null);
256 }
257
258 public void drawErrorTile(BufferedImage img) {
259 Graphics g = img.getGraphics();
260 g.setColor(Color.RED);
261 g.fillRect(0, 0, img.getWidth(), img.getHeight());
262 g.setFont(g.getFont().deriveFont(Font.PLAIN).deriveFont(36.0f));
263 g.setColor(Color.BLACK);
264
265 String text = tr("ERROR");
266 g.drawString(text, (img.getWidth() + g.getFontMetrics().stringWidth(text)) / 2, img.getHeight()/2);
267 }
268
269 protected class OffsetServerThread extends Thread {
270 OffsetServer offsetServer;
271 EastNorth oldCenter = new EastNorth(Double.NaN, Double.NaN);
272
273 public OffsetServerThread(OffsetServer offsetServer) {
274 this.offsetServer = offsetServer;
275 setDaemon(true);
276 }
277
278 private void updateOffset() {
279 if (Main.map == null || Main.map.mapView == null) return;
280 EastNorth center = Main.map.mapView.getCenter();
281 if (center.equals(oldCenter)) return;
282 oldCenter = center;
283
284 EastNorth offset = offsetServer.getOffset(getInfo(), center);
285 if (offset != null) {
286 setOffset(offset.east(),offset.north());
287 }
288 }
289
290 @Override
291 public void run() {
292 if (!offsetServerSupported) {
293 if (!offsetServer.isLayerSupported(info)) return;
294 offsetServerSupported = true;
295 }
296 offsetServerUsed = true;
297 SwingUtilities.invokeLater(new Runnable() {
298 @Override
299 public void run() {
300 Main.main.menu.imageryMenu.refreshOffsetMenu();
301 }
302 });
303 try {
304 while (offsetServerUsed) {
305 updateOffset();
306 Thread.sleep(1000);
307 }
308 } catch (InterruptedException e) {
309 }
310 offsetServerUsed = false;
311 }
312 }
313}
Note: See TracBrowser for help on using the repository browser.