1
//////////////////////////////////////////////////////////////////////
3
// JCSP ("CSP for Java") Libraries //
4
// Copyright (C) 1996-2008 Peter Welch and Paul Austin. //
5
// 2001-2004 Quickstone Technologies Limited. //
7
// This library is free software; you can redistribute it and/or //
8
// modify it under the terms of the GNU Lesser General Public //
9
// License as published by the Free Software Foundation; either //
10
// version 2.1 of the License, or (at your option) any later //
13
// This library is distributed in the hope that it will be //
14
// useful, but WITHOUT ANY WARRANTY; without even the implied //
15
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
16
// PURPOSE. See the GNU Lesser General Public License for more //
19
// You should have received a copy of the GNU Lesser General //
20
// Public License along with this library; if not, write to the //
21
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, //
22
// Boston, MA 02111-1307, USA. //
24
// Author contact: P.H.Welch@kent.ac.uk //
27
//////////////////////////////////////////////////////////////////////
32
import java.util.Vector;
33
import org.jcsp.lang.*;
36
* {@link java.awt.TextField <TT>java.awt.TextField</TT>}
37
* with a channel interface.
38
* <H2>Process Diagram</H2>
39
* <p><img src="doc-files/ActiveTextField1.gif"></p>
41
* <H2>Description</H2>
42
* <TT>ActiveTextField</TT> is a process extension of <TT>java.awt.TextField</TT>
43
* with channels for run-time configuration and event notification. The event channels
44
* should be connected to one or more application-specific server processes (instead
45
* of registering a passive object as a <I>Listener</I> to this component).
47
* All channels are optional. The <TT>configure</TT> and <TT>event</TT> channels are
48
* settable from a constructor.
49
* The <TT>event</TT> channel delivers updated text whenever
50
* the <TT>ActiveTextField</TT> is changed.
51
* Other event channels can be added to notify the occurrence of any other events
52
* the component generates (by calling the appropriate
53
* <TT>add</TT><I>XXX</I><TT>EventChannel</TT> method <I>before</I> the process is run).
54
* Messages can be sent down the <TT>configure</TT> channel at any time to configure
55
* the component. See the <A HREF="#Protocols">table below</A> for details.
57
* All channels are managed by independent internal handler processes. It is, therefore,
58
* safe for a serial application process both to service an event channel and configure
59
* the component -- no deadlock can occur.
61
* <I>IMPORTANT: it is essential that event channels from this process are
62
* always serviced -- otherwise the Java Event Thread will be blocked and the GUI
63
* will stop responding. A simple way to guarantee this is to use channels
64
* configured with overwriting buffers.
67
* final One2OneChannel myTextFieldEvent = Channel.one2one (new OverWriteOldestBuffer (n));
69
* final ActiveTextField myTextField =
70
* new ActiveTextField (null, myTextFieldEvent.out (), "Edit Me");
72
* <I>This will ensure that the Java Event Thread will never be blocked.
73
* Slow or inattentive readers may miss rapidly generated events, but
74
* the </I><TT>n</TT><I> most recent events will always be available.</I>
76
* <H2><A NAME="Protocols">Channel Protocols</A></H2>
80
* <TH COLSPAN="3">Input Channels</TH>
83
* <TH ROWSPAN="4">configure</TH>
85
* <TD>Set the text in this <TT>ActiveTextField</TT> to the value of the <TT>String</TT></TD>
91
* <LI>If this is the <TT>Boolean.TRUE</TT> object,
92
* the text field is made active</LI>
93
* <LI>If this is the <TT>Boolean.FALSE</TT> object,
94
* the text field is made inactive</LI>
95
* <LI>Other <TT>Boolean</TT> objects are ignored</LI>
100
* <TD>ActiveTextField.Configure</TD>
101
* <TD>Invoke the user-defined <TT>Configure.configure</TT> method on the textField.</TD>
104
* <TD><I>otherwise</I></TD>
105
* <TD>Append the <TT>toString</TT> form of the object to the text in this <TT>ActiveTextField</TT>.</TD>
108
* <TH COLSPAN="3">Output Channels</TH>
113
* <TD>The text in the <TT>ActiveTextField</TT> (whenever the text field is altered)</TD>
116
* <TH>componentEvent</TH>
117
* <TD>ComponentEvent</TD>
118
* <TD>See the {@link #addComponentEventChannel
119
* <TT>addComponentEventChannel</TT>} method.</TD>
122
* <TH>focusEvent</TH>
123
* <TD>FocusEvent</TD>
124
* <TD>See the {@link #addFocusEventChannel
125
* <TT>addFocusEventChannel</TT>} method.</TD>
130
* <TD>See the {@link #addKeyEventChannel
131
* <TT>addKeyEventChannel</TT>} method.</TD>
134
* <TH>mouseEvent</TH>
135
* <TD>MouseEvent</TD>
136
* <TD>See the {@link #addMouseEventChannel
137
* <TT>addMouseEventChannel</TT>} method.</TD>
140
* <TH>mouseMotionEvent</TH>
141
* <TD>MouseEvent</TD>
142
* <TD>See the {@link #addMouseMotionEventChannel
143
* <TT>addMouseMotionEventChannel</TT>} method.</TD>
149
* import org.jcsp.lang.*;
150
* import org.jcsp.util.*;
151
* import org.jcsp.awt.*;
154
* public class ActiveTextFieldExample {
156
* public static void main (String argv[]) {
158
* final ActiveClosingFrame frame =
159
* new ActiveClosingFrame ("ActiveTextFieldExample Example");
161
* final Any2OneChannel event = Channel.any2one (new OverWriteOldestBuffer (10));
163
* final String[] string =
164
* {"Entia Non Sunt Multiplicanda Praeter Necessitatem",
165
* "Less is More ... More or Less",
166
* "Everything we do, we do it to you",
167
* "Race Hazards - What Rice Hozzers?",
168
* "Cogito Ergo Occam"};
170
* final String goodbye = "Goodbye World";
172
* final ActiveTextField[] activeText =
173
* new ActiveTextField[string.length];
175
* for (int i = 0; i < string.length; i++) {
176
* activeText[i] = new ActiveTextField (null, event.out (), string[i]);
179
* Panel panel = new Panel (new GridLayout (string.length, 1));
180
* for (int i = 0; i < string.length; i++) {
181
* panel.add (activeText[i]);
184
* final Frame realFrame = frame.getActiveFrame ();
185
* realFrame.setBackground (Color.green);
186
* realFrame.add (panel);
188
* realFrame.setVisible (true);
193
* new Parallel (activeText),
195
* public void run () {
196
* boolean running = true;
198
* String s = (String) event.in ().read ();
199
* System.out.println (s);
200
* running = (! s.equals (goodbye));
202
* realFrame.setVisible (false);
213
* @see org.jcsp.awt.ActiveTextEnterField
214
* @see java.awt.TextField
215
* @see java.awt.event.ComponentEvent
216
* @see java.awt.event.FocusEvent
217
* @see java.awt.event.KeyEvent
218
* @see java.awt.event.MouseEvent
219
* @see org.jcsp.util.OverWriteOldestBuffer
221
* @author P.D. Austin and P.H. Welch
224
public class ActiveTextField extends TextField implements CSProcess
227
* The Vector construct containing the handlers.
229
private Vector vec = new Vector();
232
* The channel from which configuration messages arrive.
234
private ChannelInput configure;
237
* Constructs a new <TT>ActiveTextField</TT> with no initial text,
238
* configuration or event channels.
241
public ActiveTextField()
243
this(null, null, "", 0);
247
* Constructs a new <TT>ActiveTextField</TT> with initial text and default width,
248
* but no configuration or event channels.
250
* @param s the initial text displayed in the field.
252
public ActiveTextField(String s)
254
this(null, null, s, s.length());
258
* Constructs a new <TT>ActiveTextField</TT> with initial text and width,
259
* but no configuration or event channels.
261
* @param s the initial text displayed in the field.
262
* @param columns the width of the field.
264
public ActiveTextField(String s, int columns)
266
this(null, null, s, columns);
270
* Constructs a new <TT>ActiveTextField</TT> with configuration and event channels,
271
* but no initial text.
273
* @param configure the channel for configuration events
274
* -- can be null if no configuration is required.
275
* @param event the current text will be output when the text field is changed
276
* -- can be null if no notification is required.
278
public ActiveTextField(ChannelInput configure, ChannelOutput event)
280
this(configure, event, "", 0);
284
* Constructs a new <TT>ActiveTextField</TT> with configuration and event channels,
285
* initial text and default width.
287
* @param configure the channel for configuration events
288
* -- can be null if no configuration is required.
289
* @param event the current text will be output when the text field is changed
290
* -- can be null if no notification is required.
291
* @param s the initial text displayed in the field.
293
public ActiveTextField(ChannelInput configure, ChannelOutput event, String s)
295
this(configure, event, s, s.length());
299
* Constructs a new <TT>ActiveTextField</TT> with configuration and event channels,
300
* initial text and width.
302
* @param configure the channel for configuration events
303
* -- can be null if no configuration is required.
304
* @param event the current text will be output when the text field is changed
305
* -- can be null if no notification is required.
306
* @param s the initial text displayed in the field.
307
* @param columns the width of the field.
309
public ActiveTextField(ChannelInput configure, ChannelOutput event, String s, int columns)
313
// Only create an event handler if the event Channel is not null.
316
TextEventHandler handler = new TextEventHandler(event);
317
addTextListener(handler);
318
vec.addElement(handler);
320
this.configure = configure;
324
* Sets the configuration channel for this <TT>ActiveTextField</TT>.
325
* This method overwrites any configuration channel set in the constructor.
327
* @param configure the channel for configuration events.
328
* If the channel passed is <TT>null</TT>, no action will be taken.
330
public void setConfigureChannel(ChannelInput configure)
332
this.configure = configure;
336
* Add a new channel to this component that will be used to notify that
337
* a <TT>ComponentEvent</TT> has occurred. <I>This should be used
338
* instead of registering a ComponentListener with the component.</I> It is
339
* possible to add more than one channel by calling this method multiple times
340
* If the channel passed is <TT>null</TT>, no action will be taken.
342
* <I>NOTE: This method must be called before this process is run.</I>
344
* @param componentEvent the channel down which to send ComponentEvents.
346
public void addComponentEventChannel(ChannelOutput componentEvent)
348
if (componentEvent != null)
350
ComponentEventHandler handler = new ComponentEventHandler(componentEvent);
351
addComponentListener(handler);
352
vec.addElement(handler);
357
* Add a new channel to this component that will be used to notify that
358
* a <TT>FocusEvent</TT> has occurred. <I>This should be used
359
* instead of registering a FocusListener with the component.</I> It is
360
* possible to add more than one channel by calling this method multiple times
361
* If the channel passed is <TT>null</TT>, no action will be taken.
363
* <I>NOTE: This method must be called before this process is run.</I>
365
* @param focusEvent the channel down which to send FocusEvents.
367
public void addFocusEventChannel(ChannelOutput focusEvent)
369
if (focusEvent != null)
371
FocusEventHandler handler = new FocusEventHandler(focusEvent);
372
addFocusListener(handler);
373
vec.addElement(handler);
378
* Add a new channel to this component that will be used to notify that
379
* a <TT>KeyEvent</TT> has occurred. <I>This should be used
380
* instead of registering a KeyListener with the component.</I> It is
381
* possible to add more than one channel by calling this method multiple times
382
* If the channel passed is <TT>null</TT>, no action will be taken.
384
* <I>NOTE: This method must be called before this process is run.</I>
386
* @param keyEvent the channel down which to send KeyEvents.
388
public void addKeyEventChannel(ChannelOutput keyEvent)
390
if (keyEvent != null)
392
KeyEventHandler handler = new KeyEventHandler(keyEvent);
393
addKeyListener(handler);
394
vec.addElement(handler);
399
* Add a new channel to this component that will be used to notify that
400
* a <TT>MouseEvent</TT> has occurred. <I>This should be used
401
* instead of registering a MouseListener with the component.</I> It is
402
* possible to add more than one channel by calling this method multiple times
403
* If the channel passed is <TT>null</TT>, no action will be taken.
405
* <I>NOTE: This method must be called before this process is run.</I>
407
* @param mouseEvent the channel down which to send MouseEvents.
409
public void addMouseEventChannel(ChannelOutput mouseEvent)
411
if (mouseEvent != null)
413
MouseEventHandler handler = new MouseEventHandler(mouseEvent);
414
addMouseListener(handler);
415
vec.addElement(handler);
420
* Add a new channel to this component that will be used to notify that
421
* a <TT>MouseMotionEvent</TT> has occurred. <I>This should be used
422
* instead of registering a MouseMotionListener with the component.</I> It is
423
* possible to add more than one channel by calling this method multiple times
424
* If the channel passed is <TT>null</TT>, no action will be taken.
426
* <I>NOTE: This method must be called before this process is run.</I>
428
* @param mouseMotionEvent the channel down which to send MouseMotionEvents.
430
public void addMouseMotionEventChannel(ChannelOutput mouseMotionEvent)
432
if (mouseMotionEvent != null)
434
MouseMotionEventHandler handler = new MouseMotionEventHandler(mouseMotionEvent);
435
addMouseMotionListener(handler);
436
vec.addElement(handler);
440
* This enables general configuration of this component. Any object implementing
441
* this interface and sent down the <TT>configure</TT> channel to this component will have its
442
* <TT>configure</TT> method invoked on this component.
444
* For an example, see {@link ActiveApplet.Configure}.
446
static public interface Configure
449
* @param textField the TextField being configured.
451
public void configure(final TextField textField);
455
* The main body of this process.
459
if (configure != null)
463
Object message = configure.read();
464
if (message instanceof String)
465
setText((String) message);
466
else if (message instanceof Boolean)
468
if (message == Boolean.TRUE)
470
else if (message == Boolean.FALSE)
473
else if (message instanceof Configure)
474
((Configure) message).configure(this);
476
setText(message.toString());
b'\\ No newline at end of file'