package grapher2D; import java.awt.GridLayout; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Observable; import java.util.Observer; import javax.swing.JPanel; import javax.swing.JTextField; import variables.Variable; import expressionConsole.ExpressionConsoleModel; /** * The controller of the Model View Controller paradigm for the Grapher. In this * paradigm, the model stores information necessary to produce the view (in this * case this information includes the function string, coordinate space, and * some other things.) The controller is the UI which modifies the model (in * this case it is the function field). The view is the graphical representation * of the model. Typically there is some overlap between the roles of the view * and the model (such as zooming by drawing a rectangle on the view, or * displayed parameters in the controller which must be updated to reflect * changes in the model. The model, view, and controller communicate using the * Observer design pattern. The model is the Observable, and the controller and * view are Observers of the model. When the model changes, it sends a * notification event to all Observers, thus signaling them to update so that * they reflect the current state of the model. * * @author Curran Kelleher * */ public class Grapher2DController extends JPanel implements Observer, KeyListener { private static final long serialVersionUID = -4053890244503081186L; /** * The text field in which the user enters the function. */ JTextField functionField; /** * A flag to signify that updates from the model should be ignored. */ boolean ignoreUpdates = false; /** * Upon construction, the function field is set up. * */ public Grapher2DController() { // create the funcion field and set up listening to it functionField = new JTextField(); functionField.addKeyListener(this); // Observe the function string for changes Variable.getVariable(Grapher2DConstants.Grapher2DFunctionString) .addObserver(this, "The text displayed in the function text box."); // a GridLayout is used to make the functionField fill the panel space. setLayout(new GridLayout()); // put the function field in the panel add(functionField); } /** * Responds to notifications from the function string when it has changed. */ public void update(Observable o, Object arg) { // update the text to reflect the function string in the model. if (!ignoreUpdates) functionField.setText(Variable.getVariable( Grapher2DConstants.Grapher2DFunctionString).evaluate() .toString()); } /** * Responds to the enter key when it is pressed in the function field by * updating the model. * * @param e * the key event */ public void keyPressed(KeyEvent e) { // only act if the enter key has been pressed if (e.getKeyChar() == '\n') { // ignore the self-originated model update notification ignoreUpdates = true; // update the string function variable with the new function String. ExpressionConsoleModel.getInstance().enterExpression( Grapher2DConstants.Grapher2DFunctionString + " = \"" + functionField.getText() + "\""); // the function string variable is being observed by the view, so as // a result of this code execution, it will be appropriately // notified and will update itself. // but do not ignore subsequent updates ignoreUpdates = false; } } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { } }