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