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.groupchat;
016
017 import java.awt.BorderLayout;
018 import java.awt.Dimension;
019 import java.awt.event.ActionEvent;
020 import java.awt.event.ActionListener;
021 import java.awt.event.MouseAdapter;
022 import java.awt.event.MouseEvent;
023 import java.util.*;
024
025 import javax.swing.*;
026
027 import com.valhalla.gui.Standard;
028 import com.valhalla.jbother.*;
029 import com.valhalla.jbother.ConversationFormatter;
030 import com.valhalla.jbother.jabber.BuddyStatus;
031 import com.valhalla.jbother.jabber.MUCBuddyStatus;
032
033 /**
034 * The JPanel that contains the nickname list
035 *
036 * @author Adam Olsen
037 * @created October 28, 2005
038 * @version 1.0
039 */
040 public class GroupChatNickList extends JPanel {
041 private ResourceBundle resources = ResourceBundle.getBundle(
042 "JBotherBundle", Locale.getDefault());
043
044 private NickListModel nickListModel = new NickListModel();
045
046 private JList nickList = new JList(nickListModel);
047
048 private JScrollPane scrollPane = new JScrollPane(nickList);
049
050 private JButton clear = new JButton(Standard.getIcon("images/buttons/New24.gif"));
051
052 private JButton emoticons = new JButton(Standard.getIcon("images/buttons/smiley.gif"));
053
054 private JButton configure = new JButton(Standard.getIcon("images/buttons/preferences.gif"));
055
056 private ChatRoomPanel window;
057
058 private JLabel countLabel = new JLabel("0 users");
059 private int userCount = 0;
060 private int adminCount = 0;
061
062 private NickListPopupMenu popMenu;
063
064
065 /**
066 * Sets up the panel
067 *
068 * @param window the chatroom window that this nicklist is a part of
069 */
070 public GroupChatNickList(final ChatRoomPanel window) {
071 super();
072
073 popMenu = new NickListPopupMenu(window);
074 this.window = window;
075 setLayout(new BorderLayout());
076
077 add(countLabel, BorderLayout.NORTH);
078 add(scrollPane, BorderLayout.CENTER);
079
080 JPanel buttons = new JPanel();
081 buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS));
082 emoticons.setPreferredSize(new Dimension(26, 26));
083 clear.setPreferredSize(new Dimension(26, 26));
084 configure.setPreferredSize(new Dimension(26, 26));
085
086 buttons.add(emoticons);
087 buttons.add(clear);
088 buttons.add(configure);
089 countLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
090
091 JPanel bottomPanel = new JPanel(new BorderLayout());
092
093 JScrollPane scroll = new JScrollPane(buttons);
094 scroll.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
095 bottomPanel.add(scroll, BorderLayout.WEST);
096
097 clear.setToolTipText(resources.getString("clear"));
098 configure.setToolTipText(resources.getString("configureRoom"));
099 add(bottomPanel, BorderLayout.SOUTH);
100
101 setPreferredSize(new Dimension(120, 400));
102 NickListRenderer renderer = new NickListRenderer(window);
103 nickList.setCellRenderer(renderer);
104 nickList.addMouseListener(new DoubleClickListener());
105
106 emoticons.addActionListener(
107 new ActionListener() {
108 public void actionPerformed(ActionEvent e) {
109 ConversationFormatter.getInstance().displayEmoticonChooser(
110 BuddyList.getInstance().getTabFrame(), emoticons,
111 window.getTextEntryArea());
112 }
113 });
114
115 clear.addActionListener(
116 new ActionListener() {
117 public void actionPerformed(ActionEvent e) {
118 window.getConversationArea().setText("");
119 }
120 });
121
122 configure.addActionListener(
123 new ActionListener() {
124 public void actionPerformed(ActionEvent e) {
125 window.configurationHandler("configure");
126 }
127 });
128
129 }
130
131
132 /**
133 * Description of the Method
134 */
135 public void clear() {
136 nickListModel.clear();
137 }
138
139
140 /**
141 * Gets the JList
142 *
143 * @return the JList
144 */
145 public JList getList() {
146 return nickList;
147 }
148
149
150 /**
151 * Adds a buddy to the JList (when they sign on)
152 *
153 * @param buddy the buddy to add
154 */
155 public void addBuddy(String buddy) {
156 if (nickListModel.contains(buddy)) {
157 return;
158 }
159 nickListModel.addBuddy(buddy);
160 }
161
162
163 /**
164 * Description of the Method
165 *
166 * @param buddy Description of the Parameter
167 * @return Description of the Return Value
168 */
169 public boolean contains(String buddy) {
170 return nickListModel.contains(buddy);
171 }
172
173
174 /**
175 * Description of the Method
176 */
177 public void redraw() {
178 adminCount = 0;
179 userCount = 0;
180 SwingUtilities.invokeLater(
181 new Runnable() {
182 public void run() {
183 nickListModel.clear();
184 Hashtable table = window.getBuddyStatuses();
185 ArrayList removers = new ArrayList();
186 for (Iterator i = table.keySet().iterator(); i.hasNext(); ) {
187 MUCBuddyStatus buddy = (MUCBuddyStatus) table.get(i.next());
188 if (buddy.size() <= 0 || !buddy.getIsInRoom()) {
189 removers.add(buddy);
190 continue;
191 }
192 addBuddy(buddy.getUser());
193 }
194 repaint();
195
196 for (int i = 0; i < removers.size(); i++) {
197 window.getBuddyStatuses().remove(removers.get(i));
198 }
199 }
200
201 });
202 }
203
204
205 /**
206 * Removes a buddy from the JList
207 *
208 * @param buddy the buddy to remove
209 */
210 public void removeBuddy(String buddy) {
211 if (!window.getBuddyStatuses().containsKey(buddy)) {
212 return;
213 }
214 if (!nickListModel.contains(buddy)) {
215 return;
216 }
217 nickListModel.removeBuddy(buddy);
218 }
219
220
221 /**
222 * Description of the Method
223 *
224 * @param buddy Description of the Parameter
225 * @return Description of the Return Value
226 */
227 public boolean contains(BuddyStatus buddy) {
228 return nickListModel.contains(buddy.getUser());
229 }
230
231
232 /**
233 * The model that represents the list of buddies in the room
234 *
235 * @author Adam Olsen
236 * @created October 28, 2005
237 * @version 1.0
238 */
239 class NickListModel extends AbstractListModel {
240 private ArrayList buddies = new ArrayList();
241
242 private Object[] buddyNames = null;
243
244
245 /**
246 * Description of the Method
247 */
248 public void clear() {
249 buddies.clear();
250 fireChanged();
251 }
252
253
254 /**
255 * Description of the Method
256 *
257 * @param buddy Description of the Parameter
258 * @return Description of the Return Value
259 */
260 public boolean contains(String buddy) {
261
262 MUCBuddyStatus b = window.getBuddyStatus(buddy);
263 String a = b.getAffiliation();
264 if (a != null) {
265 if (a.equals("owner")) {
266 buddy = "aa_aa1111 " + buddy;
267 }
268 if (a.equals("admin")) {
269 buddy = "aa_aa1222 " + buddy;
270 }
271 }
272 return buddies.contains(buddy);
273 }
274
275
276 /**
277 * @return the number of elements in the list
278 */
279 public int getSize() {
280 if (buddyNames == null) {
281 return 0;
282 }
283
284 return buddyNames.length;
285 }
286
287
288 /**
289 * @param row the element you want to get
290 * @return the Object at <tt>row</tt>
291 */
292 public Object getElementAt(int row) {
293 return buddyNames[row];
294 }
295
296
297 /**
298 * @param buddy the buddy to add
299 */
300 public void addBuddy(String buddy) {
301
302 MUCBuddyStatus b = window.getBuddyStatus(buddy);
303 String a = b.getAffiliation();
304 boolean admin = false;
305 if (a != null) {
306 if (a.equals("owner")) {
307 buddy = "aa_aa1111 " + buddy;
308 admin = true;
309 } else if (a.equals("admin")) {
310 buddy = "aa_aa1222 " + buddy;
311 admin = true;
312 }
313 }
314
315 buddies.add(buddy);
316
317 if (!admin) {
318 userCount++;
319 } else {
320 adminCount++;
321 }
322
323 String text = "";
324 String append = "";
325
326 if (adminCount > 1 || adminCount == 0) {
327 append = "s";
328 }
329 text = adminCount + " admin" + append;
330
331 text += ", " + (userCount + adminCount) + " total";
332
333 countLabel.setText(text);
334
335 fireChanged();
336 }
337
338
339 /**
340 * Removes a buddy from the list
341 *
342 * @param buddy Description of the Parameter
343 */
344 public void removeBuddy(String buddy) {
345 int row = 0;
346 boolean found = false;
347
348 MUCBuddyStatus b = window.getBuddyStatus(buddy);
349 String a = b.getAffiliation();
350 boolean admin = false;
351 if (a != null) {
352 if (a.equals("owner")) {
353 buddy = "aa_aa1111 " + buddy;
354 admin = true;
355 } else if (a.equals("admin")) {
356 buddy = "aa_aa1222 " + buddy;
357 admin = true;
358 }
359 }
360
361 for (int i = 0; i < buddies.size(); i++) {
362 String item = (String) buddies.get(i);
363 if (item.equals(buddy)) {
364 found = true;
365 row = i;
366 }
367 }
368
369 if (!admin) {
370 userCount--;
371 } else {
372 adminCount--;
373 }
374
375 String text = "";
376 String append = "";
377
378 if (adminCount > 1 || adminCount == 0) {
379 append = "s";
380 }
381 text = adminCount + " admin" + append;
382 text += ", " + (userCount + adminCount) + " total";
383
384 if (found) {
385
386 buddies.remove(row);
387
388 countLabel.setText(text);
389 fireChanged();
390 }
391 }
392
393
394 /**
395 * Fires a change of the list
396 */
397 private void fireChanged() {
398 buddyNames = buddies.toArray();
399
400 Arrays.sort(buddyNames,
401 new Comparator() {
402 public int compare(Object string1, Object string2) {
403 String s1 = ((String) string1).toLowerCase();
404 String s2 = ((String) string2).toLowerCase();
405 return s1.compareTo(s2);
406 }
407
408
409 public boolean equals(Object o) {
410 return false;
411 }
412 });
413
414 SwingUtilities.invokeLater(
415 new Runnable() {
416 public void run() {
417 fireContentsChanged(NickListModel.this, 0, buddyNames.length);
418 nickList.repaint();
419 nickList.validate();
420 }
421 });
422 }
423 }
424
425
426 /**
427 * Listens for mouse events in the JList
428 *
429 * @author Adam Olsen
430 * @created October 28, 2005
431 * @version 1.0
432 */
433 class DoubleClickListener extends MouseAdapter {
434 MUCBuddyStatus buddy = null;
435
436
437 /**
438 * Description of the Method
439 *
440 * @param e Description of the Parameter
441 */
442 public void mousePressed(MouseEvent e) {
443 checkPop(e);
444 }
445
446
447 /**
448 * Description of the Method
449 *
450 * @param e Description of the Parameter
451 */
452 public void mouseReleased(MouseEvent e) {
453 checkPop(e);
454 }
455
456
457 /**
458 * Description of the Method
459 *
460 * @param e Description of the Parameter
461 */
462 public void mouseClicked(MouseEvent e) {
463 checkPop(e);
464 if (e.getClickCount() >= 2) {
465 JList list = (JList) e.getComponent();
466
467 MUCBuddyStatus buddy = window.getBuddyStatus(((String) list.getSelectedValue()).replaceAll("^aa_aa\\d{4} ", ""));
468 BuddyList.getInstance().getBuddyListTree()
469 .initiateConversation(buddy);
470 }
471 }
472
473
474 /**
475 * Shows the popup menu
476 *
477 * @param e Description of the Parameter
478 */
479 public void checkPop(MouseEvent e) {
480 if (e.isPopupTrigger()) {
481 try {
482
483 JList list = (JList) e.getComponent();
484 int index = list.locationToIndex(e.getPoint());
485 list.setSelectedIndex(index);
486
487 String user = ((String) list.getSelectedValue()).replaceAll("^aa_aa\\d{4} ", "");
488 buddy = window.getBuddyStatus(user);
489 popMenu.showMenu(e.getComponent(), e.getX(), e.getY(),
490 buddy);
491 } catch (ClassCastException ex) {
492 /*
493 * is not a buddy, so don't
494 * display the menu
495 */
496 }
497 }
498 }
499 }
500 }