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    }