/* * 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.pumping; import java.awt.*; import java.awt.event.*; import javax.swing.*; import pumping.RegularPumpingLemma; /** * This is a subclass of a HumanFirstPane that deals with * regular pumping lemmas. * * @author Jinghui Lim & Chris Morgan * @see pumping.RegularPumpingLemma * */ public class HumanRegPumpingLemmaInputPane extends HumanFirstPane { /** * Message displayed if computer wins. */ private static String I_WIN = "I WIN. Do you want to play again or concede " + "that the language is not regular?"; /** * Message displayed if player wins. */ private static String YOU_WIN = "YOU WIN. Does this mean the language is regular?"; /** * The instruction that prompts for the decomposition of w. */ private static String PROMPT_DECOMPOSITION = "Please select the decomposition of w into xyz using the sliders."; /** * Creates a HumanRegPumpingInputPane for a RegularPumpingLemma. * * @param l the RegularPumpingLemma we want to run */ public HumanRegPumpingLemmaInputPane(RegularPumpingLemma l) { super(l, "L = {" + l.getHTMLTitle() + "} Regular Pumping Lemma"); } protected void addDecompPanelGameFeatures(JPanel n) { n.setMaximumSize(new Dimension(MAX_SIZE.width, 3*MAX_SIZE.height/10)); n.setPreferredSize(new Dimension(MAX_SIZE.width, 3*MAX_SIZE.height/10)); decompButtonTitle = new String("Set xyz"); n.setBorder(BorderFactory.createTitledBorder("3. Select decomposition of w into xyz.")); } /** * After m is chosen, prompts the lemma for w * and displays it, and sets up the sliders and table accordingly. * */ protected void mEnteredReset() { String s = myLemma.getW(); myWDisplay.setText(s); myXPanel.setSliderMax(s.length()); myXPanel.setVal(0); myXPanel.setText(myLemma.getW()); myYPanel.setSliderMax(s.length()); myYPanel.setVal(0); myYPanel.setText(myLemma.getW()); refresh(); updateTable(); leftPanel.revalidate(); } protected void resetDecompPanel() { myXPanel.reset(); myYPanel.reset(); myZDisplay.setText(""); myZLength.setText(""); updateTable(); } /** * Resets the various fields of x, y, and z, * the display for i and the pumped string, and the canvas. */ protected void refresh() { try { myXPanel.setRange(0, myYPanel.getVal() - 1); myYPanel.setRange(myXPanel.getVal(), myLemma.getM()); myZDisplay.setText(myLemma.getW().substring(myYPanel.getVal())); myZLength.setText(Integer.toString(myZDisplay.getText().length())); myIDisplay.setText(""); myPumpedStringDisplay.setText(""); myLastWord.setText(""); myCanvas.reset(); if(myXPanel.getVal() >= myYPanel.getVal()) { myZDisplay.setText(""); stageMessages[3].setText("Condition violated: |y| > 0"); myZLength.setText(""); myDecompButton.setEnabled(false); } else if(myYPanel.getVal() > myLemma.getM()) { myZDisplay.setText(""); stageMessages[3].setText("Condition violated: |xy| <= m"); myZLength.setText(""); myDecompButton.setEnabled(false); } else { stageMessages[3].setText("Click \"Set xyz\" to set decomposition."); myDecompButton.setEnabled(true); } } catch(StringIndexOutOfBoundsException e) { /* * Refresh is triggered whenever the slider is moved or the * range is reset. This can cause multiple exceptions when * we are merely changing the max of the slider or adjusting * the slider. Thus, the exception is ignored. */ } } public void setDecomposition(int[] decomposition) { myXPanel.setVal(decomposition[0]); myYPanel.setVal(decomposition[0] + decomposition[1]); } /** * Calculates i and the string xyiz. * based on the user's decomposition of xyz.. */ protected void setI() { int[] d = new int[]{myXPanel.getVal(), myYPanel.getVal() - myXPanel.getVal()}; myLemma.setDecomposition(d); myLemma.chooseI(); if(myCases != null) { myCases.setDecomposition(d); myCases.setI(myLemma.getI()); } } /** * Initializes the animation canvas with the values of x, y, * and z. */ protected void setCanvas() { stages[5].setVisible(true); myCanvas.reset(); myCanvas.addText("w ="); myCanvas.addText(((RegularPumpingLemma)myLemma).getX(), "x"); myCanvas.addText(((RegularPumpingLemma)myLemma).getY(), "y"); myCanvas.addText(((RegularPumpingLemma)myLemma).getZ(), "z"); myCanvas.moveText(new int[]{0, 1, myLemma.getI(), 1}); myStepAnimation.setEnabled(true); myStartAnimation.setEnabled(false); repaint(); } /** * Creates an HTML string xyiz, with the real value of i * instead of the variable i. * * @return a string representing xyiz */ protected String createXYZ() { return "xy" + myLemma.getI() + "z"; } public void update() { RegularPumpingLemma pl = (RegularPumpingLemma)myLemma; stageMessages[0].setText("File loaded."); updateTopPane(false); if(pl.getM() == -1) return; myMDisplay.setText("" + pl.getM()); myWDisplay.setText(pl.getW()); myXPanel.setText(pl.getW()); myXPanel.setSliderMax(pl.getW().length()); myYPanel.setText(pl.getW()); myYPanel.setSliderMax(pl.getW().length()); setDecomposition(new int[]{pl.getX().length(), pl.getY().length()}, pl.getI()); updateTable(); stages[2].setVisible(true); stages[3].setVisible(true); if(pl.getX().length() == 0 && pl.getY().length() == 0) // not yet set decomposition { myDecompButton.setEnabled(false); } else { stages[4].setVisible(true); stages[5].setVisible(true); stageMessages[5].setText("Click \"Restart\" to restart the animation."); stageMessages[5].setVisible(true); displayIEnd(); myCanvas.setRestartEnabled(true); } } }