KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > ChatPanel


1 import java.awt.*;
2 import java.awt.event.*;
3 import java.awt.image.ImageObserver JavaDoc;
4 import java.io.*;
5 import javax.swing.*;
6 import javax.accessibility.Accessible JavaDoc;
7 import java.util.*;
8 import org.jivesoftware.smack.*;
9 import org.jivesoftware.smack.packet.*;
10 import org.jivesoftware.smack.util.StringUtils;
11 import whisper.*;
12
13
14 /** Panel that appears as a tab in the main window for composing a one-off message.*/
15 public final class ChatPanel extends JPanel implements Accessible JavaDoc, ImageObserver JavaDoc, MenuContainer, Serializable, WMP{
16     
17     private static final int GAP=10;
18     
19     final JPanel withPanel=new JPanel(new GridLayout(2,1,GAP,GAP));
20         final JLabel withLbl=new JLabel();
21         final JLabel statLbl=new JLabel(Lang.gs("chat encrypted"),Icons.PADLOCK,SwingConstants.LEFT);
22
23     final JEditorPane chatTextPane=new JEditorPane();
24     final JScrollPane chatTextPaneSP=new JScrollPane(chatTextPane);
25     final JScrollBar sb=chatTextPaneSP.getVerticalScrollBar();
26     
27     final JPanel bottomPanel=new JPanel(new GridLayout(2,1,GAP,GAP));
28         final JPanel writePanel=new JPanel(new BorderLayout(GAP,GAP));
29             final JTextArea text=new JTextArea(1,25);
30             final JScrollPane textSP=new JScrollPane(text);
31             final JButton sendBtn=new JButton(Lang.gs("send"),Icons.SEND);
32     
33         final JPanel btnPanel=new JPanel(new FlowLayout(FlowLayout.RIGHT,0,0));
34             final JButton saveBtn=new JButton(Lang.gs("save"),Icons.SAVE);
35             final JButton closeBtn=new JButton(Lang.gs("close"),Icons.CLOSE);
36     
37     final BtnClick click=new BtnClick();
38     
39     final JPanel thisPanel=this;
40     
41     private String JavaDoc ChatText="";
42     private final String JavaDoc Me=Lang.gs("me");
43     private Chat chat=null;
44     private boolean isEncrypting=true;
45     private SessionKey mySK=null;
46     private SessionKey theirSK=null;
47     private PublicKey theirKey=null;
48     private int messageCount=0;
49     private final int SK_USE_LIMIT=17;
50     public final String JavaDoc Name;
51     private String JavaDoc ID;
52     
53     private final String JavaDoc HEADER=GUI.getHeader();
54     
55     public ChatPanel(String JavaDoc name, String JavaDoc id, Chat chat, boolean isencrypting, String JavaDoc date){
56         super(new BorderLayout(GAP,GAP));
57         this.chat=chat;
58         this.isEncrypting=isencrypting;
59         this.Name=name;
60         this.ID=id;
61         
62         withLbl.setText(Lang.gs("chatting with")+name);
63         withLbl.setToolTipText(Lang.gs("chatting with")+id);
64         if(!isEncrypting){
65             statLbl.setText(Lang.gs("chat not encrypted"));
66             statLbl.setIcon(Icons.WARNING);
67             statLbl.setToolTipText(Lang.gs("chat no key"));
68         }
69         else{
70             theirKey=(PublicKey) WhisperIM.MainWindow.Keys.get("jabber"+StringUtils.parseBareAddress(id));
71             if(theirKey==null){
72                 //should not normally happen
73
if(WhisperIM.MainWindow.hasNoKey("jabber",StringUtils.parseBareAddress(id))){
74                     isEncrypting=false;
75                 }
76                 else{
77                     try{
78                         theirKey=WhisperIM.MainWindow.getKey("jabber",StringUtils.parseBareAddress(id));
79                     }
80                     catch(Exception JavaDoc e){
81                         isEncrypting=false;
82                     }
83                 }
84             }
85             if(theirKey==null){ //oops shouldnt happen
86
isEncrypting=false;
87                 statLbl.setText(Lang.gs("chat not encrypted"));
88                 statLbl.setIcon(Icons.WARNING);
89                 statLbl.setToolTipText(Lang.gs("chat no key"));
90             }
91             else{
92                 mySK=new SessionKey(WhisperIM.SR);
93             }
94         }
95         withPanel.add(withLbl);
96         withPanel.add(statLbl);
97         add(withPanel,BorderLayout.NORTH);
98
99         // chat history
100
chatTextPane.setEditable(false);
101         chatTextPane.setContentType("text/html");
102         java.net.URL JavaDoc base=null;
103         try{
104             base=(new File(".")).toURL();
105             ((javax.swing.text.html.HTMLDocument JavaDoc)chatTextPane.getDocument()).setBase(base);
106         }
107         catch (Exception JavaDoc e){
108             // swallow
109
}
110         announce(Lang.gs("chat started"),date);
111         GUI.setScrollBars(chatTextPaneSP);
112         add(chatTextPaneSP,BorderLayout.CENTER);
113         //write part
114
text.setLineWrap(true);
115         text.setWrapStyleWord(true);
116         textSP.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
117         if(WhisperIM.isMac){
118             textSP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
119         }
120         else{
121             textSP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
122         }
123         
124         //sendBtn.setVerticalTextPosition(AbstractButton.BOTTOM);
125
//sendBtn.setHorizontalTextPosition(AbstractButton.CENTER);
126
//sendBtn.setMargin(new Insets(0,0,0,0));
127
sendBtn.addActionListener(click);
128         sendBtn.setMnemonic(Lang.s2k("send_mn"));
129         sendBtn.setToolTipText(Lang.gs("chat send_tt"));
130         writePanel.add(textSP,BorderLayout.CENTER);
131         writePanel.add(sendBtn,BorderLayout.EAST);
132         
133         saveBtn.addActionListener(click);
134         saveBtn.setToolTipText(Lang.gs("chat save_tt"));
135         btnPanel.add(saveBtn);
136         btnPanel.add(Box.createHorizontalStrut(GAP));
137         
138         closeBtn.addActionListener(click);
139         closeBtn.setMnemonic(Lang.s2k("close_mn"));
140         closeBtn.setToolTipText(Lang.gs("chat close_tt"));
141         btnPanel.add(closeBtn);
142         
143         bottomPanel.add(writePanel);
144         bottomPanel.add(btnPanel);
145         add(bottomPanel,BorderLayout.SOUTH);
146         
147         sendBtn.setDefaultCapable(true);
148         chat.addMessageListener(new newMsgListener());
149         //help key
150
getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(WhisperIM.HELP_KEY,0),"help"); //put in help key for action help
151
getActionMap().put("help",new HelpAction(this,"messages.html#chat"));
152         //enter key
153
text.getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0),"send_messge");
154         text.getActionMap().put("send_messge", new EnterAction());
155         saveBtn.setVisible(false); //FUTURE FEATURE
156
}
157     
158     /** Processes a new chat message.*/
159     public void process(String JavaDoc msg, String JavaDoc time){
160         if(!isEncrypting){
161             ChatText=ChatText+"<font color='"+MUCPanel.theirColours[0]+"'>"+time+" "+Name+"</font>&nbsp;"+Convert.text(msg)+"<br>";
162             chatTextPane.setText(HEADER+ChatText+GUI.FOOTER);
163             sb.setValue(sb.getMaximum());
164             return;
165         }
166         (new ProcessEncryptedMessage(msg)).start();
167     }
168     
169     public void doSend(){
170         if(!isEncrypting){
171             try{
172                 chat.sendMessage(text.getText());
173             }
174             catch(XMPPException xe){
175                 GUI.showError(this,"error","error",null,xe);
176                 return;
177             }
178             ChatText=ChatText+"<font color='"+MUCPanel.myColour+"'>"+GUI.getTime()+" "+Me+"</font>&nbsp;"+Convert.text(text.getText())+"<br>";
179             text.setText("");
180             text.requestFocus();
181             chatTextPane.setText(HEADER+ChatText+GUI.FOOTER);
182             sb.setValue(sb.getMaximum());
183             return;
184         }
185         text.setEditable(false);
186         sendBtn.setEnabled(false);
187         (new SendEncryptedMessage()).start();
188     }
189     
190     public void doSentEncryptedMessage(){
191         ChatText=ChatText+"<font color='"+MUCPanel.myColour+"'>"+GUI.getTime()+" "+Me+"</font>&nbsp;"+Convert.text(text.getText())+"<br>";
192         text.setText("");
193         sendBtn.setEnabled(true);
194         text.setEditable(true);
195         text.requestFocus();
196         chatTextPane.setText(HEADER+ChatText+GUI.FOOTER);
197         sb.setValue(sb.getMaximum());
198     }
199         
200     public void doClose(){
201         text.setText("");
202         chatTextPane.setText("<html></html>");
203         ChatText="";
204         ChatText=null;
205         WhisperIM.MainWindow.Chats.remove("jabber"+StringUtils.parseBareAddress(ID));
206         WhisperIM.MainWindow.chatPane.remove(thisPanel);
207         chat=null;
208     }
209     
210     public void announce(String JavaDoc txt, String JavaDoc time){
211         ChatText=ChatText+"<font color='"+MUCPanel.announceColour+"'>"+time+" "+txt+"</font><br>";
212         chatTextPane.setText(HEADER+ChatText+GUI.FOOTER);
213         sb.setValue(sb.getMaximum());
214     }
215     
216     public void goneOffline(){
217         sendBtn.setEnabled(false);
218         announce("* "+Lang.gs("disconnected")+" *",GUI.getTime());
219         if(isEncrypting){
220             mySK.wipe();
221         }
222     }
223         
224     public void goneOnline(){
225         chat=new Chat(WhisperIM.MainWindow.Conn,ID);
226         if(isEncrypting){
227             mySK=new SessionKey(WhisperIM.SR);
228             messageCount=0;
229         }
230         announce("* "+Lang.gs("reconnected")+" *",GUI.getTime());
231         chat.addMessageListener(new newMsgListener());
232         sendBtn.setEnabled(true);
233     }
234     
235     public void doFocus(){
236         text.requestFocusInWindow();
237     }
238     
239     public JButton getDefaultButton(){
240         return sendBtn;
241     }
242     
243     final class BtnClick implements ActionListener{
244         public void actionPerformed(ActionEvent ae){
245             //get button
246
String JavaDoc b=ae.getActionCommand();
247             // call method depending on button clicked
248
if(b.equals(closeBtn.getText())){
249                 doClose();
250                 return;
251             }
252             if(b.equals(sendBtn.getText())){
253                 if(text.getText().equals("")){
254                     text.requestFocus();
255                     return;
256                 }
257                 doSend();
258                 return;
259             }
260         }
261     }
262     
263     final class newMsgListener implements PacketListener{
264         public void processPacket(Packet packet){
265             org.jivesoftware.smack.packet.Message m;
266             try{
267                 m=(org.jivesoftware.smack.packet.Message) packet;
268             }
269             catch(Exception JavaDoc e){
270                 return;
271             }
272             final String JavaDoc t=m.getBody();
273             final String JavaDoc time=GUI.getTime(m);
274             javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc(){
275                     public void run(){
276                         process(t,time);
277                     }
278                 });
279         }
280     }
281     
282     
283     final class ProcessEncryptedMessage extends Thread JavaDoc{
284         final String JavaDoc msg;
285         
286         public ProcessEncryptedMessage(String JavaDoc m){
287             super("Process Encrypted Message");
288             setDaemon(true);
289             setPriority(Thread.MIN_PRIORITY);
290             this.msg=m;
291         }
292         
293         public void run(){
294             try{
295                 final whisper.Message wm=new whisper.Message(msg);
296                 if(!wm.isValid(theirKey)){
297                     javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc(){
298                         public void run(){
299                             announce(Lang.gs("bad message received")+" - "+Lang.gs("invalid signature"),GUI.getTime());
300                         }
301                     });
302                     return;
303                 }
304                 EncryptedSessionKey esk=wm.getESK();
305                 if(theirSK==null && esk==null){
306                     try{
307                         sleep(3000);//wait 3 seconds
308
if(theirSK==null){
309                             return;
310                         }
311                     }
312                     catch(Exception JavaDoc se){
313                         return;
314                     }
315                 }
316                 if(esk!=null){
317                     theirSK=null;
318                     while(WhisperIM.KEYPAIR==null){
319                         try{
320                             sleep(3000);
321                         }
322                         catch(InterruptedException JavaDoc ie){
323                             return;
324                         }
325                     }
326                     theirSK=esk.decrypt(WhisperIM.KEYPAIR);
327                 }
328                 final String JavaDoc plaintext=wm.decrypt(theirSK);
329                 javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc(){
330                     public void run(){
331                         ChatText=ChatText+"<font color='"+MUCPanel.theirColours[0]+"'>"+GUI.getTime(wm)+" "+Name+"</font>&nbsp;"+Convert.text(plaintext)+"<br>";
332                         chatTextPane.setText(HEADER+ChatText+GUI.FOOTER);
333                         sb.setValue(sb.getMaximum());
334                         }
335                 });
336             }
337             catch (Exception JavaDoc e){
338                 javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc(){
339                         public void run(){
340                             announce(Lang.gs("bad message received")+" - "+Lang.gs("could not decrypt"),GUI.getTime());
341                         }
342                     });
343                 System.err.println("Debug: ProcessEncryptedMessage thread - "+e.getMessage());
344                 return;
345             }
346         }
347     }
348     
349     final class SendEncryptedMessage extends Thread JavaDoc{
350         
351         public SendEncryptedMessage(){
352             super("Send Encrypted Message");
353             setDaemon(true);
354             setPriority(Thread.MIN_PRIORITY);
355         }
356         
357         public void run(){
358             try{
359                 if(messageCount==SK_USE_LIMIT){
360                     mySK=new SessionKey(WhisperIM.SR);
361                     messageCount=0;
362                 }
363                 whisper.Message wm;
364                 while(WhisperIM.KEYPAIR==null){
365                     try{
366                         sleep(3000);
367                     }
368                     catch(InterruptedException JavaDoc ie){
369                         return;
370                     }
371                 }
372                 if(messageCount==0){
373                     wm=new whisper.Message(text.getText(),theirKey,mySK,WhisperIM.KEYPAIR,WhisperIM.SR);
374                 }
375                 else{
376                     wm=new whisper.Message(text.getText(),mySK,WhisperIM.KEYPAIR,WhisperIM.SR);
377                 }
378                 messageCount++;
379                 chat.sendMessage(wm.getText());
380                 javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc(){
381                     public void run(){
382                         doSentEncryptedMessage();
383                     }
384                 });
385             }
386             catch(final Exception JavaDoc e){
387                 e.printStackTrace();
388                 javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc(){
389                     public void run(){
390                         GUI.showError(thisPanel,"error","error",e.getMessage());
391                     }
392                 });
393             }
394         }
395     }
396     
397     final class EnterAction extends AbstractAction{
398         public void actionPerformed(ActionEvent e) {
399             if(text.getText().equals("")){
400                     text.requestFocus();
401                     return;
402             }
403             doSend();
404         }
405     }
406 }
Popular Tags