001    /*
002        Copyright (C) 2003 Adam Olsen
003    
004            This program is free software; you can redistribute it and/or modify
005        it under the terms of the GNU General Public License as published by
006        the Free Software Foundation; either version 1, or (at your option)
007        any later version.
008    
009        This program is distributed in the hope that it will be useful,
010        but WITHOUT ANY WARRANTY; without even the implied warranty of
011        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012        GNU General Public License for more details.
013    
014        You should have received a copy of the GNU General Public License
015        along with this program; if not, write to the Free Software
016        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
017    */
018    
019    package com.valhalla.jbother.groupchat;
020    
021    import java.awt.*;
022    import java.awt.event.*;
023    import java.util.*;
024    import javax.swing.*;
025    import javax.swing.event.*;
026    import com.valhalla.gui.*;
027    import com.valhalla.jbother.jabber.BuddyStatus;
028    import com.valhalla.jbother.menus.*;
029    import com.valhalla.jbother.*;
030    
031    /**
032     * The JPanel that contains the nickname list
033     *
034     * @author Adam Olsen
035     * @version 1.0
036    */
037    public class GroupChatNickList extends JPanel
038    {
039            private NickListModel nickListModel = new NickListModel();
040            private JList nickList = new JList( nickListModel );
041            private JScrollPane scrollPane = new JScrollPane( nickList );
042            private ChatRoomPanel window;
043            private NickListPopupMenu popMenu = new NickListPopupMenu();
044    
045            /**
046             * Sets up the panel
047             * @param window the chatroom window that this nicklist is a part of
048            */
049            public GroupChatNickList( ChatRoomPanel window )
050            {
051                    super();
052    
053                    this.window = window;
054                    setLayout( new GridLayout( 0, 1 ) );
055    
056                    add( scrollPane );
057                    setPreferredSize( new Dimension( 100, 400 ) );
058                    NickListRenderer renderer = new NickListRenderer( window );
059                    nickList.setCellRenderer( renderer );
060                    nickList.addMouseListener( new DoubleClickListener() );
061            }
062    
063            /**
064             * Gets the JList
065             * @return the JList
066            */
067            public JList getList() { return nickList; }
068    
069            /**
070             * Adds a buddy to the JList (when they sign on)
071             * @param buddy the buddy to add
072            */
073            public void addBuddy( String buddy ) { nickListModel.addBuddy( buddy ); }
074    
075            /**
076             * Removes a buddy from the JList
077             * @param buddy the buddy to remove
078            */
079            public void removeBuddy( String buddy ) { nickListModel.removeBuddy( buddy ); }
080    
081            /**
082             * The model that represents the list of buddies in the room
083             * @author Adam Olsen
084             * @version 1.0
085            */
086            class NickListModel extends AbstractListModel
087            {
088                    private ArrayList buddies = new ArrayList();
089                    private Object[] buddyNames = null;
090    
091                    /**
092                     * @return the number of elements in the list
093                    */
094                    public int getSize()
095                    {
096                            if( buddyNames == null ) return 0;
097    
098                            return buddyNames.length;
099                    }
100    
101                    /**
102                     * @param row the element you want to get
103                     * @return the Object at <tt>row</tt>
104                    */
105                    public synchronized Object getElementAt( int row )
106                    {
107                            return buddyNames[row];
108                    }
109    
110                    /**
111                     * @param buddy the buddy to add
112                    */
113                    public void addBuddy( String buddy )
114                    {
115                            buddies.add( buddy );
116                            fireChanged();
117                    }
118    
119                    /**
120                     * Removes a buddy from the list
121                    */
122                    public void removeBuddy( String buddy )
123                    {
124                            int row = 0;
125                            boolean found = false;
126    
127                            for( int i = 0; i < buddies.size(); i++ )
128                            {
129                                    String item = (String)buddies.get( i );
130                                    if( item.equals( buddy ) )
131                                    {
132                                            found = true;
133                                            row = i;
134                                    }
135                            }
136    
137                            if( found )
138                            {
139                                    buddies.remove( row );
140                                    fireChanged();
141                            }
142                    }
143    
144                    NickListModel thisPointer = this;
145    
146                    /**
147                     * Fires a change of the list
148                    */
149                    private synchronized void fireChanged()
150                    {
151                            buddyNames = buddies.toArray();
152    
153                            Arrays.sort( buddyNames );
154    
155                            SwingUtilities.invokeLater( new Runnable()
156                            {
157                                    public void run()
158                                    {
159                                            fireContentsChanged( thisPointer, 0, buddyNames.length );
160                                            nickList.repaint();
161                                            nickList.validate();
162                                    }
163                            } );
164                    }
165            }
166    
167            /**
168             * Listens for mouse events in the JList
169             * @author Adam Olsen
170             * @version 1.0
171            */
172            class DoubleClickListener extends MouseAdapter
173            {
174                    public void mousePressed( MouseEvent e ) { checkPop( e ); }
175                    public void mouseReleased( MouseEvent e ) { checkPop( e ); }
176    
177                    private boolean clicked = false;
178                    private javax.swing.Timer clickTimer = new javax.swing.Timer( 350, new TimerHandler() );
179    
180                    /**
181                     * Called when a click is recieved
182                     * We have to hack this with a timer, we cannot use the regular method for
183                     * double click detection, so we use a timer.  If we do not, we will have
184                     * text box focus problems.  The text input box should _always_ have
185                     * focus, so this is a way to ensure that.
186                    */
187                    public void mouseClicked( MouseEvent e )
188                    {
189                            checkPop( e );
190                            JList list = (JList)e.getSource();
191    
192                            if( clicked )
193                            {
194                                    BuddyStatus buddy = window.getBuddyStatus( (String)list.getSelectedValue() );
195                                    initiatePMConversation( buddy );
196                                    clickTimer.stop();
197                                    clicked = false;
198                            }
199                            else {
200                                    clicked = true;
201                                    clickTimer.start();
202                            }
203    
204                            window.getTextEntryArea().grabFocus();
205                    }
206    
207                    /**
208                     * Shows the popup menu
209                    */
210                    public void checkPop( MouseEvent e )
211                    {
212                            BuddyStatus buddy = null;
213    
214                            if( e.isPopupTrigger() )
215                            {
216                                    try {
217    
218                                            JList list = (JList)e.getComponent();
219                                            int index = list.locationToIndex( e.getPoint() );
220                                            list.setSelectedIndex( index );
221    
222                                            String user = (String)list.getSelectedValue();
223                                            buddy = window.getBuddyStatus( user );
224                                            popMenu.showMenu( e.getComponent(), e.getX(), e.getY(), buddy );
225                                    }
226                                    catch( ClassCastException ex ) { /*is not a buddy, so don't display the menu*/ }
227                            }
228                    }
229    
230                    /**
231                     * The time is up, the double click is off
232                    */
233                    class TimerHandler implements ActionListener
234                    {
235                            public void actionPerformed( ActionEvent e )
236                            {
237                                    clicked = false;
238                            }
239                    }
240            }
241    
242            /**
243             * Starts a conversation with a buddy in a groupchat
244             * @param buddy the buddy to start the conversation with
245            */
246            public void initiatePMConversation( BuddyStatus buddy )
247            {
248                    String nick = "";
249                    String room = "";
250                    String parts[] = new String[2];
251                    parts = buddy.getUser().split( "\\/" );
252                    nick = parts[1];
253                    room = parts[0];
254    
255                    if( buddy.getConversation() == null )
256                    {
257                            ChatPanel conver = new ChatPanel( buddy );
258                            buddy.setConversation( conver );
259                            MessageDelegator.getInstance().showPanel( buddy.getConversation() );
260                            MessageDelegator.getInstance().frontFrame( buddy.getConversation() );
261                    }
262                    else {
263                            MessageDelegator.getInstance().showPanel( buddy.getConversation() );
264                            MessageDelegator.getInstance().frontFrame( buddy.getConversation() );
265                    }
266    
267                    buddy.getConversation().stopTimer();
268            }
269    }