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