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

Last change on this file since 5464 was 5464, checked in by Don-vip, 12 years ago

Rework Properties a bit to simplify management of Color properties

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