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

Last change on this file since 4932 was 4162, checked in by stoecker, 13 years ago

fix #4140 - make colors in conflict dialog configurable

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