/* * JFLAP - Formal Languages and Automata Package * * * Susan H. Rodger * Computer Science Department * Duke University * August 27, 2009 * Copyright (c) 2002-2009 * All rights reserved. * JFLAP is open source software. Please see the LICENSE for terms. * */ package gui; import java.awt.*; import java.net.URL; import javax.swing.*; /** * The ImageDisplayComponent is a single component that displays * an image within itself, and sets its size to match that of the image. * * @author Thomas Finley */ public class ImageDisplayComponent extends JComponent implements Scrollable { /** * Instantiates a new ImageDisplayComponent without an image * at this time. */ public ImageDisplayComponent() { this((Image) null); } /** * Instantiates a new ImageDisplayComponent. * * @param image * the new image for this component */ public ImageDisplayComponent(Image image) { setImage(image); } /** * Instantiates a new ImageDisplayComponent. * * @param url * the new image for this component */ public ImageDisplayComponent(URL url) { setImage(getBaseImage(url)); } /** * Instantiates a new ImageDisplayComponent. * * @param filename * the path where to find the new image for this component */ public ImageDisplayComponent(String filename) { setImage(getBaseImage(filename)); } /** * Returns the image associated with this component. * * @return the image associated with this component */ public Image getImage() { return myImage; } /** * Sets the image associated with this component. * * @param image * the new image for this component * @param origin * the point in the image that is the real "origin" of the image * (should be 0,0 in most cases) */ public void setImage(Image image, Point origin) { myImage = image; myOrigin = origin; trackImage(getImage()); redefineSize(); } /** * Sets the image associated with this component, with (0,0) set as the * origin. * * @param image * the new image for this component */ public void setImage(Image image) { setImage(image, ZERO_ORIGIN); } /** * Returns an untracked unloaded base image based on a path name. * * @param path * the path name */ private Image getBaseImage(String path) { return Toolkit.getDefaultToolkit().getImage(path); } /** * Returns an untracked unloaded base image based on a URL. * * @param url * the url for the image */ private Image getBaseImage(URL url) { return Toolkit.getDefaultToolkit().getImage(url); } /** * When this method returns, the image is sure to be fully loaded. * * @param image * the image to make sure is loaded * @return true if the tracking succeeded, false if it * was interrupted */ private boolean trackImage(Image image) { if (image == null) return true; // Why not... MediaTracker tracker = new MediaTracker(this); tracker.addImage(image, 0); try { tracker.waitForID(0); } catch (InterruptedException e) { return false; } return true; } /** * Based on the image of this component, sets the preferred size. */ private void redefineSize() { Dimension d = new Dimension(1, 1); if (myImage != null) { d = new Dimension(getImage().getWidth(this), getImage().getHeight( this)); } setPreferredSize(d); setBounds(-myOrigin.x, -myOrigin.y, d.width, d.height); } /** * Paints this component. * * @param g * the graphics object to paint upon */ public void paintComponent(Graphics g) { if (myImage == null) return; Rectangle r = getVisibleRect(), r2 = new Rectangle(getPreferredSize()); int offsetx = r.width > r2.width ? (r.width - r2.width) / 2 : 0; int offsety = r.height > r2.height ? (r.height - r2.height) / 2 : 0; r = r.intersection(r2); g.drawImage(myImage, r.x + offsetx, r.y + offsety, r.x + r.width + offsetx, r.y + r.height + offsety, r.x, r.y, r.x + r.width, r.y + r.height, this); } public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { return orientation == SwingConstants.VERTICAL ? visibleRect.height : visibleRect.width; } public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { return 5; } /** * We want this view sized so that it is either larger than or just as wide * as the containing scroll pane. */ public boolean getScrollableTracksViewportWidth() { return getPreferredSize().width < getParent().getSize().width; } /** * We want this view sized so that it is either larger than or just as tall * as the containing scroll pane. */ public boolean getScrollableTracksViewportHeight() { return getPreferredSize().height < getParent().getSize().height; } /** The image to display. */ private Image myImage; /** The origin. */ private Point myOrigin; /** Default (0,0) instance of the origin. */ private static final Point ZERO_ORIGIN = new Point(0, 0); }