package edu.princeton.cs.algs4.growingtree.framework; /* * @(#)DrawingJPanel.java * * Last Modified: 9/15/01 */ import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; import java.beans.*; /** * A specific type of JPanel for the dedicated purpose of drawing some sort of node or tree onto * the panel. Everything within the class is implemented except the draw method. This * must be implemented by extending class to activate the drawing. * *

* @author Corey Sanders * @version 1.3 9/15/01 */ public class DrawingJPanel extends JPanel implements ComponentListener{ /** * Image of the Panel for drawing the tree onto. (Used so redrawing is not necessary. */ private BufferedImage drawTreeImage; /** * Graphics associate with the image of the Panel. (Used so redrawing is not necessary. */ private Graphics2D drawTreeGraphics; /** * Boolean flag whether the tree needs to be redrawn. */ private boolean drawTree = true; /** * Rectangle which represents the drawing area of the panel. */ private Rectangle drawingArea; /** * Flag whether the tree is shown or not. */ private boolean componentShown = false; /** * Sole Constructor for the JPanel that draws. The super constructor is called. Additionally, the * default background is set as white and the comoponent adds it to listen to itself. */ public DrawingJPanel() { super(); setBackground(Color.white); this.addComponentListener(this); } /** ******************** * Accesssor methods* ******************** */ /** * Gets the draw Tree Image for this panel. * * @return BufferedImage set as the drawing image. */ public BufferedImage getDrawTreeImage() { return drawTreeImage; } /** * Gets the draw Tree Graphics for this panel. * * @return Graphics2D set as the drawing graphics. */ public Graphics2D getDrawTreeGraphics() { return drawTreeGraphics; } /** * Gets whether the tree needs to be redrawn. * * @param true if the tree needs drawing. */ public boolean isDrawTree() { return drawTree; } /** * Sets whether the tree is shown or not. * * @return boolean flag as to whether the tree is shown. */ public boolean isComponentShown() { return componentShown; } /** * Gets the drawing area for this panel. * * @return Rectangle2D rectangle set as the drawing area. */ public Rectangle2D getDrawingArea() { return drawingArea; } /** ******************* * Mutator methods * ******************* */ /** * Sets the draw Tree Image for this panel. * * @param drawTreeImage BufferedImage set as the drawing image. */ protected void setDrawTreeImage(BufferedImage drawTreeImage) { this.drawTreeImage = drawTreeImage; } /** * Sets the draw Tree graphics for this panel. * * @param drawTreeImage Graphics2D set as the drawing graphics. */ protected void setDrawTreeGraphics(Graphics2D drawTreeGraphics) { this.drawTreeGraphics = drawTreeGraphics; } /** * Sets whether the tree needs drawing. * * @param animating boolean flag as to whether the tree needs drawing. */ public void setDrawTree(boolean drawTree) { this.drawTree = drawTree; } /** * Sets whether the tree is shown or not. * * @param componentShown boolean flag as to whether the tree is shown. */ public void setComponentShown(boolean componentShown) { this.componentShown = componentShown; } /** * Sets the drawing area for this panel. Keeps the Rectangle for usage in drawing. * * @param drawingArea Rectangle2D rectangle set as the drawing area. */ protected void setDrawingArea(Rectangle drawingArea) { this.drawingArea = drawingArea; } /** ******************* * Drawing methods * ******************* */ /** * Method actually called to complete the drawing of the panel. WIthin this class, the method is * empty. It must be overiden for anything to be drawn in the call. */ protected void draw() { } /** * Makes the drawing image. An image is used because the tree might not always * need to be redrawn, saving time. */ protected void makeDrawTreeImage() { Dimension dim = getSize(); int w = dim.width; int h = dim.height; if (w <= 0 || h <= 0) { return; } setDrawingArea(new Rectangle(dim)); setDrawTreeImage((BufferedImage)createImage(w,h)); setDrawTreeGraphics((Graphics2D)getDrawTreeImage().createGraphics()); makeDrawTreeGraphics(); } /** * Makes the drawing graphics. Uses the image made from makeDrawTreeImage. */ protected void makeDrawTreeGraphics() { if (getDrawTreeGraphics() == null) { return; } Dimension dim = getSize(); int w = dim.width; int h = dim.height; getDrawTreeGraphics().setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); getDrawTreeGraphics().setClip(0, 0, w, h); setDrawTree(true); repaint(); } /** * Draws onto the defined draw tree graphic. * This method is the only call to the draw method. */ protected void drawTree() { if (getDrawTreeGraphics() == null) { return; } getDrawTreeGraphics().setBackground(getBackground()); getDrawTreeGraphics().clearRect(0,0,(int)drawingArea.getWidth(), (int)drawingArea.getHeight()); draw(); setDrawTree(false); } /** * Draws the JPanel. This overides the paintComponent of JPanel, * to draw the appropriate image and redraw the graphic if necessary. The drawing is double buffered automatically, but * the image is only modified on resizing and a change of node. Therefore, dragging, hiding * and so forth, do not change the image. * * @param g Graphics used to draw to the component. */ public void paintComponent(Graphics g) { // Cast to 2D Graphics2D g2 = (Graphics2D)g; Dimension dim = getSize(); int w = dim.width; int h = dim.height; if (isDrawTree()) { drawTree(); } // Set Graphics clip g2.setClip(0,0,w,h); // Draws the image g2.drawImage(getDrawTreeImage(), 0, 0, this); } /****************************************/ /* Component Listener Interface Methods */ /****************************************/ /** * Called when the component is hidden. Sets the componentShown as false. * * @param e ComponentEvent not used for this particular listening. * */ public void componentHidden(ComponentEvent e) { setComponentShown(false); } /** * Called when the component is Moved. No action occurs here. * * @param e ComponentEvent not used for this particular listening. * */ public void componentMoved(ComponentEvent e) { } /** * Called when the component is Shown. Sets the componentShown as true. * * @param e ComponentEvent not used for this particular listening. * */ public void componentShown(ComponentEvent e) { setComponentShown(true); } /** * Called when the component is Resized. The image is modified according * to the resizing of the Component. * * @param e ComponentEvent not used for this particular listening. */ public void componentResized(ComponentEvent e) { // make the image if it is null if(getDrawTreeImage() == null) { makeDrawTreeImage(); return; } Dimension dim = getSize(); int w = dim.width; int h = dim.height; // If the image is too small. if ((w > getDrawTreeImage().getWidth()) || (h > getDrawTreeImage().getHeight())) { // Remove old image getDrawTreeImage().flush(); // Make a new image makeDrawTreeImage(); } else { // Reset drawing area setDrawingArea(new Rectangle(dim)); // Reset Graphics makeDrawTreeGraphics(); } // Reset drawing of tree setDrawTree(true); repaint(); } }