home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / in4wjcxu / src / como / commlet / superchat / superchat.java
Encoding:
Java Source  |  1996-08-14  |  14.2 KB  |  602 lines

  1. package como.commlet.superchat;
  2.  
  3. import java.awt.*;
  4. import java.applet.AudioClip;
  5. import java.util.Hashtable;
  6. import java.io.*;
  7. import java.util.*;
  8.  
  9. import como.sys.*;
  10. import como.util.*;
  11. import como.awt.*;
  12. import como.io.*;
  13. import como.commlet.*;
  14. import como.commlet.userlist.*;
  15.  
  16. public class SuperChat extends WindowCommlet
  17. {
  18.     public static final int MAX_USERS = 5;
  19.  
  20.     public static final int MSG_PLAY_SOUND = 10051;
  21.     public static final int MSG_SUPERCHAT_EVENT = 10052;
  22.     public static final int MSG_NEW_FACE = 10053;
  23.     public static final int MSG_PRIVATE_CHAT = 10054;
  24.  
  25.     int numberOfUsers = 0;
  26.     TextArea dialog;
  27.     TextField input;
  28.     FacePanel facepanel;
  29.     ScrollPanel scrollpanel;
  30.     Hashtable usernames;
  31.     Button kickbutton;
  32.     Button whisperbutton;
  33.     Button audiobuttons[];
  34.     AudioClip sounds[];
  35.     AudioClip useraddedclip = null;
  36.     AudioClip userleftclip = null;
  37.     AudioClip lineclip = null;
  38.     String soundnames[][] = {
  39.         { "Laugh", "laugh.au", "laughs." },
  40.         // just in case the SuperChat.sounds doesn't work :-)
  41.     };
  42.  
  43.  
  44.     public SuperChat() {
  45.         usernames = new Hashtable();
  46.  
  47.         return;
  48.     }
  49.  
  50.     public String getCommletName()
  51.     {
  52.         return "Super Chat Commlet, V1.0, (c) Jan Kautz & Ulrich Gall.";
  53.     }
  54.  
  55.     public String getCommletInfo()
  56.     {
  57.         return
  58.         "(c) 1996 Ulrich Gall & Jan Kautz\n"+
  59.         "\n";
  60.     }
  61.  
  62.     public void init()
  63.     {
  64.         super.init();
  65.  
  66.         setLayout(new BorderLayout());
  67.  
  68.         // NORTH
  69.         Panel p = new Panel();
  70.         p.setLayout(new BorderLayout());
  71.         p.add("West",new Label("Current Topic: "));
  72.         p.add("Center",getTopicTextField());
  73.         add("North",p);
  74.  
  75.         // CENTER
  76.         Panel centerpanel = new Panel();
  77.         centerpanel.setLayout( new BorderLayout() );
  78.  
  79.         dialog = new TextArea();
  80.         dialog.setEditable(false);
  81.  
  82.         centerpanel.add( "Center", dialog );
  83.  
  84.         Panel insidepanel = new Panel();
  85.         insidepanel.setLayout( new BorderLayout() );
  86.  
  87.         input = new TextField();
  88.         insidepanel.add( "North", input );
  89.  
  90.         // sound...
  91.         print("Loading soundfile...");
  92.  
  93.         loadSoundFile();
  94.         audiobuttons = new Button[soundnames.length];
  95.  
  96.         Panel actionpanel = new Panel();
  97.         actionpanel.setLayout( new FlowLayout() );
  98.         for( int i = 0; i < soundnames.length; i++ ) {
  99.             actionpanel.add( audiobuttons[i] = new Button( soundnames[i][0] ) );
  100.         }
  101.  
  102.         insidepanel.add( "South", actionpanel );
  103.         centerpanel.add( "South", insidepanel );
  104.         add( "Center", centerpanel );
  105.  
  106.         // WEST
  107.         Panel westpanel = new Panel();
  108.         Panel kickpanel = new Panel();
  109.         westpanel.setLayout( new BorderLayout( 10, 10 ) );
  110.         kickpanel.setLayout( new VertLayout( VertLayout.STRETCH ) );
  111.  
  112.         facepanel = new FacePanel( com, this );
  113.         scrollpanel = new ScrollPanel( (Component)facepanel, (float)0.1 );
  114.  
  115.         kickpanel.add( kickbutton = new Button( "Kick user(s)" ) );
  116.         if( !com.iAmMaster() ) kickbutton.disable();
  117.         kickpanel.add( whisperbutton = new Button( "Whisper to user(s)" ) );
  118.  
  119.         westpanel.add( "Center", scrollpanel );
  120.         westpanel.add( "South", kickpanel );
  121.  
  122.         add( "West", westpanel );
  123.         pack();
  124.  
  125.         print(getCommletName());
  126.         print(getCommletInfo());       
  127.  
  128.         print("Ready, waiting for messages...");
  129.     }
  130.  
  131.     public void loadSoundFile() {
  132.         InputStream is = com.openInputStream( "SuperChat.sounds" );
  133.         Vector lines;
  134.  
  135.         if( is == null )
  136.         {
  137.             sounds = new AudioClip[1];
  138.             return;    // could not find file
  139.         }
  140.  
  141.         lines = StreamLine.loadLines( new DataInputStream( is ) );
  142.         int nrlines = lines.size() - 3;
  143.         soundnames = new String[nrlines][3];
  144.         sounds = new AudioClip[nrlines];
  145.  
  146.         for( int i = 0; i < nrlines; i++ ) {
  147.             String line = (String)lines.elementAt( i+3 );
  148.             int first = line.indexOf( ':' );
  149.             int second = line.indexOf( ':', first+1 );
  150.             
  151.             soundnames[i][0] = line.substring( 0, first-1 ).trim();
  152.             soundnames[i][1] = line.substring( first+2, second-1 ).trim();
  153.             soundnames[i][2] = line.substring( second+2 ).trim();
  154.  
  155.             // means has still to be loaded!
  156.             sounds[i] = null;
  157.         }
  158.  
  159.         useraddedclip = com.loadAudioClip( ((String)lines.elementAt(0)).trim() );
  160.         userleftclip = com.loadAudioClip( ((String)lines.elementAt(1)).trim() );
  161.         lineclip = com.loadAudioClip( ((String)lines.elementAt(2)).trim() );
  162.     }
  163.  
  164.     public void loadSound( int i )
  165.     {
  166.         sounds[i] = com.loadAudioClip( soundnames[i][1] );
  167.     }
  168.  
  169.     public void addUser( int TheNewUser )
  170.     {
  171.         if( useraddedclip != null )
  172.             useraddedclip.play();
  173.         print(com.getUserName(TheNewUser) + " has joined the conversation.");
  174.         usernames.put(new Integer(TheNewUser),com.getUserName(TheNewUser));
  175.  
  176.         facepanel.addUser( TheNewUser );
  177.         scrollpanel.redo();
  178.  
  179.         numberOfUsers++;
  180.     }
  181.  
  182.     public void userLeft( int RankWhoLeft )
  183.     {
  184.         if( userleftclip != null )
  185.             userleftclip.play();
  186.         print(com.getUserName(RankWhoLeft) + " has left the conversation.");
  187.  
  188.         facepanel.removeUser( RankWhoLeft );
  189.         scrollpanel.redo();
  190.  
  191.         numberOfUsers--;
  192.     }
  193.  
  194.     public boolean isUserAdmitted( User who ) {
  195.  
  196.         // If you uncomment this, only MAX_USERS
  197.         // will be permitted to join this channel!
  198.         // if( numberOfUsers >= MAX_USERS ) return false;
  199.  
  200.         return true;
  201.     }
  202.  
  203.     public void stop()
  204.     {
  205.         facepanel.stop();
  206.  
  207.         com.sendToOthers(new Msg(Msg.CHAT_DIALOG_STRING,"bye bye..."));
  208.         super.stop();
  209.     }
  210.  
  211.     void print(String s)
  212.     {
  213.         int width = dialog.size().width;
  214.         Font font = dialog.getFont();
  215.         FontMetrics fm = null;
  216.  
  217.         if( font != null ) fm = dialog.getFontMetrics(font);
  218.  
  219.         if( fm != null ) {
  220.             width -= fm.stringWidth( "MMMM" );    // just like that.
  221.  
  222.             StringTokenizer st = new StringTokenizer( s, " " );
  223.             StringBuffer line = new StringBuffer();
  224.     
  225.             while( st.hasMoreTokens() ) {
  226.                 String next = st.nextToken();
  227.  
  228.                 if( fm.stringWidth( line.toString()+next+" " ) < width )
  229.                     line.append( " "+next );
  230.                 else
  231.                 {
  232.                     dialog.insertText(line+"\n",dialog.getText().length());
  233.                     line = new StringBuffer( "   "+next );
  234.                 }
  235.             }
  236.             dialog.insertText(line+"\n",dialog.getText().length());
  237.         }
  238.         else
  239.             dialog.insertText(s+"\n",dialog.getText().length());
  240.  
  241.         // move the textfield down!
  242.         int l = dialog.getText().length()-2;
  243.         dialog.select( l, l );
  244.     }
  245.  
  246.     public boolean handleMsg(Msg msg)
  247.     {
  248.         if( super.handleMsg(msg) ) return true;
  249.         if( facepanel.handleMsg( msg ) ) return true;
  250.  
  251.         if( msg.arg == null ) msg.arg = "";
  252.  
  253.         if( msg.type == Msg.NEW_MASTER ) {
  254.             if( com.iAmMaster() ) kickbutton.enable();
  255.             else kickbutton.disable();
  256.  
  257.             // let it fall through
  258.             return false;
  259.         }
  260.  
  261.         if (msg.type == Msg.NEW_USER_INFO)
  262.         {
  263.             String newname = com.getUserName(msg.from);
  264.             User newuser = com.getUser(msg.from);
  265.             if (!usernames.get(new Integer(msg.from)).equals(newname))
  266.             {
  267.                 print(usernames.get(new Integer(msg.from)) + " is now known as "+newname);
  268.                 usernames.put( new Integer( msg.from ), newname );
  269.             }
  270.  
  271.             facepanel.newUserInfo( msg.from );
  272.  
  273.             // well perhaps some other people are interested!
  274.             return false;
  275.         }
  276.  
  277.         if (msg.type == MSG_PLAY_SOUND)
  278.         {
  279.             int nr = ((Integer)msg.arg).intValue();
  280.  
  281.             if( sounds[nr] == null )
  282.             {
  283.                 loadSound( nr );
  284.             }
  285.  
  286.             sounds[nr].play();
  287.  
  288.             return true;
  289.         }
  290.  
  291.         if (msg.type == Msg.CHAT_DIALOG_STRING)
  292.         {
  293.             if (lineclip != null) lineclip.play();
  294.             print(com.getUserName(msg.from) + "> " + msg.arg);
  295.             return true;
  296.         }
  297.  
  298.         if( msg.type == MSG_SUPERCHAT_EVENT )
  299.         {
  300.             print( com.getUserName(msg.from) + " " + msg.arg );
  301.             return true;
  302.         }
  303.  
  304.         if( msg.type == MSG_PRIVATE_CHAT )
  305.         {
  306.             print( com.getUserName(msg.from)+" whispers to you: "+msg.arg );
  307.             return true;
  308.         }
  309.  
  310.         return false;
  311.     }
  312.  
  313.     public boolean action(Event evt,Object what)
  314.     {
  315.         String text = input.getText();
  316.  
  317.         if (evt.target == input)
  318.         {
  319.             com.sendToAll( new Msg( Msg.CHAT_DIALOG_STRING, text ) );
  320.             input.setText("");
  321.             return true;
  322.         }
  323.  
  324.         for( int i = 0; i < audiobuttons.length; i++ )
  325.         {
  326.             if( evt.target == audiobuttons[i] ) {
  327.                 com.sendToAll( new Msg( MSG_PLAY_SOUND, new Integer(i) ) );
  328.                 com.sendToAll( new Msg( MSG_SUPERCHAT_EVENT, soundnames[i][2] ) );
  329.                 return true;
  330.             }
  331.         }
  332.  
  333.         if( evt.target == facepanel ) {
  334.             int id = ((Integer)evt.arg).intValue();
  335.  
  336.             // well if you need to know that a user was selected/
  337.             // deselected, then you can do sth. here!
  338.         }
  339.  
  340.         if( evt.target == kickbutton || evt.target == whisperbutton ) {
  341.             Vector sel = facepanel.getSelectedUsers();
  342.             Enumeration e = sel.elements();
  343.  
  344.             while( e.hasMoreElements() ) {
  345.                 int id = ((Integer)e.nextElement()).intValue();
  346.  
  347.                 if( evt.target == kickbutton )
  348.                 {
  349.                     print( "You kicked "+com.getUserName( id )+" (reason: "+text+")." );
  350.                     com.sendTo(new Msg( Msg.KICK_USER, id, text ) );
  351.                 }
  352.                 else if( evt.target == whisperbutton ) {
  353.                     print( "You whisper to "+com.getUserName( id )+": "+text );
  354.                     com.sendTo(new Msg( SuperChat.MSG_PRIVATE_CHAT, id, text ));
  355.                 }
  356.                 input.setText("");
  357.             }
  358.         }
  359.  
  360.         return false;
  361.     }
  362. }
  363.  
  364. class FacePanel extends Panel {
  365.     static final int COLUMNS = 10;
  366.     static final int IMAGESIZE = 60;
  367.  
  368.     Hashtable users;
  369.     ComObj com;
  370.  
  371.     ImageButton myImageButton = null;
  372.     TextField myNameField = null;
  373.     TextField myCommentField = null;
  374.     Hashtable cachedata;
  375.  
  376.     RemoteFileDialog rfd = null;
  377.     Frame rfdframe = null;
  378.     String currentFaceName = null;
  379.     Component refresh;
  380.  
  381.     public FacePanel() {
  382.         super();
  383.         setLayout( new VertLayout( VertLayout.STRETCH ) );
  384.         users = new Hashtable();
  385.     }
  386.  
  387.     public FacePanel( ComObj com, Component refresher ) {
  388.         this();
  389.         this.com = com;
  390.         this.refresh = refresher;
  391.  
  392.         // add Myself right now, also I don't know anything
  393.         // about me! This is done, that the facepanel size
  394.         // is correct from the beginning.
  395.         cachedata = addUserToPanel( " ", " ", true );
  396.     }
  397.  
  398.     public void addUser( int id ) {
  399.         boolean isitme = (id == com.getMyID());
  400.  
  401.         if( isitme )
  402.         {
  403.             // well now I get the information about me!
  404.  
  405.             users.put( new Integer( id ), cachedata );
  406.             newUserInfo( id );
  407.             return;
  408.         }
  409.     
  410.         Hashtable data = addUserToPanel( com.getUserName( id ), getUserComment( id ), false );
  411.  
  412.         users.put( new Integer( id ), data );
  413.  
  414.         if( currentFaceName != null )
  415.             com.sendTo( new Msg( SuperChat.MSG_NEW_FACE, id, currentFaceName ) );
  416.     }
  417.  
  418.     public Hashtable addUserToPanel( String name, String comment, boolean isitme ) {
  419.         Panel smallpanel = new Panel();
  420.         Hashtable data = new Hashtable();
  421.         ImageButton imgbutton;
  422.         TextField nametf;
  423.         TextField commenttf;
  424.         Panel infopanel = new Panel();
  425.  
  426.         infopanel.setLayout( new BorderLayout() );
  427.         infopanel.add( "North", nametf = new TextField( name, COLUMNS ) );
  428.         infopanel.add( "Center", commenttf = new TextField( comment, COLUMNS ) );
  429.         smallpanel.setLayout( new BorderLayout( 10, 10 ) );
  430.         smallpanel.add( "West", imgbutton = new ImageButton( IMAGESIZE, IMAGESIZE, " " ) );
  431.         smallpanel.add( "Center", infopanel );
  432.  
  433.         if( isitme ) {
  434.             myImageButton = imgbutton;
  435.             myNameField = nametf;
  436.             myCommentField = commenttf;
  437.         }
  438.         else {
  439.             nametf.setEditable( false );
  440.             commenttf.setEditable( false );
  441.             imgbutton.setSwitch( true );        // means use as a switch!
  442.         }
  443.  
  444.         add( smallpanel );
  445.  
  446.         // I want the panel to be stretched, that the
  447.         // new component fits on it! Here I don't want
  448.         // to care about the parent-container (if 
  449.         // I'm too large it's ok!)
  450.         resize( size().width, preferredSize().height );
  451.         layout();
  452.         smallpanel.paintAll( smallpanel.getGraphics() );
  453.  
  454.         data.put( "name", nametf );
  455.         data.put( "comment", commenttf );
  456.         data.put( "imagebutton", imgbutton );
  457.         data.put( "panel", smallpanel );
  458.  
  459.         return data;
  460.     }
  461.  
  462.     public void removeUser( int id ) {
  463.         Integer user = new Integer( id );
  464.         Hashtable data;
  465.  
  466.         data = (Hashtable)users.get( user );
  467.         Panel panel = (Panel)data.get( "panel" );
  468.         remove( panel );
  469.  
  470.         users.remove( user );
  471.  
  472.         validate();
  473.         paint( getGraphics() );
  474.     }
  475.  
  476.     public Vector getSelectedUsers() {
  477.         Vector selectedlist = new Vector();
  478.  
  479.         Enumeration e = users.keys();
  480.         while( e.hasMoreElements() ) {
  481.             Integer user = (Integer)e.nextElement();
  482.             Hashtable data; 
  483.             
  484.             data = (Hashtable)users.get( user );
  485.             ImageButton imgbutton = (ImageButton)data.get( "imagebutton" );
  486.  
  487.             if( imgbutton.getState() == true && user.intValue() != com.getMyID() ) {
  488.                 // user is selected
  489.                 selectedlist.addElement( user );
  490.             }
  491.         }
  492.  
  493.         return selectedlist;
  494.     }
  495.  
  496.     public void newUserInfo( int id ) {
  497.         Hashtable data = (Hashtable)users.get( new Integer( id ) );
  498.         TextField name = (TextField)data.get( "name" );
  499.         TextField comment = (TextField)data.get( "comment" );
  500.  
  501.         name.setText( com.getUserName( id ) );
  502.         name.select( 0, 0 );
  503.         comment.setText( getUserComment( id ) );
  504.         comment.select( 0, 0 );
  505.     }
  506.  
  507.     public String getUserComment( int id ) {
  508.         String commentstring = (String)((User)com.getUser( id )).get( User.COMMENT );
  509.         if( commentstring == null ) return " ";
  510.         else return commentstring;
  511.     }
  512.  
  513.     public void newFace( int id, Image face ) {
  514.         Integer user = new Integer( id );
  515.  
  516.         Hashtable data = (Hashtable)users.get( user );
  517.         ImageButton imgbutton = (ImageButton)data.get( "imagebutton" );
  518.  
  519.         imgbutton.setImages( face, face );
  520.     }
  521.  
  522.     public boolean action( Event evt, Object what ) {
  523.         if( evt.target == myImageButton ) {
  524.             if( rfdframe != null ) return true;
  525.  
  526.             rfd = new RemoteFileDialog( com, "SuperChat.images", this );
  527.             rfdframe = new Frame();
  528.             rfdframe.add( "Center", rfd );
  529.             rfdframe.pack();
  530.             rfdframe.setTitle( "Choose your face..." );
  531.             rfdframe.show();
  532.  
  533.             return true;
  534.         }
  535.  
  536.         if( evt.target == rfd && rfd != null ) {
  537.             if( what != null )
  538.             {
  539.                 currentFaceName = (String)what;
  540.                 com.sendToAll( new Msg( SuperChat.MSG_NEW_FACE, com.getMyID(), currentFaceName ) );
  541.             }
  542.  
  543.             rfdframe.hide();
  544.             rfdframe.dispose();
  545.             rfdframe = null;
  546.             rfd = null;
  547.  
  548.             return true;
  549.         }
  550.  
  551.         if( evt.target == myNameField || evt.target == myCommentField )
  552.         {
  553.             User ego = com.getUser( com.getMyID() );
  554.             ego.put( User.NAME, myNameField.getText() );
  555.             ego.put( User.COMMENT, myCommentField.getText() );
  556.  
  557.             // also tells other people (and myself :-)!
  558.             com.setLocalUser( ego );
  559.             return true;
  560.         }
  561.  
  562.         Enumeration e = users.keys();
  563.         while( e.hasMoreElements() ) {
  564.             Integer user = (Integer)e.nextElement();
  565.             Hashtable data; 
  566.             
  567.             data = (Hashtable)users.get( user );
  568.             ImageButton imgbutton = (ImageButton)data.get( "imagebutton" );
  569.  
  570.             if( evt.target == imgbutton ) {
  571.                 // clicked on me: tell the refresh guy!
  572.  
  573.                 refresh.action( new Event( this, Event.ACTION_EVENT, user ), user );
  574.                 return true;
  575.             }
  576.         }
  577.  
  578.         return false;
  579.     }
  580.  
  581.     public void stop() {
  582.         if( rfdframe != null )
  583.         {
  584.             rfdframe.hide();
  585.             rfdframe.dispose();
  586.             rfdframe = null;
  587.         }
  588.     }
  589.  
  590.     public boolean handleMsg( Msg msg )
  591.     {
  592.         if( msg.type == SuperChat.MSG_NEW_FACE )
  593.         {
  594.             Image image = com.loadImage( (String)msg.arg );
  595.             newFace( msg.from, image );
  596.             return true;
  597.         }
  598.  
  599.         return false;
  600.     }
  601. }
  602.