Changeset 8095 in josm for trunk/src


Ignore:
Timestamp:
2015-02-22T01:21:48+01:00 (9 years ago)
Author:
stoecker
Message:

see #10684 - add proper overlay interface for ImageProvider()

Location:
trunk/src/org/openstreetmap/josm/tools
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/tools/ImageProvider.java

    r7834 r8095  
    3939import java.util.Hashtable;
    4040import java.util.Iterator;
     41import java.util.LinkedList;
     42import java.util.List;
    4143import java.util.Map;
    4244import java.util.concurrent.ExecutorService;
     
    8082 * How to use:
    8183 *
    82  * <code>ImageIcon icon = new ImageProvider(name).setMaxWidth(24).setMaxHeight(24).get();</code>
     84 * <code>ImageIcon icon = new ImageProvider(name).setMaxSize(ImageSizes.MAP).get();</code>
    8385 * (there are more options, see below)
    8486 *
     
    127129        /** LARGE_ICON_KEY value of on Action */
    128130        LARGEICON,
    129         /** MAP icon */
     131        /** map icon */
    130132        MAP,
    131         /** MAP icon maximum size */
     133        /** map icon maximum size */
    132134        MAPMAX,
    133         /** MENU icon size */
     135        /** menu icon size */
     136        CURSOR,
     137        /** Cursor overlay icon size */
     138        CURSOROVERLAY,
     139        /** Cursor icon size */
    134140        MENU,
    135141    }
     
    147153    public static String PROP_TRANSPARENCY_COLOR = "josm.transparency.color";
    148154
     155    /** directories in which images are searched */
    149156    protected Collection<String> dirs;
     157    /** caching identifier */
    150158    protected String id;
     159    /** sub directory the image can be found in */
    151160    protected String subdir;
     161    /** image file name */
    152162    protected String name;
     163    /** archive file to take image from */
    153164    protected File archive;
     165    /** directory inside the archive */
    154166    protected String inArchiveDir;
     167    /** width of the resulting image, -1 when original image data should be used */
    155168    protected int width = -1;
     169    /** height of the resulting image, -1 when original image data should be used */
    156170    protected int height = -1;
     171    /** maximum width of the resulting image, -1 for no restriction */
    157172    protected int maxWidth = -1;
     173    /** maximum height of the resulting image, -1 for no restriction */
    158174    protected int maxHeight = -1;
     175    /** In case of errors do not throw exception but return <code>null</code> for missing image */
    159176    protected boolean optional;
     177    /** <code>true</code> if warnings should be suppressed */
    160178    protected boolean suppressWarnings;
     179    /** list of class loaders to take images from */
    161180    protected Collection<ClassLoader> additionalClassLoaders;
     181    /** ordered list of overlay images */
     182    protected List<ImageOverlay> overlayInfo = null;
    162183
    163184    private static SVGUniverse svgUniverse;
     
    200221    /**
    201222     * Constructs a new {@code ImageProvider} from a filename in a given directory.
    202      * @param subdir    subdirectory the image lies in
    203      * @param name      the name of the image. If it does not end with '.png' or '.svg',
    204      *                  both extensions are tried.
     223     * @param subdir subdirectory the image lies in
     224     * @param name the name of the image. If it does not end with '.png' or '.svg',
     225     * both extensions are tried.
    205226     */
    206227    public ImageProvider(String subdir, String name) {
     
    211232    /**
    212233     * Constructs a new {@code ImageProvider} from a filename.
    213      * @param name      the name of the image. If it does not end with '.png' or '.svg',
    214      *                  both extensions are tried.
     234     * @param name the name of the image. If it does not end with '.png' or '.svg',
     235     * both extensions are tried.
    215236     */
    216237    public ImageProvider(String name) {
     
    232253     * If name starts with <tt>http://</tt> Id is not used for the cache.
    233254     * (A URL is unique anyway.)
     255     * @param id the id for the cached image
    234256     * @return the current object, for convenience
    235257     */
     
    256278     *
    257279     * (optional)
     280     * @param inArchiveDir path inside the archive
    258281     * @return the current object, for convenience
    259282     */
    260283    public ImageProvider setInArchiveDir(String inArchiveDir) {
    261284        this.inArchiveDir = inArchiveDir;
     285        return this;
     286    }
     287
     288    /**
     289     * Add an overlay over the image. Multiple overlays are possible.
     290     *
     291     * @param overlay overlay image and placement specification
     292     * @return the current object, for convenience
     293     * @since 8095
     294     */
     295    public ImageProvider addOverlay(ImageOverlay overlay) {
     296        if (overlayInfo == null) {
     297            overlayInfo = new LinkedList<ImageOverlay>();
     298        }
     299        overlayInfo.add(overlay);
    262300        return this;
    263301    }
     
    277315        case MENU: /* MENU is SMALLICON - only provided in case of future changes */
    278316        case SMALLICON: sizeval = Main.pref.getInteger("iconsize.smallicon", 16); break;
     317        case CURSOROVERLAY: /* same as cursor - only provided in case of future changes */
     318        case CURSOR: sizeval = Main.pref.getInteger("iconsize.cursor", 32); break;
    279319        default: sizeval = Main.pref.getInteger("iconsize.default", 24); break;
    280320        }
     
    288328     * The width part of the dimension can be -1. Then it will only set the height but
    289329     * keep the aspect ratio. (And the other way around.)
     330     * @param size final dimensions of the image
    290331     * @return the current object, for convenience
    291332     */
     
    300341     *
    301342     * If not specified, the original size of the image is used.
     343     * @param size final dimensions of the image
    302344     * @return the current object, for convenience
    303345     * @since 7687
     
    308350
    309351    /**
     352     * Set image width
     353     * @param width final width of the image
    310354     * @see #setSize
    311355     * @return the current object, for convenience
     
    317361
    318362    /**
     363     * Set image height
     364     * @param height final height of the image
    319365     * @see #setSize
    320366     * @return the current object, for convenience
     
    332378     *
    333379     * 'size' and 'maxSize' are not compatible, you should set only one of them.
     380     * @param maxSize maximum image size
    334381     * @return the current object, for convenience
    335382     */
     
    347394     *
    348395     * 'size' and 'maxSize' are not compatible, you should set only one of them.
     396     * @param size maximum image size
    349397     * @return the current object, for convenience
    350398     * @since 7687
     
    356404    /**
    357405     * Convenience method, see {@link #setMaxSize(Dimension)}.
     406     * @param maxSize maximum image size
    358407     * @return the current object, for convenience
    359408     */
     
    363412
    364413    /**
     414     * Limit the maximum width of the image.
     415     * @param maxWidth maximum image width
    365416     * @see #setMaxSize
    366417     * @return the current object, for convenience
     
    372423
    373424    /**
     425     * Limit the maximum height of the image.
     426     * @param maxHeight maximum image height
    374427     * @see #setMaxSize
    375428     * @return the current object, for convenience
     
    398451     *
    399452     * In combination with setOptional(true);
     453     * @param suppressWarnings if <code>true</code> warnings are suppressed
    400454     * @return the current object, for convenience
    401455     */
     
    407461    /**
    408462     * Add a collection of additional class loaders to search image for.
     463     * @param additionalClassLoaders class loaders to add to the internal list
    409464     * @return the current object, for convenience
    410465     */
     
    430485    /**
    431486     * Execute the image request.
     487     *
    432488     * @return the requested image or null if the request failed
    433489     * @since 7693
     
    446502            }
    447503        }
     504        if (overlayInfo != null) {
     505            ir = new ImageResource(ir, overlayInfo);
     506        }
    448507        return ir;
    449508    }
     
    539598
    540599    /**
     600     * Load an image with a given file name, but do not throw an exception
     601     * when the image cannot be found.
     602     *
    541603     * @param name The icon name (base name with or without '.png' or '.svg' extension)
    542604     * @return the requested image or null if the request failed
     
    554616            "^data:([a-zA-Z]+/[a-zA-Z+]+)?(;base64)?,(.+)$");
    555617
     618    /**
     619     * Internal implementation of the image request.
     620     *
     621     * @param additionalClassLoaders the list of class loaders to use
     622     * @return the requested image or null if the request failed
     623     */
    556624    private ImageResource getIfAvailableImpl(Collection<ClassLoader> additionalClassLoaders) {
    557625        synchronized (cache) {
     
    661729    }
    662730
     731    /**
     732     * Internal implementation of the image request for URL's.
     733     *
     734     * @param url URL of the image
     735     * @param type data type of the image
     736     * @return the requested image or null if the request failed
     737     */
    663738    private static ImageResource getIfAvailableHttp(String url, ImageType type) {
    664739        CachedFile cf = new CachedFile(url)
     
    689764    }
    690765
     766    /**
     767     * Internal implementation of the image request for inline images (<b>data:</b> urls).
     768     *
     769     * @param url the data URL for image extraction
     770     * @return the requested image or null if the request failed
     771     */
    691772    private static ImageResource getIfAvailableDataUrl(String url) {
    692773        try {
     
    737818    }
    738819
     820    /**
     821     * Internal implementation of the image request for wiki images.
     822     *
     823     * @param name image file name
     824     * @param type data type of the image
     825     * @return the requested image or null if the request failed
     826     */
    739827    private static ImageResource getIfAvailableWiki(String name, ImageType type) {
    740828        final Collection<String> defaultBaseUrls = Arrays.asList(
     
    767855    }
    768856
     857    /**
     858     * Internal implementation of the image request for images in Zip archives.
     859     *
     860     * @param fullName image file name
     861     * @param archive the archive to get image from
     862     * @param inArchiveDir directory of the image inside the archive or <code>null</code>
     863     * @param type data type of the image
     864     * @return the requested image or null if the request failed
     865     */
    769866    private static ImageResource getIfAvailableZip(String fullName, File archive, String inArchiveDir, ImageType type) {
    770867        try (ZipFile zipFile = new ZipFile(archive, StandardCharsets.UTF_8)) {
     
    814911    }
    815912
     913    /**
     914     * Internal implementation of the image request for local images.
     915     *
     916     * @param path image file path
     917     * @param type data type of the image
     918     * @return the requested image or null if the request failed
     919     */
    816920    private static ImageResource getIfAvailableLocalURL(URL path, ImageType type) {
    817921        switch (type) {
     
    9291033
    9301034    /**
    931      * Reads the wiki page on a certain file in html format in order to find the real image URL.
     1035     * Return URL of wiki image for an Wiki image described by and Wiki file info page
     1036     *
     1037     * @param base base URL for Wiki image
     1038     * @param fn filename of the Wiki image
     1039     * @return image URL for a Wiki image or null in case of error
    9321040     */
    9331041    private static String getImgUrlFromWikiInfoPage(final String base, final String fn) {
     
    9771085        ImageIcon img = get("cursor", name);
    9781086        if (overlay != null) {
    979             img = overlay(img, ImageProvider.get("cursor/modifier/" + overlay), OverlayPosition.SOUTHEAST);
     1087            img = new ImageProvider("cursor", name).setMaxSize(ImageSizes.CURSOR)
     1088                .addOverlay(new ImageOverlay(new ImageProvider("cursor/modifier/" + overlay)
     1089                    .setMaxSize(ImageSizes.CURSOROVERLAY))).get();
    9801090        }
    9811091        if (GraphicsEnvironment.isHeadless()) {
  • trunk/src/org/openstreetmap/josm/tools/ImageResource.java

    r7937 r8095  
    66import java.awt.image.BufferedImage;
    77import java.util.HashMap;
     8import java.util.List;
    89import java.util.Map;
    910
     
    1819 * It can be backed by a svg or raster image.
    1920 *
    20  * In the first case, 'svg' is not null and in the latter case, 'imgCache' has
    21  * at least one entry for the key DEFAULT_DIMENSION.
     21 * In the first case, <code>svg</code> is not <code>null</code> and in the latter case,
     22 * <code>baseImage</code> is not <code>null</code>.
    2223 * @since 4271
    2324 */
     
    2829     */
    2930    private Map<Dimension, Image> imgCache = new HashMap<>();
     31    /**
     32     * SVG diagram information in case of SVG vector image.
     33     */
    3034    private SVGDiagram svg;
    3135    /**
     
    3337     */
    3438    public static final Dimension DEFAULT_DIMENSION = new Dimension(-1, -1);
     39    /**
     40     * ordered list of overlay images
     41     */
     42    protected List<ImageOverlay> overlayInfo = null;
     43    private Image baseImage = null;
    3544
    3645    /**
     
    4049    public ImageResource(Image img) {
    4150        CheckParameterUtil.ensureParameterNotNull(img);
     51        this.baseImage = img;
    4252        imgCache.put(DEFAULT_DIMENSION, img);
    4353    }
     
    5060        CheckParameterUtil.ensureParameterNotNull(svg);
    5161        this.svg = svg;
     62    }
     63
     64    /**
     65     * Constructs a new {@code ImageResource} from another one and sets overlays.
     66     * @param res the existing resource
     67     * @param overlayInfo the overlay to apply
     68     * @since 8095
     69     */
     70    public ImageResource(ImageResource res, List<ImageOverlay> overlayInfo) {
     71        this.svg = res.svg;
     72        this.baseImage = res.baseImage;
     73        this.overlayInfo = overlayInfo;
    5274    }
    5375
     
    87109        }
    88110        if (svg != null) {
    89             img = ImageProvider.createImageFromSvg(svg, dim);
    90             if (img == null) {
     111            BufferedImage bimg = ImageProvider.createImageFromSvg(svg, dim);
     112            if (bimg == null) {
    91113                return null;
    92114            }
    93             imgCache.put(dim, img);
    94             return new ImageIcon(img);
     115            if (overlayInfo != null) {
     116                for (ImageOverlay o : overlayInfo) {
     117                    o.apply(bimg);
     118                }
     119            }
     120            imgCache.put(dim, bimg);
     121            return new ImageIcon(bimg);
    95122        } else {
    96             Image base = imgCache.get(DEFAULT_DIMENSION);
    97             if (base == null) throw new AssertionError();
     123            if (baseImage == null) throw new AssertionError();
    98124
    99125            int width = dim.width;
    100126            int height = dim.height;
    101             ImageIcon icon = new ImageIcon(base);
    102             if (width == -1) {
     127            ImageIcon icon = new ImageIcon(baseImage);
     128            if (width == -1 && height == -1) {
     129                width = icon.getIconWidth();
     130                height = icon.getIconHeight();
     131            } else if (width == -1) {
    103132                width = Math.max(1, icon.getIconWidth() * height / icon.getIconHeight());
    104133            } else if (height == -1) {
     
    106135            }
    107136            Image i = icon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
    108             img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    109             img.getGraphics().drawImage(i, 0, 0, null);
    110             imgCache.put(dim, img);
    111             return new ImageIcon(img);
     137            BufferedImage bimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
     138            bimg.getGraphics().drawImage(i, 0, 0, null);
     139            if (overlayInfo != null) {
     140                for (ImageOverlay o : overlayInfo) {
     141                    o.apply(bimg);
     142                }
     143            }
     144            imgCache.put(dim, bimg);
     145            return new ImageIcon(bimg);
    112146        }
    113147    }
     
    117151     * to fit maximum dimensions. (Keeps aspect ratio)
    118152     *
    119      * @param maxSize The maximum size. One of the dimensions (widht or height) can be -1,
     153     * @param maxSize The maximum size. One of the dimensions (width or height) can be -1,
    120154     * which means it is not bounded.
    121155     * @return ImageIcon object for the image of this resource, scaled down if needed, according to maxSize
     
    130164            realHeight = svg.getHeight();
    131165        } else {
    132             Image base = imgCache.get(DEFAULT_DIMENSION);
    133             if (base == null) throw new AssertionError();
    134             ImageIcon icon = new ImageIcon(base);
     166            if (baseImage == null) throw new AssertionError();
     167            ImageIcon icon = new ImageIcon(baseImage);
    135168            realWidth = icon.getIconWidth();
    136169            realHeight = icon.getIconHeight();
     
    152185        else if (maxHeight == -1)
    153186            return getImageIcon(new Dimension(maxWidth, -1));
     187        else if (realWidth / maxWidth > realHeight / maxHeight)
     188            return getImageIcon(new Dimension(maxWidth, -1));
    154189        else
    155             if (realWidth / maxWidth > realHeight / maxHeight)
    156                 return getImageIcon(new Dimension(maxWidth, -1));
    157             else
    158                 return getImageIcon(new Dimension(-1, maxHeight));
     190            return getImageIcon(new Dimension(-1, maxHeight));
    159191   }
    160192}
Note: See TracChangeset for help on using the changeset viewer.