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