Changeset 22550 in osm for applications/editors/josm/plugins/wmsplugin
- Timestamp:
- 2010-08-03T08:21:38+02:00 (15 years ago)
- Location:
- applications/editors/josm/plugins/wmsplugin
- Files:
-
- 4 edited
-
.classpath (modified) (1 diff)
-
build.xml (modified) (3 diffs)
-
josm-wmsplugin.launch (modified) (1 diff)
-
src/wmsplugin/WMSLayer.java (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/wmsplugin/.classpath
r18597 r22550 2 2 <classpath> 3 3 <classpathentry kind="src" path="src"/> 4 <classpathentry including="images/" kind="src" path=""/> 4 5 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> 5 6 <classpathentry combineaccessrules="false" kind="src" path="/JOSM"/> -
applications/editors/josm/plugins/wmsplugin/build.xml
r22006 r22550 29 29 30 30 <property name="commit.message" value="add commit message" /> 31 <property name="plugin.main.version" value=" 2830" />31 <property name="plugin.main.version" value="3408" /> 32 32 33 33 … … 93 93 94 94 <!-- 95 ************************** Publishing the plugin *********************************** 95 ************************** Publishing the plugin *********************************** 96 96 --> 97 97 <!-- 98 ** extracts the JOSM release for the JOSM version in ../core and saves it in the 98 ** extracts the JOSM release for the JOSM version in ../core and saves it in the 99 99 ** property ${coreversion.info.entry.revision} 100 100 ** … … 145 145 146 146 <!-- 147 ** commits the plugin.jar 147 ** commits the plugin.jar 148 148 --> 149 149 <target name="commit-dist"> 150 150 <echo> 151 151 ***** Properties of published ${plugin.jar} ***** 152 Commit message : '${commit.message}' 152 Commit message : '${commit.message}' 153 153 Plugin-Mainversion: ${plugin.main.version} 154 154 JOSM build version: ${coreversion.info.entry.revision} 155 155 Plugin-Version : ${version.entry.commit.revision} 156 ***** / Properties of published ${plugin.jar} ***** 157 156 ***** / Properties of published ${plugin.jar} ***** 157 158 158 Now commiting ${plugin.jar} ... 159 159 </echo> -
applications/editors/josm/plugins/wmsplugin/josm-wmsplugin.launch
r19417 r22550 7 7 <listEntry value="1"/> 8 8 </listAttribute> 9 <stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 5"/>9 <stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JDK 6"/> 10 10 <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.openstreetmap.josm.gui.MainApplication"/> 11 11 <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="wmsplugin"/> -
applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSLayer.java
r22286 r22550 13 13 import java.io.ObjectInputStream; 14 14 import java.io.ObjectOutputStream; 15 import java.util.List; 15 16 import java.util.concurrent.ExecutorService; 16 17 import java.util.concurrent.Executors; 17 18 18 19 import javax.swing.AbstractAction; 20 import javax.swing.Action; 19 21 import javax.swing.Icon; 20 22 import javax.swing.ImageIcon; 21 23 import javax.swing.JCheckBoxMenuItem; 22 24 import javax.swing.JFileChooser; 23 import javax.swing.JMenuItem;24 25 import javax.swing.JOptionPane; 25 import javax.swing.JSeparator;26 26 27 27 import org.openstreetmap.josm.Main; … … 30 30 import org.openstreetmap.josm.data.Bounds; 31 31 import org.openstreetmap.josm.data.ProjectionBounds; 32 import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent; 33 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener; 32 34 import org.openstreetmap.josm.data.coor.EastNorth; 33 35 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; 36 import org.openstreetmap.josm.data.preferences.BooleanProperty; 34 37 import org.openstreetmap.josm.gui.MapView; 35 38 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; … … 38 41 import org.openstreetmap.josm.io.CacheFiles; 39 42 import org.openstreetmap.josm.tools.ImageProvider; 40 import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;41 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;42 43 43 44 /** … … 46 47 */ 47 48 public class WMSLayer extends Layer implements PreferenceChangedListener { 48 protected static final Icon icon = 49 new ImageIcon(Toolkit.getDefaultToolkit().createImage(WMSPlugin.class.getResource("/images/wms_small.png"))); 50 51 public int messageNum = 5; //limit for messages per layer 52 protected MapView mv; 53 protected String resolution; 54 protected boolean stopAfterPaint = false; 55 protected int imageSize = 500; 56 protected int dax = 10; 57 protected int day = 10; 58 protected int minZoom = 3; 59 protected double dx = 0.0; 60 protected double dy = 0.0; 61 protected double pixelPerDegree; 62 protected GeorefImage[][] images = new GeorefImage[dax][day]; 63 JCheckBoxMenuItem startstop = new JCheckBoxMenuItem(tr("Automatic downloading"), true); 64 protected JCheckBoxMenuItem alphaChannel = new JCheckBoxMenuItem(new ToggleAlphaAction()); 65 protected String baseURL; 66 protected String cookies; 67 protected final int serializeFormatVersion = 5; 68 69 private ExecutorService executor = null; 70 71 /** set to true if this layer uses an invalid base url */ 72 private boolean usesInvalidUrl = false; 73 /** set to true if the user confirmed to use an potentially invalid WMS base url */ 74 private boolean isInvalidUrlConfirmed = false; 75 76 public WMSLayer() { 77 this(tr("Blank Layer"), null, null); 78 initializeImages(); 79 mv = Main.map.mapView; 80 } 81 82 public WMSLayer(String name, String baseURL, String cookies) { 83 super(name); 84 alphaChannel.setSelected(Main.pref.getBoolean("wmsplugin.alpha_channel")); 85 setBackgroundLayer(true); /* set global background variable */ 86 initializeImages(); 87 this.baseURL = baseURL; 88 this.cookies = cookies; 89 WMSGrabber.getProjection(baseURL, true); 90 mv = Main.map.mapView; 91 92 // quick hack to predefine the PixelDensity to reuse the cache 93 int codeIndex = getName().indexOf("#PPD="); 94 if (codeIndex != -1) { 95 pixelPerDegree = Double.valueOf(getName().substring(codeIndex+5)); 96 } else { 97 pixelPerDegree = getPPD(); 98 } 99 resolution = mv.getDist100PixelText(); 100 101 executor = Executors.newFixedThreadPool( 102 Main.pref.getInteger("wmsplugin.numThreads", 103 WMSPlugin.simultaneousConnections)); 104 if (baseURL != null && !baseURL.startsWith("html:") && !WMSGrabber.isUrlWithPatterns(baseURL)) { 105 if (!(baseURL.endsWith("&") || baseURL.endsWith("?"))) { 106 if (!confirmMalformedUrl(baseURL)) { 107 System.out.println(tr("Warning: WMS layer deactivated because of malformed base url ''{0}''", baseURL)); 108 usesInvalidUrl = true; 109 setName(getName() + tr("(deactivated)")); 110 return; 111 } else { 112 isInvalidUrlConfirmed = true; 113 } 114 } 115 } 116 117 Main.pref.addPreferenceChangeListener(this); 118 } 119 120 public boolean hasAutoDownload(){ 121 return startstop.isSelected(); 122 } 123 124 public double getDx(){ 125 return dx; 126 } 127 128 public double getDy(){ 129 return dy; 130 } 131 132 @Override 133 public void destroy() { 134 try { 135 executor.shutdownNow(); 136 // Might not be initialized, so catch NullPointer as well 137 } catch(Exception x) { 138 x.printStackTrace(); 139 } 140 } 141 142 public double getPPD(){ 143 ProjectionBounds bounds = mv.getProjectionBounds(); 144 return mv.getWidth() / (bounds.max.east() - bounds.min.east()); 145 } 146 147 public void initializeImages() { 148 images = new GeorefImage[dax][day]; 149 for(int x = 0; x<dax; ++x) { 150 for(int y = 0; y<day; ++y) { 151 images[x][y]= new GeorefImage(false); 152 } 153 } 154 } 155 156 @Override public Icon getIcon() { 157 return icon; 158 } 159 160 @Override public String getToolTipText() { 161 if(startstop.isSelected()) 162 return tr("WMS layer ({0}), automatically downloading in zoom {1}", getName(), resolution); 163 else 164 return tr("WMS layer ({0}), downloading in zoom {1}", getName(), resolution); 165 } 166 167 @Override public boolean isMergable(Layer other) { 168 return false; 169 } 170 171 @Override public void mergeFrom(Layer from) { 172 } 173 174 private ProjectionBounds XYtoBounds (int x, int y) { 175 return new ProjectionBounds( 176 new EastNorth( x * imageSize / pixelPerDegree, y * imageSize / pixelPerDegree), 177 new EastNorth((x + 1) * imageSize / pixelPerDegree, (y + 1) * imageSize / pixelPerDegree)); 178 } 179 180 private int modulo (int a, int b) { 181 return a % b >= 0 ? a%b : a%b+b; 182 } 183 184 private boolean zoomIsTooBig() { 185 //don't download when it's too outzoomed 186 return pixelPerDegree / getPPD() > minZoom; 187 } 188 189 @Override public void paint(Graphics2D g, final MapView mv, Bounds bounds) { 190 if(baseURL == null) return; 191 if (usesInvalidUrl && !isInvalidUrlConfirmed) return; 192 193 if (zoomIsTooBig()) { 194 for(int x = 0; x<dax; ++x) { 195 for(int y = 0; y<day; ++y) { 196 images[modulo(x,dax)][modulo(y,day)].paint(g, mv, dx, dy); 197 } 198 } 199 } else { 200 downloadAndPaintVisible(g, mv, false); 201 } 202 } 203 204 public void displace(double dx, double dy) { 205 this.dx += dx; 206 this.dy += dy; 207 } 208 209 protected boolean confirmMalformedUrl(String url) { 210 if (isInvalidUrlConfirmed) 211 return true; 212 String msg = tr("<html>The base URL<br>" 213 + "''{0}''<br>" 214 + "for this WMS layer does neither end with a ''&'' nor with a ''?''.<br>" 215 + "This is likely to lead to invalid WMS request. You should check your<br>" 216 + "preference settings.<br>" 217 + "Do you want to fetch WMS tiles anyway?", 218 url); 219 String [] options = new String[] { 220 tr("Yes, fetch images"), 221 tr("No, abort") 222 }; 223 int ret = JOptionPane.showOptionDialog( 224 Main.parent, 225 msg, 226 tr("Invalid URL?"), 227 JOptionPane.YES_NO_OPTION, 228 JOptionPane.WARNING_MESSAGE, 229 null, 230 options, options[1] 231 ); 232 switch(ret) { 233 case JOptionPane.YES_OPTION: return true; 234 default: return false; 235 } 236 } 237 238 protected void downloadAndPaintVisible(Graphics g, final MapView mv, 239 boolean real){ 240 if (usesInvalidUrl) 241 return; 242 243 ProjectionBounds bounds = mv.getProjectionBounds(); 244 int bminx= (int)Math.floor (((bounds.min.east() - dx) * pixelPerDegree) / imageSize ); 245 int bminy= (int)Math.floor (((bounds.min.north() - dy) * pixelPerDegree) / imageSize ); 246 int bmaxx= (int)Math.ceil (((bounds.max.east() - dx) * pixelPerDegree) / imageSize ); 247 int bmaxy= (int)Math.ceil (((bounds.max.north() - dy) * pixelPerDegree) / imageSize ); 248 249 for(int x = bminx; x<bmaxx; ++x) { 250 for(int y = bminy; y<bmaxy; ++y){ 251 GeorefImage img = images[modulo(x,dax)][modulo(y,day)]; 252 if((!img.paint(g, mv, dx, dy) || img.infotext) && !img.downloadingStarted){ 253 img.downloadingStarted = true; 254 img.image = null; 255 img.flushedResizedCachedInstance(); 256 Grabber gr = WMSPlugin.getGrabber(XYtoBounds(x,y), img, mv, this); 257 if(!gr.loadFromCache(real)){ 258 gr.setPriority(1); 259 executor.submit(gr); 260 } 261 } 262 } 263 } 264 } 265 266 @Override public void visitBoundingBox(BoundingXYVisitor v) { 267 for(int x = 0; x<dax; ++x) { 268 for(int y = 0; y<day; ++y) 269 if(images[x][y].image!=null){ 270 v.visit(images[x][y].min); 271 v.visit(images[x][y].max); 272 } 273 } 274 } 275 276 @Override public Object getInfoComponent() { 277 return getToolTipText(); 278 } 279 280 @Override public Component[] getMenuEntries() { 281 return new Component[]{ 282 new JMenuItem(LayerListDialog.getInstance().createActivateLayerAction(this)), 283 new JMenuItem(LayerListDialog.getInstance().createShowHideLayerAction(this)), 284 new JMenuItem(LayerListDialog.getInstance().createDeleteLayerAction(this)), 285 new JSeparator(), 286 new JMenuItem(new LoadWmsAction()), 287 new JMenuItem(new SaveWmsAction()), 288 new JMenuItem(new BookmarkWmsAction()), 289 new JSeparator(), 290 startstop, 291 alphaChannel, 292 new JMenuItem(new ChangeResolutionAction()), 293 new JMenuItem(new ReloadErrorTilesAction()), 294 new JMenuItem(new DownloadAction()), 295 new JSeparator(), 296 new JMenuItem(new LayerListPopup.InfoAction(this)) 297 }; 298 } 299 300 public GeorefImage findImage(EastNorth eastNorth) { 301 for(int x = 0; x<dax; ++x) { 302 for(int y = 0; y<day; ++y) 303 if(images[x][y].image!=null && images[x][y].min!=null && images[x][y].max!=null) 304 if(images[x][y].contains(eastNorth, dx, dy)) 305 return images[x][y]; 306 } 307 return null; 308 } 309 310 public class DownloadAction extends AbstractAction { 311 public DownloadAction() { 312 super(tr("Download visible tiles")); 313 } 314 public void actionPerformed(ActionEvent ev) { 315 if (zoomIsTooBig()) { 316 JOptionPane.showMessageDialog( 317 Main.parent, 318 tr("The requested area is too big. Please zoom in a little, or change resolution"), 319 tr("Error"), 320 JOptionPane.ERROR_MESSAGE 321 ); 322 } else { 323 downloadAndPaintVisible(mv.getGraphics(), mv, true); 324 } 325 } 326 } 327 328 public class ChangeResolutionAction extends AbstractAction { 329 public ChangeResolutionAction() { 330 super(tr("Change resolution")); 331 } 332 public void actionPerformed(ActionEvent ev) { 333 initializeImages(); 334 resolution = mv.getDist100PixelText(); 335 pixelPerDegree = getPPD(); 336 mv.repaint(); 337 } 338 } 339 340 public class ReloadErrorTilesAction extends AbstractAction { 341 public ReloadErrorTilesAction() { 342 super(tr("Reload erroneous tiles")); 343 } 344 public void actionPerformed(ActionEvent ev) { 345 // Delete small files, because they're probably blank tiles. 346 // See https://josm.openstreetmap.de/ticket/2307 347 WMSPlugin.cache.customCleanUp(CacheFiles.CLEAN_SMALL_FILES, 4096); 348 349 for (int x = 0; x < dax; ++x) { 350 for (int y = 0; y < day; ++y) { 351 GeorefImage img = images[modulo(x,dax)][modulo(y,day)]; 352 if(img.failed){ 353 img.image = null; 354 img.flushedResizedCachedInstance(); 355 img.downloadingStarted = false; 356 img.failed = false; 357 mv.repaint(); 358 } 359 } 360 } 361 } 362 } 363 364 public class ToggleAlphaAction extends AbstractAction { 365 public ToggleAlphaAction() { 366 super(tr("Alpha channel")); 367 } 368 public void actionPerformed(ActionEvent ev) { 369 JCheckBoxMenuItem checkbox = (JCheckBoxMenuItem) ev.getSource(); 370 boolean alphaChannel = checkbox.isSelected(); 371 Main.pref.put("wmsplugin.alpha_channel", alphaChannel); 372 373 // clear all resized cached instances and repaint the layer 374 for (int x = 0; x < dax; ++x) { 375 for (int y = 0; y < day; ++y) { 376 GeorefImage img = images[modulo(x, dax)][modulo(y, day)]; 377 img.flushedResizedCachedInstance(); 378 } 379 } 380 mv.repaint(); 381 } 382 } 383 384 public class SaveWmsAction extends AbstractAction { 385 public SaveWmsAction() { 386 super(tr("Save WMS layer to file"), ImageProvider.get("save")); 387 } 388 public void actionPerformed(ActionEvent ev) { 389 File f = SaveActionBase.createAndOpenSaveFileChooser( 390 tr("Save WMS layer"), ".wms"); 391 try { 392 if (f != null) { 393 ObjectOutputStream oos = new ObjectOutputStream( 394 new FileOutputStream(f) 395 ); 396 oos.writeInt(serializeFormatVersion); 397 oos.writeInt(dax); 398 oos.writeInt(day); 399 oos.writeInt(imageSize); 400 oos.writeDouble(pixelPerDegree); 401 oos.writeObject(getName()); 402 oos.writeObject(baseURL); 403 oos.writeObject(images); 404 oos.close(); 405 } 406 } catch (Exception ex) { 407 ex.printStackTrace(System.out); 408 } 409 } 410 } 411 412 public class LoadWmsAction extends AbstractAction { 413 public LoadWmsAction() { 414 super(tr("Load WMS layer from file"), ImageProvider.get("load")); 415 } 416 public void actionPerformed(ActionEvent ev) { 417 JFileChooser fc = DiskAccessAction.createAndOpenFileChooser(true, 418 false, tr("Load WMS layer"), "wms"); 419 if(fc == null) return; 420 File f = fc.getSelectedFile(); 421 if (f == null) return; 422 try 423 { 424 FileInputStream fis = new FileInputStream(f); 425 ObjectInputStream ois = new ObjectInputStream(fis); 426 int sfv = ois.readInt(); 427 if (sfv != serializeFormatVersion) { 428 JOptionPane.showMessageDialog(Main.parent, 429 tr("Unsupported WMS file version; found {0}, expected {1}", sfv, serializeFormatVersion), 430 tr("File Format Error"), 431 JOptionPane.ERROR_MESSAGE); 432 return; 433 } 434 startstop.setSelected(false); 435 dax = ois.readInt(); 436 day = ois.readInt(); 437 imageSize = ois.readInt(); 438 pixelPerDegree = ois.readDouble(); 439 setName((String)ois.readObject()); 440 baseURL = (String) ois.readObject(); 441 images = (GeorefImage[][])ois.readObject(); 442 ois.close(); 443 fis.close(); 444 mv.repaint(); 445 } 446 catch (Exception ex) { 447 // FIXME be more specific 448 ex.printStackTrace(System.out); 449 JOptionPane.showMessageDialog(Main.parent, 450 tr("Error loading file"), 451 tr("Error"), 452 JOptionPane.ERROR_MESSAGE); 453 return; 454 } 455 } 456 } 457 /** 458 * This action will add a WMS layer menu entry with the current WMS layer 459 * URL and name extended by the current resolution. 460 * When using the menu entry again, the WMS cache will be used properly. 461 */ 462 public class BookmarkWmsAction extends AbstractAction { 463 public BookmarkWmsAction() { 464 super(tr("Set WMS Bookmark")); 465 } 466 public void actionPerformed(ActionEvent ev) { 467 int i = 0; 468 while (Main.pref.hasKey("wmsplugin.url."+i+".url")) { 469 i++; 470 } 471 String baseName; 472 // cut old parameter 473 int parameterIndex = getName().indexOf("#PPD="); 474 if (parameterIndex != -1) { 475 baseName = getName().substring(0,parameterIndex); 476 } 477 else { 478 baseName = getName(); 479 } 480 Main.pref.put("wmsplugin.url."+ i +".url",baseURL ); 481 Main.pref.put("wmsplugin.url."+String.valueOf(i)+".name", 482 baseName + "#PPD=" + pixelPerDegree ); 483 WMSPlugin.refreshMenu(); 484 } 485 } 486 487 public void preferenceChanged(PreferenceChangeEvent event) { 488 if (event.getKey().equals("wmsplugin.simultaneousConnections")) { 489 executor.shutdownNow(); 490 executor = Executors.newFixedThreadPool( 491 Main.pref.getInteger("wmsplugin.numThreads", 492 WMSPlugin.simultaneousConnections)); 493 } 494 } 49 protected static final Icon icon = 50 new ImageIcon(Toolkit.getDefaultToolkit().createImage(WMSPlugin.class.getResource("/images/wms_small.png"))); 51 52 private static final BooleanProperty PROP_ALPHA_CHANNEL = new BooleanProperty("wmsplugin.alpha_channel", true); 53 54 public int messageNum = 5; //limit for messages per layer 55 protected MapView mv; 56 protected String resolution; 57 protected boolean stopAfterPaint = false; 58 protected int imageSize = 500; 59 protected int dax = 10; 60 protected int day = 10; 61 protected int minZoom = 3; 62 protected double dx = 0.0; 63 protected double dy = 0.0; 64 protected double pixelPerDegree; 65 protected GeorefImage[][] images = new GeorefImage[dax][day]; 66 protected String baseURL; 67 protected String cookies; 68 protected final int serializeFormatVersion = 5; 69 protected boolean autoDownloadEnabled = true; 70 71 private ExecutorService executor = null; 72 73 /** set to true if this layer uses an invalid base url */ 74 private boolean usesInvalidUrl = false; 75 /** set to true if the user confirmed to use an potentially invalid WMS base url */ 76 private boolean isInvalidUrlConfirmed = false; 77 78 public WMSLayer() { 79 this(tr("Blank Layer"), null, null); 80 initializeImages(); 81 mv = Main.map.mapView; 82 } 83 84 public WMSLayer(String name, String baseURL, String cookies) { 85 super(name); 86 setBackgroundLayer(true); /* set global background variable */ 87 initializeImages(); 88 this.baseURL = baseURL; 89 this.cookies = cookies; 90 WMSGrabber.getProjection(baseURL, true); 91 mv = Main.map.mapView; 92 93 // quick hack to predefine the PixelDensity to reuse the cache 94 int codeIndex = getName().indexOf("#PPD="); 95 if (codeIndex != -1) { 96 pixelPerDegree = Double.valueOf(getName().substring(codeIndex+5)); 97 } else { 98 pixelPerDegree = getPPD(); 99 } 100 resolution = mv.getDist100PixelText(); 101 102 executor = Executors.newFixedThreadPool( 103 Main.pref.getInteger("wmsplugin.numThreads", 104 WMSPlugin.simultaneousConnections)); 105 if (baseURL != null && !baseURL.startsWith("html:") && !WMSGrabber.isUrlWithPatterns(baseURL)) { 106 if (!(baseURL.endsWith("&") || baseURL.endsWith("?"))) { 107 if (!confirmMalformedUrl(baseURL)) { 108 System.out.println(tr("Warning: WMS layer deactivated because of malformed base url ''{0}''", baseURL)); 109 usesInvalidUrl = true; 110 setName(getName() + tr("(deactivated)")); 111 return; 112 } else { 113 isInvalidUrlConfirmed = true; 114 } 115 } 116 } 117 118 Main.pref.addPreferenceChangeListener(this); 119 } 120 121 public boolean hasAutoDownload(){ 122 return autoDownloadEnabled; 123 } 124 125 public double getDx(){ 126 return dx; 127 } 128 129 public double getDy(){ 130 return dy; 131 } 132 133 @Override 134 public void destroy() { 135 try { 136 executor.shutdownNow(); 137 // Might not be initialized, so catch NullPointer as well 138 } catch(Exception x) { 139 x.printStackTrace(); 140 } 141 } 142 143 public double getPPD(){ 144 ProjectionBounds bounds = mv.getProjectionBounds(); 145 return mv.getWidth() / (bounds.max.east() - bounds.min.east()); 146 } 147 148 public void initializeImages() { 149 images = new GeorefImage[dax][day]; 150 for(int x = 0; x<dax; ++x) { 151 for(int y = 0; y<day; ++y) { 152 images[x][y]= new GeorefImage(false); 153 } 154 } 155 } 156 157 @Override public Icon getIcon() { 158 return icon; 159 } 160 161 @Override public String getToolTipText() { 162 if(autoDownloadEnabled) 163 return tr("WMS layer ({0}), automatically downloading in zoom {1}", getName(), resolution); 164 else 165 return tr("WMS layer ({0}), downloading in zoom {1}", getName(), resolution); 166 } 167 168 @Override public boolean isMergable(Layer other) { 169 return false; 170 } 171 172 @Override public void mergeFrom(Layer from) { 173 } 174 175 private ProjectionBounds XYtoBounds (int x, int y) { 176 return new ProjectionBounds( 177 new EastNorth( x * imageSize / pixelPerDegree, y * imageSize / pixelPerDegree), 178 new EastNorth((x + 1) * imageSize / pixelPerDegree, (y + 1) * imageSize / pixelPerDegree)); 179 } 180 181 private int modulo (int a, int b) { 182 return a % b >= 0 ? a%b : a%b+b; 183 } 184 185 private boolean zoomIsTooBig() { 186 //don't download when it's too outzoomed 187 return pixelPerDegree / getPPD() > minZoom; 188 } 189 190 @Override public void paint(Graphics2D g, final MapView mv, Bounds bounds) { 191 if(baseURL == null) return; 192 if (usesInvalidUrl && !isInvalidUrlConfirmed) return; 193 194 if (zoomIsTooBig()) { 195 for(int x = 0; x<dax; ++x) { 196 for(int y = 0; y<day; ++y) { 197 images[modulo(x,dax)][modulo(y,day)].paint(g, mv, dx, dy); 198 } 199 } 200 } else { 201 downloadAndPaintVisible(g, mv, false); 202 } 203 } 204 205 public void displace(double dx, double dy) { 206 this.dx += dx; 207 this.dy += dy; 208 } 209 210 protected boolean confirmMalformedUrl(String url) { 211 if (isInvalidUrlConfirmed) 212 return true; 213 String msg = tr("<html>The base URL<br>" 214 + "''{0}''<br>" 215 + "for this WMS layer does neither end with a ''&'' nor with a ''?''.<br>" 216 + "This is likely to lead to invalid WMS request. You should check your<br>" 217 + "preference settings.<br>" 218 + "Do you want to fetch WMS tiles anyway?", 219 url); 220 String [] options = new String[] { 221 tr("Yes, fetch images"), 222 tr("No, abort") 223 }; 224 int ret = JOptionPane.showOptionDialog( 225 Main.parent, 226 msg, 227 tr("Invalid URL?"), 228 JOptionPane.YES_NO_OPTION, 229 JOptionPane.WARNING_MESSAGE, 230 null, 231 options, options[1] 232 ); 233 switch(ret) { 234 case JOptionPane.YES_OPTION: return true; 235 default: return false; 236 } 237 } 238 239 protected void downloadAndPaintVisible(Graphics g, final MapView mv, 240 boolean real){ 241 if (usesInvalidUrl) 242 return; 243 244 ProjectionBounds bounds = mv.getProjectionBounds(); 245 int bminx= (int)Math.floor (((bounds.min.east() - dx) * pixelPerDegree) / imageSize ); 246 int bminy= (int)Math.floor (((bounds.min.north() - dy) * pixelPerDegree) / imageSize ); 247 int bmaxx= (int)Math.ceil (((bounds.max.east() - dx) * pixelPerDegree) / imageSize ); 248 int bmaxy= (int)Math.ceil (((bounds.max.north() - dy) * pixelPerDegree) / imageSize ); 249 250 for(int x = bminx; x<bmaxx; ++x) { 251 for(int y = bminy; y<bmaxy; ++y){ 252 GeorefImage img = images[modulo(x,dax)][modulo(y,day)]; 253 if((!img.paint(g, mv, dx, dy) || img.infotext) && !img.downloadingStarted){ 254 img.downloadingStarted = true; 255 img.image = null; 256 img.flushedResizedCachedInstance(); 257 Grabber gr = WMSPlugin.getGrabber(XYtoBounds(x,y), img, mv, this); 258 if(!gr.loadFromCache(real)){ 259 gr.setPriority(1); 260 executor.submit(gr); 261 } 262 } 263 } 264 } 265 } 266 267 @Override public void visitBoundingBox(BoundingXYVisitor v) { 268 for(int x = 0; x<dax; ++x) { 269 for(int y = 0; y<day; ++y) 270 if(images[x][y].image!=null){ 271 v.visit(images[x][y].min); 272 v.visit(images[x][y].max); 273 } 274 } 275 } 276 277 @Override public Object getInfoComponent() { 278 return getToolTipText(); 279 } 280 281 @Override public Action[] getMenuEntries() { 282 return new Action[]{ 283 LayerListDialog.getInstance().createActivateLayerAction(this), 284 LayerListDialog.getInstance().createShowHideLayerAction(), 285 LayerListDialog.getInstance().createDeleteLayerAction(), 286 SeparatorLayerAction.INSTANCE, 287 new LoadWmsAction(), 288 new SaveWmsAction(), 289 new BookmarkWmsAction(), 290 SeparatorLayerAction.INSTANCE, 291 new StartStopAction(), 292 new ToggleAlphaAction(), 293 new ChangeResolutionAction(), 294 new ReloadErrorTilesAction(), 295 new DownloadAction(), 296 SeparatorLayerAction.INSTANCE, 297 new LayerListPopup.InfoAction(this) 298 }; 299 } 300 301 public GeorefImage findImage(EastNorth eastNorth) { 302 for(int x = 0; x<dax; ++x) { 303 for(int y = 0; y<day; ++y) 304 if(images[x][y].image!=null && images[x][y].min!=null && images[x][y].max!=null) 305 if(images[x][y].contains(eastNorth, dx, dy)) 306 return images[x][y]; 307 } 308 return null; 309 } 310 311 public class DownloadAction extends AbstractAction { 312 public DownloadAction() { 313 super(tr("Download visible tiles")); 314 } 315 public void actionPerformed(ActionEvent ev) { 316 if (zoomIsTooBig()) { 317 JOptionPane.showMessageDialog( 318 Main.parent, 319 tr("The requested area is too big. Please zoom in a little, or change resolution"), 320 tr("Error"), 321 JOptionPane.ERROR_MESSAGE 322 ); 323 } else { 324 downloadAndPaintVisible(mv.getGraphics(), mv, true); 325 } 326 } 327 } 328 329 public class ChangeResolutionAction extends AbstractAction { 330 public ChangeResolutionAction() { 331 super(tr("Change resolution")); 332 } 333 public void actionPerformed(ActionEvent ev) { 334 initializeImages(); 335 resolution = mv.getDist100PixelText(); 336 pixelPerDegree = getPPD(); 337 mv.repaint(); 338 } 339 } 340 341 public class ReloadErrorTilesAction extends AbstractAction { 342 public ReloadErrorTilesAction() { 343 super(tr("Reload erroneous tiles")); 344 } 345 public void actionPerformed(ActionEvent ev) { 346 // Delete small files, because they're probably blank tiles. 347 // See https://josm.openstreetmap.de/ticket/2307 348 WMSPlugin.cache.customCleanUp(CacheFiles.CLEAN_SMALL_FILES, 4096); 349 350 for (int x = 0; x < dax; ++x) { 351 for (int y = 0; y < day; ++y) { 352 GeorefImage img = images[modulo(x,dax)][modulo(y,day)]; 353 if(img.failed){ 354 img.image = null; 355 img.flushedResizedCachedInstance(); 356 img.downloadingStarted = false; 357 img.failed = false; 358 mv.repaint(); 359 } 360 } 361 } 362 } 363 } 364 365 public class ToggleAlphaAction extends AbstractAction implements LayerAction { 366 public ToggleAlphaAction() { 367 super(tr("Alpha channel")); 368 } 369 public void actionPerformed(ActionEvent ev) { 370 JCheckBoxMenuItem checkbox = (JCheckBoxMenuItem) ev.getSource(); 371 boolean alphaChannel = checkbox.isSelected(); 372 PROP_ALPHA_CHANNEL.put(alphaChannel); 373 374 // clear all resized cached instances and repaint the layer 375 for (int x = 0; x < dax; ++x) { 376 for (int y = 0; y < day; ++y) { 377 GeorefImage img = images[modulo(x, dax)][modulo(y, day)]; 378 img.flushedResizedCachedInstance(); 379 } 380 } 381 mv.repaint(); 382 } 383 public Component createMenuComponent() { 384 JCheckBoxMenuItem item = new JCheckBoxMenuItem(this); 385 item.setSelected(PROP_ALPHA_CHANNEL.get()); 386 return item; 387 } 388 public boolean supportLayers(List<Layer> layers) { 389 return layers.size() == 1 && layers.get(0) instanceof WMSLayer; 390 } 391 } 392 393 public class SaveWmsAction extends AbstractAction { 394 public SaveWmsAction() { 395 super(tr("Save WMS layer to file"), ImageProvider.get("save")); 396 } 397 public void actionPerformed(ActionEvent ev) { 398 File f = SaveActionBase.createAndOpenSaveFileChooser( 399 tr("Save WMS layer"), ".wms"); 400 try { 401 if (f != null) { 402 ObjectOutputStream oos = new ObjectOutputStream( 403 new FileOutputStream(f) 404 ); 405 oos.writeInt(serializeFormatVersion); 406 oos.writeInt(dax); 407 oos.writeInt(day); 408 oos.writeInt(imageSize); 409 oos.writeDouble(pixelPerDegree); 410 oos.writeObject(getName()); 411 oos.writeObject(baseURL); 412 oos.writeObject(images); 413 oos.close(); 414 } 415 } catch (Exception ex) { 416 ex.printStackTrace(System.out); 417 } 418 } 419 } 420 421 public class LoadWmsAction extends AbstractAction { 422 public LoadWmsAction() { 423 super(tr("Load WMS layer from file"), ImageProvider.get("load")); 424 } 425 public void actionPerformed(ActionEvent ev) { 426 JFileChooser fc = DiskAccessAction.createAndOpenFileChooser(true, 427 false, tr("Load WMS layer"), "wms"); 428 if(fc == null) return; 429 File f = fc.getSelectedFile(); 430 if (f == null) return; 431 try 432 { 433 FileInputStream fis = new FileInputStream(f); 434 ObjectInputStream ois = new ObjectInputStream(fis); 435 int sfv = ois.readInt(); 436 if (sfv != serializeFormatVersion) { 437 JOptionPane.showMessageDialog(Main.parent, 438 tr("Unsupported WMS file version; found {0}, expected {1}", sfv, serializeFormatVersion), 439 tr("File Format Error"), 440 JOptionPane.ERROR_MESSAGE); 441 return; 442 } 443 autoDownloadEnabled = false; 444 dax = ois.readInt(); 445 day = ois.readInt(); 446 imageSize = ois.readInt(); 447 pixelPerDegree = ois.readDouble(); 448 setName((String)ois.readObject()); 449 baseURL = (String) ois.readObject(); 450 images = (GeorefImage[][])ois.readObject(); 451 ois.close(); 452 fis.close(); 453 mv.repaint(); 454 } 455 catch (Exception ex) { 456 // FIXME be more specific 457 ex.printStackTrace(System.out); 458 JOptionPane.showMessageDialog(Main.parent, 459 tr("Error loading file"), 460 tr("Error"), 461 JOptionPane.ERROR_MESSAGE); 462 return; 463 } 464 } 465 } 466 /** 467 * This action will add a WMS layer menu entry with the current WMS layer 468 * URL and name extended by the current resolution. 469 * When using the menu entry again, the WMS cache will be used properly. 470 */ 471 public class BookmarkWmsAction extends AbstractAction { 472 public BookmarkWmsAction() { 473 super(tr("Set WMS Bookmark")); 474 } 475 public void actionPerformed(ActionEvent ev) { 476 int i = 0; 477 while (Main.pref.hasKey("wmsplugin.url."+i+".url")) { 478 i++; 479 } 480 String baseName; 481 // cut old parameter 482 int parameterIndex = getName().indexOf("#PPD="); 483 if (parameterIndex != -1) { 484 baseName = getName().substring(0,parameterIndex); 485 } 486 else { 487 baseName = getName(); 488 } 489 Main.pref.put("wmsplugin.url."+ i +".url",baseURL ); 490 Main.pref.put("wmsplugin.url."+String.valueOf(i)+".name", 491 baseName + "#PPD=" + pixelPerDegree ); 492 WMSPlugin.refreshMenu(); 493 } 494 } 495 496 private class StartStopAction extends AbstractAction implements LayerAction { 497 498 public StartStopAction() { 499 super(tr("Automatic downloading")); 500 } 501 502 public Component createMenuComponent() { 503 JCheckBoxMenuItem item = new JCheckBoxMenuItem(this); 504 item.setSelected(autoDownloadEnabled); 505 return item; 506 } 507 508 public boolean supportLayers(List<Layer> layers) { 509 return layers.size() == 1 && layers.get(0) instanceof WMSLayer; 510 } 511 512 public void actionPerformed(ActionEvent e) { 513 autoDownloadEnabled = !autoDownloadEnabled; 514 } 515 516 } 517 518 public void preferenceChanged(PreferenceChangeEvent event) { 519 if (event.getKey().equals("wmsplugin.simultaneousConnections")) { 520 executor.shutdownNow(); 521 executor = Executors.newFixedThreadPool( 522 Main.pref.getInteger("wmsplugin.numThreads", 523 WMSPlugin.simultaneousConnections)); 524 } 525 } 495 526 }
Note:
See TracChangeset
for help on using the changeset viewer.
