View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation.
9    *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.gui;
21  
22  import java.awt.BorderLayout;
23  import java.awt.FlowLayout;
24  import java.awt.GridBagLayout;
25  import java.awt.event.ActionEvent;
26  import java.awt.event.ItemEvent;
27  import java.awt.event.ItemListener;
28  
29  import javax.swing.*;
30  import javax.swing.JComboBox;
31  import javax.swing.JPanel;
32  import javax.swing.JPopupMenu;
33  import javax.swing.JScrollPane;
34  import javax.swing.JSplitPane;
35  import javax.swing.JTable;
36  import javax.swing.ListSelectionModel;
37  import javax.swing.SwingUtilities;
38  import javax.swing.border.*;
39  
40  import org.xnap.XNap;
41  import org.xnap.chat.ChannelInfo;
42  import org.xnap.chat.ChatManager;
43  import org.xnap.chat.ChatProvider;
44  import org.xnap.chat.ChatProviderEvent;
45  import org.xnap.chat.ChatProviderListener;
46  import org.xnap.chat.action.AbstractJoinAction;
47  import org.xnap.event.ListEvent;
48  import org.xnap.event.ListListener;
49  import org.xnap.gui.component.XNapButton;
50  import org.xnap.gui.component.XNapMenuItem;
51  import org.xnap.gui.event.DoubleClickListener;
52  import org.xnap.gui.event.PopupListener;
53  import org.xnap.gui.list.ChatProviderCellRenderer;
54  import org.xnap.gui.table.ChannelTableModel;
55  import org.xnap.gui.util.GUIHelper;
56  import org.xnap.gui.util.GridBagHelper;
57  import org.xnap.util.Preferences;
58  
59  public class ChatProviderPanel extends JPanel 
60      implements ActionProvider, ChatProviderListener, ListListener, 
61  			   ItemListener
62  {
63  
64      //--- Constant(s) ---
65  
66      // --- Data Field(s) ---
67  
68      private static Preferences prefs = Preferences.getInstance();
69  
70      private ConsolePane cpMessages;
71      private ChannelTableModel tmChannels;
72      private JComboBox jcbServers;
73      private JTable jta;
74      private JPanel jpActions;
75      
76      private JSplitPane jspH;
77  
78      private JoinChannelAction acJoinChannel = new JoinChannelAction();
79      
80      //--- Constructor(s) ---
81  
82      public ChatProviderPanel() 
83      {
84  		initialize();
85  
86  		ChatProvider[] providers = ChatManager.getInstance().getProviders();
87  		for (int i = 0; i < providers.length; i++) {
88  			jcbServers.addItem(providers[i]);
89  		}
90  
91  		ChatManager.getInstance().addProviderListListener(this);
92      }
93  
94      // --- Method(s) ---
95  
96      private void initialize()
97      {
98  		JPanel jpTop = new JPanel(new GridBagLayout());
99  		jpTop.setBorder(new EmptyBorder(5, 5, 5, 5));
100 
101 		// server combo box
102 		JLabel l = GridBagHelper.addLabel(jpTop, XNap.tr("Server"));
103 	
104     	jcbServers = new JComboBox();
105 		l.setLabelFor(jcbServers);
106 		jcbServers.addItemListener(this);
107 		jcbServers.setRenderer(new ChatProviderCellRenderer());
108     	GridBagHelper.addComponent(jpTop, jcbServers);
109 
110 		// actions
111 		jpActions = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
112 		GridBagHelper.add(jpTop, jpActions);
113 
114 		// channel table
115 		tmChannels = new ChannelTableModel();
116 		jta = tmChannels.createTable(prefs, "channel");
117 		jta.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
118 		DoubleClickListener.install(jta, acJoinChannel);
119 		GUIHelper.bindEnterKeyLocally(jta, acJoinChannel);
120 		
121 		JScrollPane jspChannels = new JScrollPane(jta);
122 
123 		// table context menu
124 		JPopupMenu popup = new JPopupMenu();
125 		popup.add(new XNapMenuItem(acJoinChannel));
126 	
127 		jta.addMouseListener(new PopupListener(popup));
128 
129 		// console
130 		cpMessages = new ConsolePane();
131 
132 		// split pane
133 		jspH = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
134 		jspH.add(jspChannels, JSplitPane.LEFT);
135 		jspH.add(cpMessages, JSplitPane.RIGHT);
136 		jspH.setDividerLocation(prefs.getChatGlobalVerticalDividerLocation());
137 		jspH.setResizeWeight(0);
138 		jspH.setOneTouchExpandable(true);
139 		jspH.setBorder(GUIHelper.createEmptyBorder());
140 
141 		setLayout(new BorderLayout());
142 		add(jpTop, BorderLayout.NORTH);
143 		add(jspH, BorderLayout.CENTER);
144 
145 		GUIHelper.setMnemonics(this);
146     }
147 
148     /***
149      * Invoked when the list of channels has been updated.
150      */
151     public void channelsUpdated(final ChatProviderEvent event)
152     {
153 		Runnable runner = new Runnable() 
154 			{
155 				public void run() 
156 				{
157 					ChatProvider p = getSelectedProvider();
158 					if (p == event.getSource()) {
159 						tmChannels.set(p);
160 					}
161 				}
162 			};
163 		SwingUtilities.invokeLater(runner);
164     }
165 
166     /***
167      * Invoked when a message has been received.
168      */
169     public void messageReceived(ChatProviderEvent event)
170     {
171 		cpMessages.appendLater(event.getMessage());
172     }
173 
174     public int getDividerLocation()
175     {
176 		return jspH.getDividerLocation();
177     }
178 
179     /***
180      * Invoked when a {@link ChatProvider} object is added to the 
181      * {@link ChatManager}.
182      */
183     public void itemAdded(ListEvent e)
184     {
185         final Object obj = e.getItem();
186 		Runnable runner = new Runnable() 
187 			{
188 				public void run() 
189 				{
190 					jcbServers.addItem(obj);
191 				}
192 			};
193 		SwingUtilities.invokeLater(runner);
194     }
195     
196     /***
197      * Invoked when a {@link ChatProvider} object is removed from
198      * {@link ChatManager}.
199      */
200     public void itemRemoved(ListEvent e)
201     {
202         final Object obj = e.getItem();
203 		Runnable runner = new Runnable() 
204 			{
205 				public void run() 
206 				{
207 					jcbServers.removeItem(obj);
208 				}
209 			};
210 		SwingUtilities.invokeLater(runner);
211     }
212 
213     /***
214      * Invoked when a ChatProvider is selected from the ComboBox.
215      */
216     public void itemStateChanged(ItemEvent e)
217     {
218 		if (e.getStateChange() == ItemEvent.SELECTED) {
219 			ChatProvider p = (ChatProvider)e.getItem();
220 
221 			p.addChatProviderListener(this);
222 
223 			tmChannels.set(p);
224 			cpMessages.setLater(p.getMessages());
225 			jpActions.removeAll();
226 			Action[] actions = p.getActions();
227 			if (actions != null) {
228 				for (int i = 0; i < actions.length; i++) {
229 					jpActions.add(new XNapButton(actions[i]));
230 				}
231 			}
232 			// redraw
233 			jpActions.updateUI();
234 		}
235 		else if (e.getStateChange() == ItemEvent.DESELECTED) {
236 			((ChatProvider)e.getItem()).removeChatProviderListener(this);
237 
238 			tmChannels.clear();
239 			cpMessages.setLater("");
240 			jpActions.removeAll();
241 		}
242     }
243 
244     public ChannelInfo getSelectedChannel()
245     {
246 		int i = jta.getSelectedRow();
247 		return (i != -1) ? tmChannels.get(i) : null;
248     }
249     
250     public ChatProvider getSelectedProvider() 
251     {
252 		return (ChatProvider)jcbServers.getSelectedItem();
253     }
254 
255     public Action[] getActions()
256     {
257 		return (new Action[] {
258 			acJoinChannel
259 		});
260     }
261 
262     public void savePrefs()
263     {
264 		prefs.setChatGlobalVerticalDividerLocation(jspH.getDividerLocation());
265     }
266 
267 	//--- Inner Class(es) ---
268 
269     private class JoinChannelAction extends AbstractJoinAction {
270 
271         public JoinChannelAction() 
272 		{
273 		}
274 
275         public void actionPerformed(ActionEvent event) 
276 		{
277 			ChannelInfo c = getSelectedChannel();
278 			if (c != null) {
279 				getSelectedProvider().join(c.getName());
280 			}
281 			else {
282 				StatusBar.setText(XNap.tr("Please select a channel"));
283 			}
284         }
285     }	
286    
287 }