KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JMainFrame


1 import java.awt.*;
2 import java.awt.event.*;
3 import java.awt.image.ImageObserver JavaDoc;
4 import java.io.*;
5 import java.util.*;
6 import javax.swing.*;
7 import javax.swing.event.*;
8 import javax.swing.tree.*;
9 import javax.accessibility.Accessible JavaDoc;
10 import org.jivesoftware.smack.*;
11 import org.jivesoftware.smackx.*;
12 import org.jivesoftware.smack.packet.*;
13 import org.jivesoftware.smack.filter.*;
14 import org.jivesoftware.smack.util.StringUtils;
15 import whisper.PublicKey;
16
17
18 /** Main window.*/
19 public final class JMainFrame extends JFrame implements Accessible JavaDoc, ImageObserver JavaDoc, MenuContainer, RootPaneContainer, Serializable, WindowConstants{
20     
21     final JFrame frame=this; // refer to self so inner classes can refer to.
22
// The menu
23
final JMenuBar menuBar=new JMenuBar();
24     final JMenu myStatus=new JMenu();
25         final JMenuItem online=new JMenuItem("",Icons.STATUS_ONLINE);
26         final JMenuItem available=new JMenuItem("",Icons.STATUS_AVAILABLE);
27         final JMenuItem away=new JMenuItem("",Icons.STATUS_AWAY);
28         final JMenuItem xa=new JMenuItem("",Icons.STATUS_XA);
29         final JMenuItem dnd=new JMenuItem("",Icons.STATUS_DND);
30         final JMenuItem invisible=new JMenuItem("",Icons.STATUS_INVISIBLE);
31         final JMenuItem offline=new JMenuItem("",Icons.STATUS_OFFLINE);
32     final JButton myProfile=new JButton();
33     final JMenu chatMenu=new JMenu();
34         final JMenuItem message=new JMenuItem("",Icons.MESSAGE);
35         final JMenuItem singleChat=new JMenuItem("",Icons.SINGLE_CHAT);
36         final JMenuItem groupChat=new JMenuItem("",Icons.GROUP_CHAT);
37         final JMenuItem secureChannel=new JMenuItem("",Icons.SECURE_CHANNEL);
38     final JMenu toolsMenu=new JMenu();
39         final JMenuItem disco=new JMenuItem("",Icons.DISCO);
40     final JButton preferences=new JButton();
41     final JButton help=new JButton();
42     final JButton about=new JButton();
43     final JButton quit=new JButton();
44     final MenuClick menuClick=new MenuClick(); // action listener
45
// The main part
46
final JContactsPanel contactListPanel=new JContactsPanel();
47     final JTabbedPane chatPane=new JTabbedPane();
48     final JSplitPane splitPane=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
49     // Status bar
50
final public JLabel statusLbl=new JLabel("Whisper Instant Messanger");
51     
52     final CloseWindowClick closeWindowClick=new CloseWindowClick(); // window event listener
53
final PresenceChange presenceChange=new PresenceChange(); //listener for when usuer changes their presence via menu
54

55     /** Group list.
56     * key - string contain name
57     * value - a DefaultMutableTreeNode*/

58     final public Hashtable Groups=new Hashtable();
59     
60     /** User list.
61     * key - protocol+id
62     * value - contactlistitem.*/

63     final public Hashtable Contacts=new Hashtable();
64     
65     /** public keys.
66     * key - string of protocol+id
67     * value whisper public key.*/

68     final public Hashtable Keys=new Hashtable();
69     
70     
71     /** Connects keys to filenames.
72     * key is protocol+id.
73     * value is filename format wpk[n].dat*/

74     public final Hashtable keyFilenames=new Hashtable();
75         
76     private int nextkeyid=0;
77     
78     public byte[] keycachekey=new byte[20];
79     
80     /** User profiles
81     * key - string of protocol+id
82     * value - Profile object.*/

83     final public Hashtable Profiles=new Hashtable();
84     
85     /** Current chats.
86     * key -protocol+id
87     * value ChatPanels.*/

88     final public Hashtable Chats=new Hashtable();
89     
90     /** Current MUCs.
91     * key - roomname blue@example.net
92     * value MUCPanels.*/

93     final public Hashtable MUCs=new Hashtable();
94         
95     /** users current presence mode.
96     * Links to action commands of status menu items*/

97     public String JavaDoc currentPresence="online";
98     
99     // Current presence type.*/
100
private Presence.Mode PM=Presence.Mode.AVAILABLE;
101     
102     /** The connection.*/
103     public XMPPConnection Conn=null;
104     
105     /** The Service Discovery Manager.*/
106     public ServiceDiscoveryManager SDM=null;
107     
108     /** Jabbber roster.*/
109     public Roster roster;
110     
111     /** Vector of ids of that we know have no key.
112     * element is string of form protocol+id.*/

113     final private Vector noKeys=new Vector(5,5);
114     
115     public Profile MyProfile=new Profile();
116     public boolean gotMyProfile=false;
117         
118     public MyProfileWindow myProfileWindow=null;
119     public OptionsDialog2 optionsDialog=null;
120     
121     public ConnectionDialog connectionDialog;
122     
123     public DISCOWindow discoWindow;
124         
125     public SecureChannelPanel secureChannelPanel;
126         
127     private KeyPairRefreshThread kprThread=new KeyPairRefreshThread();
128         
129     public boolean intentionalQuit=false; //whether the user is quitting the app
130

131     private final Insets i=new Insets(0,3,0,3);
132     
133     /** Creates a new main frame instance.*/
134     public JMainFrame(){
135         super("Whisper IM ");
136         setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // action will depend on user prefs, normally will minimise
137
setIconImage(Icons.LOGO.getImage());
138         Container cp=getContentPane();
139         cp.setLayout(new BorderLayout());
140         createMenu(); // create the menu bar
141
//chatPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
142
ToolTipManager.sharedInstance().registerComponent(chatPane);
143         Dimension min=new Dimension(0,0);
144         chatPane.setMinimumSize(min);
145         chatPane.addChangeListener(new TabChangeListener());
146         contactListPanel.setMinimumSize(min);
147         splitPane.setOneTouchExpandable(true);
148         cp.add(splitPane,BorderLayout.CENTER);
149         cp.add(statusLbl,BorderLayout.SOUTH);
150         setLang(); // set labels accourding to language in use
151
addWindowListener(closeWindowClick); // listen for attempt to close the window
152
myProfile.setActionCommand("myProfile");
153         about.setActionCommand("about");
154         help.setActionCommand("help");
155         preferences.setActionCommand("preferences");
156         quit.setActionCommand("quit");
157         // keys
158
ActionMap am=getRootPane().getActionMap();
159         InputMap im=getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
160         // help keys
161
im.put(KeyStroke.getKeyStroke(WhisperIM.HELP_KEY,0),"help"); //put in help key for action help
162
am.put("help",new HelpAction(this,"main_window.html"));
163         // contacts list
164
contactListPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(WhisperIM.HELP_KEY,0),"help"); //put in help key for action help
165
contactListPanel.getActionMap().put("help",new HelpAction(this,"contacts.html"));
166         // short cuts
167
int ctrl=Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
168         
169         im.put(KeyStroke.getKeyStroke(KeyEvent.VK_U,ctrl),"adduser");
170         am.put("adduser",new KeyPress("adduser"));
171         
172         im.put(KeyStroke.getKeyStroke(KeyEvent.VK_M,ctrl),"newmessage");
173         am.put("newmessage",new KeyPress("newmessage"));
174         
175         im.put(KeyStroke.getKeyStroke(KeyEvent.VK_N,ctrl),"newchat");
176         am.put("newchat",new KeyPress("newchat"));
177         
178         im.put(KeyStroke.getKeyStroke(KeyEvent.VK_G,ctrl),"newgroupchat");
179         am.put("newgroupchat",new KeyPress("newgroupchat"));
180         
181         im.put(KeyStroke.getKeyStroke(KeyEvent.VK_Q,ctrl),"quit");
182         am.put("quit",new KeyPress("quit"));
183         
184         im.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME,ctrl),"firsttab");
185         am.put("firsttab",new KeyPress("firsttab"));
186         
187         im.put(KeyStroke.getKeyStroke(KeyEvent.VK_END,ctrl),"lasttab");
188         am.put("lasttab",new KeyPress("lasttab"));
189         
190         pack();
191         addMouseListener(new MouseAction());
192         addKeyListener(new KeyAction());
193     }
194     
195     /** Places the contact list on the right hand side.*/
196     public void contactListOnRight(){
197         splitPane.remove(contactListPanel);
198         splitPane.remove(chatPane);
199         splitPane.setResizeWeight(1.0);
200         splitPane.setLeftComponent(chatPane);
201         splitPane.setRightComponent(contactListPanel);
202     }
203     
204     /** Places the contact list on the left hand side.*/
205     public void contactListOnLeft(){
206         splitPane.remove(contactListPanel);
207         splitPane.remove(chatPane);
208         splitPane.setResizeWeight(0.0);
209         splitPane.setLeftComponent(contactListPanel);
210         splitPane.setRightComponent(chatPane);
211     }
212     
213     private int s2i(String JavaDoc s){
214         try{
215             int result=Integer.parseInt(s);
216             return result;
217         }
218         catch (Exception JavaDoc e){
219             return 0;
220         }
221     }
222     
223     public void show(){
224         doInit();
225         if(Conn!=null && Conn.isConnected()){
226             try{
227                 MyProfile.setFromVCard(VCard.fetch(Conn));
228                 gotMyProfile=true;
229             }
230             catch (XMPPException xe){
231                 GUI.showError(this,"error","error",null,xe);
232             }
233         }
234         loadKeyCache();
235         System.gc();
236         setCursor(GUI.NORMAL);
237     }
238     
239     /** Called from new account window when new account is created.*/
240     public void show_new(String JavaDoc accountname){
241         doInit();
242         if(Conn!=null && Conn.isConnected()){
243             try{
244                 VCard me=VCard.fetch(Conn);
245                 if(me.getFullName()==null){
246                     me.setFullName(accountname);
247                 }
248                 if(me.getNickname()==null){
249                     me.setNickname(accountname);
250                 }
251                 me.setKey(WhisperIM.KEYPAIR.publicKey());
252                 me.upload(Conn);
253                 MyProfile.setFromVCard(me);
254                 gotMyProfile=true;
255             }
256             catch (XMPPException xe){
257                 GUI.showError(this,"error","error",null,xe);
258             }
259         }
260         System.gc();
261         setCursor(GUI.NORMAL);
262     }
263     
264     /** Shows the options dialog.*/
265     public void showOptions(){
266         if(optionsDialog==null){
267             setCursor(GUI.WAIT);
268             optionsDialog=new OptionsDialog2();
269             optionsDialog.doSet(null);
270             setCursor(GUI.NORMAL);
271         }
272         if(!optionsDialog.isVisible()){
273             optionsDialog.setLocationRelativeTo(this);
274         }
275         optionsDialog.show();
276     }
277     
278     public void showSecureChannel(){
279         if(secureChannelPanel!=null){
280             chatPane.setSelectedComponent(secureChannelPanel);
281             return;
282         }
283         (new JoinSecureChannelDialog()).show();
284     }
285         
286     private void doInit(){
287         kprThread.start();
288         Runtime.getRuntime().addShutdownHook(new ShutDownThread());
289         if(WhisperIM.UserPref.getProperty("remember_window_size").equals("true")){
290             Properties winSize=new Properties();
291             try{ // try and load window size and postion properties
292
FileInputStream fis=new FileInputStream(new File(WhisperIM.userDir,"window.properties"));
293                 winSize.load(fis);
294                 fis.close();
295                 setLocation(s2i(winSize.getProperty("x")),s2i(winSize.getProperty("y")) );
296                 setSize(s2i(winSize.getProperty("w")),s2i(winSize.getProperty("h")) );
297                 splitPane.setDividerLocation(s2i(winSize.getProperty("divider")));
298             }
299             catch (Exception JavaDoc e){
300                 setSize(getPreferredSize());
301                 setLocationRelativeTo(null);
302             }
303         }
304         else{
305             // use default size and centre on screen
306
setSize(getPreferredSize());
307             setLocationRelativeTo(null);
308         }
309         if(WhisperIM.UserPref.getProperty("contact_list_location").equals("right")){
310             contactListOnRight();
311         }
312         else{
313             contactListOnLeft();
314         }
315         statusLbl.setText("Whisper IM "+WhisperIM.VERSION+" : "+WhisperIM.accountSettings.JabberUserName+"@"+WhisperIM.accountSettings.JabberServer);
316         super.show();
317         setCursor(GUI.WAIT);
318         // Connect
319
connectionDialog=new ConnectionDialog();
320         connectionDialog.connect();
321         boolean connected=connectionDialog.getResult();
322         if(!connected){
323             setCursor(GUI.NORMAL);
324             currentPresence="offline";
325             contactListPanel.disable();
326             contactListPanel.setEnabled(false);
327             myProfile.setEnabled(false);
328             chatMenu.setEnabled(false);
329             disco.setEnabled(false);
330             setTitle("Whisper IM "+Lang.gs("status_"+currentPresence));
331             myStatus.setToolTipText(Lang.gs("menu_status_tt")+Lang.gs("status_"+currentPresence));
332             myStatus.setIcon(new ImageIcon("img/status_"+currentPresence+".png"));
333         }
334         if(connected){
335             doRoster();
336             frame.setTitle("Whisper IM "+Lang.gs("status_"+currentPresence));
337         }
338         Idle.init();
339     }
340     
341     public void doRoster(){
342         (new DoRosterThread()).start();
343     }
344     
345     public ContactListItem addGroup(String JavaDoc name){
346         ContactListItem cli=new ContactListItem(name);
347         DefaultMutableTreeNode g=new DefaultMutableTreeNode(cli);
348         contactListPanel.treeModel.insertNodeInto(g,contactListPanel.top,contactListPanel.top.getChildCount());
349         contactListPanel.tree.scrollPathToVisible(new TreePath(g.getPath()));
350         Groups.put(name,g);
351         roster.createGroup(name);
352         return cli;
353     }
354     
355     public void addUser(String JavaDoc protocol,String JavaDoc id,String JavaDoc name,String JavaDoc group){
356         String JavaDoc g[]=new String JavaDoc[1];
357         g[0]=group;
358         try{
359             roster.createEntry(id,name,g);
360         }
361         catch(XMPPException xe){
362             GUI.showError(frame,"error","error",null,xe);
363             return;
364         }
365         ContactListItem contact;
366         RosterEntry re=roster.getEntry(id);
367         if(id.indexOf("@")!=-1){
368             if(re==null){
369                 contact=new ContactListItem(name,id,roster.getPresence(id), RosterPacket.ItemType.FROM);
370             }
371             else{
372                 contact=new ContactListItem(name,id,roster.getPresence(id), roster.getEntry(id).getType());
373             }
374         }
375         else{
376             //Its a service
377
contact=new ContactListItem(name,id,ContactListItem.SERVICE);
378         }
379         
380         DefaultMutableTreeNode n=new DefaultMutableTreeNode(contact);
381         Contacts.put(protocol+id,contact);
382         
383         if(group==null){
384             contactListPanel.treeModel.insertNodeInto(n,contactListPanel.top,0);
385         }
386         else{
387             DefaultMutableTreeNode parent=(DefaultMutableTreeNode)Groups.get(group);
388             contactListPanel.treeModel.insertNodeInto(n,parent,parent.getChildCount());
389         }
390         contactListPanel.tree.scrollPathToVisible(new TreePath(n.getPath()));
391     }
392     
393     /** Loads the key cache key.*/
394     public void loadKeyCacheKey() throws Exception JavaDoc{
395             FileInputStream kckis=new FileInputStream(new File(WhisperIM.userDir,WhisperIM.KCK_FILE_NAME));
396             byte[] size=new byte[2];
397             int r=kckis.read(size);
398             if(r!=2){
399                 throw new Exception JavaDoc("kck.dat is truncated");
400             }
401             int ekcksize=whisper.Util.calcLength(size);
402             whisper.Util.wipe(size);
403             byte[]ekck=new byte[ekcksize]; //encrypted key cache key
404
r=kckis.read(ekck);
405             if(r!=ekcksize){
406                 throw new Exception JavaDoc("kck.dat is corrupted");
407             }
408             kckis.close();
409             keycachekey=whisper.RSA.decryptSessionKey(WhisperIM.KEYPAIR.publicKey().getN(),WhisperIM.KEYPAIR.privateKey().getD(),WhisperIM.KEYPAIR.privateKey().getP() ,WhisperIM.KEYPAIR.privateKey().getQ() ,WhisperIM.KEYPAIR.privateKey().getDP() ,WhisperIM.KEYPAIR.privateKey().getDQ() ,WhisperIM.KEYPAIR.privateKey().getQInvP(),ekck);
410             whisper.Util.wipe(ekck);
411     }
412     
413     /** Loads the public key cache.*/
414     private void loadKeyCache(){
415         String JavaDoc warnings="";
416         try{//get list of files
417
File[] filelist=WhisperIM.userDir.listFiles();
418             if(filelist==null ||filelist.length==0){
419                 return;
420             }
421             String JavaDoc filename;
422             int n;
423             for(int i=0;i<filelist.length;i++){ //iterate thru list
424
filename=filelist[i].getName();
425                 if(filename.startsWith("wpk") && filename.endsWith(".dat") && filename.length()>7){
426                     //check theres an int after wpk and before .dat
427
n=-1;
428                     try{
429                         n=Integer.parseInt(filename.substring(3,filename.length()-4));
430                     }
431                     catch(Exception JavaDoc nfe){
432                         n=-1;
433                     }
434                     if(n>0){
435                         //the file name is ok, so process
436
try{
437                             readKey(filename);
438                         }
439                         catch(Exception JavaDoc rke){
440                             warnings=warnings+filename+" "+rke.getMessage()+"\r\n";
441                             n=-1;
442                         }
443                         if(n>=nextkeyid){ // alter next key id if requires
444
nextkeyid=n; //nextkeyid is inc'd, see getNextKeyID()
445
}
446                     }
447                 }
448             }
449         }
450         catch(Exception JavaDoc e){
451             e.printStackTrace();
452             GUI.showError(this,null,"error",e.getMessage());
453         }
454         if(!warnings.equals("")){
455             GUI.showWarning(this,null,"key cache problem", warnings);
456         }
457     }
458     
459     private void readKey(String JavaDoc filename) throws Exception JavaDoc{
460         File f=new File(WhisperIM.userDir,filename);
461         whisper.WhisperInputStream wis=new whisper.WhisperInputStream(f,keycachekey);
462         whisper.PublicKey pubKey=(PublicKey)wis.read();
463         wis.close();
464         // Add to memory cache and key file list
465
// get the id's
466
Vector ids=whisper.Parse.getTags(pubKey.getID());
467         String JavaDoc protocol;
468         String JavaDoc uid;
469         String JavaDoc tag;
470         for(int i=0;i<ids.size();i++){ //iterate thru the id's
471
tag=((String JavaDoc)ids.elementAt(i)).trim();
472             protocol=tag.substring(1,tag.indexOf(">"));
473             uid=whisper.Parse.getTag(pubKey.getID(),protocol);
474             Keys.put(protocol+uid,pubKey); // add to memory cache
475
keyFilenames.put(protocol+uid,filename); //add to filename list
476
}
477     }
478     
479     public void saveKey(whisper.PublicKey key, String JavaDoc filename){
480         try{
481             File f=new File(WhisperIM.userDir,filename);
482             whisper.WhisperOutputStream wis=new whisper.WhisperOutputStream(f,keycachekey,WhisperIM.SR,null);
483             wis.write(key);
484             wis.close();
485         }
486         catch(Exception JavaDoc e){
487             e.printStackTrace();
488         }
489     }
490     
491     public synchronized int getNextKeyID(){
492         nextkeyid++;
493         return nextkeyid;
494     }
495     
496     /** Returns true if we already know a user does not have a whisper key.*/
497     public boolean hasNoKey(String JavaDoc protocol,String JavaDoc id){
498         // iterate thru the vector
499
if(noKeys.isEmpty()){ return false;}
500         for (int i=0;i<noKeys.size();i++){
501             if( ( (String JavaDoc) (noKeys.elementAt(i)) ).equals(protocol+id) ){
502                 return true;
503             }
504         }
505         return false;
506     }
507     
508     /** Call when we have discovered a user does not have a whisper key.*/
509     public void noKey(String JavaDoc protocol,String JavaDoc id){
510         noKeys.add(protocol+id);
511     }
512     
513     /** Used to get key when not already in the Keys hashtable.
514     * Returns <code>null</code> if user does not have a whisper key.*/

515     public whisper.PublicKey getKey(String JavaDoc protocol,String JavaDoc id) throws XMPPException{
516         id=id.toLowerCase();
517         if(protocol.equals("jabber")){
518             id=StringUtils.parseBareAddress(id);
519         }
520         VCard vcard=VCard.fetch(Conn,id);
521         // add profile to cache
522
WhisperIM.MainWindow.Profiles.put("jabber"+id,new Profile(vcard));
523         whisper.PublicKey key=vcard.getKey();
524         if(key==null){
525             noKey("jabber",id); // remember this
526
return null;
527         }
528         // validate key
529
if(!isKeyValid(key,id,protocol)){
530             noKey("jabber",id);
531             return null;
532         }
533         // add to memory cache
534
Keys.put(protocol+id,key);
535         //save
536
saveKey(key,"wpk"+getNextKeyID()+".dat");
537         return key;
538     }
539     
540     public boolean isKeyValid(whisper.PublicKey key, String JavaDoc id, String JavaDoc protocol){
541         if(!key.isValid()){ // check signature
542
return false;
543         }
544         
545         // check date stamp - allow 48 hours for potentail timezone wierdness and inaccurate clocks
546
java.util.GregorianCalendar JavaDoc tm=whisper.Util.getCalendar(); // get todays date
547
tm.add(java.util.Calendar.DATE,2); // add 2 days
548
try{
549             if(whisper.Util.parseTime(key.date()).after(tm)){ // timestamp of key is in future
550
return false;
551             }
552         }
553         catch (whisper.WhisperException we){ //bad timestamp in key
554
return false;
555         }
556         // check the id of key
557
String JavaDoc keyid=whisper.Parse.getTag(key.getID(),protocol);
558         if(keyid==null){
559             return false;
560         }
561         if(!keyid.equals(id)){ // check matches
562
return false;
563         }
564         return true;
565     }
566     
567     public void chatWith(String JavaDoc id){
568         if(!Conn.isConnected()){
569             GUI.showWarning(this,"menu_chat","need to be connected");
570             return;
571         }
572         try{
573         String JavaDoc bareID=StringUtils.parseBareAddress(id.toLowerCase());
574         // see if already chatting
575
ChatPanel ccp=(ChatPanel)Chats.get("jabber"+bareID);
576         if(ccp!=null){
577             chatPane.setSelectedComponent(ccp);
578             ccp.doFocus();
579             return;
580         }
581         String JavaDoc name=bareID;
582         String JavaDoc tabname=StringUtils.parseName(name)+"@";
583         ContactListItem cli=(ContactListItem)Contacts.get("jabber"+bareID);
584         if(cli!=null){
585             name=cli.toString();
586             tabname=name;
587         }
588         ChatPanel cp;
589         whisper.PublicKey pk=null;
590         if(hasNoKey("jabber",bareID)){
591             cp=new ChatPanel(name,id,new Chat(Conn,id),false,GUI.getDate());
592         }
593         else{
594             pk=(whisper.PublicKey)Keys.get("jabber"+bareID);
595             if(pk==null){
596                 try{
597                     pk=getKey("jabber",bareID);
598                 }
599                 catch(XMPPException xe){
600                     if(WhisperIM.UserPref.getProperty("warn_unencrypted").equals("true")){
601                         GUI.showWarning(this,"no key","no public key",id+"\r\n"+xe.getMessage());
602                     }
603                 }
604                 if(pk==null){
605                     cp=new ChatPanel(name,id,new Chat(Conn,id),false,GUI.getDate());
606                 }
607                 else{
608                     cp=new ChatPanel(name,id,new Chat(Conn,id),true,GUI.getDate());
609                 }
610             }
611             else{
612                 cp=new ChatPanel(name,id,new Chat(Conn,id),true,GUI.getDate());
613             }
614         }
615         Chats.put("jabber"+bareID,cp);
616         chatPane.addTab(tabname,Icons.CHAT,cp,Lang.gs("chatting with")+id);
617         chatPane.setSelectedComponent(cp);
618         cp.doFocus();
619         }// end of try
620
catch(Exception JavaDoc e){
621             e.printStackTrace();
622             GUI.showError(this,"error","error",e.getMessage());
623         }
624     }
625     
626     public void doConnectionClosed(Exception JavaDoc e){
627         for(int i=0;i<chatPane.getTabCount();i++){
628                     ((WMP)chatPane.getComponentAt(i)).goneOffline();
629         }
630         currentPresence="offline";
631         contactListPanel.disable();
632         contactListPanel.setEnabled(false);
633         myProfile.setEnabled(false);
634         chatMenu.setEnabled(false);
635         disco.setEnabled(false);
636         frame.setTitle("Whisper IM "+Lang.gs("status_"+currentPresence));
637         myStatus.setToolTipText(Lang.gs("menu_status_tt")+Lang.gs("status_"+currentPresence));
638         myStatus.setIcon(new ImageIcon("img/status_"+currentPresence+".png"));
639         GUI.showError(this,"connection error","connection closed",Conn.getHost()+"\r\n"+e.getMessage());
640     }
641     
642     public void setLang(){
643         // menu first
644
//myStatus.setText(Lang.gs("menu_status"));
645
online.setText(Lang.gs("status_online"));
646             available.setText(Lang.gs("status_available"));
647             away.setText(Lang.gs("status_away"));
648             xa.setText(Lang.gs("status_xa"));
649             dnd.setText(Lang.gs("status_dnd"));
650             invisible.setText(Lang.gs("status_invisible"));
651             offline.setText(Lang.gs("status_offline"));
652         myStatus.setMnemonic(Lang.s2k("menu_status_mn"));
653         myStatus.setToolTipText(Lang.gs("menu_status_tt")+Lang.gs("status_"+currentPresence));
654         //myProfile.setText(Lang.gs("menu_profile"));
655
myProfile.setMnemonic(Lang.s2k("menu_profile_mn"));
656         myProfile.setToolTipText(Lang.gs("menu_profile_tt"));
657         //chatMenu.setText(Lang.gs("menu_chat"));
658
chatMenu.setMnemonic(Lang.s2k("menu_chat_mn"));
659         chatMenu.setToolTipText(Lang.gs("menu_chat_tt"));
660             message.setText(Lang.gs("menu_chat_sendmessage"));
661             singleChat.setText(Lang.gs("menu_chat_chat"));
662             groupChat.setText(Lang.gs("menu_chat_groupchat"));
663             secureChannel.setText(Lang.gs("secure channel"));
664         //toolsMenu.setText(Lang.gs("menu_tools"));
665
toolsMenu.setMnemonic(Lang.s2k("menu_tools_mn"));
666         toolsMenu.setToolTipText(Lang.gs("menu_tools_tt"));
667             disco.setText(Lang.gs("menu_tools_disco"));
668         //preferences.setText(Lang.gs("menu_preferences"));
669
preferences.setMnemonic(Lang.s2k("menu_preferences_mn"));
670         preferences.setToolTipText(Lang.gs("menu_preferences_tt"));
671         //help.setText(Lang.gs("menu_help"));
672
help.setMnemonic(Lang.s2k("menu_help_mn"));
673         help.setToolTipText(Lang.gs("menu_help_tt"));
674         //about.setText(Lang.gs("menu_about"));
675
about.setMnemonic(Lang.s2k("menu_about_mn"));
676         about.setToolTipText(Lang.gs("menu_about_tt"));
677         //quit.setText(Lang.gs("menu_quit"));
678
quit.setMnemonic(Lang.s2k("menu_quit_mn"));
679         quit.setToolTipText(Lang.gs("menu_quit_tt"));
680         // now contacts list
681
contactListPanel.setLang();
682         if(myProfileWindow!=null){
683             myProfileWindow.setLang();
684         }
685         if(connectionDialog!=null){
686             connectionDialog.setLang();
687         }
688         if(discoWindow!=null){
689             discoWindow.setLang();
690         }
691     }
692     
693     private void doMI(JMenuItem mi, ImageIcon icon){
694         mi.setIcon(icon);
695         mi.setVerticalTextPosition(AbstractButton.BOTTOM);
696         mi.setHorizontalTextPosition(AbstractButton.CENTER);
697         mi.setMargin(i);
698         mi.setIconTextGap(0);
699         mi.addActionListener(menuClick);
700         menuBar.add(mi);
701         mi.setBorderPainted(false);
702     }
703     
704     private void doMI(JButton mi, ImageIcon icon){
705         mi.setIcon(icon);
706         mi.setVerticalTextPosition(AbstractButton.BOTTOM);
707         mi.setHorizontalTextPosition(AbstractButton.CENTER);
708         mi.setMargin(i);
709         mi.setIconTextGap(0);
710         mi.addActionListener(menuClick);
711         menuBar.add(mi);
712         mi.setBorderPainted(false);
713     }
714     
715     /** Creates the menu bar.*/
716     private void createMenu(){
717         doMI(myStatus,Icons.STATUS_ONLINE);// default status
718
myStatus.add(online);
719             online.setActionCommand("online");
720             online.addActionListener(presenceChange);
721             myStatus.add(available);
722             available.addActionListener(presenceChange);
723             available.setActionCommand("available");
724             myStatus.add(away);
725             away.addActionListener(presenceChange);
726             away.setActionCommand("away");
727             myStatus.add(xa);
728             xa.addActionListener(presenceChange);
729             xa.setActionCommand("xa");
730             myStatus.add(dnd);
731             dnd.addActionListener(presenceChange);
732             dnd.setActionCommand("dnd");
733             myStatus.add(invisible);
734             invisible.addActionListener(presenceChange);
735             invisible.setActionCommand("invisible");
736             myStatus.add(offline);
737             offline.setActionCommand("offline");
738             offline.addActionListener(presenceChange);
739         
740         doMI(myProfile,Icons.PROFILE);
741         doMI(chatMenu,Icons.PRIVATE_MESSAGE);
742             chatMenu.add(singleChat);
743             singleChat.addActionListener(menuClick);
744             chatMenu.add(message);
745             message.addActionListener(menuClick);
746             chatMenu.add(groupChat);
747             groupChat.addActionListener(menuClick);
748             chatMenu.addSeparator();
749             chatMenu.add(secureChannel);
750             secureChannel.addActionListener(menuClick);
751             
752         doMI(toolsMenu,Icons.TOOLS);
753             disco.addActionListener(menuClick);
754             toolsMenu.add(disco);
755             
756         doMI(preferences,Icons.PREFERENCES);
757         doMI(help,Icons.HELP);
758         doMI(about,Icons.ABOUT);
759         menuBar.add(Box.createHorizontalGlue());// the quit button will be stuck to the far right
760
doMI(quit,Icons.QUIT);
761         setJMenuBar(menuBar);
762     }
763     
764     public void doQuit(){
765         Idle.stop();
766         intentionalQuit=true;
767         hide();
768         if(discoWindow!=null){
769             discoWindow.dispose();
770         }
771         if(myProfileWindow!=null){
772             myProfileWindow.dispose();
773         }
774         if(optionsDialog!=null){
775             optionsDialog.dispose();
776         }
777         kprThread.interrupt();
778         WhisperIM.KEYPAIR.privateKey().wipe();
779         whisper.Util.wipe(keycachekey);
780         WhisperIM.KEYPAIR=null;
781         if(WhisperIM.UserPref.getProperty("remember_window_size").equals("true")){
782             // save window size and postion
783
Properties winSize=new Properties();
784             FileOutputStream fos=null;
785             try{
786                 fos=new FileOutputStream(new File(WhisperIM.userDir,"window.properties"),false);
787                 winSize.setProperty("x",getX()+"");
788                 winSize.setProperty("y",getY()+"");
789                 winSize.setProperty("w",getWidth()+"");
790                 winSize.setProperty("h",getHeight()+"");
791                 winSize.setProperty("divider",splitPane.getDividerLocation()+"");
792                 winSize.store(fos,"Whisper Main Window starting size and location");
793                 fos.close();
794             }
795             catch(Exception JavaDoc e){
796                 try{
797                     e.printStackTrace();
798                     if(fos!=null){fos.close();}
799                 }
800                 catch(Exception JavaDoc e2){
801                     e2.printStackTrace();
802                 }
803             }
804         }
805         if(Conn!=null && Conn.isConnected()){
806             try{
807                 Conn.close();
808             }
809             catch(Exception JavaDoc e3){
810                 e3.printStackTrace();
811             }
812         }
813         dispose();
814         System.exit(0);
815     }
816     
817     final class MenuClick implements ActionListener{
818         public void actionPerformed(ActionEvent ae){
819             try{
820             //get menu item
821
String JavaDoc m=ae.getActionCommand();
822                 if(m.equals("about")){
823                     GUI.showAbout(frame);
824                     return;
825                 }
826                 if(m.equals(message.getText())){
827                     ComposeMessagePanel cmp=new ComposeMessagePanel();
828                     chatPane.addTab("",Icons.MESSAGE,cmp,Lang.gs("compose_tt"));
829                     chatPane.setSelectedComponent(cmp);
830                     cmp.doFocus();
831                     return;
832                 }
833                 if(m.equals(singleChat.getText())){
834                     (new ChatWithDialog()).show();
835                     return;
836                 }
837                 if(m.equals("quit")){
838                     doQuit();
839                     return;
840                 }
841                 if(m.equals("myProfile")){
842                     if(myProfileWindow==null){
843                         setCursor(GUI.WAIT);
844                         myProfileWindow=new MyProfileWindow();
845                         setCursor(GUI.NORMAL);
846                     }
847                     myProfileWindow.show();
848                     return;
849                 }
850                 if(m.equals(groupChat.getText())){
851                     (new JoinMUCDialog()).show();
852                     return;
853                 }
854                 if(m.equals("preferences")){
855                     showOptions();
856                     return;
857                 }
858                 if(m.equals(disco.getText())){
859                     if(discoWindow==null){
860                         setCursor(GUI.WAIT);
861                         discoWindow=new DISCOWindow();
862                         setCursor(GUI.NORMAL);
863                     }
864                     discoWindow.show();
865                     return;
866                 }
867                 if(m.equals("help")){
868                     HelpWindow.show(WhisperIM.MainWindow,"main_window.html");
869                     return;
870                 }
871                 if(m.equals(secureChannel.getText())){
872                     showSecureChannel();
873                     return;
874                 }
875             }
876             catch (Throwable JavaDoc t){
877                 GUI.errorStop(null,t);
878             }
879         }
880     }
881     
882     /** Action listener for when the use changes their presence.*/
883     final class PresenceChange implements ActionListener{
884         public void actionPerformed(ActionEvent ae){
885             //get which one
886
String JavaDoc m=ae.getActionCommand();
887             if(currentPresence.equals(m)){
888                 return; //no change
889
}
890             if(currentPresence.equals("offline")){ // need to reconnect
891
connectionDialog.connect();
892                 if(connectionDialog.getResult()==false){
893                     return; // reconnection canceled or failed, so return
894
}
895                 statusLbl.setText("Whisper IM "+WhisperIM.VERSION+" : "+WhisperIM.accountSettings.JabberUserName+"@"+WhisperIM.accountSettings.JabberServer);
896                 // remove roster
897
DefaultMutableTreeNode dmtn;
898                 Enumeration e=Groups.elements();
899                 while(e.hasMoreElements()){
900                     dmtn=(DefaultMutableTreeNode)e.nextElement();
901                     dmtn.removeAllChildren();
902                 }
903                 Groups.clear();
904                 Contacts.clear();
905                 contactListPanel.top.removeAllChildren();
906                 contactListPanel.top=new DefaultMutableTreeNode(new ContactListItem());
907                 contactListPanel.treeModel=new DefaultTreeModel(contactListPanel.top);
908                 contactListPanel.tree.setModel(contactListPanel.treeModel);
909                 // re-do roster
910
doRoster();
911                 //re-enable controls
912
for(int i=0;i<chatPane.getTabCount();i++){
913                     ((WMP)chatPane.getComponentAt(i)).goneOnline();
914                 }
915                 contactListPanel.enable();
916                 myProfile.setEnabled(true);
917                 chatMenu.setEnabled(true);
918                 disco.setEnabled(true);
919                 contactListPanel.tree.expandRow(contactListPanel.tree.getRowCount()-1);
920             }
921             currentPresence=m;
922             if(m.equals("offline")){ //going offline
923
for(int i=0;i<chatPane.getTabCount();i++){
924                     ((WMP)chatPane.getComponentAt(i)).goneOffline();
925                 }
926                 contactListPanel.disable();
927                 contactListPanel.setEnabled(false);
928                 myProfile.setEnabled(false);
929                 chatMenu.setEnabled(false);
930                 disco.setEnabled(false);
931                 Conn.close();
932             }
933             else{
934                 Presence p=new Presence(Presence.Type.AVAILABLE);
935                 p.setFrom(Conn.getUser());
936                 if(m.equals("invisible")){
937                     p.setMode(Presence.Mode.INVISIBLE);
938                 }
939                 if(m.equals("dnd")){
940                     p.setMode(Presence.Mode.DO_NOT_DISTURB);
941                 }
942                 if(m.equals("xa")){
943                     p.setMode(Presence.Mode.EXTENDED_AWAY);
944                 }
945                 if(m.equals("away")){
946                     p.setMode(Presence.Mode.AWAY);
947                 }
948                 if(m.equals("available")){
949                     p.setMode(Presence.Mode.CHAT);
950                 }
951                 if(m.equals("online")){
952                     p.setMode(Presence.Mode.AVAILABLE);
953                 }
954                 PM=p.getMode(); //remember this for if user set status text...
955
Conn.sendPacket(p);
956             }
957             // set display
958
frame.setTitle("Whisper IM "+Lang.gs("status_"+currentPresence));
959             
960             myStatus.setToolTipText(Lang.gs("menu_status_tt")+Lang.gs("status_"+currentPresence));
961             myStatus.setIcon(new ImageIcon("img/status_"+m+".png"));
962         }
963     }
964     
965     final class CloseWindowClick extends WindowAdapter{
966         public CloseWindowClick(){
967             super();
968         }
969         public void windowClosing(WindowEvent e){
970             if(WhisperIM.UserPref.getProperty("close_action").equals("quit")){
971                 doQuit();
972             }
973             frame.setExtendedState(java.awt.Frame.ICONIFIED);
974         }
975     }
976     
977     final class TabChangeListener implements ChangeListener{
978         
979         public void stateChanged(ChangeEvent e){
980             if(chatPane.getTabCount()==0 || chatPane.getSelectedIndex()==-1){
981                 return;
982             }
983             WMP wp=(WMP)chatPane.getSelectedComponent();
984             getRootPane().setDefaultButton(wp.getDefaultButton());
985             wp.doFocus();
986         }
987     }
988     
989     final class KeyPress extends AbstractAction{
990         private String JavaDoc name;
991         
992         public KeyPress(String JavaDoc name){
993             super(name);
994             this.name=name;
995         }
996         
997         public void actionPerformed(ActionEvent e) {
998             if(name.equals("newchat")){
999                 (new ChatWithDialog()).show();
1000                return;
1001            }
1002            if(name.equals("newmessage")){
1003                ComposeMessagePanel cmp=new ComposeMessagePanel();
1004                chatPane.addTab("",Icons.MESSAGE,cmp,Lang.gs("compose_tt"));
1005                chatPane.setSelectedComponent(cmp);
1006                cmp.doFocus();
1007                return;
1008            }
1009            if(name.equals("adduser")){
1010                (new AddContactDialog(WhisperIM.MainWindow)).show();
1011                return;
1012            }
1013            if(name.equals("newgroupchat")){
1014                (new JoinMUCDialog()).show();
1015                return;
1016            }
1017            if(name.equals("quit")){
1018                doQuit();
1019                return;
1020            }
1021            
1022            if(chatPane.getTabCount()<1){
1023                return;
1024            }
1025            if(name.equals("firsttab")){
1026                chatPane.setSelectedIndex(0);
1027            }
1028            if(name.equals("lasttab")){
1029                chatPane.setSelectedIndex(chatPane.getTabCount()-1);
1030            }
1031            WMP wmp=(WMP)chatPane.getSelectedComponent();
1032            if(wmp!=null){
1033                wmp.doFocus();
1034            }
1035        }
1036    }
1037    
1038    final class DoRosterThread extends Thread JavaDoc{
1039        
1040        public DoRosterThread(){
1041            super("DoRosterThread in JMainFrame class");
1042            setPriority(Thread.MIN_PRIORITY);
1043            setDaemon(true);
1044        }
1045        
1046        public void run(){
1047            try{
1048                roster=Conn.getRoster();
1049                roster.addRosterListener(new PresenceChangeListener() );
1050                Iterator i;
1051                Iterator ei;
1052                RosterGroup rg;
1053                RosterEntry re;
1054                ContactListItem cli;
1055                ContactListItem gcli;
1056                DefaultMutableTreeNode dmtn;
1057                i=roster.getUnfiledEntries();
1058                while(i.hasNext()){
1059                    re=(RosterEntry)i.next();
1060                    if(re.getUser().indexOf("@")!=-1){
1061                        cli=new ContactListItem(re.getName(),re.getUser(),roster.getPresence(re.getUser()),re.getType());
1062                    }
1063                    else{//service
1064
cli=new ContactListItem(re.getName(),re.getUser(),ContactListItem.SERVICE);
1065                    }
1066                    final ContactListItem finalcli=cli;
1067                    javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc(){
1068                        public void run(){
1069                            contactListPanel.top.add(new DefaultMutableTreeNode(finalcli));
1070                        }
1071                    });
1072                    Contacts.put("jabber"+re.getUser(),cli);
1073                }
1074                i=roster.getGroups();
1075                while(i.hasNext()){
1076                    rg=(RosterGroup)i.next();
1077                    gcli=new ContactListItem(rg.getName());
1078                    dmtn=new DefaultMutableTreeNode(gcli);
1079                    Groups.put(rg.getName(),dmtn);
1080                    final DefaultMutableTreeNode finaldmtn=dmtn;
1081                    javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc(){
1082                        public void run(){
1083                            contactListPanel.top.add(finaldmtn);
1084                        }
1085                    });
1086                    ei=rg.getEntries();
1087                    while(ei.hasNext()){
1088                        re=(RosterEntry)ei.next();
1089                        if(re.getUser().indexOf("@")!=-1){
1090                            cli=new ContactListItem(re.getName(),re.getUser(),roster.getPresence(re.getUser()),re.getType());
1091                        }
1092                        else{//service
1093
cli=new ContactListItem(re.getName(),re.getUser(),ContactListItem.SERVICE);
1094                        }
1095                        Contacts.put("jabber"+re.getUser(),cli);
1096                        final ContactListItem finalcli2=cli;
1097                        javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc(){
1098                            public void run(){
1099                                finaldmtn.add(new DefaultMutableTreeNode(finalcli2));
1100                            }
1101                        });
1102                    }
1103                }
1104                javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc(){
1105                    public void run(){
1106                        contactListPanel.tree.expandRow(contactListPanel.tree.getRowCount()-1);
1107                    }
1108                });
1109            }
1110            catch(Exception JavaDoc e){
1111                e.printStackTrace();
1112            }
1113        }
1114    }
1115}
Popular Tags