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}