import java.util.Vector;
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import javax.swing.border.*;
class NoWrapJTextPane extends JTextPane
{
public void setSize(Dimension d)
{
if (d.width < getParent().getSize().width)
d.width = getParent().getSize().width;
super.setSize(d);
}
public boolean getScrollableTracksViewportWidth()
{
return false;
}
}
class StateHierarchyRenderer extends JLabel implements ListCellRenderer
{
Font fontB = new Font("Monospaced", Font.BOLD, 12);
Color lightyellow = new Color(255, 255, 96);
svmapplet applet;
public StateHierarchyRenderer(svmapplet applet)
{
this.applet = applet;
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
String s = value.toString();
setText(s);
if (isSelected)
{
setBackground(new Color(94,121,173));
setBorder(BorderFactory.createRaisedBevelBorder());
setForeground(Color.white);
}
else
{
String PathName = applet.getStatePath(index);
setBorder(BorderFactory.createLineBorder(Color.white, 1));
setForeground(new Color(1,1,139));
if (list == applet.States && applet.Model.isLeafState(PathName) && applet.Model.isInState(PathName))
{
setBackground(lightyellow);
setBorder(BorderFactory.createLineBorder(Color.white, 1));
}
else
{
setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
if (index % 2 == 0)
setBackground(new Color(240,240,255));
else
setBackground(Color.white);
}
}
setOpaque(true);
setFont(fontB);
return this;
}
}
public class svmapplet extends Applet implements ActionListener, MouseListener, ListSelectionListener
{
JTextPane Dump;
JTextField Input;
JTextPane StateDisplay;
JList Events;
JList States;
Hierarchy StateHierarchy;
Vector EnabledEvents = new Vector();
JScrollPane spStates;
JScrollPane spDump;
JScrollPane spEvents;
Style PromptStyle, CommandStyle;
StateMachine Model;
static String ModelParameter = "Model";
private void dump(String msg, Style style)
{
try
{
Document doc = Dump.getDocument();
doc.insertString(doc.getLength(), msg, style);
Dump.setCaretPosition(doc.getLength()-msg.length());
}
catch (BadLocationException e)
{
}
}
public void init()
{
try
{
Model = (StateMachine) (Class.forName(getParameter(ModelParameter)).newInstance());
}
catch(Exception e)
{
promptInvalidModel();
return;
}
createWidgets();
Model.initModel();
updateEvents();
updateHierarchy();
States.setSelectedIndex(0);
dump(Model.getCurrentState() + " > ", PromptStyle);
}
private void updateEvents()
{
EventList el = Model.getEnabledEvents();
EnabledEvents.clear();
while (el != null)
{
EnabledEvents.add(el.Event);
el = el.Next;
}
Events.setListData(EnabledEvents);
}
private void updateHierarchy()
{
StateHierarchy=Model.getHierarchy();
int index = States.getSelectedIndex();
Vector v = new Vector();
Hierarchy h = StateHierarchy;
while (h != null)
{
String name = "";
for (int i=0; i<h.Level; i++)
name = name + " ";
name=name + (Model.isLeafState(h.PathName) ? "- " : "+ ");
v.add(name + h.StateName);
h = h.Next;
}
States.setListData(v);
States.setSelectedIndex(index);
}
public void actionPerformed (ActionEvent ae)
{
if (ae.getSource() == Input)
{
String e = Input.getText();
Input.setText("");
Model.handleEvent(e);
dump(e+"\n", CommandStyle);
dump(Model.getCurrentState()+" > ", PromptStyle);
updateEvents();
updateHierarchy();
}
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() == 2 && e.getSource() == Events)
{
String ev = (String)Events.getModel().getElementAt(Events.getSelectedIndex());
Model.handleEvent(ev);
dump(ev+"\n", CommandStyle);
dump(Model.getCurrentState()+" > ", PromptStyle);
updateEvents();
updateHierarchy();
}
}
public String getStatePath(int index)
{
Hierarchy h = StateHierarchy;
for (int i=0; i<index; i++)
h = h.Next;
return h.PathName;
}
public void valueChanged(ListSelectionEvent e)
{
if (e.getSource() == States)
{
int idx = States.getSelectedIndex();
StateDisplay.setText(getStatePath(idx));
}
}
private void createWidgets()
{
setLayout(new BorderLayout());
JLabel scclb = new JLabel("SCC Demonstration -- a Preview to Version 0.1", JLabel.CENTER);
scclb.setForeground(Color.red);
scclb.setBackground(Color.white);
scclb.setOpaque(true);
scclb.setPreferredSize(new Dimension(10, 25));
Dump = new NoWrapJTextPane();
Dump.setEditable(false);
Input = new JTextField();
Events = new JList();
Events.setPreferredSize(new Dimension(80, 10));
Events.setCellRenderer(new StateHierarchyRenderer(this));
States = new JList();
States.setCellRenderer(new StateHierarchyRenderer(this));
StateDisplay = new JTextPane();
StateDisplay.setEditable(false);
Dump.setBackground(Color.white);
Input.setBackground(Color.white);
Events.setBackground(Color.white);
States.setBackground(Color.white);
Font fontB = new Font("Monospaced", Font.BOLD, 12);
Font font = new Font("Monospaced", 0, 12);
Font fonts = new Font("Monospaced", 0, 12);
Font fontl = new Font("Serif", Font.BOLD, 15);
Dump.setFont(fonts);
Input.setFont(font);
Events.setFont(fontB);
States.setFont(fontB);
StateDisplay.setFont(font);
scclb.setFont(fontl);
PromptStyle = Dump.addStyle("prompt", null);
StyleConstants.setForeground(PromptStyle, Color.blue);
CommandStyle = Dump.addStyle("command", null);
StyleConstants.setForeground(CommandStyle, Color.red);
StyleConstants.setBold(CommandStyle, true);
spDump = new JScrollPane(Dump);
spEvents = new JScrollPane(Events);
spStates = new JScrollPane(States);
spEvents.setBorder(BorderFactory.createEmptyBorder());
JLabel eventslb = new JLabel("Events", JLabel.CENTER);
JLabel dumplb = new JLabel("Output", JLabel.CENTER);
JLabel inputlb = new JLabel("Command", JLabel.CENTER);
JLabel stateslb = new JLabel("State Hierarchy", JLabel.CENTER);
Color lightblue = new Color(172,215,229);
Color pink = new Color(0xFFC0C0);
eventslb.setBackground(lightblue);
eventslb.setForeground(Color.blue);
eventslb.setOpaque(true);
dumplb.setBackground(lightblue);
dumplb.setForeground(Color.blue);
dumplb.setOpaque(true);
stateslb.setBackground(lightblue);
stateslb.setForeground(Color.blue);
stateslb.setOpaque(true);
inputlb.setBackground(pink);
inputlb.setForeground(Color.blue);
inputlb.setOpaque(true);
StateDisplay.setBackground(lightblue);
JPanel pl = new JPanel(),
pr = new JPanel(),
prb = new JPanel(),
pll = new JPanel(),
prr = new JPanel();
pl.setLayout(new BorderLayout());
pr.setLayout(new BorderLayout());
prb.setLayout(new BorderLayout());
pll.setLayout(new BorderLayout());
prr.setLayout(new BorderLayout());
prb.add(inputlb, "North");
prb.add(Input, "Center");
pl.add(eventslb, "North");
pl.add(spEvents, "Center");
pr.add(dumplb, "North");
pr.add(spDump, "Center");
pr.add(prb, "South");
pll.add(stateslb, "North");
pll.add(spStates, "Center");
pll.add(StateDisplay, "South");
pll.setPreferredSize(new Dimension(165, 10));
pll.setBorder(BorderFactory.createEtchedBorder());
JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pl, pr);
sp.setDividerSize(4);
sp.setBorder(BorderFactory.createEtchedBorder());
JTextPane authorlb = new JTextPane();
StyledDocument doc = authorlb.getStyledDocument();
MutableAttributeSet standard = new SimpleAttributeSet();
StyleConstants.setAlignment(standard, StyleConstants.ALIGN_RIGHT);
StyleConstants.setItalic(standard, true);
StyleConstants.setForeground(standard, Color.gray);
StyleConstants.setFontFamily(standard, "Serif");
doc.setParagraphAttributes(0, 0, standard, true);
authorlb.setText("Thomas Huining Feng, MSDL, McGill, Nov. 2003");
authorlb.setEditable(false);
authorlb.setBackground(Color.white);
authorlb.setForeground(Color.red);
authorlb.setOpaque(true);
authorlb.setBorder(BorderFactory.createEmptyBorder(4, 0, 4, 0));
prr.add(sp, "Center");
prr.add(authorlb, "South");
JSplitPane sp2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, pll, prr);
sp2.setOneTouchExpandable(true);
sp2.setBorder(BorderFactory.createEmptyBorder());
add(scclb, "North");
add(sp2, "Center");
Events.addMouseListener(this);
Input.addActionListener(this);
States.addListSelectionListener(this);
setSize(new Dimension(600, 210));
Input.requestFocus();
}
private void promptInvalidModel()
{
setLayout(new BorderLayout());
JLabel scclb = new JLabel("SCC Demonstration -- a Preview to Version 0.1, Thomas", JLabel.CENTER);
scclb.setForeground(Color.red);
scclb.setBackground(Color.white);
scclb.setOpaque(true);
JLabel invalidlb = new JLabel("ERROR: Model \""+getParameter(ModelParameter)+"\" could not be loaded.", JLabel.CENTER);
invalidlb.setForeground(Color.blue);
invalidlb.setBackground(Color.white);
invalidlb.setOpaque(true);
invalidlb.setBorder(BorderFactory.createEtchedBorder());
Font fontlB = new Font("SansSerif", Font.BOLD, 16);
Font fontl = new Font("SansSerif", Font.BOLD, 14);
scclb.setFont(fontl);
invalidlb.setFont(fontlB);
add(scclb, "North");
add(invalidlb, "Center");
}
}