The code is: (save it in a file "duckMachine/Window.java")
import java.io.*; import duckMachine.architecture.*; import duckMachine.operatingSystem.*; import duckMachine.GUI.*; /** * The graphical interaction with the machine. * @author Amr Sabry * @version jdk-1.1 */ public class Window { /** * The machine and the graphical interface communicate via pipes. * The machine knows nothing about the interface, but the interface * needs to know the machine's state to display it. */ public static void main (String args[]) { try { // create two pipes, and pass them to the machine constructor. PipedInputStream machineInPipe = new PipedInputStream(); PipedOutputStream machineOutPipe = new PipedOutputStream(); MachineI mach = new Machine(machineInPipe, machineOutPipe); // connect the machineOutPipe to the GUI's input pipe PipedInputStream guiInPipe = new PipedInputStream(machineOutPipe); // connect the machineInPipe to the GUI's output pipe PipedOutputStream guiOutPipe = new PipedOutputStream(machineInPipe); // create a (non visible) frame that displays the state of the machine // and uses guiInPipe and guiOutPipe to communicate with the machine // The class MachineFrame is defined in the GUI package. MachineFrame shell = new MachineFrame(mach, guiInPipe, guiOutPipe); // display the frame ... shell.setLocation(100,100); shell.pack(); shell.show(); } catch (Throwable e) { // no exceptions should reach this point!!! e.printStackTrace(); throw new Error("Unexpected error"); } } }
public class ALUPanel extends PanelThe constructor for the class takes the machine's ALU as an argument:
public ALUPanel (duckMachine.architecture.ALUI alu) {The constructor should create graphical components to display the values of the ALU flags, and "add" them to the current panel. (You can look at the graphical representation I chose by running my program, but please feel free to modify and improve on my interface.) To function properly, the class must have a method:
public void updatePanel (ALUI alu)that should update the display by reading the new values of the ALU flags. This method will be called by other parts of the program whenever we need to refresh the display with a new machine state.
public class CommThread implements RunnableThe constructor of the class takes two arguments that it saves in appropriate instance variables:
private ShellCommand command; private MachineFrame machineFrame; public CommThread (ShellCommand c, MachineFrame pf) { command = c; machineFrame = pf; }The class has one public method required by the interface Runnable:
public void run () { try { command.execCommand(machineFrame.mach); machineFrame.refresh(); machineFrame.controlPanel.endCommand(); } catch (ShellE e) { // due to machine error machineFrame.controlPanel.reportError(e.toString()); } }The actions performed in the new thread are to execute the machine command, refresh the panel to reflect the new machine status, and notify the control panel that we are done.
public class ControlPanel extends Panel implements ActionListenerThe constructor for the class takes one argument:
public ControlPanel (MachineFrame mf)which it saves in an instance variable. The constructor also creates and adds to the current panel two graphical components:
killButton = new Button("Stop"); killButton.addActionListener(this);For the other buttons, we have:
loadButton = new Button("Load Object File"); loadButton.addActionListener(new loadListener(machineFrame)); stepButton = new Button("Step"); stepButton.addActionListener(new stepListener(machineFrame)); runButton = new Button("Run"); runButton.addActionListener(new runListener(machineFrame));Each button registers a different object to responds to its clicks.
public void startCommand (Runnable command) public void endCommand () public void reportStatus (String message) public void reportError (String message) public void actionPerformed (ActionEvent evt)The control panel must create a thread to run machine commands. Otherwise machine commands that block waiting for input, or that go in infinite loops, would cause the interface to hang. The methods:
public void startCommand (Runnable command) public void endCommand ()manage the command threads. We will only allow one command thread to run at a time (otherwise we would have to support concurrent programs running on our hardware machine). The method startCommand checks that no other commands are running, and if none are running, creates a new thread and starts it. If some other command is running, we refuse to start the new command, and display an error message on the errPort using the method reportError. The method endCommand simply records that no commands are running so that we can start a new command. When creating a thread, you must be careful to give it a low priority so that you can kill it if required. As expected, the two methods:
public void reportStatus (String message) public void reportError (String message)just display messages on the errPort. I display status messages in green, and error messages in red. The method:
public void actionPerformed (ActionEvent evt)will be called when the Stop button is pushed. It is required because we implement the interface ActionListener. The method should stop the thread running the current command.
sabry@cs.uoregon.edu