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

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

fix #6723 - Cannot change Imagery fade color from Imagery settings

  • Property svn:eol-style set to native
File size: 10.6 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("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 private final ImageryAdjustAction adjustAction = new ImageryAdjustAction(this);
75 private final AbstractAction useServerOffsetAction = new AbstractAction(tr("(use server offset)")) {
76 @Override
77 public void actionPerformed(ActionEvent e) {
78 enableOffsetServer(true);
79 }
80 };
81
82 protected OffsetServerThread createoffsetServerThread() {
83 return new OffsetServerThread(new OsmosnimkiOffsetServer(
84 OsmosnimkiOffsetServer.PROP_SERVER_URL.get()));
85 }
86
87 public ImageryLayer(ImageryInfo info) {
88 super(info.getName());
89 this.info = info;
90 if (info.getIcon() != null) {
91 icon = new ImageProvider(info.getIcon()).setOptional(true).
92 setMaxHeight(ICON_SIZE).setMaxWidth(ICON_SIZE).get();
93 }
94 if (icon == null) {
95 icon = ImageProvider.get("imagery_small");
96 }
97 this.sharpenLevel = PROP_SHARPEN_LEVEL.get();
98 if (OffsetServer.PROP_SERVER_ENABLED.get()) {
99 offsetServerThread = createoffsetServerThread();
100 offsetServerThread.start();
101 }
102 }
103
104 public double getPPD(){
105 if (Main.map == null || Main.map.mapView == null) return Main.getProjection().getDefaultZoomInPPD();
106 ProjectionBounds bounds = Main.map.mapView.getProjectionBounds();
107 return Main.map.mapView.getWidth() / (bounds.maxEast - bounds.minEast);
108 }
109
110 public double getDx() {
111 return dx;
112 }
113
114 public double getDy() {
115 return dy;
116 }
117
118 public void setOffset(double dx, double dy) {
119 this.dx = dx;
120 this.dy = dy;
121 }
122
123 public void displace(double dx, double dy) {
124 setOffset(this.dx += dx, this.dy += dy);
125 }
126
127 public ImageryInfo getInfo() {
128 return info;
129 }
130
131 @Override
132 public Icon getIcon() {
133 return icon;
134 }
135
136 @Override
137 public boolean isMergable(Layer other) {
138 return false;
139 }
140
141 @Override
142 public void mergeFrom(Layer from) {
143 }
144
145 @Override
146 public Object getInfoComponent() {
147 return getToolTipText();
148 }
149
150 public static ImageryLayer create(ImageryInfo info) {
151 if (info.getImageryType() == ImageryType.WMS || info.getImageryType() == ImageryType.HTML)
152 return new WMSLayer(info);
153 else if (info.getImageryType() == ImageryType.TMS || info.getImageryType() == ImageryType.BING || info.getImageryType() == ImageryType.SCANEX)
154 return new TMSLayer(info);
155 else throw new AssertionError();
156 }
157
158 class ApplyOffsetAction extends AbstractAction {
159 private OffsetBookmark b;
160 ApplyOffsetAction(OffsetBookmark b) {
161 super(b.name);
162 this.b = b;
163 }
164
165 @Override
166 public void actionPerformed(ActionEvent ev) {
167 setOffset(b.dx, b.dy);
168 enableOffsetServer(false);
169 Main.main.menu.imageryMenu.refreshOffsetMenu();
170 Main.map.repaint();
171 }
172 }
173
174 public class OffsetAction extends AbstractAction implements LayerAction {
175 @Override
176 public void actionPerformed(ActionEvent e) {
177 }
178
179 @Override
180 public Component createMenuComponent() {
181 return getOffsetMenuItem();
182 }
183
184 @Override
185 public boolean supportLayers(List<Layer> layers) {
186 return false;
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
314 /* (non-Javadoc)
315 * @see org.openstreetmap.josm.gui.layer.Layer#destroy()
316 */
317 @Override
318 public void destroy() {
319 adjustAction.destroy();
320 }
321}
Note: See TracBrowser for help on using the repository browser.