001package jmri.util.swing;
002
003import java.awt.Graphics;
004import java.awt.Image;
005import java.awt.image.BufferedImage;
006import javax.swing.JPanel;
007import org.slf4j.Logger;
008import org.slf4j.LoggerFactory;
009
010/**
011 * Common utility to draw a BufferedImage as background behind a JPanel.
012 * Used in jmri.jmrit.catalog, jmri.jmrit.display.palette (via LayoutEditor 'Add Items' menu).
013 *
014 * @author Egbert Broerse copyright (c) 2017
015 */
016public class ImagePanel extends JPanel {
017
018    private BufferedImage back = null;
019    private BufferedImage clip = null;
020
021    /**
022     * Set background images for ImagePanel.
023     * For specifics, 
024     * see the setupPanel() private method in {@link jmri.jmrit.catalog.PreviewDialog}
025     * and the makeButtonPanel() private method in {@link jmri.jmrit.catalog.CatalogPanel}
026     *
027     * @param img Image to load as background
028     */
029    public void setImage(Image img) {
030        if (!(img instanceof BufferedImage)){
031            throw new IllegalArgumentException("Not a Buffered Image: "+img);
032        }
033        back = (BufferedImage) img;
034        repaint();
035        log.debug("DrawPanel ready");
036    }
037
038    @Override
039    protected void paintComponent(Graphics g) {
040        super.paintComponent(g);
041        if (back != null) {
042            int imgWidth;
043            int imgHeight;
044            imgWidth = back.getWidth(this);
045            imgHeight = back.getHeight(this);
046            double frameRatio = (double) getWidth() / (double) getHeight();
047            double imgRatio = (double) imgWidth / (double) imgHeight;
048            log.debug("ratios: fr {} - img {}", frameRatio, imgRatio);
049
050            // maintain squares on non square panels, enlarge to fill full frame
051            if (frameRatio < imgRatio) { // image more oblong than frame
052                imgWidth = (int) (imgHeight * frameRatio); // clip width
053                // keep full imgHeight
054            } else { // image taller than frame
055                // keep full imgWidth
056                imgHeight = (int) (imgWidth / frameRatio); // clip height
057            }
058            // clip part of back image
059            clip = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
060            clip = back.getSubimage(0, 0, Math.min(imgWidth, back.getWidth(this)),
061                    Math.min(imgHeight, back.getHeight(this))); // catch clip size error on change to different pane
062
063            g.drawImage(clip, 0, 0, getWidth(), getHeight(), this);
064        }
065    }
066
067    private static final Logger log = LoggerFactory.getLogger(ImagePanel.class);
068
069}