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 can not be null
078             if (icon==null)
079             return null;
080             */
081            icon.setImage(icon.getImage().getScaledInstance(-1, iconHeight, java.awt.Image.SCALE_FAST));
082            icons.put(re.getIconPath(), icon);
083        }
084        return icon;
085    }
086    
087    public ImageIcon getReversedIcon(RosterEntry re) {
088        if ((re == null) || (re.getIconPath() == null)) {
089            return null;
090        }
091
092        ImageIcon revicon = icons.get("rev_"+re.getIconPath());
093        if (revicon == null) {
094            ImageIcon icon = getIcon(re);
095            if (icon==null) {
096                return null;
097            }
098            // Flip the image horizontally
099            AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
100            tx.translate(-icon.getImage().getWidth(null), 0);
101            AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
102            BufferedImage bi = new BufferedImage( icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
103            Graphics g = bi.createGraphics();
104            icon.paintIcon(null, g, 0,0);
105            g.dispose();            
106            revicon = new ImageIcon();
107            revicon.setImage(op.filter( bi, null).getScaledInstance(-1, iconHeight, java.awt.Image.SCALE_FAST));
108            icons.put("rev_"+re.getIconPath(), revicon);
109        }
110        return revicon;
111    }
112}