import java.awt.*; import java.applet.*; import java.io.*; import java.util.*; /** * DrawingPanel is the graphical panel attached to the * animation frame AlgAnimFrame. It contains the methods * to draw objects for the animation algorithm or instances of another * classes, which contain the drawing methods. *

* This class is TO BE MODIFIED/COMPLETED, mainly in the * paint(Graphics) method to include the statements * draw objects corresponding to the particular animation algorithm. * Additional methods are also required to perform the animation of the * particular algorithm. * * @see AlgAnimFrame#drawingPanel */ public class DrawingPanel extends Panel { /** * Height of the drawing panel set during the initialization of the * class or after each invoke of the repaint() method. */ public int panel_height = 100; /** * Width of the drawing panel set during the initialization of the * class or after each invoke of the repaint() method. */ public int panel_width = 100; /** * Inset of the drawing panel, i.e. the edge pads on the four sides of * of the panel that are not to be drawn. */ public int offset = 10; int pref_height = 200; int pref_width = 250; int delayDuration = 200; FontMetrics fm; Dimension offscreensize = null; Image offscreen = null; Graphics offGraphics = null; TablePanel table; Histogram hashStats, collisionStats; /** * Font objects initialized during the class initialization, which * can be readily used during the animation. Initialization fonts * on the fly during the animation will slow down the screen update * significantly (especially on SGI Irix platform). Therefore, * this fonts are only initialized during the creation of the class * and used by any other classes that require them to reduce * font initialization overhead. */ public Font bigFont; /** * Font objects initialized during the class initialization, which * can be readily used during the animation. * @see DrawingPanel#bigFont */ public Font smallFont, tinyFont, hugeFont, fixFont; Color darkGreen = new Color(0, 140, 0); ComBox tableLabel; ComBox fileLabel; Color[] tone; /** * Creates a panel with white background and initializes the fonts * to be used during the animation. * @see DrawingPanel#bigFont * @see DrawingPanel#smallFont * @see DrawingPanel#tinyFont * @see DrawingPanel#hugeFont * @see DrawingPanel#fixFont */ public DrawingPanel() { tone = new Color[50]; for (int i = 0; i < 30; i++) tone[i] = new Color(190 + i*2, 190 + i*2, 190 + i*2); smallFont = new Font("Dialog", Font.PLAIN, 10); fm = this.getFontMetrics(smallFont); bigFont = new Font("Dialog", Font.PLAIN, 12); hugeFont = new Font("Dialog", Font.PLAIN, 14); fixFont = new Font("Courier", Font.PLAIN, 12); tinyFont = new Font("Dialog", Font.PLAIN, 8); setBackground(Color.white); panel_height = size().height; panel_width = size().width; tableLabel = new ComBox(0, 0, "Hash Table Contents", Color.white, Color.blue, fixFont); fileLabel = new ComBox(0, 0, "FILE", Color.yellow, Color.black, fixFont); setLayout(null); table = new TablePanel(300); table.setDrawingPanel(this); table.reshape(0, 0, 270, 133); add(table); hashStats = new Histogram(); hashStats.setTitle("Hashing Freq Stats"); hashStats.setXLabel("number of hashes"); hashStats.setYLabel("number of keys"); hashStats.setYMax(40); hashStats.setYStep(10); hashStats.setXMax(10); hashStats.setXStep(5); hashStats.reshape(10, 10, 260, 330); add(hashStats); collisionStats = new Histogram(); collisionStats.setTitle("Collision Stats"); collisionStats.setXLabel("k(th) items"); collisionStats.setYLabel("number of collisions during insertions"); collisionStats.setYMax(10); collisionStats.setYStep(5); collisionStats.setXMax(20); collisionStats.setXStep(10); collisionStats.reshape(500, 255, 300, 180); add(collisionStats); } // DrawingPanel() public void incHashStat(int i) { hashStats.incValueX(i); hashStats.repaint(); } public void setColStat(int x, int y) { collisionStats.setValueXY(x, y); collisionStats.repaint(); } /** * Causing a short delay of 1/3 of the normal delay duration. * This method is normally used during debugging to speed up * the achievement of certain system state. */ public void shortDelay() { try { Thread.sleep(delayDuration/3); } catch (InterruptedException e) {} } /** * Invoke a delay for a certain duration specified by * setDelay(int). * @see DrawingPanel#setDelay */ public void delay() { if (noAnim) { shortDelay(); return; } try { Thread.sleep(delayDuration); } catch (InterruptedException e) {} } /** * Set the delay duration between animation update. * @param delay Delay duration in milliseconds. */ public void setDelay(int delay) { this.delayDuration = delay; } //----------- Animation methods and variables -------------------- boolean noAnim = false; ComBox comment1 = null; String inputWord = new String(); int inputX = panel_width - 440, inputY = 10; Color inputBG = darkGreen; String hashWord = new String(); int hashX = panel_width - 466; Color hashBG; String inputText = new String(); String displayText = new String(); String rehashString = new String(); public void init() { inputWord = new String(); hashWord = new String(); comment1 = null; inputText = new String(); displayText = new String(); hashStats.init(); collisionStats.init(); hashStats.setYMax(40); hashStats.setYStep(10); hashStats.setXMax(10); hashStats.setXStep(5); collisionStats.setYMax(10); collisionStats.setYStep(5); collisionStats.setXMax(20); collisionStats.setXStep(10); } public void setRehashFunction(String rehashString) { this.rehashString = rehashString.trim(); } public void setInputText(String inputText) { this.inputText = inputText; this.displayText = inputText.substring(0, 38); repaint(); delay(); } public void setInput(String word, int hash) { hashWord = new String(); inputX = panel_width - 310; inputBG = darkGreen; inputWord = word; inputY = 17; for (int i = 0; i < word.length()+1; i++) { inputText = inputText.substring(1); displayText = inputText.substring(0,38); inputX -= 8; if (noAnim) continue; repaint(); delay(); } for (int i = word.length() + 1; i < 15; i+=2) { if (noAnim) break; inputX -= 16; repaint(); delay(); } inputX = panel_width - 452; repaint(); delay(); comment1 = new ComBox(panel_width - 500, 10, "Hashing...", fixFont); repaint(); inputY += 20; repaint(); delay(); inputY = 60; repaint(); delay(); delay(); hashBG = tone[0]; hashWord = ""+hash; hashX = inputX - 26; for (int i = 0; i < 3; i++) { if (noAnim) { inputY = 96; break; } inputY += 12; repaint(); delay(); } comment1 = null; repaint(); } public void rehash(int newIndex) { comment1 = new ComBox(inputX - 40, inputY - 20, "Collision! Re-Hashing...", fixFont); repaint(); int srcY = inputY; int destY = 270; for (int i = 0; i < 5; i++) { if (noAnim) { inputY = destY; break; } inputY += (destY - srcY)/5; repaint(); delay(); } comment1 = null; repaint(); hashBG = tone[0]; hashWord = ""+newIndex; hashX = inputX - 26; for (int i = 0; i < 3; i++) { if (noAnim) { inputY = destY - 36; break; } inputY -= 12; repaint(); delay(); } repaint(); delay(); } public void contains(String word) { if (noAnim) return; int index = table.indexOf(word); if (index < 0) return; table.scroll2posn(index); int srcX = inputX, srcY = inputY; int destY = yPosnOf(index); for (int i = 0; i < 3; i++) { inputY += (destY - srcY)/3; repaint(); delay(); } inputY = destY; repaint(); delay(); int destX = panel_width - 402; for (int i = 0; i < 2; i++) { inputX += (destX - srcX)/3; hashX = inputX - 26; repaint(); delay(); } inputX = destX; hashX = inputX - 26; repaint(); delay(); comment1 = new ComBox(inputX - 40, inputY + 20, "Key already exists...", fixFont); repaint(); for (int i = 0; i < 5; i++) { hashBG = inputBG = tone[i*6]; repaint(); delay(); } inputWord = new String(); repaint(); delay(); comment1 = null; repaint(); } public void collision(String word, int index) { if (noAnim) return; table.scroll2posn(index); int srcY = inputY; int destY = yPosnOf(index); int srcX = inputX; int destX = panel_width - 402; for (int i = 0; i < 3; i++) { inputY += (destY - srcY)/3; repaint(); delay(); } inputY = destY; repaint(); delay(); for (int i = 0; i < 2; i++) { inputX += (destX - srcX)/3; hashX = inputX - 26; repaint(); delay(); } inputX = destX; hashX = inputX - 26; repaint(); delay(); // bounce back for (int i = 0; i < 2; i++) { inputX -= (destX - srcX)/3; hashX = inputX - 26; repaint(); delay(); } inputX = srcX; hashX = inputX - 26; repaint(); delay(); } public void setTableEntry(String word, int index) { int srcX = inputX, srcY = inputY; table.scroll2posn(index); int destY = yPosnOf(index); for (int i = 0; i < 3; i++) { if (noAnim) break; inputY += (destY - srcY)/3; repaint(); delay(); } inputY = destY; repaint(); delay(); comment1 = new ComBox(inputX - 40, destY + 20, "Insert into Hash Table...", fixFont); repaint(); int destX = panel_width - 280; for (int i = 0; i < 5; i++) { if (noAnim) break; inputX += (destX - srcX)/5; hashX = inputX - 26; repaint(); delay(); } inputX = destX; hashX = inputX - 26; repaint(); delay(); inputWord = new String(); comment1 = null; repaint(); } public void fillBox(Graphics g, int x, int y, String str, Color fg, Color bg, int max_length) { if (table == null) return; int vertSpace = table.draw.vertSpace; int horizSpace = max_length * 8; g.setColor(bg); g.fillRect(x, y, horizSpace, vertSpace); g.setColor(fg); g.setFont(fixFont); if (str != null) g.drawString(str, x + 2, y + vertSpace - 4); } public void drawBox(Graphics g, int x, int y, String str, Color fg, Color bg, int max_length) { if (table == null) return; table.draw.drawBox(g, x, y, str, fg, bg, max_length); } public int yPosnOf(int index) { return (121 + (index - table.draw.start) * (table.draw.vertSpace + 2)); } public void setNoAnim(boolean noAnim) { this.noAnim = noAnim; } //--------------------------------------------------------------------- /** * This method is invoked when the repaint() method is called. * The update method is override here to eliminate flashing. * @param g Graphical context */ public void update(Graphics g) { Dimension d = size(); if (d.width < 1 || d.height < 1) return; if ((offscreen == null) || (d.width != offscreensize.width) || (d.height != offscreensize.height)) { offscreen = createImage(d.width, d.height); offscreensize = d; offGraphics = offscreen.getGraphics(); } offGraphics.setColor(getBackground()); offGraphics.fillRect(0, 0, d.width, d.height); offGraphics.setFont(smallFont); fm = offGraphics.getFontMetrics(); paint(offGraphics); g.drawImage(offscreen, 0, 0, null); } /** * Method to draw objects on the drawing panel. This method is * TO BE COMPLETED to incorporate the drawing methods/statements. */ public void paint(Graphics g) { if (panel_width != size().width) { table.reshape(size().width - 280, 120, 270, 133); } panel_height = size().height; panel_width = size().width; fileLabel.setTopLeft(panel_width - 38, 9); fileLabel.draw(g); if (inputWord.length() > 0) { if (hashWord.length() > 0) fillBox(g, hashX, inputY, hashWord, Color.red, hashBG, 3); fillBox(g, inputX, inputY, inputWord, Color.white, inputBG, 15); } //g.setColor( Color.black ); //g.drawRect( 1, 1, panel_width-2, panel_height-2 ); tableLabel.setTopLeft(panel_width - 254, 90); tableLabel.draw(g); drawBox(g, panel_width - 310, 17, displayText, Color.black, Color.white, 34); if (table != null) { table.drawClusters(g, offset + 50, panel_height - 50); } // draw Hash function g.setColor(Color.black); g.fillRect(panel_width - 486, 55, 160, 30); g.setColor(Color.white); g.drawRect(panel_width - 485, 56, 157, 27); fillBox(g, panel_width - 470, 60, "Hash Function, H()", Color.cyan, Color.black, 17); // draw rehash function g.setColor(Color.gray); g.fillRect(panel_width - 502, 265, 192, 30); g.setColor(Color.white); g.drawRect(panel_width - 501, 266, 189, 27); fillBox(g, panel_width - 490, 270, "Rehash " + rehashString, Color.yellow, Color.gray, 21); if (comment1 != null) comment1.draw(g); } // paint() /** * Returns the initial preferred size of the drawing panel. * This method is called by the layout manager during the creation * of the corresponding drawing frame. */ public Dimension getPreferredSize() { return new Dimension( pref_width, pref_height ); } // getPreferredSize() } // class DrawingPanel