/*
* 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.ContextFreePumpingLemma;
/**
* This is a subclass of HumanFirstPane
that deals with
* context-free pumping lemmas.
*
* @author Jinghui Lim & Chris Morgan
* @see pumping.ContextFreePumpingLemma
*
*/
public class HumanCFPumpingLemmaInputPane 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 context-free?";
/**
* Message displayed if player wins.
*/
private static String YOU_WIN = "YOU WIN. Does this mean the language is context-free?";
/**
* The SliderPanel
that controls u of the decomposition.
*/
private SliderPanel myUPanel;
/**
* The SliderPanel
that controls v of the decomposition.
*/
private SliderPanel myVPanel;
/**
* Creates a HumanCFPumpingInputPane
for a ContextFreePumpingLemma
.
*
* @param l the ContextFreePumpingLemma
we want to run
*/
public HumanCFPumpingLemmaInputPane(ContextFreePumpingLemma l)
{
super(l, "L = {" + l.getHTMLTitle() + "} Context-Free Pumping Lemma");
}
protected void addDecompPanelGameFeatures(JPanel n){
decompButtonTitle = new String("Set uvxyz");
n.setMaximumSize(new Dimension(MAX_SIZE.width, 9*MAX_SIZE.height/20));
n.setPreferredSize(new Dimension(MAX_SIZE.width, 9*MAX_SIZE.height/20));
myUPanel = new SliderPanel("u", this);
sliderPanel.add(myUPanel);
myVPanel = new SliderPanel("v", this);
sliderPanel.add(myVPanel);
n.setBorder(BorderFactory.createTitledBorder("3. Select decomposition of w into uvxyz."));
}
/**
* After m is chosen, prompts the lemma for w
* and displays it, and sets up the sliders and table accordingly.
*
*/
protected void mEnteredReset()
{
/*int m = Integer.parseInt(myMDisplay.getText());
reset();
myMDisplay.setText(Integer.toString(m));*/
String s = myLemma.getW();
myWDisplay.setText(s);
myUPanel.setSliderMax(s.length());
myUPanel.setText(s);
myUPanel.setVal(0);
myVPanel.setSliderMax(s.length());
myVPanel.setText(s);
myVPanel.setVal(0);
myXPanel.setSliderMax(s.length());
myXPanel.setText(s);
myXPanel.setVal(0);
myYPanel.setSliderMax(s.length());
myYPanel.setText(s);
myYPanel.setVal(0);
refresh();
updateTable();
leftPanel.revalidate();
}
protected void resetDecompPanel()
{
myUPanel.reset();
myVPanel.reset();
myXPanel.reset();
myYPanel.reset();
myZDisplay.setText("");
myZLength.setText("");
updateTable();
}
/**
* Resets the various fields of u, v, x, y,
* and z, the display for i and the pumped string, and
* the canvas.
*/
protected void refresh()
{
try
{
/*
* Reset the range of each panel depending on the values of the
* other panels.
*/
myUPanel.setRange(0, myVPanel.getVal());
myVPanel.setRange(myUPanel.getVal(), myXPanel.getVal());
myXPanel.setRange(myVPanel.getVal(), myYPanel.getVal());
myYPanel.setRange(myXPanel.getVal(), myLemma.getW().length());
/*
* Set the text and length of z.
*/
myZDisplay.setText(myLemma.getW().substring(myYPanel.getVal()));
myZLength.setText(Integer.toString(myZDisplay.getText().length()));
/*
* Clear the display of i and the pumped string, and reset the
* canvas.
*/
myIDisplay.setText("");
myPumpedStringDisplay.setText("");
myLastWord.setText("");
myCanvas.reset();
/*
* Check various conditions.
*/
if(myUPanel.getVal() > myVPanel.getVal())
{
myZDisplay.setText("");
stageMessages[3].setText("Condition violated: |v| >= 0");
myZLength.setText("");
myDecompButton.setEnabled(false);
}
else if(myVPanel.getVal() > myXPanel.getVal())
{
myZDisplay.setText("");
stageMessages[3].setText("Condition violated: |x| >= 0");
myZLength.setText("");
myDecompButton.setEnabled(false);
}
else if(myXPanel.getVal() > myYPanel.getVal())
{
myZDisplay.setText("");
stageMessages[3].setText("Condition violated: |y| >= 0");
myZLength.setText("");
myDecompButton.setEnabled(false);
}
else if(myYPanel.getVal() - myUPanel.getVal() > myLemma.getM())
{
myZDisplay.setText("");
stageMessages[3].setText("Condition violated: |vxy| <= m");
myZLength.setText("");
myDecompButton.setEnabled(false);
}
else if((myVPanel.getVal() - myUPanel.getVal()) +
(myYPanel.getVal() - myXPanel.getVal()) < 1)
{
myZDisplay.setText("");
stageMessages[3].setText("Condition violated: |vy| >= 1");
myZLength.setText("");
myDecompButton.setEnabled(false);
}
else
{
stageMessages[3].setText("Click \"Set uvxyz\" 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)
{
int u = decomposition[0];
int v = decomposition[1];
int x = decomposition[2];
int y = decomposition[3];
myUPanel.setVal(u);
myVPanel.setVal(u + v);
myXPanel.setVal(u + v + x);
myYPanel.setVal(u + v + x + y);
myLemma.setDecomposition(decomposition);
}
/**
* Calculates i and the string uvixyiz.
* based on the user's decomposition of uvxyz.
*/
protected void setI()
{
int[] d = new int[]{myUPanel.getVal(), myVPanel.getVal() - myUPanel.getVal(),
myXPanel.getVal() - myVPanel.getVal(), myYPanel.getVal() - myXPanel.getVal(),
myLemma.getW().length() - myYPanel.getVal()};
myLemma.setDecomposition(d);
myLemma.chooseI();
if(myCases != null)
{
myCases.setDecomposition(d);
myCases.setI(myLemma.getI());
}
}
/**
* Initializes the animation canvas with the values of u, v,
* x, y, and z.
*
*/
protected void setCanvas()
{
stages[5].setVisible(true);
myCanvas.reset();
myCanvas.addText("w =");
myCanvas.addText(((ContextFreePumpingLemma)myLemma).getU(), "u");
myCanvas.addText(((ContextFreePumpingLemma)myLemma).getV(), "v");
myCanvas.addText(((ContextFreePumpingLemma)myLemma).getX(), "x");
myCanvas.addText(((ContextFreePumpingLemma)myLemma).getY(), "y");
myCanvas.addText(((ContextFreePumpingLemma)myLemma).getZ(), "z");
myCanvas.moveText(new int[]{0, 1, myLemma.getI(), 1, myLemma.getI(), 1});
myStepAnimation.setEnabled(true);
myStartAnimation.setEnabled(false);
repaint();
}
/**
* Creates an HTML string uvixyiz, with the
* real value of i instead of the variable i.
*
* @return a string representing uvixyiz
*/
protected String createXYZ()
{
return "uv" + myLemma.getI() + "xy" +
myLemma.getI() + "z";
}
public void update()
{
ContextFreePumpingLemma pl = (ContextFreePumpingLemma)myLemma;
stageMessages[0].setText("File loaded.");
updateTopPane(false);
/*
* Has m been entered?
*
* If it hasn't, no point doing the rest.
* If it has, then go on and load m and w.
*/
if(pl.getM() == -1)
return;
myMDisplay.setText("" + pl.getM());
myWDisplay.setText(pl.getW());
/*
* Regardless of whether the decomposition has been set, we load
* the stuff in the sliders and table, and send the temporary
* decomposition to the case panel. Even if it hasn't been chosen,
* it won't cause anything to go wrong.
*
* Everything below has to be done in a specific order.
*/
int[] decomposition = new int[]{pl.getU().length(), pl.getV().length(),
pl.getX().length(), pl.getY().length()};
/*
* We need to call SliderPanel.setText and SliderPanel.setSliderMax
* before calling setDecomposition. Otherwise, the sliders' default
* max is 10, and if we try to set the value anything above 10, we
* will just get 10.
*/
myUPanel.setText(pl.getW());
myUPanel.setSliderMax(pl.getW().length());
myVPanel.setText(pl.getW());
myVPanel.setSliderMax(pl.getW().length());
myXPanel.setText(pl.getW());
myXPanel.setSliderMax(pl.getW().length());
myYPanel.setText(pl.getW());
myYPanel.setSliderMax(pl.getW().length());
setDecomposition(decomposition, pl.getI());
if (myCases != null) {
myCases.setDecomposition(decomposition);
myCases.setListButtonEnabled(true);
}
updateTable();
stages[2].setVisible(true);
stages[3].setVisible(true);
/*
* If the decomposition hasn't been set, i.e. the sliders are all set to zero,
* don't allow setting of decomposition.
*
* Else, initialize animation etc.
*/
if(pl.getU().length() == 0 && pl.getV().length() == 0 &&
pl.getX().length() == 0 && pl.getY().length() == 0)
{
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);
if (myCases != null)
myCases.setAddReplaceButtonsEnabled(true);
displayIEnd();
myCanvas.setRestartEnabled(true);
}
}
}