Ticket #7563: wms_auto_zoom.patch

File wms_auto_zoom.patch, 8.0 KB (added by xeen, 13 years ago)
  • src/org/openstreetmap/josm/gui/layer/WMSLayer.java

     
    2020import java.io.ObjectInput;
    2121import java.io.ObjectOutput;
    2222import java.util.ArrayList;
     23import java.util.Arrays;
    2324import java.util.Collections;
    2425import java.util.HashSet;
    2526import java.util.Iterator;
     
    106107    public static final IntegerProperty PROP_IMAGE_SIZE = new IntegerProperty("imagery.wms.imageSize", 500);
    107108
    108109    public int messageNum = 5; //limit for messages per layer
    109     protected String resolution;
     110    protected double resolution;
     111    protected String resolutionText;
    110112    protected int imageSize;
    111113    protected int dax = 10;
    112114    protected int day = 10;
     
    116118    protected GeorefImage[][] images;
    117119    protected final int serializeFormatVersion = 5;
    118120    protected boolean autoDownloadEnabled = true;
     121    protected boolean autoResolutionEnabled = true;
    119122    protected boolean settingsChanged;
    120123    public WmsCache cache;
    121124    private AttributionSupport attribution = new AttributionSupport();
     
    179182                cache.loadIndex();
    180183            }
    181184        }
    182         if(this.info.getPixelPerDegree() == 0.0) {
    183             this.info.setPixelPerDegree(getPPD());
    184         }
    185         resolution = Main.map.mapView.getDist100PixelText();
    186185
     186        // if automatic resolution is enabled, ensure that the first zoom level
     187        // is already snapped. Otherwise it may load tiles that will never get
     188        // used again when zooming.
     189        updateResolutionSetting(this, autoResolutionEnabled);
     190
    187191        final MouseAdapter adapter = new MouseAdapter() {
    188192            @Override
    189193            public void mouseClicked(MouseEvent e) {
     
    286290
    287291    @Override public String getToolTipText() {
    288292        if(autoDownloadEnabled)
    289             return tr("WMS layer ({0}), automatically downloading in zoom {1}", getName(), resolution);
     293            return tr("WMS layer ({0}), automatically downloading in zoom {1}", getName(), resolutionText);
    290294        else
    291             return tr("WMS layer ({0}), downloading in zoom {1}", getName(), resolution);
     295            return tr("WMS layer ({0}), downloading in zoom {1}", getName(), resolutionText);
    292296    }
    293297
    294298    private int modulo (int a, int b) {
     
    300304        return info.getPixelPerDegree() / getPPD() > minZoom;
    301305    }
    302306
     307
     308    private ArrayList<Double> usedResos = new ArrayList<Double>();// FIXME: debug
     309
     310
    303311    @Override public void paint(Graphics2D g, final MapView mv, Bounds b) {
    304312        if(info.getUrl() == null || (usesInvalidUrl && !isInvalidUrlConfirmed)) return;
    305313
     314        if (autoResolutionEnabled) {
     315            double pixelScaling = mv.getDist100Pixel() / resolution;
     316            System.out.println("pixelSacling: " + pixelScaling + "     reso is: " + resolution); // FIXME: debug
     317            if (pixelScaling > 2 || pixelScaling < 0.7) {
     318                System.out.println("CHANING RESO ---------- "); // FIXME: debug
     319                Collections.sort(usedResos);
     320                System.out.println(Arrays.toString(usedResos.toArray()));
     321                changeResolution(this, true);
     322            }
     323        }
     324        // FIXME: debug
     325        if(!usedResos.contains(this.resolution)) {
     326            usedResos.add(this.resolution);
     327        }
     328
    306329        settingsChanged = false;
    307330
    308331        ProjectionBounds bounds = mv.getProjectionBounds();
     
    477500                new LayerSaveAsAction(this),
    478501                new BookmarkWmsAction(),
    479502                SeparatorLayerAction.INSTANCE,
    480                 new ZoomToNativeResolution(),
    481503                new StartStopAction(),
    482504                new ToggleAlphaAction(),
     505                new ToggleAutoResolutionAction(),
    483506                new ChangeResolutionAction(),
     507                new ZoomToNativeResolution(),
    484508                new ReloadErrorTilesAction(),
    485509                new DownloadAction(),
    486510                SeparatorLayerAction.INSTANCE,
     
    666690        }
    667691    }
    668692
    669     public static class ChangeResolutionAction extends AbstractAction implements LayerAction {
    670         public ChangeResolutionAction() {
    671             super(tr("Change resolution"));
     693    /**
     694     * Updates the given layer’s resolution settings to the current zoom level. Does
     695     * not update existing tiles, only new ones will be subject to the new settings.
     696     *
     697     * @param layer
     698     * @param round  Set to true if the resolution should snap to certain values instead of
     699     *               matching the current zoom level perfectly
     700     */
     701    private static void updateResolutionSetting(WMSLayer layer, boolean round) {
     702        if(round) {
     703            layer.resolution = Math.round(Main.map.mapView.getDist100Pixel());
     704            layer.resolutionText = MapView.getDistText(layer.resolution);
     705        } else {
     706            layer.resolution = Main.map.mapView.getDist100Pixel();
     707            layer.resolutionText = Main.map.mapView.getDist100PixelText();
    672708        }
     709        layer.info.setPixelPerDegree(layer.getPPD());
     710    }
    673711
    674         private void changeResolution(WMSLayer layer) {
    675             layer.resolution = Main.map.mapView.getDist100PixelText();
    676             layer.info.setPixelPerDegree(layer.getPPD());
    677             layer.settingsChanged = true;
     712    /**
     713     * Updates the given layer’s resolution settings to the current zoom level and
     714     * updates existing tiles. If round is true, tiles will be updated gradually, if
     715     * false they will be removed instantly (and redrawn only after the new resolution
     716     * image has been loaded).
     717     * @param layer
     718     * @param round  Set to true if the resolution should snap to certain values instead of
     719     *               matching the current zoom level perfectly
     720     */
     721    private static void changeResolution(WMSLayer layer, boolean round) {
     722        updateResolutionSetting(layer, round);
     723
     724        layer.settingsChanged = true;
     725
     726        // Don’t move tiles off screen when the resolution is rounded. This
     727        // prevents some flickering when zooming with auto-resolution enabled
     728        // and instead gradually updates each tile.
     729        if(!round) {
    678730            for(int x = 0; x<layer.dax; ++x) {
    679731                for(int y = 0; y<layer.day; ++y) {
    680732                    layer.images[x][y].changePosition(-1, -1);
    681733                }
    682734            }
    683735        }
     736    }
    684737
     738
     739    public static class ChangeResolutionAction extends AbstractAction implements LayerAction {
     740        public ChangeResolutionAction() {
     741            super(tr("Change resolution"));
     742        }
     743
    685744        @Override
    686745        public void actionPerformed(ActionEvent ev) {
    687746
     
    690749
    691750            List<Layer> layers = LayerListDialog.getInstance().getModel().getSelectedLayers();
    692751            for (Layer l: layers) {
    693                 changeResolution((WMSLayer) l);
     752                changeResolution((WMSLayer) l, false);
    694753            }
    695754            Main.map.mapView.repaint();
    696755        }
     
    767826        }
    768827    }
    769828
     829
     830    public class ToggleAutoResolutionAction extends AbstractAction implements LayerAction {
     831        public ToggleAutoResolutionAction() {
     832            super(tr("Automatically change resolution"));
     833        }
     834
     835        @Override
     836        public void actionPerformed(ActionEvent ev) {
     837            JCheckBoxMenuItem checkbox = (JCheckBoxMenuItem) ev.getSource();
     838            autoResolutionEnabled = checkbox.isSelected();
     839        }
     840
     841        @Override
     842        public Component createMenuComponent() {
     843            JCheckBoxMenuItem item = new JCheckBoxMenuItem(this);
     844            item.setSelected(autoResolutionEnabled);
     845            return item;
     846        }
     847
     848        @Override
     849        public boolean supportLayers(List<Layer> layers) {
     850            return layers.size() == 1 && layers.get(0) instanceof WMSLayer;
     851        }
     852    }
     853
    770854    /**
    771855     * This action will add a WMS layer menu entry with the current WMS layer
    772856     * URL and name extended by the current resolution.