JCSP を使って書いたチャットのコード(2)
既に忘れかけてたけど-_-、一応 jcsp.awt を用いたバージョン。
まぁ、ここは日記の使い勝手検証目的みたいなもんだし^^;。
jcsp.awt はテキスト入出力時のフォーカス制御などに柔軟性が無いなど、まともなアプリケーションにしようと思ったら苦労することが多くありそう。
統一的なインターフェイスと並列化による即応性は魅力なんですけどねぇ…。
[ActiveChat.java]
import java.awt.*;
import jcsp.awt.*;
import jcsp.lang.*;
import jcsp.plugNplay.*;
import jcsp.util.*;class ActiveChat {
public static void main(String[] args) throws Exception {
Any2OneChannel sendSocket =
Any2OneChannel.create(new OverWriteOldestBuffer(10));CSProcess[] nodes = new CSProcess[5];
Channel[] readSockets =
One2OneChannel.create(
nodes.length - 1,
new OverWriteOldestBuffer(10));for (int i = 0; i < nodes.length - 1; i++) {
nodes[i] = new ChatWindow("node:"+i, readSockets[i], sendSocket);
}
AltingChannelInput receiverAdder =
One2OneChannel.create(new OverWriteOldestBuffer(1));
nodes[nodes.length - 1] =
new DynamicDelta(sendSocket, receiverAdder, readSockets);new Parallel(nodes).run();
}
}class ChatWindow implements CSProcess {
private String name;
private ChannelInput in;
private ChannelOutput out;ActiveClosingFrame frame;
ActiveTextArea view;
ActiveTextEnterField input;
Filter filter;public ChatWindow(String name, ChannelInput in, ChannelOutput out) {
this.name = name;
this.in = in;
this.out = out;filter = new Filter(out) {
protected Object filter(Object o) {
if (((String)o).length() == 0) return null;
input.getActiveTextField().setText("");
return o + "\n";
}
};frame = new ActiveClosingFrame("Example");
view = new ActiveTextArea(in, null, "", 20, 60);
view.setEditable(false);
input = new ActiveTextEnterField(null, filter.out(), "");Panel p = new Panel(new BorderLayout());
p.add(view, BorderLayout.CENTER);
p.add(input.getActiveTextField(), BorderLayout.SOUTH);final Frame realFrame = frame.getActiveFrame();
realFrame.setBackground(Color.green);
realFrame.add(p);
realFrame.pack();
realFrame.setVisible(true);
}public void run() {
new Parallel(
new CSProcess[] {
frame,
view,
input,
filter
}
).run();
}
}/**
* write に filter を付加する。
* 利用者はオリジナルの代わりに Filter#out() で得た ChannelOutput を用いる。
*/
abstract class Filter implements CSProcess {
private Channel in;
private ChannelOutput out;
protected Filter(ChannelOutput out) {
this.out = out;
in = One2OneChannel.create(new OverWriteOldestBuffer(10));
}
public final ChannelOutput out() {
return in;
}
public final void run() {
Object o;
while (true) {
o = filter(in.read());
if (o != null) out.write(o);
}
}
/** null を返すことで送信を拒否することもできる。 */
protected abstract Object filter(Object o);
}