1 import java.awt.*; 2 import java.awt.event.*; 3 import java.awt.image.ImageObserver ; 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 ; 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 19 public final class JMainFrame extends JFrame implements Accessible , ImageObserver , MenuContainer, RootPaneContainer, Serializable, WindowConstants{ 20 21 final JFrame frame=this; 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(); final JContactsPanel contactListPanel=new JContactsPanel(); 47 final JTabbedPane chatPane=new JTabbedPane(); 48 final JSplitPane splitPane=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); 49 final public JLabel statusLbl=new JLabel("Whisper Instant Messanger"); 51 52 final CloseWindowClick closeWindowClick=new CloseWindowClick(); final PresenceChange presenceChange=new PresenceChange(); 55 58 final public Hashtable Groups=new Hashtable(); 59 60 63 final public Hashtable Contacts=new Hashtable(); 64 65 68 final public Hashtable Keys=new Hashtable(); 69 70 71 74 public final Hashtable keyFilenames=new Hashtable(); 75 76 private int nextkeyid=0; 77 78 public byte[] keycachekey=new byte[20]; 79 80 83 final public Hashtable Profiles=new Hashtable(); 84 85 88 final public Hashtable Chats=new Hashtable(); 89 90 93 final public Hashtable MUCs=new Hashtable(); 94 95 97 public String currentPresence="online"; 98 99 private Presence.Mode PM=Presence.Mode.AVAILABLE; 101 102 103 public XMPPConnection Conn=null; 104 105 106 public ServiceDiscoveryManager SDM=null; 107 108 109 public Roster roster; 110 111 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; 131 private final Insets i=new Insets(0,3,0,3); 132 133 134 public JMainFrame(){ 135 super("Whisper IM "); 136 setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); setIconImage(Icons.LOGO.getImage()); 138 Container cp=getContentPane(); 139 cp.setLayout(new BorderLayout()); 140 createMenu(); 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(); addWindowListener(closeWindowClick); myProfile.setActionCommand("myProfile"); 153 about.setActionCommand("about"); 154 help.setActionCommand("help"); 155 preferences.setActionCommand("preferences"); 156 quit.setActionCommand("quit"); 157 ActionMap am=getRootPane().getActionMap(); 159 InputMap im=getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 160 im.put(KeyStroke.getKeyStroke(WhisperIM.HELP_KEY,0),"help"); am.put("help",new HelpAction(this,"main_window.html")); 163 contactListPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(WhisperIM.HELP_KEY,0),"help"); contactListPanel.getActionMap().put("help",new HelpAction(this,"contacts.html")); 166 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 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 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 s){ 214 try{ 215 int result=Integer.parseInt(s); 216 return result; 217 } 218 catch (Exception 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 240 public void show_new(String 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 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{ 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 e){ 300 setSize(getPreferredSize()); 301 setLocationRelativeTo(null); 302 } 303 } 304 else{ 305 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 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 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 protocol,String id,String name,String group){ 356 String g[]=new String [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 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 394 public void loadKeyCacheKey() throws Exception { 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 ("kck.dat is truncated"); 400 } 401 int ekcksize=whisper.Util.calcLength(size); 402 whisper.Util.wipe(size); 403 byte[]ekck=new byte[ekcksize]; r=kckis.read(ekck); 405 if(r!=ekcksize){ 406 throw new Exception ("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 414 private void loadKeyCache(){ 415 String warnings=""; 416 try{ File[] filelist=WhisperIM.userDir.listFiles(); 418 if(filelist==null ||filelist.length==0){ 419 return; 420 } 421 String filename; 422 int n; 423 for(int i=0;i<filelist.length;i++){ filename=filelist[i].getName(); 425 if(filename.startsWith("wpk") && filename.endsWith(".dat") && filename.length()>7){ 426 n=-1; 428 try{ 429 n=Integer.parseInt(filename.substring(3,filename.length()-4)); 430 } 431 catch(Exception nfe){ 432 n=-1; 433 } 434 if(n>0){ 435 try{ 437 readKey(filename); 438 } 439 catch(Exception rke){ 440 warnings=warnings+filename+" "+rke.getMessage()+"\r\n"; 441 n=-1; 442 } 443 if(n>=nextkeyid){ nextkeyid=n; } 446 } 447 } 448 } 449 } 450 catch(Exception 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 filename) throws Exception { 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 Vector ids=whisper.Parse.getTags(pubKey.getID()); 467 String protocol; 468 String uid; 469 String tag; 470 for(int i=0;i<ids.size();i++){ tag=((String )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); keyFilenames.put(protocol+uid,filename); } 477 } 478 479 public void saveKey(whisper.PublicKey key, String 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 e){ 487 e.printStackTrace(); 488 } 489 } 490 491 public synchronized int getNextKeyID(){ 492 nextkeyid++; 493 return nextkeyid; 494 } 495 496 497 public boolean hasNoKey(String protocol,String id){ 498 if(noKeys.isEmpty()){ return false;} 500 for (int i=0;i<noKeys.size();i++){ 501 if( ( (String ) (noKeys.elementAt(i)) ).equals(protocol+id) ){ 502 return true; 503 } 504 } 505 return false; 506 } 507 508 509 public void noKey(String protocol,String id){ 510 noKeys.add(protocol+id); 511 } 512 513 515 public whisper.PublicKey getKey(String protocol,String 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 WhisperIM.MainWindow.Profiles.put("jabber"+id,new Profile(vcard)); 523 whisper.PublicKey key=vcard.getKey(); 524 if(key==null){ 525 noKey("jabber",id); return null; 527 } 528 if(!isKeyValid(key,id,protocol)){ 530 noKey("jabber",id); 531 return null; 532 } 533 Keys.put(protocol+id,key); 535 saveKey(key,"wpk"+getNextKeyID()+".dat"); 537 return key; 538 } 539 540 public boolean isKeyValid(whisper.PublicKey key, String id, String protocol){ 541 if(!key.isValid()){ return false; 543 } 544 545 java.util.GregorianCalendar tm=whisper.Util.getCalendar(); tm.add(java.util.Calendar.DATE,2); try{ 549 if(whisper.Util.parseTime(key.date()).after(tm)){ return false; 551 } 552 } 553 catch (whisper.WhisperException we){ return false; 555 } 556 String keyid=whisper.Parse.getTag(key.getID(),protocol); 558 if(keyid==null){ 559 return false; 560 } 561 if(!keyid.equals(id)){ return false; 563 } 564 return true; 565 } 566 567 public void chatWith(String id){ 568 if(!Conn.isConnected()){ 569 GUI.showWarning(this,"menu_chat","need to be connected"); 570 return; 571 } 572 try{ 573 String bareID=StringUtils.parseBareAddress(id.toLowerCase()); 574 ChatPanel ccp=(ChatPanel)Chats.get("jabber"+bareID); 576 if(ccp!=null){ 577 chatPane.setSelectedComponent(ccp); 578 ccp.doFocus(); 579 return; 580 } 581 String name=bareID; 582 String 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 } catch(Exception e){ 621 e.printStackTrace(); 622 GUI.showError(this,"error","error",e.getMessage()); 623 } 624 } 625 626 public void doConnectionClosed(Exception 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 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.setMnemonic(Lang.s2k("menu_profile_mn")); 656 myProfile.setToolTipText(Lang.gs("menu_profile_tt")); 657 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.setMnemonic(Lang.s2k("menu_tools_mn")); 666 toolsMenu.setToolTipText(Lang.gs("menu_tools_tt")); 667 disco.setText(Lang.gs("menu_tools_disco")); 668 preferences.setMnemonic(Lang.s2k("menu_preferences_mn")); 670 preferences.setToolTipText(Lang.gs("menu_preferences_tt")); 671 help.setMnemonic(Lang.s2k("menu_help_mn")); 673 help.setToolTipText(Lang.gs("menu_help_tt")); 674 about.setMnemonic(Lang.s2k("menu_about_mn")); 676 about.setToolTipText(Lang.gs("menu_about_tt")); 677 quit.setMnemonic(Lang.s2k("menu_quit_mn")); 679 quit.setToolTipText(Lang.gs("menu_quit_tt")); 680 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 716 private void createMenu(){ 717 doMI(myStatus,Icons.STATUS_ONLINE); 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()); 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 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 e){ 796 try{ 797 e.printStackTrace(); 798 if(fos!=null){fos.close();} 799 } 800 catch(Exception e2){ 801 e2.printStackTrace(); 802 } 803 } 804 } 805 if(Conn!=null && Conn.isConnected()){ 806 try{ 807 Conn.close(); 808 } 809 catch(Exception 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 String 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 t){ 877 GUI.errorStop(null,t); 878 } 879 } 880 } 881 882 883 final class PresenceChange implements ActionListener{ 884 public void actionPerformed(ActionEvent ae){ 885 String m=ae.getActionCommand(); 887 if(currentPresence.equals(m)){ 888 return; } 890 if(currentPresence.equals("offline")){ connectionDialog.connect(); 892 if(connectionDialog.getResult()==false){ 893 return; } 895 statusLbl.setText("Whisper IM "+WhisperIM.VERSION+" : "+WhisperIM.accountSettings.JabberUserName+"@"+WhisperIM.accountSettings.JabberServer); 896 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 doRoster(); 911 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")){ 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(); Conn.sendPacket(p); 956 } 957 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 name; 991 992 public KeyPress(String 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 { 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{ cli=new ContactListItem(re.getName(),re.getUser(),ContactListItem.SERVICE); 1065 } 1066 final ContactListItem finalcli=cli; 1067 javax.swing.SwingUtilities.invokeLater(new Runnable (){ 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 (){ 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{ 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 (){ 1098 public void run(){ 1099 finaldmtn.add(new DefaultMutableTreeNode(finalcli2)); 1100 } 1101 }); 1102 } 1103 } 1104 javax.swing.SwingUtilities.invokeLater(new Runnable (){ 1105 public void run(){ 1106 contactListPanel.tree.expandRow(contactListPanel.tree.getRowCount()-1); 1107 } 1108 }); 1109 } 1110 catch(Exception e){ 1111 e.printStackTrace(); 1112 } 1113 } 1114 } 1115} | Popular Tags |