changeset 133:8dce4348966c

*** empty log message ***
author kono
date Wed, 27 Aug 2008 18:27:12 +0900
parents 70fc1e70652c
children 4ad47fad8fa4
files rep/SessionManager.java rep/SessionManagerGUI.java rep/SessionManagerList.java rep/gui/ConnectionPanel.java rep/gui/DefaultTableModelTest.java rep/gui/JTableTest.java rep/net/REPNet.java sample/graph/Graph.java
diffstat 8 files changed, 34 insertions(+), 565 deletions(-) [+]
line wrap: on
line diff
--- a/rep/SessionManager.java	Wed Aug 27 18:22:36 2008 +0900
+++ b/rep/SessionManager.java	Wed Aug 27 18:27:12 2008 +0900
@@ -17,6 +17,7 @@
 import java.util.StringTokenizer;
 
 import rep.channel.REPServerSocketChannel;
+import rep.channel.REPSocketChannel;
 import rep.simulator.REPSelector;
 import rep.xml.SessionXMLDecoder;
 import rep.xml.SessionXMLEncoder;
@@ -38,7 +39,6 @@
 	
 	
 	private SessionList sessionlist;
-	//SocketChannel sessionchannel;
 	private SessionManagerGUI gui;
 	private Selector selector;
 	private SessionManagerList smList;
@@ -46,9 +46,6 @@
 	private boolean isMaster = true;
 	private EditorList  ownEditorList;
 	private String maxHost;
-	//private boolean addressIsGlobal;
-	//private SocketChannel sessionchannel;
-	//private boolean co;
 	private static int temp_port;
 	private static int send_port;
 	
@@ -65,8 +62,7 @@
 	
 	public void sessionManagerNet(int port) throws InterruptedException, IOException {
 	
-		//ServerSocketChannel ssc = ServerSocketChannel.open();
-		REPServerSocketChannel ssc = REPServerSocketChannel.open();
+		REPServerSocketChannel<REPCommand> ssc = REPServerSocketChannel.open();
 		
 		ssc.configureBlocking(false);	//reuse address 必須
 		
@@ -93,7 +89,7 @@
 					
 				}else if(key.isReadable()){
 					
-					SocketChannel channel = (SocketChannel)key.channel();
+					REPSocketChannel<REPCommand> channel = (REPSocketChannel<REPCommand>)key.channel();
 					REPPacketReceive receive = new REPPacketReceive(channel);
 					receive.setkey(key);
 					REPCommand receivedCommand = receive.unpackUConv();
@@ -169,21 +165,10 @@
 			command.setCMD(REP.SMCMD_UPDATE);
 			smList.sendExcept(channel, command);
 			
-			
-//			if(isMaster){
-//				command.setCMD(REP.SMCMD_UPDATE_ACK);
-//				smList.sendToSlave(command);
-//			}else{
-//				command.setCMD(REP.SMCMD_UPDATE);
-//				smList.sendToMaster(command);
-//			}
 			break;
 			
-//		case REP.SMCMD_PUT_ACK:
-//			break;
-			
+
 		case REP.SMCMD_SELECT:
-//			sessionlist.addEditor(channel, repCmd.sid, repCmd);	//sessionlistへ追加
 			editor = new Editor(channel);
 			
 			session = sessionlist.getSession(receivedCommand.sid);
@@ -191,9 +176,6 @@
 			if(session.isOwner()){
 				int eid2 = session.addEditor(editor);
 				editor.setEID(eid2);
-				//REPPacketSend send = new REPPacketSend(channel);
-				//receivedCommand.setCMD(REP.SMCMD_SELECT_ACK);
-				//receivedCommand.setEID(eid2);
 				sendCommand.setCMD(REP.SMCMD_SELECT_ACK);
 				sendCommand.setEID(eid2);
 				send.send(sendCommand);
@@ -399,41 +381,7 @@
 		return kindOfCmd;
 	}
 
-	private String setUTF16(String string) {
-    	//CharBuffer cb = CharBuffer.wrap(string);
-   		Charset charset = Charset.forName("UTF-16");
-   		ByteBuffer buffer = ByteBuffer.allocateDirect(string.length() * 2);
-		//CharsetEncoder encoder = charset.newEncoder();
-		try {
-			buffer = charset.encode(string);
-		} catch (IllegalStateException e) {
-			e.printStackTrace();
-		}
-		buffer.rewind();
-		String text = null;
-		for(int i=0;i<string.length();i++) {
-			text +=buffer.getChar();
-		}
-		String string2 = text;
-		return string2;
-	}
 
-	private boolean setMaxHost(SocketChannel channel, String host) {
-		if(maxHost == null) {
-			maxHost = myHost;
-			sessionlist.setMaxHost(maxHost);
-		}
-		if(host.compareTo(maxHost) > 0){
-			//host > MaxHost なら maxHost = host
-			//masterを設定する。
-			maxHost = host;
-			sessionlist.setMaxHost(maxHost);
-			setMaster(false, channel);
-			return true;
-		}else{
-			return false;
-		}
-	}
 
 	private void setMyHostName(String localHostName) {
 		myHost = localHostName + temp_port;
@@ -523,42 +471,15 @@
 		return host;
 	}
 
-//	private String getSocketString(SocketChannel sessionchannel) {
-//		SocketAddress socket = sessionchannel.socket().getRemoteSocketAddress();
-//		//String inetAddressString = sessionchannel.socket().getInetAddress().toString();
-//		StringTokenizer stn = new StringTokenizer(socket.toString(), "/");
-//		String socketString = null;
-//		while(stn.hasMoreTokens()){
-//			socketString = stn.nextToken();
-//			//System.out.println(socketString);
-//		}
-//		return socketString;
-//	}
-
 	public void connectionOccured(ConnectionEvent event) {
 		connectSession(event.getHost());
 	}
 
 	public void ActionOccured(REPActionEvent event) {
 		
-		/*** 元の ***/
-//		SocketChannel editorChannel = event.getEditorChannel();
-//		int sid = event.getSID();
-//		Editor editor = new Editor(editorChannel);
-//		editor.setHost(this.myHost);
-//		Session session = sessionlist.getSession(sid);
-//		session.addEditor(editor);
-//		
-//		Editor owner = session.getMaster();
-//		
-//		REPCommand command = new REPCommand();
-//		command.setCMD(REP.SMCMD_SELECT);
-//		command.setSID(sid);
-//		command.setString(editor.getHost() + ":" + editor.getPort());
-//		owner.send(command);
 		
 		/*** 書き直し ***/
-		SocketChannel channel = event.getEditorChannel();
+		REPSocketChannel channel = event.getEditorChannel();
 		int sid = event.getSID();
 		Session session = sessionlist.getSession(sid);
 		if(session.isOwner()){
@@ -570,7 +491,7 @@
 			REPPacketSend sender = new REPPacketSend(channel);
 			sender.send(sendCommand);
 		}else {
-			SocketChannel editorChannel = event.getEditorChannel();
+			REPSocketChannel editorChannel = event.getEditorChannel();
 			sid = event.getSID();
 			Editor editor = new Editor(editorChannel);
 			editor.setHost(myHost);
@@ -587,16 +508,9 @@
 		}
 		
 		
-		//REPPacketSend send = new REPPacketSend(editorChannel);
-		//send.send(new REPCommand(REP.SMCMD_SELECT_ACK, sid, eid, 0,0,0,""));
-		
-		
-		
-		//sessionlist.sendSelect(sid);
 	}
 
 	public void undo() {
-		// TODO Auto-generated method stub
 		ownEditorList.undoAllEditors();
 		System.out.println("Undo!");
 	}
--- a/rep/SessionManagerGUI.java	Wed Aug 27 18:22:36 2008 +0900
+++ b/rep/SessionManagerGUI.java	Wed Aug 27 18:27:12 2008 +0900
@@ -1,15 +1,9 @@
 package rep;
 
-import java.awt.BorderLayout;
 import java.awt.Container;
-import java.nio.channels.SocketChannel;
+import javax.swing.JFrame;
+import rep.channel.REPSocketChannel;
 
-import javax.swing.JButton;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-
-import rep.gui.ConnectionPanel;
 
 public class SessionManagerGUI implements Runnable{
 	public static void main(String[] args) {
@@ -50,19 +44,16 @@
 		rp.addConnectionListener(listener);
 	}
 
-	public void setComboEditor(int eid, SocketChannel channel) {
-		// TODO Auto-generated method stub
+	public void setComboEditor(int eid, REPSocketChannel channel) {
 		rp.setComboEditor(eid, channel);
 		rp.setTableEditor(eid, channel);
 	}
 
-	public void addREPActionListener(REPActionListener listener) {
-		// TODO Auto-generated method stub
+	public void addREPActionListener(REPActionListener<REPCommand> listener) {
 		rp.addREPActionListener(listener);
 	}
 
 	public void setComboSession(int sessionID, String string) {
-		// TODO Auto-generated method stub
 		rp.setComboSession(sessionID, string);
 		rp.setTableSession(sessionID, string);
 	}
--- a/rep/SessionManagerList.java	Wed Aug 27 18:22:36 2008 +0900
+++ b/rep/SessionManagerList.java	Wed Aug 27 18:27:12 2008 +0900
@@ -1,30 +1,30 @@
 package rep;
 
-import java.nio.channels.SocketChannel;
 import java.util.LinkedList;
 import java.util.List;
 
+import rep.channel.REPSocketChannel;
 import rep.xml.SessionXMLEncoder;
 
 public class SessionManagerList {
 
-	private List<SocketChannel> list = new LinkedList<SocketChannel>();
+	private List<REPSocketChannel<REPCommand>> list = new LinkedList<REPSocketChannel<REPCommand>>();
 	private int mySMID;
-	private SocketChannel master;
+	private REPSocketChannel<REPCommand> master;
 
-	public void add(SocketChannel channel) {
+	public void add(REPSocketChannel<REPCommand> channel) {
 		list.add(channel);
 	}
 
 	public void sendUpdate(int sessionID, String string) {
-		for(SocketChannel channel : list){
+		for(REPSocketChannel<REPCommand> channel : list){
 			REPPacketSend send = new REPPacketSend(channel);
 			send.send(new REPCommand(REP.SMCMD_UPDATE, 0, mySMID, 0, 0, string.length(), string));
 		}
 	}
 
 	public void sendJoin(REPCommand command) {
-		for(SocketChannel channel : list){
+		for(REPSocketChannel<REPCommand> channel : list){
 			REPPacketSend send = new REPPacketSend(channel);
 			send.send(command);
 		}
@@ -38,14 +38,14 @@
 	
 	public void sendUpdateDown(REPCommand command){
 		command.setCMD(REP.SMCMD_UPDATE_DOWN);
-		for(SocketChannel channel : list){
+		for(REPSocketChannel<REPCommand> channel : list){
 			if(channel == master) continue;
 			REPPacketSend send = new REPPacketSend(channel);
 			send.send(command);
 		}
 	}
 	
-	public void setMaster(SocketChannel channel){
+	public void setMaster(REPSocketChannel<REPCommand> channel){
 		this.master = channel;
 	}
 
@@ -53,13 +53,13 @@
 		SessionXMLEncoder encoder = new SessionXMLEncoder(sessionlist);
 		command.setString(encoder.sessionListToXML());
 		
-		for(SocketChannel channel : list){
+		for(REPSocketChannel<REPCommand> channel : list){
 			REPPacketSend send = new REPPacketSend(channel);
 			send.send(command);
 		}
 	}
 
-	public void send(SocketChannel channel, REPCommand repCmd) {
+	public void send(REPSocketChannel<REPCommand> channel, REPCommand repCmd) {
 		
 	}
 
@@ -69,15 +69,15 @@
 	}
 
 	public void sendToSlave(REPCommand repCmd) {
-		for(SocketChannel channel : list){
+		for(REPSocketChannel<REPCommand> channel : list){
 			if(channel.equals(master)) continue;
 			REPPacketSend send = new REPPacketSend(channel);
 			send.send(repCmd);
 		}
 	}
 
-	public void sendExcept(SocketChannel exceptChannel, REPCommand command) {
-		for(SocketChannel channel : list){
+	public void sendExcept(REPSocketChannel<REPCommand> exceptChannel, REPCommand command) {
+		for(REPSocketChannel<REPCommand> channel : list){
 			if(channel.equals(exceptChannel)) continue;
 			REPPacketSend send = new REPPacketSend(channel);
 			send.send(command);
--- a/rep/gui/ConnectionPanel.java	Wed Aug 27 18:22:36 2008 +0900
+++ b/rep/gui/ConnectionPanel.java	Wed Aug 27 18:27:12 2008 +0900
@@ -1,6 +1,5 @@
 package rep.gui;
 
-import java.awt.LayoutManager;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 
@@ -12,9 +11,13 @@
 
 public class ConnectionPanel extends JPanel implements ActionListener{
 	
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
 	private JButton button;
 	private JTextField textField;
-	private String host;
+	public String host;
 
 	public ConnectionPanel(ConnectionListener connectionlistener){
 		button = new JButton("Connect");
--- a/rep/gui/DefaultTableModelTest.java	Wed Aug 27 18:22:36 2008 +0900
+++ b/rep/gui/DefaultTableModelTest.java	Wed Aug 27 18:27:12 2008 +0900
@@ -1,1 +1,1 @@
-package rep.gui;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

class DefaultTableModelTest extends JFrame {

	DefaultTableModelTest() {
		getContentPane().setLayout(new FlowLayout());

		String[][] rowData = {
			{ "A1", "B1", "C1" },
			{ "A2", "B2", "C2" },
			{ "A3", "B3", "C3" },
			{ "A4", "B4", "C4" },
		};
		String[] colNames = { "A", "B", "C" };

		DefaultTableModel tm = new DefaultTableModel(rowData, colNames);
		JTable tb = new JTable(tm);
		JScrollPane sp = new JScrollPane(tb);
		sp.setPreferredSize(new Dimension(230, 80));
		getContentPane().add(sp);

		String[] data = { "A5", "B5", "C5" };
		tm.addRow(data);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("DefaultTableModelTest");
		setSize(250, 120);
		setVisible(true);
	}
	public static void main(String[] args) {
		new DefaultTableModelTest();
	}
}
\ No newline at end of file
+package rep.gui;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

class DefaultTableModelTest extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	DefaultTableModelTest() {
		getContentPane().setLayout(new FlowLayout());

		String[][] rowData = {
			{ "A1", "B1", "C1" },
			{ "A2", "B2", "C2" },
			{ "A3", "B3", "C3" },
			{ "A4", "B4", "C4" },
		};
		String[] colNames = { "A", "B", "C" };

		DefaultTableModel tm = new DefaultTableModel(rowData, colNames);
		JTable tb = new JTable(tm);
		JScrollPane sp = new JScrollPane(tb);
		sp.setPreferredSize(new Dimension(230, 80));
		getContentPane().add(sp);

		String[] data = { "A5", "B5", "C5" };
		tm.addRow(data);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("DefaultTableModelTest");
		setSize(250, 120);
		setVisible(true);
	}
	public static void main(String[] args) {
		new DefaultTableModelTest();
	}
}
\ No newline at end of file
--- a/rep/gui/JTableTest.java	Wed Aug 27 18:22:36 2008 +0900
+++ b/rep/gui/JTableTest.java	Wed Aug 27 18:27:12 2008 +0900
@@ -1,1 +1,1 @@
-package rep.gui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.*;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

class JTableTest extends JFrame implements ActionListener, FocusListener, ListSelectionListener{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JTable tb;
	JTableTest() {
		getContentPane().setLayout(new FlowLayout());

		tb = new JTable(10, 5);
		tb.setValueAt("AAA", 0, 0);
		tb.setValueAt("BBB", 1, 1);
		tb.setValueAt("CCC", 2, 2);
		
		tb.addFocusListener(this);
		

		JScrollPane sp = new JScrollPane(tb);
		sp.setPreferredSize(new Dimension(230, 80));
		getContentPane().add(sp);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("JTableTest");
		setSize(250, 120);
		setVisible(true);
	}
	public static void main(String[] args) {
		new JTableTest();
	}
	public void actionPerformed(ActionEvent event) {
		//if(event.getSource() == tb){
		//	int a = tb.getSelectedColumn();
		//	int b = tb.getSelectedRow();
		//	System.out.println("Selected item is " + a + ":" + b);
		//}
	}

	public void focusGained(FocusEvent event) {
		int column = tb.getSelectedColumn();
		int row = tb.getSelectedRow();
		System.out.println("Gained item is " + column + ":" + row);
	}
	public void focusLost(FocusEvent event) {
		
	}
	public void valueChanged(ListSelectionEvent event) {
		int column = tb.getSelectedColumn();
		int row = tb.getSelectedRow();
		Object value = tb.getValueAt(row, column);
		System.out.println("Gained item is " + column + ":" + row + "," + value);
	}
}
\ No newline at end of file
+package rep.gui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

class JTableTest extends JFrame implements ActionListener, FocusListener, ListSelectionListener{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JTable tb;
	JTableTest() {
		getContentPane().setLayout(new FlowLayout());

		tb = new JTable(10, 5);
		tb.setValueAt("AAA", 0, 0);
		tb.setValueAt("BBB", 1, 1);
		tb.setValueAt("CCC", 2, 2);
		
		tb.addFocusListener(this);
		

		JScrollPane sp = new JScrollPane(tb);
		sp.setPreferredSize(new Dimension(230, 80));
		getContentPane().add(sp);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("JTableTest");
		setSize(250, 120);
		setVisible(true);
	}
	public static void main(String[] args) {
		new JTableTest();
	}
	public void actionPerformed(ActionEvent event) {
		//if(event.getSource() == tb){
		//	int a = tb.getSelectedColumn();
		//	int b = tb.getSelectedRow();
		//	System.out.println("Selected item is " + a + ":" + b);
		//}
	}

	public void focusGained(FocusEvent event) {
		int column = tb.getSelectedColumn();
		int row = tb.getSelectedRow();
		System.out.println("Gained item is " + column + ":" + row);
	}
	public void focusLost(FocusEvent event) {
		
	}
	public void valueChanged(ListSelectionEvent event) {
		int column = tb.getSelectedColumn();
		int row = tb.getSelectedRow();
		Object value = tb.getValueAt(row, column);
		System.out.println("Gained item is " + column + ":" + row + "," + value);
	}
}
\ No newline at end of file
--- a/rep/net/REPNet.java	Wed Aug 27 18:22:36 2008 +0900
+++ b/rep/net/REPNet.java	Wed Aug 27 18:27:12 2008 +0900
@@ -7,10 +7,11 @@
 import rep.REPCommand;
 import rep.REPPacketReceive;
 import rep.REPPacketSend;
+import rep.channel.REPSocketChannel;
 
 public class REPNet {
-	private SocketChannel sc;
-	private REPPacketReceive repreceive;
+	private REPSocketChannel<REPCommand> sc;
+	public REPPacketReceive repreceive;
 	private REPPacketSend repsend;
 
 	public void sm_connect(String host, int port){
@@ -18,7 +19,7 @@
 		//String host = "localhost";
 		InetSocketAddress addr = new InetSocketAddress(host, port);
 		try {
-			sc = SocketChannel.open();
+			sc = REPSocketChannel.open();
 			sc.configureBlocking(true);
 			sc.connect(addr);
 			while(!sc.finishConnect()){
@@ -32,7 +33,6 @@
 	}
 
 	public void send(REPCommand command) {
-		// TODO Auto-generated method stub
 		repsend.send(command);
 	}
 }
--- a/sample/graph/Graph.java	Wed Aug 27 18:22:36 2008 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,439 +0,0 @@
-package sample.graph;
-
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All  Rights Reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 
- * -Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- * 
- * -Redistribution in binary form must reproduct the above copyright
- *  notice, this list of conditions and the following disclaimer in
- *  the documentation and/or other materials provided with the distribution.
- * 
- * Neither the name of Sun Microsystems, Inc. or the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- * 
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
- * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
- * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT
- * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT
- * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS
- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
- * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
- * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
- * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN
- * IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- * 
- * You acknowledge that Software is not designed, licensed or intended for
- * use in the design, construction, operation or maintenance of any nuclear
- * facility.
- */
-
-/*
- * @(#)Graph.java	1.13 03/01/23
- */
-
-import java.util.*;
-import java.awt.*;
-import java.applet.Applet;
-import java.awt.event.*;
-
-
-class Node {
-    double x;
-    double y;
-
-    double dx;
-    double dy;
-
-    boolean fixed;
-
-    String lbl;
-}
-
-
-class Edge {
-    int from;
-    int to;
-
-    double len;
-}
-
-
-class GraphPanel extends Panel
-    implements Runnable, MouseListener, MouseMotionListener {
-    Graph graph;
-    int nnodes;
-    Node nodes[] = new Node[100];
-
-    int nedges;
-    Edge edges[] = new Edge[200];
-
-    Thread relaxer;
-    boolean stress;
-    boolean random;
-    
-    GraphPanel(Graph graph) {
-	this.graph = graph;
-	addMouseListener(this);
-    }
-
-    int findNode(String lbl) {
-	for (int i = 0 ; i < nnodes ; i++) {
-	    if (nodes[i].lbl.equals(lbl)) {
-		return i;
-	    }
-	}
-	return addNode(lbl);
-    }
-    int addNode(String lbl) {
-	Node n = new Node();
-	n.x = 10 + 380*Math.random();
-	n.y = 10 + 380*Math.random();
-	n.lbl = lbl;
-	nodes[nnodes] = n;
-	return nnodes++;
-    }
-    void addEdge(String from, String to, int len) {
-	Edge e = new Edge();
-	e.from = findNode(from);
-	e.to = findNode(to);
-	e.len = len;
-	edges[nedges++] = e;
-    }
-
-    public void run() {
-        Thread me = Thread.currentThread();
-	while (relaxer == me) {
-	    relax();
-	    if (random && (Math.random() < 0.03)) {
-		Node n = nodes[(int)(Math.random() * nnodes)];
-		if (!n.fixed) {
-		    n.x += 100*Math.random() - 50;
-		    n.y += 100*Math.random() - 50;
-		}
-		graph.play(graph.getCodeBase(), "audio/drip.au");
-	    }
-	    try {
-		Thread.sleep(100);
-	    } catch (InterruptedException e) {
-		break;
-	    }
-	}
-    }
-
-    synchronized void relax() {
-	for (int i = 0 ; i < nedges ; i++) {
-	    Edge e = edges[i];
-	    double vx = nodes[e.to].x - nodes[e.from].x;
-	    double vy = nodes[e.to].y - nodes[e.from].y;
-	    double len = Math.sqrt(vx * vx + vy * vy);
-            len = (len == 0) ? .0001 : len;
-	    double f = (edges[i].len - len) / (len * 3);
-	    double dx = f * vx;
-	    double dy = f * vy;
-
-	    nodes[e.to].dx += dx;
-	    nodes[e.to].dy += dy;
-	    nodes[e.from].dx += -dx;
-	    nodes[e.from].dy += -dy;
-	}
-
-	for (int i = 0 ; i < nnodes ; i++) {
-	    Node n1 = nodes[i];
-	    double dx = 0;
-	    double dy = 0;
-
-	    for (int j = 0 ; j < nnodes ; j++) {
-		if (i == j) {
-		    continue;
-		}
-		Node n2 = nodes[j];
-		double vx = n1.x - n2.x;
-		double vy = n1.y - n2.y;
-		double len = vx * vx + vy * vy;
-		if (len == 0) {
-		    dx += Math.random();
-		    dy += Math.random();
-		} else if (len < 100*100) {
-		    dx += vx / len;
-		    dy += vy / len;
-		}
-	    }
-	    double dlen = dx * dx + dy * dy;
-	    if (dlen > 0) {
-		dlen = Math.sqrt(dlen) / 2;
-		n1.dx += dx / dlen;
-		n1.dy += dy / dlen;
-	    }
-	}
-
-	Dimension d = getSize();
-	for (int i = 0 ; i < nnodes ; i++) {
-	    Node n = nodes[i];
-	    if (!n.fixed) {
-		n.x += Math.max(-5, Math.min(5, n.dx));
-		n.y += Math.max(-5, Math.min(5, n.dy));
-            }
-            if (n.x < 0) {
-                n.x = 0;
-            } else if (n.x > d.width) {
-                n.x = d.width;
-            }
-            if (n.y < 0) {
-                n.y = 0;
-            } else if (n.y > d.height) {
-                n.y = d.height;
-            }
-	    n.dx /= 2;
-	    n.dy /= 2;
-	}
-	repaint();
-    }
-
-    Node pick;
-    boolean pickfixed;
-    Image offscreen;
-    Dimension offscreensize;
-    Graphics offgraphics;
-
-    final Color fixedColor = Color.red;
-    final Color selectColor = Color.pink;
-    final Color edgeColor = Color.black;
-    final Color nodeColor = new Color(250, 220, 100);
-    final Color stressColor = Color.darkGray;
-    final Color arcColor1 = Color.black;
-    final Color arcColor2 = Color.pink;
-    final Color arcColor3 = Color.red;
-
-    public void paintNode(Graphics g, Node n, FontMetrics fm) {
-	int x = (int)n.x;
-	int y = (int)n.y;
-	g.setColor((n == pick) ? selectColor : (n.fixed ? fixedColor : nodeColor));
-	int w = fm.stringWidth(n.lbl) + 10;
-	int h = fm.getHeight() + 4;
-	g.fillRect(x - w/2, y - h / 2, w, h);
-	g.setColor(Color.black);
-	g.drawRect(x - w/2, y - h / 2, w-1, h-1);
-	g.drawString(n.lbl, x - (w-10)/2, (y - (h-4)/2) + fm.getAscent());
-    }
-
-    public synchronized void update(Graphics g) {
-	Dimension d = getSize();
-	if ((offscreen == null) || (d.width != offscreensize.width) || (d.height != offscreensize.height)) {
-	    offscreen = createImage(d.width, d.height);
-	    offscreensize = d;
-	    if (offgraphics != null) {
-	        offgraphics.dispose();
-	    }
-	    offgraphics = offscreen.getGraphics();
-	    offgraphics.setFont(getFont());
-	}
-
-	offgraphics.setColor(getBackground());
-	offgraphics.fillRect(0, 0, d.width, d.height);
-	for (int i = 0 ; i < nedges ; i++) {
-	    Edge e = edges[i];
-	    int x1 = (int)nodes[e.from].x;
-	    int y1 = (int)nodes[e.from].y;
-	    int x2 = (int)nodes[e.to].x;
-	    int y2 = (int)nodes[e.to].y;
-	    int len = (int)Math.abs(Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)) - e.len);
-	    offgraphics.setColor((len < 10) ? arcColor1 : (len < 20 ? arcColor2 : arcColor3)) ;
-	    offgraphics.drawLine(x1, y1, x2, y2);
-	    if (stress) {
-		String lbl = String.valueOf(len);
-		offgraphics.setColor(stressColor);
-		offgraphics.drawString(lbl, x1 + (x2-x1)/2, y1 + (y2-y1)/2);
-		offgraphics.setColor(edgeColor);
-	    }
-	}
-
-	FontMetrics fm = offgraphics.getFontMetrics();
-	for (int i = 0 ; i < nnodes ; i++) {
-	    paintNode(offgraphics, nodes[i], fm);
-	}
-	g.drawImage(offscreen, 0, 0, null);
-    }
-
-    //1.1 event handling
-    public void mouseClicked(MouseEvent e) {
-    }
-
-    public void mousePressed(MouseEvent e) {
-        addMouseMotionListener(this);
-	double bestdist = Double.MAX_VALUE;
-	int x = e.getX();
-	int y = e.getY();
-	for (int i = 0 ; i < nnodes ; i++) {
-	    Node n = nodes[i];
-	    double dist = (n.x - x) * (n.x - x) + (n.y - y) * (n.y - y);
-	    if (dist < bestdist) {
-		pick = n;
-		bestdist = dist;
-	    }
-	}
-	pickfixed = pick.fixed;
-	pick.fixed = true;
-	pick.x = x;
-	pick.y = y;
-	repaint();
-	e.consume();
-    }
-
-    public void mouseReleased(MouseEvent e) {
-        removeMouseMotionListener(this);
-        if (pick != null) {
-            pick.x = e.getX();
-            pick.y = e.getY();
-            pick.fixed = pickfixed;
-            pick = null;
-        }
-	repaint();
-	e.consume();
-    }
-
-    public void mouseEntered(MouseEvent e) {
-    }
-
-    public void mouseExited(MouseEvent e) {
-    }
-
-    public void mouseDragged(MouseEvent e) {
-	pick.x = e.getX();
-	pick.y = e.getY();
-	repaint();
-	e.consume();
-    }
-
-    public void mouseMoved(MouseEvent e) {
-    }
-
-    public void start() {
-	relaxer = new Thread(this);
-	relaxer.start();
-    }
-
-    public void stop() {
-	relaxer = null;
-    }
-
-}
-
-
-public class Graph extends Applet implements ActionListener, ItemListener {
-
-    GraphPanel panel;
-    Panel controlPanel;
-
-    Button scramble = new Button("Scramble");
-    Button shake = new Button("Shake");
-    Checkbox stress = new Checkbox("Stress");
-    Checkbox random = new Checkbox("Random");
-
-    public void init() {
-	setLayout(new BorderLayout());
-
-	panel = new GraphPanel(this);
-	add("Center", panel);
-	controlPanel = new Panel();
-	add("South", controlPanel);
-
-	controlPanel.add(scramble); scramble.addActionListener(this);
-	controlPanel.add(shake); shake.addActionListener(this);
-	controlPanel.add(stress); stress.addItemListener(this);
-	controlPanel.add(random); random.addItemListener(this);
-
-	String edges = getParameter("edges");
-	for (StringTokenizer t = new StringTokenizer(edges, ",") ; t.hasMoreTokens() ; ) {
-	    String str = t.nextToken();
-	    int i = str.indexOf('-');
-	    if (i > 0) {
-		int len = 50;
-		int j = str.indexOf('/');
-		if (j > 0) {
-		    len = Integer.valueOf(str.substring(j+1)).intValue();
-		    str = str.substring(0, j);
-		}
-		panel.addEdge(str.substring(0,i), str.substring(i+1), len);
-	    }
-	}
-	Dimension d = getSize();
-	String center = getParameter("center");
-	if (center != null){
-	    Node n = panel.nodes[panel.findNode(center)];
-	    n.x = d.width / 2;
-	    n.y = d.height / 2;
-	    n.fixed = true;
-	}
-    }
-
-    public void destroy() {
-        remove(panel);
-        remove(controlPanel);
-    }
-
-    public void start() {
-	panel.start();
-    }
-
-    public void stop() {
-	panel.stop();
-    }
-
-    public void actionPerformed(ActionEvent e) {
-	Object src = e.getSource();
-
-	if (src == scramble) {
-	    play(getCodeBase(), "audio/computer.au");
-	    Dimension d = getSize();
-	    for (int i = 0 ; i < panel.nnodes ; i++) {
-		Node n = panel.nodes[i];
-		if (!n.fixed) {
-		    n.x = 10 + (d.width-20)*Math.random();
-		    n.y = 10 + (d.height-20)*Math.random();
-		}
-	    }
-	    return;
-	}
-
-	if (src == shake) {
-	    play(getCodeBase(), "audio/gong.au");
-	    Dimension d = getSize();
-	    for (int i = 0 ; i < panel.nnodes ; i++) {
-		Node n = panel.nodes[i];
-		if (!n.fixed) {
-		    n.x += 80*Math.random() - 40;
-		    n.y += 80*Math.random() - 40;
-		}
-	    }
-	}
-
-    }
-
-    public void itemStateChanged(ItemEvent e) {
-	Object src = e.getSource();
-	boolean on = e.getStateChange() == ItemEvent.SELECTED;
-	if (src == stress) panel.stress = on;
-	else if (src == random) panel.random = on;
-    }
-
-    public String getAppletInfo() {
-	return "Title: GraphLayout \nAuthor: <unknown>";
-    }
-
-    public String[][] getParameterInfo() {
-	String[][] info = {
-	    {"edges", "delimited string", "A comma-delimited list of all the edges.  It takes the form of 'C-N1,C-N2,C-N3,C-NX,N1-N2/M12,N2-N3/M23,N3-NX/M3X,...' where C is the name of center node (see 'center' parameter) and NX is a node attached to the center node.  For the edges connecting nodes to eachother (and not to the center node) you may (optionally) specify a length MXY separated from the edge name by a forward slash."},
-	    {"center", "string", "The name of the center node."}
-	};
-	return info;
-    }
-
-}