/** * A simple applet class to demonstrate a pattern matching algorithm. * You can specify a pattern matching algorithm from the menu, and * also specify a pattern and a text. * When you click on the applet, a thread is forked which animates * the pattern matching algorithm. * * @author Masayuki Takeda * @version 0.01b, 2012 (Viggo Kann) */ import java.applet.Applet; import java.awt.*; import java.awt.event.*; import javax.swing.JTextField; public class PatternMatchingItem extends java.applet.Applet implements Runnable, ActionListener, ItemListener { static Font font0 = new Font("SansSerif", Font.BOLD, 18); static int fontHeight = 20; static Font font1 = new Font("SansSerif", Font.BOLD, fontHeight); static int charWidth = 20, charHeight = 30; /** * The thread that is sorting (or null). */ private Thread kicker; public int Sleep_Value = 50; public JTextField p_input, t_input; public int Offset = 180; public boolean Pause_Flag; /** * pattern, text, and information about one matching stage */ char P[], T[]; int M, N; int Position, Current; int Comparisons = 0; boolean Match[], Trivial[], Mismatch, Found; boolean threadDone; /** * The name of the algorithm. */ String algName; /** * The pattern matching algorithm (or null). */ PatternMatchingAlgorithm algorithm; /** * Pause a while, and draw the pattern and the text. * @see PatternMatchingAlgorithm */ void pause(int position, boolean trivial[], int current, boolean mismatch, boolean found, int comparisons) { Position = position; for (int i = 0; i < M; i++) Trivial[i] = trivial[i]; Current = current; Mismatch = mismatch; Found = found; Comparisons = comparisons; if (kicker != null) { repaint(); } if (Sleep_Value == 0) { /* Step by Step */ Pause_Flag = true; while (Pause_Flag && !algorithm.stopRequested) { try {Thread.sleep(10);} catch (InterruptedException e){} } } else { try {Thread.sleep(Sleep_Value);} catch (InterruptedException e){} } } public void set_pattern_and_text(String pattern, String text) { N = text.length(); M = pattern.length(); T = new char [N]; P = new char [M]; text. getChars(0, N, T, 0); pattern.getChars(0, M, P, 0); Match = new boolean [M]; Trivial = new boolean [M]; Position = -1; Current = -1; } /** * Initialize the applet. */ public void init() { Button b; Panel buttons = new Panel(); // buttons.setLayout(new GridLayout(1,3)); // buttons.setLayout(new GridLayout(3,1)); buttons.add(b = new Button("start")); b.addActionListener(this); buttons.add(b = new Button("stop") ); b.addActionListener(this); buttons.add(b = new Button("next step")); b.addActionListener(this); Panel tools = new Panel(); Choice ch = new Choice(); ch.addItemListener(this); ch.addItem("Naive"); ch.addItem("Morris_Pratt"); ch.addItem("Knuth_Morris_Pratt"); ch.addItem("Horspool"); ch.addItem("Boyer_Moore"); ch.addItem("Boyer_Moore_Galil"); tools.add(ch); ch = new Choice(); ch.addItemListener(this); ch.addItem("very fast"); ch.addItem("fast"); ch.addItem("medium"); ch.addItem("slow"); ch.addItem("very slow"); ch.addItem("step by step"); tools.add(ch); Panel input = new Panel(); input.setLayout(new GridLayout(2,2)); input.add(new Label("pattern")); p_input = new JTextField("abaabab"); p_input.setFont(font1); input.add(p_input); input.add(new Label("text")); t_input = new JTextField("abbabbabaababaaa"); t_input.setFont(font1); input.add(t_input); add(buttons); add(tools); add(input); algName = "Naive"; set_pattern_and_text(p_input.getText(), t_input.getText()); } void print_char(Graphics g, int off_x, int off_y, char t[], int idx) { int x_coord = off_x + charWidth*idx; int y_coord = off_y; g.setFont(font1); g.fillRect(x_coord, y_coord - fontHeight, charWidth, fontHeight); g.setColor(Color.black); g.drawChars(t, idx, 1, x_coord+3, y_coord-2); } void new_alignment(Graphics g) { /* print pattern */ for (int i = 0; i < N; i++) { g.setColor(Color.white); print_char(g, 10, Offset, T, i); } g.setColor(Color.darkGray); g.drawLine(10, Offset, 10+charWidth*N, Offset); g.drawLine(10+charWidth*N, Offset-charHeight, 10+charWidth*N, Offset); /* print pattern */ for (int j = 0; j < M; j++) { g.setColor(Color.white); if (Trivial[j] == true) { g.setColor(Color.green); } print_char(g, 10+charWidth*Position, Offset+charHeight, P, j); } g.setColor(Color.darkGray); g.drawLine(10+charWidth*Position, Offset+charHeight, 10+charWidth*(Position+M), Offset+charHeight); g.drawLine(10+charWidth*(Position+M), Offset+charHeight-charHeight, 10+charWidth*(Position+M), Offset+charHeight); } void current_status(Graphics g) { /* print text */ g.setColor(Color.white); if (Position+Current <= N) { if (Mismatch) { g.setColor(Color.red); } else { g.setColor(Color.yellow); } print_char(g, 10, Offset, T, Position+Current); } /* print pattern */ if (Current < M && !Mismatch) { g.setColor(Color.yellow); print_char(g, 10+charWidth*Position, Offset+charHeight, P, Current); } } /** * Paint the pattern and the text with matching information */ public void paint(Graphics g) { g.setFont(font0); /* print text */ if (Position < 0) { g.setColor(Color.red); g.drawString("Choose an algorithm, and click the start button.", 30, Offset); g.drawString("You can alter the pattern and the text.", 30, Offset+charHeight); return ; } g.setColor(Color.blue); g.setFont(font1); g.drawString(algName + " algorithm", 10, Offset-charHeight); if (Current < 0) { new_alignment(g); } else { current_status(g); if (Found) g.drawString("Found!!!", 20*charWidth, Offset-charHeight); } g.setColor(getBackground()); g.fillRect(10, Offset + 60 - fontHeight, 30*charWidth, fontHeight); g.setColor(Color.black); g.drawString("Comparisons = "+Comparisons, 10, Offset+60); } public void update(Graphics g) { if (Current == -1) { g.setFont(font1); g.setColor(getBackground()); g.fillRect(0,0,600,350); g.setColor(Color.white); } paint(g); } /** * Run the pattern matching algorithm. This method is * called by class Thread once the pattern matching algorithm * is started. * @see java.lang.Thread#run * @see PatternMatchingItem#mouseUp */ public void run() { if (!threadDone) try { algorithm = (PatternMatchingAlgorithm)Class.forName(algName).newInstance(); algorithm.setParent(this); algorithm.init(); // p_input.disable(); // t_input.disable(); algorithm.find(T,N,P,M); // p_input.enable(); // t_input.enable(); } catch(Exception e) { } } /** * Stop the applet. Kill any pattern matching algorithm that * is still processing. */ public synchronized void stop() { if (kicker != null) { try { threadDone = true; } catch (IllegalThreadStateException e) { // ignore this exception } kicker = null; } if (algorithm != null){ try { algorithm.stop(); } catch (IllegalThreadStateException e) { // ignore this exception } } // Input.dispose(); } private synchronized void startPatternMatching() { if (kicker == null || !kicker.isAlive()) { set_pattern_and_text(p_input.getText(), t_input.getText()); repaint(); kicker = new Thread(this); kicker.start(); } } public void actionPerformed(ActionEvent e) { Object o = e.getSource(); if (o instanceof Button) { Button b = (Button) o; String arg = b.getLabel(); if (arg.equals("start")) { startPatternMatching(); } else if (arg.equals("stop")) { if (algorithm != null) algorithm.stop(); } else if (arg.equals("next step")) { Pause_Flag = false; } } } public void itemStateChanged(ItemEvent e) { Object o = e.getSource(); if (o instanceof Choice) { Choice c = (Choice) o; String arg = c.getSelectedItem(); if (arg.equals("very slow")) { Sleep_Value = 2000; } else if (arg.equals("slow")) { Sleep_Value = 1000; } else if (arg.equals("medium")) { Sleep_Value = 500; } else if (arg.equals("fast")) { Sleep_Value = 200; } else if (arg.equals("very fast")) { Sleep_Value = 50; } else if (arg.equals("step by step")) { Sleep_Value = 0; } else { algName = (String)arg; } } } }