// File: IO12.java (Module 13) // // Author: Rahul Simha // Created: Nov 28, 1998 // // A chat program using pipes. import java.awt.*; import java.awt.event.*; import java.io.*; class ChatClient extends Frame implements Runnable { OutputStream out_stream; // The streams. InputStream in_stream; PrintWriter pw; TextField tf; // For the user to write in. Panel message_panel; // To display the conversation. GridLayout grid_layout; ScrollPane sc; public ChatClient (OutputStream out_stream, InputStream in_stream) { // Store the stream references and create a PrintWriter this.out_stream = out_stream; this.in_stream = in_stream; pw = new PrintWriter (out_stream, true); // Create the frame. this.setSize (400,200); this.setLocation (0,100); this.setTitle ("Chat Client"); this.setBackground (Color.white); // this.setLayout (new BorderLayout()); // This is where messages will be displayed: grid_layout = new GridLayout (1,1); message_panel = new Panel (grid_layout); sc = new ScrollPane (); sc.add (message_panel); this.add (sc, BorderLayout.CENTER); tf = new TextField (); tf.setForeground (Color.blue); tf.addActionListener ( new ActionListener () { public void actionPerformed (ActionEvent a) { if (tf.getText().equalsIgnoreCase ("Bye")) { try { pw.println ("Bye"); ChatClient.this.out_stream.close (); ChatClient.this.dispose (); } catch (IOException e) { System.out.println (e); } } else { display_text ("ME: " + tf.getText(), Color.blue); pw.println (tf.getText()); tf.setText(""); } } } ); this.add (tf, BorderLayout.SOUTH); this.setVisible (true); } // Display text on a message panel using Label's. void display_text (String s, Color c) { // Create the label. Label L = new Label (s); L.setForeground (c); // Add to the message panel. message_panel.add (L); message_panel.invalidate(); // Increment the layout rows for the next message. grid_layout.setRows (grid_layout.getRows() + 1); // Scroll to the bottom. int height = sc.getViewportSize().height; sc.setScrollPosition (0, height); // Re-compute the display. this.validate(); } // Must implement the run() method. public void run () { try { // Only reading needs to be done here. InputStreamReader isr = new InputStreamReader (in_stream); LineNumberReader lnr = new LineNumberReader (isr); // Read line by line. String s = lnr.readLine(); while (s != null) { s = s.trim(); display_text ("YOU: " + s, Color.red); if (s.equalsIgnoreCase ("Bye")) break; s = lnr.readLine(); } in_stream.close (); } catch (IOException e) { System.out.println (e); } } } // This is an independent quit button to quit the application. class QuitButton extends Frame { public QuitButton () { this.setSize (80,50); this.setLocation (0, 0); this.setTitle ("Quit button"); Button quitb = new Button ("QUIT"); quitb.setBackground (Color.red); quitb.addActionListener ( new ActionListener () { public void actionPerformed (ActionEvent a) { System.exit (0); } } ); this.add (quitb, BorderLayout.CENTER); this.setVisible (true); } } public class IO12 { public static void main (String[] argv) { // Create an independent quit button. QuitButton q = new QuitButton (); try { // Create the matching pipes. Note that one pipe // is given to the constructor of the other. PipedOutputStream pipe_out1 = new PipedOutputStream (); PipedInputStream pipe_in1 = new PipedInputStream (pipe_out1); PipedOutputStream pipe_out2 = new PipedOutputStream (); PipedInputStream pipe_in2 = new PipedInputStream (pipe_out2); // Create one client instance and thread. ChatClient c1 = new ChatClient (pipe_out1, pipe_in2); Thread c1_thread = new Thread (c1); // Create another client instance and thread. ChatClient c2 = new ChatClient (pipe_out2, pipe_in1); Thread c2_thread = new Thread (c2); // Start the threads. c1_thread.start(); c2_thread.start(); } catch (IOException e) { System.out.println (e); } } }