Ticket #6137: wiki-image-provider.patch

File wiki-image-provider.patch, 7.0 KB (added by cmuelle8, 15 years ago)

fetch wiki:// style links in ImageProvider to interoperate with osm wiki as an icon source

  • src/org/openstreetmap/josm/tools/ImageProvider.java

     
    1515import java.awt.Toolkit;
    1616import java.awt.Transparency;
    1717import java.awt.image.BufferedImage;
     18import java.io.ByteArrayInputStream;
    1819import java.io.File;
    1920import java.io.IOException;
    2021import java.io.InputStream;
     
    3435import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    3536import org.openstreetmap.josm.io.MirroredInputStream;
    3637import org.openstreetmap.josm.plugins.PluginHandler;
     38import org.xml.sax.Attributes;
     39import org.xml.sax.EntityResolver;
     40import org.xml.sax.InputSource;
     41import org.xml.sax.SAXException;
     42import org.xml.sax.XMLReader;
     43import org.xml.sax.helpers.DefaultHandler;
     44import org.xml.sax.helpers.XMLReaderFactory;
    3745
    3846/**
    3947 * Helperclass to support the application with images.
     
    7987        if (icon == null) {
    8088            String ext = name.indexOf('.') != -1 ? "" : ".png";
    8189            throw new NullPointerException(tr(
    82             "Fatal: failed to locate image ''{0}''. This is a serious configuration problem. JOSM will stop working.",
    83             name+ext));
     90                    "Fatal: failed to locate image ''{0}''. This is a serious configuration problem. JOSM will stop working.",
     91                    name+ext));
    8492        }
    8593        return icon;
    8694    }
     
    119127     *                  around certain issues.
    120128     */
    121129    public static ImageIcon getIfAvailable(Collection<String> dirs, String id, String subdir, String name, File archive, boolean sanitize) {
    122         ImageWrapper iw = getIfAvailableImpl(dirs, id, subdir, name, archive);
    123         if (iw == null)
    124             return null;
    125         if (sanitize && !iw.sanitized) {
    126             iw.img = sanitize(iw.img);
    127             iw.sanitized = true;
     130        ImageIcon icon = new ImageIcon();
     131        if (name.matches("^wiki(:[0-9]+)?://.*")) {
     132            getIfAvailableWikiImpl(icon, dirs, id, name, sanitize);
     133        } else {
     134            ImageWrapper iw = getIfAvailableImpl(dirs, id, subdir, name, archive);
     135            if (iw == null)
     136                return null;
     137            if (sanitize && !iw.sanitized) {
     138                iw.img = sanitize(iw.img);
     139                iw.sanitized = true;
     140            }
     141            icon.setImage(iw.img);
    128142        }
    129         return new ImageIcon(iw.img);
     143        return icon;
    130144    }
    131145
     146    private static void getIfAvailableWikiImpl(final ImageIcon icon, Collection<String> dirs, String id, final String name, final boolean sanitize) {
     147        ImageWrapper iw = cache.get(name);
     148        if (iw != null) {
     149            icon.setImage(iw.img);
     150        } else {
     151            // do not return null, since we will loose control over the icon object else
     152            icon.setImage(getIfAvailable(dirs, id, null, "misc/no_icon.png", null, sanitize).getImage());
     153
     154            Main.worker.execute(new Runnable(){
     155                public void run() {
     156                    try {
     157                        final String base = Main.pref.get("url.openstreetmap-wiki", "http://wiki.openstreetmap.org/wiki/File:");
     158                        final String fn = name.substring(name.lastIndexOf('/') + 1);
     159
     160                        final XMLReader parser = XMLReaderFactory.createXMLReader();
     161                        parser.setContentHandler(new DefaultHandler() {
     162                            @Override
     163                            public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
     164                                System.out.println();
     165                                if (localName.equalsIgnoreCase("img")) {
     166                                    String val = atts.getValue("src");
     167                                    if (val.endsWith(fn)) {
     168                                        try {
     169                                            // mirror just the unscaled image..
     170                                            MirroredInputStream is = new MirroredInputStream(val, new File(Main.pref.getPreferencesDir(),
     171                                            "images").toString());
     172
     173                                            Image img = Toolkit.getDefaultToolkit().createImage(is.getFile().toURI().toURL());
     174                                            int width = 0;
     175                                            try {
     176                                                // this allows definition of custom sizes via the icon-image url
     177                                                width = Integer.parseInt(name.replaceFirst("^wiki:([0-9]+)?.*", "$1"));
     178                                            } catch (Exception e) {
     179                                                // use a default if left empty (e.g. wiki://Signet_Cycleroute.png)
     180                                                width = 20;
     181                                            }
     182                                            img = img.getScaledInstance(width, -1, Image.SCALE_SMOOTH);
     183
     184                                            if (sanitize) {
     185                                                img = sanitize(img);
     186                                            }
     187
     188                                            // ..but put the scaled image into the cache
     189                                            cache.put(name, new ImageWrapper(img, sanitize));
     190
     191                                            // finally, update the icon image that up to now displayed "no_icon"
     192                                            icon.setImage(img);
     193
     194                                            throw new SAXException(); // done parsing, quit early
     195                                        } catch (IOException e) {
     196                                            System.out.println("INFO: fetching " + base + fn + "failed");
     197                                        }
     198                                    }
     199                                }
     200                            }
     201                        });
     202
     203                        parser.setEntityResolver(new EntityResolver() {
     204                            public InputSource resolveEntity (String publicId, String systemId) {
     205                                return new InputSource(new ByteArrayInputStream(new byte[0]));
     206                            }
     207                        });
     208                        parser.parse(new InputSource(new MirroredInputStream(
     209                                base + fn,
     210                                new File(Main.pref.getPreferencesDir(), "images").toString()
     211                        )));
     212                    } catch (Exception e) {
     213                        if (!(e instanceof SAXException)) {
     214                            e.printStackTrace();
     215                        }
     216                    }
     217                }
     218            });
     219        }
     220    }
     221
    132222    private static ImageWrapper getIfAvailableImpl(Collection<String> dirs, String id, String subdir, String name, File archive) {
    133223        if (name == null)
    134224            return null;