|
CSP for Java (JCSP) 1.1-rc4 |
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectorg.jcsp.awt.ActiveButtonControl
public class ActiveButtonControl
This is a user-programmable finite state machine for
controlling an array of ActiveButton
s.
ActiveButton
s. It is connected to the array
by its event and configure channels, matching pairs of which
must be attached to individual buttons. A button push generates a message down
the attached event channel, which triggers a state transition in the
ActiveButtonControl and a report that is sent down its report
channel. The report consists of the new state just reached (an Integer)
and, optionally, the channel index identifying which button was pushed (also an
Integer) and the message generated by the button (the String
that was labelling it). Also, the labels on all the buttons may be reset on
entry to a new state, together with their enable/disable status (via messages
sent back by ActiveButtonControl on its configure channels).
All external channels must be supplied as parameters to a constructor. The constructor must also be passed an array of String arrays (one String array defining the labels allowed for each attached button), the state table and a starting state.
The state table is an array of ActiveButtonState
s. Each
ActiveButtonState has three arrays, all of size equal to the number
of buttons being controlled. The first array holds the indices defining the
label to be displayed on each button when in that state. The second array
holds the booleans defining the enable/disable status for each button for
that state. The third array holds the states to change into if the corresponding
button is pushed when in that state.
Input Channels | ||
---|---|---|
event[i] | String | The label on the attached ActiveButton (when it is pressed and released). |
Output Channels | ||
configure[i] | String | Defines the label on the attached ActiveButton . |
Boolean | Defines the enable/disable status on the attached ActiveButton . |
|
report | Integer | The new state (after a state transition). Note: depending on the state transition table, this may be the same as the previous state.. |
Integer |
The channel index identifying which button caused the state transition.
Note: this will be output after the above state information only if
requested - see setReportButtonIndex .
|
|
String |
The label on the button that caused the state transition.
Note: this will be output after the above information only if
requested - see setReportButtonLabel .
|
import java.awt.*; import org.jcsp.lang.*; import org.jcsp.util.*; import org.jcsp.awt.*; public class ActiveButtonControlExample { public static void main (String argv[]) { final Frame root = new Frame ("ActiveButtonControl Example"); final String[][] labels = { new String[] {"Hello World", "JCSP", "Restart"}, new String[] {"Rocket Science", "JCSP", "occam"}, new String[] {"Deadlock", "JCSP", "occam"}, new String[] {"Race Hazard", "JCSP", "occam"}, new String[] {"Starvation", "JCSP", "Quit", "Back"}, new String[] {"Threads", "JCSP", "occam"}, new String[] {"Livelock", "JCSP", "occam"}, new String[] {"Monitors", "JCSP", "occam"}, new String[] {"Alchemy", "JCSP", "Smile"} }; final int nButtons = labels.length; final One2OneChannel[] fromButton = Channel.one2oneArray (nButtons, new OverWriteOldestBuffer (1)); final Any2OneChannel[] toButton = Channel.any2oneArray (nButtons); final One2OneChannel report = Channel.one2one (); final ActiveButton[] button = new ActiveButton[nButtons]; for (int i = 0; i < nButtons; i++) { button[i] = new ActiveButton (toButton[i].in (), fromButton[i].out (), "XXXXXXXXX"); button[i].setBackground (Color.green); } root.setSize (450, 200); root.setLayout (new GridLayout (nButtons/3, 3)); for (int i = 0; i < nButtons; i++) { root.add (button[i]); } root.setVisible (true); final int initial = 0; // state names final int diagonal = 1; final int opposite = 2; final int centre = 3; final int full = 4; final int terminal = 5; final String[] stateName = { "initial", "diagonal", "opposite", "centre", "full", "terminal" }; final ActiveButtonState[] state = new ActiveButtonState[stateName.length]; try { state[initial] = new ActiveButtonState ( new int[] { 0, 0, 1, 0, 1, 1, // label index 1, 1, 1 }, new boolean[] { true, true, false, true, false, false, // enable/disable false, false, false }, new int[] { diagonal, initial, initial, initial, initial, initial, // next state initial, initial, initial } );[In this example, nine buttons are laid out in a 3x3 grid in the root frame. The layout of the above state definition reflects this grid. Note that this code is enclosed within a try-catch block since the ActiveButtonState
constructor
performs numerous consistency checks on its parameters and may throw an exception.
The label index array specifies that, in this initial state, the north-west button and its east and south neighbours display their 0-index labels (i.e. "Hello World", "Rocket Science" and "Race Hazard" respectively). All the other buttons display their 1-index labels (which all happen to be "JCSP").
The enable/disable array specifies that, in this initial state, all those buttons displaying "JCSP" are disabled and all the others are enabled.
The next state array specifies that, in this initial state, if the top-left button is pushed, then the state should change to diagonal. However, if any other button is pushed, the state remains as initial. Note that it doesn't actually matter what is defined for those buttons that are disabled in this state.
The diagonal, opposite, centre and full states are defined similarly. We pick up the program for the definition of its terminal state (where all the labels are "JCSP" and all the buttons are disabled).]
state[terminal] = new ActiveButtonState ( new int[] { 1, 1, 1, 1, 1, 1, // label index 1, 1, 1 }, new boolean[] { false, false, false, false, false, false, // enable/disable false, false, false }, new int[] { terminal, terminal, terminal, terminal, terminal, terminal, // next state terminal, terminal, terminal } ); } catch (ActiveButtonState.BadArguments e) { System.out.println (e); System.exit (0); }; new Parallel ( new CSProcess[] { new Parallel (button), new CSProcess () { public void run () { final ActiveButtonControl control; try { control = new ActiveButtonControl ( fromButton.in (), toButton.out (), report.out (), labels, state, initial ); control.setReportButtonIndex (true); control.setReportButtonLabel (true); control.run (); } catch (ActiveButtonControl.BadArguments e) { System.out.println (e); System.exit (0); } } }, new CSProcess () { public void run () { boolean running = true; while (running) { final int newState = ((Integer) report.in ().read ()).intValue (); final int buttonIndex = ((Integer) report.in ().read ()).intValue (); final String buttonString = (String) report.in ().read (); System.out.println ( "Button " + buttonIndex + " (" + buttonString + ") pressed ==> " + stateName[newState] ); running = (newState != terminal); } final CSTimer tim = new CSTimer (); // countdown to exit final long interval = 1000; // one second long timeout = tim.read (); for (int i = 10; i >= 0; i--) { timeout += interval; tim.after (timeout); final String iString = (new Integer (i)).toString (); for (int j = 0; j < nButtons; j++) { toButton[j].write (iString); } } root.setVisible (false); System.exit (0); } } } ).run (); } }The countdown to exit sequence is just for fun. In its terminal state, this ActiveButtonControl disables all its buttons and will never change state again. This leaves the buttons free to be configured by some other process, such as the last one above once it has detected that the controller is dead. This is why the toButton configure channels were created as Any2OneChannelImpl, rather than the more usual One2OneChannelImpl.
ActiveButton
,
ActiveButtonState
Nested Class Summary | |
---|---|
static class |
ActiveButtonControl.BadArguments
This gets thrown if a consistency check fails in the ActiveButtonControl
constructor. |
Constructor Summary | |
---|---|
ActiveButtonControl(AltingChannelInput[] event,
ChannelOutput[] configure,
ChannelOutput report,
String[][] label,
ActiveButtonState[] state,
int startState)
Constructs a new ActiveButtonControl, performing consistency checks on its supplied arguments. |
|
ActiveButtonControl(AltingChannelInput[] event,
ChannelOutput[] configure,
ChannelOutput report,
String[][] label,
ActiveButtonState[] state,
int startState,
boolean verbose)
Constructs a new ActiveButtonControl, performing consistency checks on its supplied arguments, with a verbose reporting option. |
Method Summary | |
---|---|
void |
run()
Main body of the process. |
void |
setReportButtonIndex(boolean condition)
Defines whether the index of the pushed button causing a state transition should be included in the report. |
void |
setReportButtonLabel(boolean condition)
Defines whether the label on the pushed button causing a state transition should be included in the report. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructor Detail |
---|
public ActiveButtonControl(AltingChannelInput[] event, ChannelOutput[] configure, ChannelOutput report, String[][] label, ActiveButtonState[] state, int startState) throws ActiveButtonControl.BadArguments
event
- equal-indexed elements of event and configure
must be connected to the same ActiveButton
.configure
- equal-indexed elements of event and configure
must be connected to the same ActiveButton
.report
- the channel on which state transitions are reported. A report has
up to three messages: the new state, the index of the button triggering
the transition (optional
) and its label
(optional
).label
- an array of string arrays (one for each controlled botton). Each
string array defines the label set allowed for each button.state
- the state transition table.startState
- the starting state for this finite state machine.
ActiveButtonControl.BadArguments
- if the consistency check fails.
The exception contains details of the error.public ActiveButtonControl(AltingChannelInput[] event, ChannelOutput[] configure, ChannelOutput report, String[][] label, ActiveButtonState[] state, int startState, boolean verbose) throws ActiveButtonControl.BadArguments
event
- equal-indexed elements of event and configure
must be connected to the same ActiveButton
.configure
- equal-indexed elements of event and configure
must be connected to the same ActiveButton
.report
- the channel on which state transitions are reported. A report has
up to three messages: the new state, the index of the button triggering
the transition (optional
) and its label
(optional
).label
- an array of string arrays (one for each controlled botton). Each
string array defines the label set allowed for each button.state
- the state transition table.startState
- the starting state for this finite state machine.verbose
- if true, a running commentary is printed on the consistency checks
and state transitions as they occur.
ActiveButtonControl.BadArguments
- if the consistency check fails.
The exception contains details of the error.Method Detail |
---|
public void setReportButtonIndex(boolean condition)
condition
- if true, the button index is reported - otherwise it is not reported.public void setReportButtonLabel(boolean condition)
condition
- if true, the button label is reported - otherwise it is not reported.public void run()
run
in interface CSProcess
|
CSP for Java (JCSP) 1.1-rc4 |
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |