/* * Proj1ImageView.java * * CMSC 498B, Spring 2002, Project #1 * -- A Java program that displays all GIF/JPEG images found in a directory along with their names. * * Bongshin Lee, February 2002 */ import java.awt.*; import java.awt.event.*; import java.awt.font.*; import java.awt.geom.*; import java.io.*; import java.util.*; import javax.swing.*; public class Proj1ImageView extends JFrame { JScrollBar vScroll; // vertical scrollbar ImageComponent iComponent; // a component to draw images // default box & pad size static int boxSize = 150; static int padSize = 15; public static void main(String[] args) { if (args.length < 1) { System.out.println("Usage: java Proj1ImageView imageDir [boxSize] [padSize]"); } else { // parse input parameters if (args.length > 1) { boxSize = Integer.parseInt(args[1]); if (args.length > 2) padSize = Integer.parseInt(args[2]); } File dir = new File(args[0]); // check whether the specified directory exists if (dir.exists()) { Proj1ImageView iView = new Proj1ImageView(dir); } else { System.out.println(args[0] + " is an invalid directory."); } } } public Proj1ImageView(File dir) { setTitle("CMSC 498B Project #1 - Proj1ImageView"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); iComponent = new ImageComponent(this, dir, boxSize, padSize); iComponent.setPreferredSize(new Dimension(500, 500)); // add a ComponentListener to Proj1ImageView (JFrame) ComponentEventHandler handler = new ComponentEventHandler(); handler.setImageComponent(iComponent); addComponentListener(handler); vScroll = new JScrollBar(JScrollBar.VERTICAL); // add a AdjustmentListener to the vertical scrollbar vScroll.addAdjustmentListener(new AdjustmentListener() { public void adjustmentValueChanged(AdjustmentEvent ae) { // the value of scrollbar has changed iComponent.setScrollValue(vScroll.getValue()); iComponent.repaint(new Rectangle(iComponent.getWidth(), iComponent.getHeight())); } }); // add image component & scrollbar to the frame getContentPane().add(iComponent); getContentPane().add(vScroll, BorderLayout.EAST); pack(); setVisible(true); } // show/hide vertical scrollbar public void showVScroll(boolean show) { if (show) { getContentPane().add(vScroll, BorderLayout.EAST); } else { getContentPane().remove(vScroll); } } // set the values for vertical scrollbar public void setScrollValues(int extent, int maximum) { vScroll.setValues(0, extent, 0, maximum); vScroll.setBlockIncrement(extent); } } class ImageComponent extends JComponent { Proj1ImageView parent; // container of this ImageComponent Vector images = new Vector(); // stores all images Vector names = new Vector(); // stores all image file names Font font = new Font("Helvetica", Font.PLAIN, 10); int perRow; // # of images per row int actualHeight; // height to display all images int scrollValue = 0; // current position of the vertical scrollbar int boxSize, padSize; // box & pad size int fontHeight; // height of the font boolean vScrollShow = true; // visibility of the vertical scrollbar public ImageComponent(Proj1ImageView iv, File baseDir, int box, int pad) { parent = iv; // remember the container of this ImageComponent boxSize = box + 6; // boxSize includes the gray border padSize = pad; // search all images in the specified directory searchImages(baseDir); } public void setScrollValue(int sValue) { scrollValue = sValue; } // calculate height to display all images // based on the # of images and current width public void calcHeight() { Graphics2D g2 = (Graphics2D)getGraphics(); g2.setFont(font); fontHeight = g2.getFontMetrics().getHeight(); int width = getWidth(); perRow = width / (boxSize + 2 * padSize); // # of images per row if (perRow == 0) perRow = 1; // min # of images per row is 1 int rows = images.size() / perRow; // # of rows to display all images if (images.size() == rows * perRow) { actualHeight = rows * (boxSize + 2 * padSize + fontHeight); } else { actualHeight = (rows + 1) * (boxSize + 2 * padSize + fontHeight); } } public void reLayout() { calcHeight(); if (actualHeight > getHeight()) { if (!vScrollShow) { // if scrollbar is needed but now shown before // we have to show scrollbar parent.showVScroll(true); vScrollShow = true; calcHeight(); } } else { if (vScrollShow) { // if scrollbar is not needed but shown before // we have to hide scrollbar parent.showVScroll(false); vScrollShow = false; calcHeight(); } } // set values for vertical scrollbar parent.setScrollValues(getHeight(), actualHeight); } // search all image files in a directory private void searchImages(File baseDir) { File[] files; files = baseDir.listFiles(); if (files == null) return; // if directory is empty, return for (int i = 0; i < files.length; i++) { // check the file is image file based on the extension String lowerName = files[i].getName().toLowerCase(); if (lowerName.endsWith(".jpg") || lowerName.endsWith(".gif") || lowerName.endsWith(".jpeg")) { if (loadImage(files[i].getAbsolutePath())) { names.add(files[i].getName()); } } } } private boolean loadImage(String fileName) { Image image = Toolkit.getDefaultToolkit().createImage(fileName); MediaTracker mt = new MediaTracker(this); mt.addImage(image, 0); try { mt.waitForID(0); images.add(image); // store the loaded image in the images vector return true; } catch (InterruptedException e) { System.out.println("Couldn't load image: " + fileName); return false; } } public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D)g; // white background g2.setColor(Color.white); g2.fillRect(0, 0, getWidth(), getHeight()); if (images.size() == 0) return; // we don't have anything to draw // the minimum row number to be shown in current viewport int startRow = scrollValue / (boxSize + 2 * padSize + fontHeight); // the maximum row number to be shown in current viewport int endRow = (scrollValue + getHeight()) / (boxSize + 2 * padSize + fontHeight); int n = startRow * perRow; // the index of image to be shown first for (int i = startRow; i < endRow + 1; i++) { for (int j = 0; j < perRow; j++) { // draw 3pixel lightgray border using rectangle g2.setColor(Color.lightGray); int left = j * (boxSize + 2 * padSize) + padSize; int right = left + boxSize; int top = i * (boxSize + 2 * padSize + fontHeight) + padSize - scrollValue; int bottom = top + boxSize; g2.fillRect(left, top, boxSize, 3); // upper line g2.fillRect(left, top, 3, boxSize); // left line g2.fillRect(right - 3, top, 3, boxSize); // right line g2.fillRect(left, bottom - 3, boxSize, 3); // bottom line Image img = (Image)images.elementAt(n); // calculate scaled image size int width = boxSize - 6; int height = boxSize - 6; int imgWidth = img.getWidth(this); int imgHeight = img.getHeight(this); double ratio = (double)imgWidth / imgHeight; if (ratio > 1) { height = width * imgHeight / imgWidth; // wide and short } else if (ratio < 1) { width = height * imgWidth / imgHeight; // thin and long } // draw a scaled image at the center of the box g2.drawImage(img, left + (boxSize - width) / 2, top + (boxSize - height) / 2, width, height, this); // draw the file name centered, immediately below the gray bordered box String fileName = (String)names.elementAt(n++); drawFileName(g2, fileName, left, bottom); if (n == images.size()) return; // end of images } } } private void drawFileName(Graphics2D g2, String fileName, int left, int bottom) { g2.setColor(Color.black); FontRenderContext frc = g2.getFontRenderContext(); Rectangle2D bounds = g2.getFont().getStringBounds(fileName, frc); LineMetrics lm = g2.getFont().getLineMetrics(fileName, frc); float fWidth = (float)bounds.getWidth(); // width of the file name string // get assent of the file string to compute base line float fHeight = (float)lm.getAscent(); g2.drawString(fileName, left + (boxSize - fWidth) / 2, bottom + fHeight); } } class ComponentEventHandler implements ComponentListener { ImageComponent iComponent; public void setImageComponent(ImageComponent ic) { iComponent = ic; } public void componentResized(ComponentEvent ce) { // the size of frame has changed // relayout & redraw images on ImageComponent iComponent.reLayout(); iComponent.revalidate(); } public void componentMoved(ComponentEvent ce) { } public void componentShown(ComponentEvent ce) { } public void componentHidden(ComponentEvent ce) { } }