001 /*
002 * Copyright (C) 2003 Adam Olsen
003 * This program is free software; you can redistribute it and/or modify
004 * it under the terms of the GNU General Public License as published by
005 * the Free Software Foundation; either version 1, or (at your option)
006 * any later version.
007 * This program is distributed in the hope that it will be useful,
008 * but WITHOUT ANY WARRANTY; without even the implied warranty of
009 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
010 * GNU General Public License for more details.
011 * You should have received a copy of the GNU General Public License
012 * along with this program; if not, write to the Free Software
013 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
014 */
015 package com.valhalla.jbother;
016
017 import java.awt.*;
018 import java.awt.event.*;
019 import java.io.BufferedReader;
020 import java.io.File;
021 import java.io.FileReader;
022 import java.io.IOException;
023 import java.util.*;
024 import java.lang.reflect.Array;
025
026 import javax.swing.*;
027 import com.valhalla.jbother.actions.*;
028
029 import org.jivesoftware.smack.XMPPConnection;
030 import org.jivesoftware.smack.packet.*;
031
032 import com.valhalla.gui.DialogTracker;
033 import com.valhalla.gui.Standard;
034 import com.valhalla.jbother.groupchat.ChatRoomPanel;
035 import com.valhalla.jbother.jabber.BuddyStatus;
036 import com.valhalla.jbother.jabber.ParsedBuddyInfo;
037 import com.valhalla.jbother.jabber.smack.SecureExtension;
038 import com.valhalla.jbother.menus.BuddyListBuddiesMenu;
039 import com.valhalla.jbother.menus.SetStatusMenu;
040 import com.valhalla.jbother.plugins.events.ConnectEvent;
041 import com.valhalla.jbother.plugins.events.StatusChangedEvent;
042 import com.valhalla.misc.GnuPG;
043 import com.valhalla.pluginmanager.PluginChain;
044 import com.valhalla.settings.*;
045 import net.infonode.tabbedpanel.*;
046 import net.infonode.tabbedpanel.titledtab.*;
047 import net.infonode.util.*;
048
049 /**
050 * BuddyList is the main controller for the buddy list, as as the buddy list is
051 * the main component of the IM application it performs most of the work once
052 * it's been initialized.
053 *
054 *@author Adam Olsen
055 *@author Andrey Zakirov
056 *@created October 26, 2004
057 *@update April 10, 2005
058 *@version 1.0
059 */
060 public class BuddyList extends JPanel
061 {
062 private static BuddyList singleton = null;
063
064 private static JFrame frame;
065
066 private ResourceBundle resources = ResourceBundle.getBundle(
067 "JBotherBundle", Locale.getDefault() );
068
069 private XMPPConnection connection;
070
071 //the connection to the jabber server
072 private BuddyListTree buddyListTree;
073
074 private boolean signoff = false;
075
076 private TabFrame tabFrame;
077
078 private Hashtable buddyStatuses = null;
079
080 private Presence.Mode currentMode = null;
081
082 private String currentStatusString = resources.getString( "available" );
083
084 private AwayHandler awayHandler = new AwayHandler();
085
086 private javax.swing.Timer awayTimer = null;
087
088 // private javax.swing.Timer pingTimer = new javax.swing.Timer( 300000,
089 // new PingHandler() );
090
091 private boolean idleAway = false;
092
093 private Hashtable blockedUsers = new Hashtable();
094
095 private static BuddyList buddyList = null;
096
097 private boolean docked = false;
098
099 private String gnupgPassword = null;
100
101 private boolean encrypting = false;
102
103 private Hashtable notDeliveredHash = new Hashtable();
104
105 private Hashtable notDisplayedHash = new Hashtable();
106
107 private Hashtable notOfflineHash = new Hashtable();
108
109 private JButton jbButton = new JButton();
110
111 private JButton statusButton = new JButton();
112
113 private BuddyListBuddiesMenu jbMenu = new BuddyListBuddiesMenu( this );
114
115 private SetStatusMenu statusMenu = new SetStatusMenu( this, true, statusButton );
116
117 private long date = new Date().getTime();
118 private JToggleButton showOffline = new JToggleButton( StatusIconCache.getStatusIcon( (Presence.Mode)null ) );
119 private JToggleButton showAway = new JToggleButton( StatusIconCache.getStatusIcon( Presence.Mode.AWAY ) );
120 private JToggleButton sound = new JToggleButton(Standard.getIcon("images/buttons/speaker.png"));
121 private boolean added = false;
122
123
124 /**
125 * Constructor for the buddy list. BuddyList is a singleton, so it's
126 * constructor is private
127 */
128 private BuddyList()
129 {
130 initComponents();
131 }
132
133
134 /**
135 * Gets the containerFrame attribute of the BuddyList object
136 *
137 *@return The containerFrame value
138 */
139 public JFrame getContainerFrame()
140 {
141 return frame;
142 }
143
144
145 /**
146 * Gets the BuddyList singleton
147 *
148 *@return the BuddyList singleton
149 *@deprecated Use getInstance() instead
150 */
151 public static BuddyList getSingleton()
152 {
153 return getInstance();
154 }
155
156
157 /**
158 * Gets the BuddyList singleton
159 *
160 *@return the BuddyList singleton
161 */
162 public static BuddyList getInstance()
163 {
164 if( singleton == null )
165 {
166 singleton = new BuddyList();
167 }
168 return singleton;
169 }
170
171 /*class PingHandler implements ActionListener
172 {
173 public void actionPerformed( ActionEvent e )
174 {
175 if( !checkConnection() ) return;
176
177 if( idleAway )
178 {
179 BuddyList.getInstance().setStatus(Presence.Mode.AWAY,
180 resources.getString("autoAway"), false);
181 }
182 else {
183 BuddyList.getInstance().setStatus(currentMode,currentStatusString,false);
184 }
185 }
186 }*/
187
188 public void updateButtons( String mode )
189 {
190 ImageIcon icon = Standard.getIcon("imagethemes/statusicons/"
191 + mode + "/offline.png");
192
193 showOffline.setIcon( icon );
194
195 icon = Standard.getIcon("imagethemes/statusicons/"
196 + mode + "/away.png");
197
198 showAway.setIcon( icon );
199 showOffline.validate();
200 showAway.validate();
201 }
202
203 public void resetAwayTimer()
204 {
205 int aTime = 0;
206
207 try {
208 aTime = Integer.parseInt(Settings.getInstance().getProperty("autoAwayMinutes", "15"));
209 }
210 catch( Exception e ) { }
211
212 resetAwayTimer( aTime );
213 }
214
215 /**
216 * Starts the away timer
217 */
218 public void resetAwayTimer( int aTime )
219 {
220 com.valhalla.Logger.debug( "Away timer is set for " + ( aTime * 60 * 1000 ) );
221 if( aTime > 0 )
222 {
223 if( awayTimer != null ) awayTimer.stop();
224 awayTimer = new javax.swing.Timer(aTime * 60 * 1000, awayHandler);
225 awayTimer.start();
226 com.valhalla.Logger.debug( "Starting away timer " + aTime);
227 }
228 else if( awayTimer != null )
229 {
230 awayTimer.stop();
231 awayTimer = null;
232 }
233
234 if( !added )
235 {
236 added = true;
237 AWTEventListener listener = new MyAWTEventListener();
238 Toolkit.getDefaultToolkit().addAWTEventListener( listener,
239 AWTEvent.KEY_EVENT_MASK );
240 }
241 }
242
243
244 /**
245 * Loads the blocked users information
246 */
247 protected void loadBlockedUsers()
248 {
249 File file = new File( JBother.profileDir + File.separatorChar
250 + "blocked" );
251 String line = "";
252
253 try
254 {
255 FileReader fr = new FileReader( file );
256 BufferedReader in = new BufferedReader( fr );
257
258 while( ( line = in.readLine() ) != null )
259 {
260 blockedUsers.put( line, "blocked" );
261 com.valhalla.Logger.debug( "Blocked> " + line );
262 }
263
264 fr.close();
265 }
266 catch( IOException e )
267 {
268 com.valhalla.Logger.debug( "Blocked users file was not found or could not be read." );
269 return;
270 }
271 }
272
273
274 /**
275 * Description of the Method
276 */
277 private void loadNotDeliveredMessages()
278 {
279 final String notDeliveredMessages = Settings.getInstance().getProperty( "notDeliveredMessages" );
280 String[] notDeliveredMessage;
281 String[] notDeliveredMessageLast;
282 String[] info = new String[2];
283 if( notDeliveredMessages != null )
284 {
285 notDeliveredMessage = notDeliveredMessages.split( ";" );
286 if( notDeliveredMessage.length > 0 )
287 {
288 for( int i = 0; i < notDeliveredMessage.length; i++ )
289 {
290 notDeliveredMessageLast = notDeliveredMessage[i].split( "," );
291 if( notDeliveredMessageLast.length == 3 )
292 {
293 info[0] = notDeliveredMessageLast[1];
294 info[1] = notDeliveredMessageLast[2];
295 notDeliveredHash.put( notDeliveredMessageLast[0], info );
296 }
297 }
298 }
299 }
300 }
301
302
303 /**
304 * Gets the eventMessage attribute of the BuddyList object
305 *
306 *@param messageId Description of the Parameter
307 *@param type Description of the Parameter
308 *@return The eventMessage value
309 */
310 public String[] getEventMessage( String messageId, int type )
311 {
312 Hashtable tempHash;
313 switch ( type )
314 {
315 case 1:
316 tempHash = notDeliveredHash;
317 break;
318 case 2:
319 tempHash = notDisplayedHash;
320 break;
321 case 3:
322 tempHash = notOfflineHash;
323 break;
324 default:
325 return null;
326 }
327 String[] eventMessage = (String[])tempHash.get( messageId );
328 tempHash.remove( messageId );
329 return eventMessage;
330 }
331
332
333 /**
334 * Description of the Method
335 *
336 *@param messageId Description of the Parameter
337 *@param userJID Description of the Parameter
338 *@param timeStamp Description of the Parameter
339 *@param type Description of the Parameter
340 *@return Description of the Return Value
341 */
342 public boolean putEventMessage( String messageId, String userJID, String timeStamp, int type )
343 {
344 Hashtable tempHash;
345 switch ( type )
346 {
347 case 1:
348 tempHash = notDeliveredHash;
349 break;
350 case 2:
351 tempHash = notDisplayedHash;
352 break;
353 case 3:
354 tempHash = notOfflineHash;
355 break;
356 default:
357 return false;
358 }
359 if( ( messageId != null ) && ( userJID != null ) && ( timeStamp != null ) )
360 {
361 String[] info = new String[2];
362 info[0] = userJID;
363 info[1] = timeStamp;
364 tempHash.put( messageId, info );
365 return true;
366 }
367 return false;
368 }
369
370
371 /**
372 * Gets the statusButton attribute of the BuddyList object
373 *
374 *@return The statusButton value
375 */
376 public JButton getStatusButton()
377 {
378 return statusButton;
379 }
380
381
382 /**
383 * Returns the away timer
384 *
385 *@return the away timer
386 */
387 public javax.swing.Timer getAwayTimer()
388 {
389 return awayTimer;
390 }
391
392
393 /**
394 * Sets the idleAway attribute of the BuddyList object
395 *
396 *@param idleAway The new idleAway value
397 */
398 public void setIdleAway( boolean idleAway )
399 {
400 this.idleAway = idleAway;
401 }
402
403
404 /**
405 * Gets the idleAway attribute of the BuddyList object
406 *
407 *@return The idleAway value
408 */
409 public boolean getIdleAway()
410 {
411 return idleAway;
412 }
413
414
415 /**
416 * Gets the awayHandler attribute of the BuddyList object
417 *
418 *@return The awayHandler value
419 */
420 public AwayHandler getAwayHandler()
421 {
422 return awayHandler;
423 }
424
425
426 /**
427 * Sets up the current connection
428 *
429 *@param connection the current connection
430 */
431 public void init( XMPPConnection connection )
432 {
433 this.connection = connection;
434 if( connection == null )
435 {
436 return;
437 }
438 if( buddyStatuses == null )
439 {
440 buddyStatuses = new Hashtable();
441 }
442
443 ConnectEvent event = new ConnectEvent( connection );
444 PluginChain.fireEvent( event );
445
446 buddyListTree.setConnection( connection );
447 statusMenu.setIcon( Presence.Mode.AVAILABLE );
448 //pingTimer.start();
449 }
450
451
452 /**
453 * Clears the buddy tree
454 */
455 public void clearTree()
456 {
457 buddyListTree.clearBuddies();
458 }
459
460
461 /**
462 * initializes the buddy tree by loading the offline buddies
463 */
464 public void initBuddies()
465 {
466 buddyListTree.loadOfflineBuddies();
467 }
468
469
470 /**
471 * Sets the current presence mode
472 *
473 *@param mode the mode to set it to
474 */
475 public void setCurrentPresenceMode( Presence.Mode mode )
476 {
477 this.currentMode = mode;
478 }
479
480
481 /**
482 * Sets the current status string
483 *
484 *@param string the string to use
485 */
486 public void setCurrentStatusString( String string )
487 {
488 this.currentStatusString = string;
489 }
490
491
492 /**
493 * Gets the current presence mode
494 *
495 *@return the current presence mode
496 */
497 public Presence.Mode getCurrentPresenceMode()
498 {
499 return this.currentMode;
500 }
501
502
503 /**
504 * Returns the current status string
505 *
506 *@return the current status string
507 */
508 public String getCurrentStatusString()
509 {
510 return this.currentStatusString;
511 }
512
513
514 /**
515 * Returns the group chat frame
516 *
517 *@return the group chat frame
518 */
519 public TabFrame getTabFrame()
520 {
521 return tabFrame;
522 }
523
524
525 /**
526 * Starts the group chat frame
527 */
528 public void startTabFrame()
529 {
530 if( tabFrame == null )
531 {
532 tabFrame = new TabFrame();
533 }
534 }
535
536
537 /**
538 * checks to see if there are no more chat room windows in the
539 * groupchatframe if there are no more, the groupchatframe is destroyed
540 */
541 public void stopTabFrame()
542 {
543 if( tabFrame == null )
544 {
545 return;
546 }
547
548 if( tabFrame.tabsLeft() <= 0 )
549 {
550 tabFrame.saveStates();
551
552 if( !docked )
553 {
554 tabFrame.removeTabListeners();
555 DialogTracker.removeDialog( tabFrame );
556 tabFrame = null;
557 com.valhalla.Logger.debug( "Removing chat frame" );
558 }
559 }
560 }
561
562
563 /**
564 * Removes a ChatPanel
565 *
566 *@param panel the chat panel to remove
567 */
568 public void removeTabPanel( TabFramePanel panel )
569 {
570 if( tabFrame == null )
571 {
572 return;
573 }
574
575 tabFrame.removePanel( panel );
576 stopTabFrame();
577 }
578
579
580 /**
581 * Adds a chat room window to the groupchat frame. If there is not
582 * groupchat frame one is created
583 *
584 *@param panel The feature to be added to the TabPanel attribute
585 */
586 public void addTabPanel( TabFramePanel panel )
587 {
588 if( tabFrame == null )
589 {
590 tabFrame = new TabFrame();
591 }
592 tabFrame.addPanel( panel );
593
594 if( !tabFrame.isVisible() )
595 {
596 tabFrame.setVisible( true );
597 tabFrame.toFront();
598 }
599 }
600
601
602 /**
603 * Gets the buddy status
604 *
605 *@param userId the user id of the BuddyStatus
606 *@return The buddyStatus value
607 */
608 public BuddyStatus getBuddyStatus( String userId )
609 {
610 if( userId == null )
611 {
612 return null;
613 }
614 if( buddyStatuses == null )
615 {
616 buddyStatuses = new Hashtable();
617 }
618 BuddyStatus buddy = new BuddyStatus( userId );
619
620 if( buddyStatuses.get( userId.toLowerCase() ) != null )
621 {
622 buddy = (BuddyStatus)buddyStatuses.get( userId.toLowerCase() );
623 }
624 else
625 {
626 buddy.newPubKey();
627 buddyStatuses.put( userId.toLowerCase(), buddy );
628 }
629
630 return buddy;
631 }
632
633
634 /**
635 * Returns all the buddy status that are available
636 *
637 *@return the Hashtable containing all the buddy statuses
638 */
639 public Hashtable getBuddyStatuses()
640 {
641 return this.buddyStatuses;
642 }
643
644
645 /**
646 * Returns the current connection
647 *
648 *@return the current connection
649 */
650 public XMPPConnection getConnection()
651 {
652 return this.connection;
653 }
654
655
656 /**
657 * Checks to see if a connection is active
658 *
659 *@return true if the connection is active (connected)
660 */
661 public boolean checkConnection()
662 {
663 if( connection == null || !connection.isConnected() )
664 {
665 return false;
666 }
667 else
668 {
669 return true;
670 }
671 }
672
673
674 /**
675 * Displays a generic connection error
676 */
677 public void connectionError()
678 {
679 Standard.warningMessage( null, resources.getString( "connectionError" ),
680 resources.getString( "notConnected" ) );
681 }
682
683
684 /**
685 * Gets the docked attribute of the BuddyList object
686 *
687 *@return The docked value
688 */
689 public boolean isDocked()
690 {
691 return docked;
692 }
693
694
695 /**
696 * Description of the Method
697 */
698 public void dockYourself()
699 {
700 if( frame != null )
701 {
702 frame.remove( this );
703 frame.dispose();
704 }
705
706 if( tabFrame == null )
707 {
708 tabFrame = new TabFrame();
709 }
710 tabFrame.dockBuddyList( this );
711 // tabFrame.setJMenuBar(topMenu);
712 frame = tabFrame;
713 frame.setVisible( true );
714 docked = true;
715 }
716
717
718 /**
719 * Sets the tabFrame attribute of the BuddyList object
720 *
721 *@param frame The new tabFrame value
722 */
723 public void setTabFrame( TabFrame frame )
724 {
725 this.tabFrame = frame;
726 }
727
728
729 /**
730 * Description of the Method
731 */
732 public void undock()
733 {
734 docked = false;
735 if( tabFrame != null )
736 {
737 tabFrame.undock();
738 stopTabFrame();
739 }
740
741 if( tabFrame != null )
742 {
743 tabFrame.setVisible( true );
744 }
745
746 BuddyListContainerFrame f = new BuddyListContainerFrame( this );
747 frame = f;
748 frame.setVisible( true );
749 }
750
751
752 /**
753 * Loads the settings for this profile
754 */
755 public void loadSettings()
756 {
757 ConnectorThread.getInstance().resetCredentials();
758 buddyStatuses = new Hashtable();
759 loadBlockedUsers();
760 loadNotDeliveredMessages();
761 gnupgPassword = null;
762
763 Vector panels = MessageDelegator.getInstance().getPanels();
764 int size = panels.size();
765 for( int i = 0; i < size; i++ )
766 {
767 ConversationPanel panel = (ConversationPanel)panels.get( 0 );
768 panel.closeHandler();
769 }
770
771 panels.removeAllElements();
772
773 if( tabFrame != null )
774 {
775 tabFrame.dispose();
776 tabFrame = null;
777 }
778
779 if( Settings.getInstance().getBoolean( "useTabbedWindow" )
780 && Settings.getInstance().getBoolean( "dockBuddyList" ) )
781 {
782 dockYourself();
783 }
784 else if( docked )
785 {
786 docked = false;
787 }
788
789 if( !docked )
790 {
791 BuddyListContainerFrame f = new BuddyListContainerFrame( this );
792 frame = f;
793 }
794
795 frame.setVisible( true );
796
797 statusMenu.reloadStatusIcons();
798 statusMenu.setModeChecked( null );
799
800 if( Arguments.getInstance().getBoolean( "xmlconsole" ) )
801 {
802
803 ParsedBuddyInfo info = new ParsedBuddyInfo( resources.getString( "xmlConsole" ) );
804 String userId = info.getUserId().toLowerCase();
805 final BuddyStatus buddyStatus = BuddyList.getInstance()
806 .getBuddyStatus( userId );
807 buddyStatus.setName( resources.getString( "xmlConsole" ) );
808 if( buddyStatus.getConversation() == null )
809 {
810 buddyStatus.setConversation( ConsolePanel.getInstance( buddyStatus ) );
811 MessageDelegator.getInstance().showPanel(
812 buddyStatus.getConversation() );
813 MessageDelegator.getInstance().frontFrame(
814 buddyStatus.getConversation() );
815 }
816 }
817
818 sound.setSelected(!Settings.getInstance().getBoolean("noSound"));
819 showOffline.setSelected( Settings.getInstance().getBoolean(
820 "showOfflineBuddies") );
821 showAway.setSelected(!Settings.getInstance().getBoolean("dontShowAwayBuddies"));
822 }
823
824
825 /**
826 * Saves the current settings - like the height and width of the buddy list
827 */
828 public void saveSettings()
829 {
830 if( frame.isVisible() )
831 {
832 if( !docked )
833 {
834 //save the current buddy list size and position
835 Dimension size = new Dimension( frame.getSize() );
836 Point location = new Point( frame.getLocationOnScreen() );
837
838 Settings.getInstance().setProperty( "buddyListX",
839 new Double( location.getX() ).toString() );
840 Settings.getInstance().setProperty( "buddyListY",
841 new Double( location.getY() ).toString() );
842 Settings.getInstance().setProperty( "buddyListWidth",
843 new Integer( size.width ).toString() );
844 Settings.getInstance().setProperty( "buddyListHeight",
845 new Integer( size.height ).toString() );
846
847
848 }
849
850 }
851
852 Settings.writeSettings();
853 }
854
855
856 /**
857 * Returns the buddy list tree
858 *
859 *@return the buddy list tree
860 */
861 public BuddyListTree getBuddyListTree()
862 {
863 return this.buddyListTree;
864 }
865
866
867 /**
868 * Init components just does some initial setup, sets the size and
869 * preferred location of the buddy list. Sets up an new initial tree.
870 */
871 private void initComponents()
872 {
873 JPanel container = this;
874
875 container.setLayout( new BorderLayout() );
876 container.setBorder( BorderFactory.createEmptyBorder( 1, 1, 1, 1 ) );
877
878 showOffline.setPreferredSize( new Dimension( 24, 24 ) );
879 ShowOfflineAction.addItem( showOffline );
880 showOffline.setToolTipText(resources.getString("showOfflineBuddies"));
881
882 showAway.setPreferredSize(new Dimension(24,24));
883 showAway.setToolTipText(resources.getString("showAwayBuddies"));
884 ShowAwayAction.addItem(showAway);
885 sound.setPreferredSize(new Dimension(24,24));
886 sound.setToolTipText(resources.getString("soundToggle"));
887 sound.addActionListener(new ActionListener()
888 {
889 public void actionPerformed(ActionEvent e) {
890 Settings.getInstance().setBoolean("noSound", !sound.isSelected());
891 com.valhalla.Logger.debug( Settings.getInstance().getBoolean( "noSound" ) + "" );
892 }
893 });
894
895 JPanel buttonPanel = new JPanel();
896 buttonPanel.setLayout( new BoxLayout( buttonPanel, BoxLayout.X_AXIS ) );
897 buttonPanel.setBorder( BorderFactory.createEmptyBorder( 1, 1, 1, 1 ) );
898 buttonPanel.add( showOffline );
899 buttonPanel.add( Box.createRigidArea(new Dimension(2,0)));
900 buttonPanel.add(showAway);
901 buttonPanel.add( Box.createRigidArea(new Dimension(2,0)));
902
903 buttonPanel.add(sound);
904 buttonPanel.add( Box.createHorizontalGlue());
905 container.add( buttonPanel, BorderLayout.NORTH );
906
907 jbButton.addMouseListener( new ButtonListener() );
908 jbButton.setToolTipText(resources.getString("jbotherMenu"));
909 jbButton.setIcon( Standard.getIcon( "images/frameicon.png" ) );
910 statusButton.addMouseListener( new Button2Listener() );
911
912 statusButton.setText( resources.getString( "offline" ) );
913 buddyListTree = new BuddyListTree();
914
915 // so the menus get the correct size
916 JFrame temp = new JFrame();
917 temp.getContentPane().setLayout(new FlowLayout());
918 temp.getContentPane().add(jbMenu);
919 temp.getContentPane().add(statusMenu);
920 temp.pack();
921 temp.dispose();
922
923 container.add( buddyListTree, BorderLayout.CENTER );
924
925 JPanel status = new JPanel();
926
927 GridBagLayout gbl = new GridBagLayout();
928 status.setLayout( gbl );
929 status.setMaximumSize( new Dimension( 1000, jbButton.getHeight() ) );
930
931 GridBagConstraints gbc = new GridBagConstraints();
932 gbc.fill = GridBagConstraints.HORIZONTAL;
933 gbc.weightx = 1;
934 gbc.weighty = 1;
935 gbc.anchor = GridBagConstraints.EAST;
936 gbc.insets = new Insets( 1, 1, 1, 1 );
937 gbc.gridx = 1;
938 gbc.gridy = 1;
939 gbl.addLayoutComponent( statusButton, gbc );
940 gbc.fill = GridBagConstraints.NONE;
941 gbc.weightx = 0;
942 gbc.weighty = 0;
943 gbc.anchor = GridBagConstraints.WEST;
944 gbc.insets = new Insets( 1, 1, 1, 1 );
945 gbc.gridx = 0;
946 gbc.gridy = 1;
947 gbl.addLayoutComponent( jbButton, gbc );
948
949 status.add( jbButton );
950 status.add( statusButton );
951
952 container.add( status, BorderLayout.SOUTH );
953
954 }
955
956
957 /**
958 * Description of the Class
959 *
960 *@author synic
961 *@created April 12, 2005
962 */
963 class ButtonListener extends MouseAdapter
964 {
965 public void mousePressed( MouseEvent e )
966 {
967 jbMenu.showMenu( e.getComponent(), jbButton.getX() - 1, jbButton.getY() - jbMenu.getHeight() - 1 );
968 }
969 }
970
971
972 /**
973 * Description of the Class
974 *
975 *@author synic
976 *@created April 12, 2005
977 */
978 class Button2Listener extends MouseAdapter
979 {
980 public void mousePressed( MouseEvent e )
981 {
982 statusMenu.showMenu( e.getComponent(), jbButton.getX() - 1, statusButton.getY() - statusMenu.getHeight() - 1 );
983 }
984
985 }
986
987 /**
988 * Sets whether or not we have signed off
989 *
990 *@param value true if we have signed off
991 */
992 public void setSignoff( boolean value )
993 {
994 this.signoff = value;
995 }
996
997
998 /**
999 * Gets whether or not we have signed off
1000 *
1001 *@return true if we have signed off
1002 */
1003 public boolean getSignoff()
1004 {
1005 return signoff;
1006 }
1007
1008
1009 /**
1010 * Gets the displayed name, or "me"
1011 *
1012 *@return the myDisplayedName setting
1013 */
1014 public String getMyName()
1015 {
1016 if( Settings.getInstance().getProperty( "myDisplayedName" ) != null )
1017 {
1018 return Settings.getInstance().getProperty( "myDisplayedName" );
1019 }
1020 return connection.getUser();
1021 }
1022
1023
1024 /**
1025 * Listens for user input events. If JBother is set to go "Away" on idle,
1026 * this will restart the idle timer.
1027 *
1028 *@author Adam Olsen
1029 *@created October 26, 2004
1030 *@version 1.0
1031 */
1032 public class MyAWTEventListener implements AWTEventListener
1033 {
1034 /**
1035 * Called by the event listener
1036 *
1037 *@param evt the event
1038 */
1039 public void eventDispatched( AWTEvent evt )
1040 {
1041 setLastActive();
1042 if( awayTimer != null && awayTimer.isRunning() )
1043 {
1044 awayTimer.restart();
1045 }
1046 else if( idleAway )
1047 {
1048 setStatus( Presence.Mode.AVAILABLE, getCurrentStatusString(),
1049 false );
1050 if( awayTimer != null ) awayTimer.start();
1051 idleAway = false;
1052 }
1053
1054 }
1055 }
1056
1057
1058 /**
1059 * Closes the application
1060 */
1061 public void quitHandler()
1062 {
1063 saveSettings();
1064 if( connection != null && connection.isConnected() )
1065 {
1066 connection.close();
1067 }
1068 //and finally close the connection
1069
1070 com.valhalla.Logger.closeLog();
1071 System.exit( 0 );
1072 }
1073
1074
1075 /**
1076 * signs off, clears the buddy list
1077 */
1078 public void signOff()
1079 {
1080 //pingTimer.stop();
1081 signoff = false;
1082 buddyListTree.clearBuddies();
1083 if( awayTimer != null ) awayTimer.stop();
1084 currentMode = null;
1085 sendStatusChangedEvent();
1086
1087 if( connection != null )
1088 {
1089 if( !statusMenu.blinkTimerIsRunning() )
1090 {
1091 statusMenu.startBlinkTimer();
1092 }
1093 Thread thread = new Thread( new ConnectionCloseThread() );
1094 thread.start();
1095 }
1096
1097 if( buddyStatuses != null )
1098 {
1099 Iterator iterator = buddyStatuses.keySet().iterator();
1100 while( iterator.hasNext() )
1101 {
1102 String user = (String)iterator.next();
1103 BuddyStatus buddy = (BuddyStatus)buddyStatuses.get( user );
1104 buddy.resetBuddy();
1105 if( buddy.getConversation() != null
1106 && buddy.getConversation() instanceof ChatPanel )
1107 {
1108 ( (ChatPanel)buddy.getConversation() ).disconnected();
1109 }
1110 }
1111 }
1112
1113 if( tabFrame != null )
1114 {
1115 ArrayList remove = new ArrayList();
1116
1117 TabbedPanel pane = tabFrame.getTabPane();
1118 for( int i = 0; i < pane.getTabCount(); i++ )
1119 {
1120 TabFramePanel panel = (TabFramePanel)pane.getTabAt(i).getContentComponent();
1121 if( panel instanceof ChatRoomPanel )
1122 {
1123 remove.add( panel );
1124 }
1125 }
1126
1127 for( int i = 0; i < remove.size(); i++ )
1128 {
1129 TabFramePanel panel = (TabFramePanel)remove.get( i );
1130 removeTabPanel( panel );
1131 ( (ChatRoomPanel)panel ).serverNoticeMessage( "You have been disconnected" );
1132 ( (ChatRoomPanel)panel ).disconnect();
1133 }
1134 }
1135 }
1136
1137
1138 /**
1139 * Description of the Class
1140 *
1141 *@author synic
1142 *@created April 12, 2005
1143 */
1144 class ConnectionCloseThread implements Runnable
1145 {
1146 /**
1147 * Main processing method for the ConnectionCloseThread object
1148 */
1149 public void run()
1150 {
1151 connection.close();
1152 SwingUtilities.invokeLater(
1153 new Runnable()
1154 {
1155 public void run()
1156 {
1157 statusMenu.stopBlinkTimer();
1158 statusMenu.setIcon( (Presence.Mode)null );
1159 }
1160 } );
1161
1162 connection = null;
1163 }
1164 }
1165
1166
1167 /**
1168 * Close down the buddy list. Also closes down any other windows that might
1169 * be open
1170 */
1171 public void kill()
1172 {
1173 if( tabFrame != null )
1174 {
1175 tabFrame.leaveAll();
1176 }
1177
1178 saveSettings();
1179
1180 setVisible( false );
1181
1182 currentMode = Presence.Mode.AVAILABLE;
1183 currentStatusString = resources.getString( "available" );
1184 connection = null;
1185
1186 awayTimer.stop();
1187
1188 Vector panels = MessageDelegator.getInstance().getPanels();
1189 int size = panels.size();
1190 for( int i = 0; i < size; i++ )
1191 {
1192 ConversationPanel panel = (ConversationPanel)panels.get( 0 );
1193 panel.closeHandler();
1194 }
1195
1196 panels.removeAllElements();
1197
1198 DialogTracker.kill();
1199 signoff = false;
1200 }
1201
1202
1203 /**
1204 * Gets a list of blocked users
1205 *
1206 *@return the list of blocked users
1207 */
1208 public Hashtable getBlockedUsers()
1209 {
1210 return blockedUsers;
1211 }
1212
1213
1214 /**
1215 * Sets the list of blocked users
1216 *
1217 *@param users the list of blocked users
1218 */
1219 public void setBlockedUsers( Hashtable users )
1220 {
1221 this.blockedUsers = users;
1222 }
1223
1224
1225 /**
1226 * Gets the GnuPG password
1227 *
1228 *@return GnuPG password
1229 */
1230 public String getGnuPGPassword()
1231 {
1232 return gnupgPassword;
1233 }
1234
1235
1236 /**
1237 * Sets the GnuPG password
1238 *
1239 *@param gnupgPassword GnuPG password
1240 */
1241 public void setGnuPGPassword( String gnupgPassword )
1242 {
1243 this.gnupgPassword = gnupgPassword;
1244 }
1245
1246
1247 /**
1248 * Gets the encryption status
1249 *
1250 *@return encryption status
1251 */
1252 public boolean isEncrypting()
1253 {
1254 return encrypting;
1255 }
1256
1257
1258 /**
1259 * Sets the encryption status
1260 *
1261 *@param variant encryption status
1262 */
1263
1264 public void isEncrypting( boolean variant )
1265 {
1266 this.encrypting = variant;
1267 }
1268
1269
1270
1271
1272 /**
1273 * Updates all the dialogs window icons
1274 */
1275 public void updateIcons()
1276 {
1277 StatusIconCache.clearStatusIconCache();
1278 ImageIcon icon = StatusIconCache.getStatusIcon( org.jivesoftware.smack.packet.Presence.Mode.AVAILABLE );
1279 if( icon != null )
1280 {
1281 // statusMenu.setIcon(icon);
1282 }
1283 statusMenu.reloadStatusIcons();
1284 }
1285
1286
1287 /**
1288 * send StatusChanged event to plugins (and mb elsewhere too)
1289 */
1290 private void sendStatusChangedEvent()
1291 {
1292 StatusChangedEvent event = new StatusChangedEvent( getInstance() );
1293 PluginChain.fireEvent( event );
1294 }
1295
1296
1297 /**
1298 * Set the current status by sending a Jabber packet
1299 *
1300 *@param mode the mode to set it to
1301 *@param defaultMessage the status message to set it to
1302 *@param getMessage whether or not to get a new message
1303 *@return true if the status packet was sent successfully
1304 */
1305 public boolean setStatus( Presence.Mode mode, String defaultMessage,
1306 boolean getMessage )
1307 {
1308 String result;
1309 if( getMessage )
1310 {
1311 StatusDialog statusDlg = new StatusDialog( mode );
1312 return false;
1313 }
1314 else
1315 {
1316 result = defaultMessage;
1317 }
1318 if( result == null || result.equals( "" ) )
1319 {
1320 return false;
1321 }
1322 else
1323 {
1324 if( mode != Presence.Mode.AWAY ) idleAway = false;
1325 if( awayTimer != null )
1326 {
1327 if( mode == Presence.Mode.AVAILABLE )
1328 {
1329 awayTimer.start();
1330 }
1331 else
1332 {
1333 awayTimer.stop();
1334 }
1335 }
1336
1337 int priority = 5;
1338 try
1339 {
1340 priority = Integer.parseInt( Settings.getInstance().getProperty(
1341 "priority", "5" ) );
1342 }
1343 catch( NumberFormatException nfe )
1344 {
1345 }
1346
1347 if( !checkConnection() )
1348 {
1349 ConnectorThread.getInstance().init( mode, result, idleAway ).start();
1350 return true;
1351 }
1352
1353 Presence presence = new Presence( Presence.Type.AVAILABLE, result,
1354 priority, mode );
1355
1356 if( mode == Presence.Mode.INVISIBLE )
1357 {
1358 final String r = result;
1359 final int p = priority;
1360 presence = new Presence( Presence.Type.AVAILABLE, result,
1361 priority, mode )
1362 {
1363 public String toXML()
1364 {
1365 return "<presence type='invisible'>\n" +
1366 "<status>" + r + "</status>\n" +
1367 "<priority>" + p + " </priority>\n" +
1368 "</presence>\n";
1369
1370 }
1371 };
1372 }
1373
1374 GnuPG gnupg = new GnuPG();
1375 String signedData = null;
1376 SecureExtension signedExtension = new SecureExtension( "signed" );
1377 String gnupgSecretKey = Settings.getInstance().getProperty(
1378 "gnupgSecretKeyID" );
1379
1380 if( JBotherLoader.isGPGEnabled()
1381 && Settings.getInstance().getBoolean( "gnupgSignPresence" )
1382 && gnupgSecretKey != null )
1383 {
1384 signedData = gnupg.signExtension( result, gnupgSecretKey );
1385 if( signedData != null )
1386 {
1387 signedData = signedData.replaceAll( "(\n)+$", "" );
1388 signedExtension.setData( signedData );
1389 presence.addExtension( signedExtension );
1390 }
1391
1392 }
1393 connection.sendPacket( presence );
1394
1395 setCurrentPresenceMode( mode );
1396 if( !idleAway )
1397 {
1398 setCurrentStatusString( result );
1399 }
1400
1401 // if the group chat window is open, set the status there too
1402 if( getTabFrame() != null )
1403 {
1404 getTabFrame().setStatus( mode, result );
1405 }
1406
1407 ParsedBuddyInfo info = new ParsedBuddyInfo( connection.getUser() );
1408 BuddyStatus buddy = BuddyList.getInstance().getBuddyStatus(
1409 info.getUserId() );
1410 buddy.addResource( info.getResource(), priority, mode, result );
1411 statusMenu.loadSelfStatuses();
1412
1413 updateIcons();
1414 sendStatusChangedEvent();
1415 statusMenu.setModeChecked( mode );
1416 statusButton.setText( resources.getString( mode.toString() ) );
1417 statusButton.repaint();
1418
1419 }
1420 return true;
1421 }
1422
1423 /**
1424 * Gets the statusMenu attribute of the BuddyList object
1425 *
1426 *@return The statusMenu value
1427 */
1428 public SetStatusMenu getStatusMenu()
1429 {
1430 return statusMenu;
1431 }
1432
1433
1434 /**
1435 * Gets the buddiesMenu attribute of the BuddyList object
1436 *
1437 *@return The buddiesMenu value
1438 */
1439 public BuddyListBuddiesMenu getBuddiesMenu()
1440 {
1441 return jbMenu;
1442 }
1443
1444
1445 /**
1446 * Sets the lastActive attribute of the BuddyList object
1447 */
1448 public void setLastActive()
1449 {
1450 this.date = new Date().getTime();
1451
1452 }
1453
1454
1455 /**
1456 * Gets the lastActive attribute of the BuddyList object
1457 *
1458 *@return The lastActive value
1459 */
1460 public long getLastActive()
1461 {
1462 return this.date/1000;
1463 }
1464
1465 }
1466