001package jmri.jmrit.roster;
002
003import java.awt.Graphics;
004import java.awt.geom.AffineTransform;
005import java.awt.image.AffineTransformOp;
006import java.awt.image.BufferedImage;
007import java.util.HashMap;
008
009import javax.swing.ImageIcon;
010
011import jmri.InstanceManagerAutoDefault;
012
013/**
014 * Generate and cache icons at a given height. A managed instance will generate
015 * icons for a default height, while unmanaged instances can be created to
016 * generate icons at different heights.
017 * <hr>
018 * This file is part of JMRI.
019 * <p>
020 * JMRI is free software; you can redistribute it and/or modify it under the
021 * terms of version 2 of the GNU General Public License as published by the Free
022 * Software Foundation. See the "COPYING" file for a copy of this license.
023 * <p>
024 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
025 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
026 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
027 *
028 * @author Lionel Jeanson Copyright (C) 2009
029 */
030public class RosterIconFactory implements InstanceManagerAutoDefault {
031
032    private final int iconHeight;
033    HashMap<String, ImageIcon> icons = new HashMap<>();
034
035    public RosterIconFactory(int h) {
036        iconHeight = h;
037    }
038
039    public RosterIconFactory() {
040        iconHeight = 19; // OS X, because of Apple look'n feel constraints, ComboBox cannot be higher than this 19pixels
041    }
042    
043    public int getIconFactoryHeight() {
044        return iconHeight;
045    }
046
047    public ImageIcon getIcon(String id) {
048        if (id == null) {
049            return null;
050        }
051        RosterEntry re = Roster.getDefault().entryFromTitle(id);
052        if (re == null) {
053            return null;
054        }
055        return getIcon(re);
056    }
057    
058    public ImageIcon getReversedIcon(String id) {
059        if (id == null) {
060            return null;
061        }
062        RosterEntry re = Roster.getDefault().entryFromTitle(id);
063        if (re == null) {
064            return null;
065        }
066        return getReversedIcon(re);
067    }
068
069    public ImageIcon getIcon(RosterEntry re) {
070        if ((re == null) || (re.getIconPath() == null)) {
071            return null;
072        }
073
074        ImageIcon icon = icons.get(re.getIconPath());
075        if (icon == null) {
076            icon = new ImageIcon(re.getIconPath(), re.getId());
077            icon.setImage(icon.getImage().getScaledInstance(-1, iconHeight, java.awt.Image.SCALE_FAST));
078            icons.put(re.getIconPath(), icon);
079        }
080        return icon;
081    }
082    
083    public ImageIcon getReversedIcon(RosterEntry re) {
084        if ((re == null) || (re.getIconPath() == null)) {
085            return null;
086        }
087
088        ImageIcon revicon = icons.get("rev_"+re.getIconPath());
089        if (revicon == null) {
090            ImageIcon icon = getIcon(re);
091            if (icon==null) {
092                return null;
093            }
094            // Flip the image horizontally
095            AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
096            tx.translate(-icon.getImage().getWidth(null), 0);
097            AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
098            BufferedImage bi = new BufferedImage( icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
099            Graphics g = bi.createGraphics();
100            icon.paintIcon(null, g, 0,0);
101            g.dispose();            
102            revicon = new ImageIcon();
103            revicon.setImage(op.filter( bi, null).getScaledInstance(-1, iconHeight, java.awt.Image.SCALE_FAST));
104            icons.put("rev_"+re.getIconPath(), revicon);
105        }
106        return revicon;
107    }
108}