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.menus; 016 017 import java.awt.event.ActionEvent; 018 import java.awt.event.ActionListener; 019 import java.net.URL; 020 import java.util.*; 021 import java.util.regex.*; 022 023 import javax.swing.*; 024 import org.jivesoftware.smack.packet.Presence; 025 026 import com.valhalla.gui.*; 027 import com.valhalla.jbother.*; 028 import com.valhalla.jbother.jabber.*; 029 import com.valhalla.settings.Settings; 030 031 /** 032 * Allows the user to change his/her status 033 * 034 * @author Adam Olsen 035 * @author Yury Soldak (tail) 036 * @created November 11, 2004 037 * @version 1.5 038 */ 039 public class SetStatusMenu extends JMenu 040 { 041 private BuddyList blist; 042 private ResourceBundle resources = ResourceBundle.getBundle( "JBotherBundle", Locale.getDefault() ); 043 private SelfStatuses statuses = com.valhalla.jbother.jabber.SelfStatuses.getInstance(); 044 private SetStatusMenu thisPointer = this; 045 private ImageIcon current = null; 046 047 private javax.swing.Timer blinkTimer = null; 048 049 /** 050 * Sets up the SetStatusMenu 051 * 052 * @param blist the BuddyList that this menu is attached to 053 */ 054 public SetStatusMenu( BuddyList blist ) 055 { 056 this.blist = blist; 057 Iterator statusIterator = statuses.getContent().iterator(); 058 SelfStatus curStatus; 059 while( statusIterator.hasNext() ) 060 { 061 curStatus = (SelfStatus)statusIterator.next(); 062 JCheckBoxMenuItem item = new JCheckBoxMenuItem( curStatus.getTitle() ); 063 if( curStatus.getMode() == blist.getCurrentPresenceMode() ) 064 { 065 item.setState( true ); 066 } 067 add( item ); 068 } 069 this.setIcon( StatusIconCache.getStatusIcon( Presence.Mode.AVAILABLE ) ); 070 071 if( System.getProperty( "mrj.version" ) != null ) 072 { 073 setText( resources.getString( "status" ) ); 074 } 075 076 if( Settings.getInstance().getProperty( "statusTheme" ) == null ) 077 { 078 Settings.getInstance().setProperty( "statusTheme", "default" ); 079 } 080 081 reloadStatusIcons(); 082 083 setUpListeners(); 084 } 085 086 /** 087 * starts the blink timer 088 */ 089 public void startBlinkTimer() 090 { 091 current = (ImageIcon)getIcon(); 092 blinkTimer = new javax.swing.Timer( 400, new BlinkHandler() ); 093 blinkTimer.start(); 094 } 095 096 /** 097 * @return true if the blink timer is still running 098 */ 099 public boolean blinkTimerIsRunning() 100 { 101 if( blinkTimer != null && blinkTimer.isRunning() ) return true; 102 else return false; 103 } 104 105 /** 106 * stops the blink timer 107 */ 108 public void stopBlinkTimer() 109 { 110 if( blinkTimer != null ) blinkTimer.stop(); 111 blinkTimer = null; 112 setIcon( current ); 113 } 114 115 class BlinkHandler implements ActionListener 116 { 117 private ImageIcon off = StatusIconCache.getStatusIcon( null ); 118 private ImageIcon on = StatusIconCache.getStatusIcon( Presence.Mode.AVAILABLE ); 119 private ImageIcon current = on; 120 121 public void actionPerformed( ActionEvent e ) 122 { 123 if( current == on ) current = off; 124 else if( current == off ) current = on; 125 126 thisPointer.setIcon( current ); 127 } 128 } 129 130 /** 131 * Loads self statuses (information about the current online user) and creates a tooltip 132 * on the SetStatusMenu with this information 133 */ 134 public void loadSelfStatuses() 135 { 136 if( !blist.checkConnection() ) return; 137 138 setIcon( StatusIconCache.getStatusIcon( BuddyList.getInstance().getCurrentPresenceMode() ) ); 139 String me = blist.getConnection().getUser().replaceAll( "/.*", "" ); 140 141 BuddyStatus buddy = blist.getBuddyStatus( me ); 142 String user = buddy.getUser(); 143 String server = buddy.getUser(); 144 if( user.indexOf( '@' ) > -1 ) 145 { 146 String parts[] = new String[2]; 147 parts = buddy.getUser().split( "@" ); 148 user = parts[0]; 149 server = parts[0]; 150 if( parts[1] != null ) 151 { 152 server = parts[1]; 153 } 154 } 155 156 String resources = ""; 157 Iterator i = buddy.keySet().iterator(); 158 int resourceCount = 0; 159 160 while( i.hasNext() ) 161 { 162 String key = (String)i.next(); 163 164 if( !key.equals( "N/A" ) ) 165 { 166 boolean add = false; 167 168 if( key.equals( buddy.getHighestResource() ) ) 169 { 170 add = true; 171 } 172 else 173 { 174 resources += " "; 175 } 176 177 resources += key + " (" + buddy.get( key ) + ")"; 178 if( add ) 179 { 180 resources += " <b>*</b>"; 181 } 182 if( i.hasNext() ) 183 { 184 resources += "<br>"; 185 } 186 resourceCount++; 187 } 188 } 189 190 String tooltip = "<html><table border='0'><tr><td colspan='2'><b><font size='+1'>" + user + 191 "</font></b><table border='0' cellpadding='2' cellspacing='2'><tr><td nowrap><b>" + this.resources.getString( "server" ) + 192 ":</b></td><td nowrap>" + server + "</td></tr>"; 193 194 if( resourceCount > 0 ) 195 { 196 tooltip += "<tr><td nowrap valign=\"top\"><b>" + this.resources.getString( "pluralResources" ) + 197 ":</b></td><td nowrap>" + resources + "</td></tr>"; 198 } 199 200 String statusMessage = blist.getCurrentStatusString(); 201 if( statusMessage != null && !statusMessage.equals( "" ) ) 202 { 203 tooltip += "<tr><td nowrap><b>" + this.resources.getString( "currentStatusMessage" ) + 204 ":</b></td><td nowrap>" + statusMessage + 205 "</td></tr></table></td></tr></table></html>"; 206 } 207 208 setToolTipText( tooltip ); 209 } 210 211 /** 212 * Reloads the status icons (in case the theme changes, etc) 213 */ 214 public void reloadStatusIcons() 215 { 216 Iterator statusIterator = statuses.getContent().iterator(); 217 Presence.Mode mode; 218 SelfStatus current; 219 int i = 0; 220 while( statusIterator.hasNext() ) 221 { 222 current = (SelfStatus)statusIterator.next(); 223 mode = current.getMode(); 224 getItem( i ).setIcon( StatusIconCache.getStatusIcon( mode ) ); 225 if( blist != null && mode == blist.getCurrentPresenceMode() ) 226 { 227 getItem( i ).setSelected( true ); 228 setIcon( StatusIconCache.getStatusIcon( mode ) ); 229 } 230 else { 231 getItem( i ).setSelected( false ); 232 } 233 i++; 234 } 235 } 236 237 /** 238 * Sets the checked item to the mode represented 239 * @param mode the mode to check 240 */ 241 public void setModeChecked( Presence.Mode mode ) 242 { 243 Iterator statusIterator = statuses.getContent().iterator(); 244 int i = 0; 245 while( statusIterator.hasNext() ) 246 { 247 SelfStatus current = (SelfStatus)statusIterator.next(); 248 Presence.Mode m = current.getMode(); 249 if( m == mode ) 250 { 251 getItem( i ).setSelected( true ); 252 setIcon( StatusIconCache.getStatusIcon( mode ) ); 253 } 254 else { 255 getItem( i ).setSelected( false ); 256 } 257 258 i++; 259 } 260 } 261 262 /** 263 * Sets this menus icon 264 * 265 * @param mode the mode that the icon represents 266 */ 267 public void setIcon( Presence.Mode mode ) 268 { 269 super.setIcon( StatusIconCache.getStatusIcon( mode ) ); 270 } 271 272 /** 273 * Sets up the various event listeners in the menu 274 */ 275 private void setUpListeners() 276 { 277 MenuListener listener = new MenuListener(); 278 for( int i = 0; i < getItemCount(); i++ ) 279 { 280 getItem( i ).addActionListener( listener ); 281 } 282 } 283 284 /** 285 * Unchecks all the items in this menu except the one currently being used 286 * 287 * @param item Description of the Parameter 288 */ 289 private void uncheckAll( JCheckBoxMenuItem item ) 290 { 291 JCheckBoxMenuItem curItem; 292 for( int i = 0; i < getItemCount(); i++ ) 293 { 294 curItem = (JCheckBoxMenuItem)getItem( i ); 295 if( curItem != item ) 296 { 297 if( curItem.getState() ) 298 { 299 curItem.setState( false ); 300 } 301 } 302 else 303 { 304 if( !curItem.getState() ) 305 { 306 curItem.setState( true ); 307 } 308 } 309 } 310 } 311 312 /** 313 * Sets the current status 314 * 315 * @param item which item was clicked 316 * @param mode the mode to change to 317 * @param defaultMessage the default message to pick 318 * @param getMessage set to true if the user should specify a message 319 */ 320 private void setStatus( JCheckBoxMenuItem item, Presence.Mode mode, String defaultMessage, boolean getMessage ) 321 { 322 if( blist.setStatus( mode, defaultMessage, getMessage ) ) 323 { 324 uncheckAll( item ); 325 } 326 else 327 { 328 item.setState( !item.getState() ); 329 } 330 } 331 332 /** 333 * Listens for items in the menu to be clicked 334 * 335 * @author Adam Olsen 336 * @created November 11, 2004 337 * @version 1.0 338 */ 339 class MenuListener implements ActionListener 340 { 341 /** 342 * Description of the Method 343 * 344 * @param e Description of the Parameter 345 */ 346 public void actionPerformed( ActionEvent e ) 347 { 348 JCheckBoxMenuItem item = (JCheckBoxMenuItem)e.getSource(); 349 SelfStatus status = statuses.getStatus( item.getText() ); 350 351 if( status.getMode() == null ) 352 { 353 uncheckAll( item ); 354 ConnectorThread.setCancelled( true ); 355 stopBlinkTimer(); 356 BuddyList.getInstance().signOff(); 357 } 358 else { 359 ConnectorThread.setCancelled( false ); 360 setStatus( item, status.getMode(), status.getTitle(), true ); 361 } 362 } 363 } 364 365 } 366