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.plugin.pircbot;
21  
22  import javax.swing.AbstractAction;
23  import javax.swing.Action;
24  import javax.swing.JPanel;
25  import javax.swing.JPopupMenu;
26  import javax.swing.JScrollPane;
27  import javax.swing.ListSelectionModel;
28  import javax.swing.event.TreeSelectionEvent;
29  import javax.swing.event.TreeSelectionListener;
30  import javax.swing.tree.TreePath;
31  
32  import java.awt.GridBagLayout;
33  import java.awt.event.ActionEvent;
34  import java.io.File;
35  import java.io.IOException;
36  import java.util.Iterator;
37  import java.util.LinkedList;
38  
39  import org.xnap.XNap;
40  import org.xnap.event.StateEvent;
41  import org.xnap.event.StateListener;
42  import org.xnap.gui.ActionProvider;
43  import org.xnap.gui.StatusBar;
44  import org.xnap.gui.action.CollapseAllNodesAction;
45  import org.xnap.gui.action.ExpandAllNodesAction;
46  import org.xnap.gui.component.XNapButton;
47  import org.xnap.gui.component.XNapMenuItem;
48  import org.xnap.gui.event.DoubleClickListener;
49  import org.xnap.gui.event.PopupListener;
50  import org.xnap.gui.table.JTreeTable;
51  import org.xnap.gui.table.TreeTableNode;
52  import org.xnap.gui.tree.NetworkTreeCellRenderer;
53  import org.xnap.gui.util.GUIHelper;
54  import org.xnap.gui.util.GridBagHelper;
55  import org.xnap.gui.util.IconHelper;
56  import org.xnap.util.FileHelper;
57  
58  public class PircBotPanel extends JPanel 
59      implements ActionProvider, StateListener, TreeSelectionListener {
60  
61      // --- Constants(s) ---
62  
63      public static final String SERVER_FILENAME = "pircbot_servers";
64  
65      // --- Data Field(s) ---
66  
67      private PircBotServerTableModel tmServers;
68      private JTreeTable jttServers;
69  
70      private Action acConnect = new ConnectAction();
71      private Action acDisconnect = new DisconnectAction();
72      private Action acNew = new NewAction();
73      private Action acEdit = new EditAction();
74      private Action acRemove = new RemoveAction();
75  	private Action acCollapseAllNodes;
76  	private Action acExpandAllNodes;
77  
78  	private PircBotServer currentServer;
79  
80      // --- Constructor(s) ---
81  
82      public PircBotPanel() 
83      {
84  		initialize();
85  
86  		// create the default network node
87  		tmServers.add(XNap.tr("Local"));
88  
89  		readFile();
90  
91  		// disable all actions
92  		valueChanged();
93      }
94  
95      // --- Method(s) ---
96  
97      private void initialize()
98      {
99          setLayout(new GridBagLayout());
100 
101 		// connections
102 		GridBagHelper.add
103 			(this, GUIHelper.createSeparator(XNap.tr("Servers")));
104 
105 		tmServers = new PircBotServerTableModel();
106 		jttServers = tmServers.createTreeTable
107 			(PircBotPlugin.getInstance().getPreferences(), "server");
108 		jttServers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
109 		jttServers.getTree().getSelectionModel().addTreeSelectionListener(this);
110 		jttServers.getTree().setCellRenderer
111 			(new NetworkTreeCellRenderer(tmServers));
112 		jttServers.getTableHeader().setReorderingAllowed(false);
113 		DoubleClickListener.install(jttServers, acConnect);
114 		GUIHelper.bindEnterKey(jttServers, acConnect);
115 		//AutoTreeExpander.install(jttServers.getTree());
116 		GridBagHelper.add(this, new JScrollPane(jttServers));
117 
118 		acCollapseAllNodes = new CollapseAllNodesAction(jttServers.getTree());
119 		acExpandAllNodes = new ExpandAllNodesAction(jttServers.getTree());
120 
121 
122 		// table context menu
123 		JPopupMenu popup  = new JPopupMenu();
124 		popup.add(new XNapMenuItem(acConnect));
125 		popup.add(new XNapMenuItem(acDisconnect));
126 		popup.addSeparator();
127 		popup.add(new XNapMenuItem(acEdit));
128 		popup.add(new XNapMenuItem(acRemove));
129 
130 		jttServers.addMouseListener(new PopupListener(popup));
131 
132 		// button
133 		JPanel jpButtons = new JPanel(new GridBagLayout());
134 		GridBagHelper.add(this, jpButtons);
135 
136 		GridBagHelper.addComponent(jpButtons, new XNapButton(acConnect));
137 		GridBagHelper.addComponent(jpButtons, new XNapButton(acDisconnect));
138 
139 		GridBagHelper.addComponent(jpButtons, new XNapButton(acNew));
140 		GridBagHelper.addComponent(jpButtons, new XNapButton(acEdit));
141 		GridBagHelper.addComponent(jpButtons, new XNapButton(acRemove));
142 
143 		GridBagHelper.addVerticalSpacer(this);
144 		GUIHelper.setMnemonics(this);
145     }
146 
147     /***
148      * Returns the selected network.
149      *
150      * @return null, if no network is selected.
151      */
152     public String getSelectedNetwork()
153     {
154 		TreePath path = jttServers.getTree().getSelectionPath();
155 		if (path != null) {
156 			TreeTableNode node = (TreeTableNode)path.getLastPathComponent();
157 			return (node instanceof PircBotNetworkNode) 
158 				? (String)node.getData() : null;
159 		}
160 		return null;
161     }
162 
163     /***
164      * Returns the selected server.
165      *
166      * @return null, if no server is selected.
167      */
168     public PircBotServer getSelectedServer()
169     {
170 		TreePath path = jttServers.getTree().getSelectionPath();
171 		if (path != null) {
172 			TreeTableNode node = (TreeTableNode)path.getLastPathComponent();
173 			return (node instanceof PircBotNetworkNode) 
174 				? null : (PircBotServer)node.getData();
175 		}
176 		return null;
177     }
178 
179     public Action[] getActions()
180     {
181 		return new Action[] { 
182 			acConnect, acDisconnect, null, 
183 			acCollapseAllNodes, acExpandAllNodes 
184 		};
185     }
186 
187     public void savePrefs()
188     {
189 		// disconnect servers
190 		for (Iterator i = tmServers.servers(); i.hasNext();) {
191 			((PircBotServer)i.next()).close();
192 		}
193 
194 		writeFile();
195     }
196 
197 	public void stateChanged(StateEvent e)
198 	{
199 		valueChanged();
200 	}
201 
202     public void valueChanged(TreeSelectionEvent e) 
203 	{
204 		valueChanged();
205 	}
206 
207     public void valueChanged()
208     {
209 		if (currentServer != null) {
210 			currentServer.removeStateListener(this);
211 		}
212 
213 		currentServer = getSelectedServer();
214 
215 		if (currentServer != null) {
216 			currentServer.addStateListener(this);
217 		}
218 
219 		acConnect.setEnabled(currentServer != null 
220 							 && currentServer.isDisconnected());
221 		acDisconnect.setEnabled(currentServer != null 
222 								&& currentServer.isConnected());
223 
224 		acEdit.setEnabled(currentServer != null);
225 		acRemove.setEnabled(currentServer != null);
226     }
227 
228     private void addDefaultServers()
229     {
230 		PircBotServerData data = new PircBotServerData();
231 		data.network = "FreeNode";
232 		data.name = "irc.freenode.net";
233 		data.host = "irc.freenode.net";
234 		data.port = 6667;
235 		data.autoJoinChannels = "#xnap";
236 		tmServers.add(new PircBotServer(data));
237 
238 		addServer("SourceForge", "irc.sourceforge.net", 
239 				  "irc.sourceforge.net");
240     }
241 
242     private void addServer(String network, String name, String host)
243     {
244 		PircBotServerData data = new PircBotServerData();
245 		data.network = network;
246 		data.name = name;
247 		data.host = host;
248 		data.port = 6667;
249 		tmServers.add(new PircBotServer(data));
250     }
251 
252     private void readFile()
253     {
254 		LinkedList list = new LinkedList();
255 		try {
256 			File f = new File(FileHelper.getHomeDir() + SERVER_FILENAME);
257 			FileHelper.readBinary(f, list);
258 		}
259 		catch (IOException e) {
260 			addDefaultServers();
261 			StatusBar.setText(XNap.tr("Could not read file {0}",
262 									  SERVER_FILENAME));
263 		}
264 		for (Iterator i = list.iterator(); i.hasNext();) {
265 			Object o = i.next();
266 			if (o instanceof PircBotServerData) {
267 				PircBotServerData data = (PircBotServerData)o;
268 				if (data.network == null) {
269 					data.network = XNap.tr("Local");
270 				}
271 
272 				PircBotServer s = new PircBotServer(data);
273 				tmServers.add(s);
274 			}
275 		}
276     }
277 
278     private void writeFile()
279     {
280 		LinkedList list = new LinkedList();
281 		for (Iterator i = tmServers.servers(); i.hasNext();) {
282 			list.add(((PircBotServer)i.next()).getData());
283 		}
284 
285 		try {
286 			File f = new File(FileHelper.getHomeDir() + SERVER_FILENAME);
287 			FileHelper.writeBinary(f, list);
288 		}
289 		catch (IOException e) {
290 			StatusBar.setText(XNap.tr("Could not write file {0}",
291 									  SERVER_FILENAME));
292 		}
293     }
294 
295     // --- Inner Class(es) ---
296 
297     /***
298      * Connects to the selected server.
299      */
300     private class ConnectAction extends AbstractAction {
301 
302         public ConnectAction() 
303 		{
304             putValue(Action.NAME, XNap.tr("Connect"));
305             putValue(Action.SHORT_DESCRIPTION,
306 					 XNap.tr("Connects to the selected server."));
307 			putValue(IconHelper.XNAP_ICON, "connect_creating.png");
308         }
309 
310         public void actionPerformed(ActionEvent event) 
311 		{
312 			PircBotServer server = getSelectedServer();
313 			if (server != null) {
314 				server.connect();
315 				valueChanged();
316 			}
317 		}
318 
319     } 
320 
321     /***
322      * Disconnects from selected server.
323      */
324     private class DisconnectAction extends AbstractAction {
325 
326         public DisconnectAction() 
327 		{
328             putValue(Action.NAME, XNap.tr("Disconnect"));
329             putValue(Action.SHORT_DESCRIPTION,
330 					 XNap.tr("Disconnects from the selected server."));
331 			putValue(IconHelper.XNAP_ICON, "connect_no.png");
332         }
333 
334         public void actionPerformed(ActionEvent event) 
335 		{
336 			PircBotServer server = getSelectedServer();
337 			if (server != null) {
338 				server.getBot().disconnect();
339 				valueChanged();
340 			}
341 		}
342 
343     } 
344 
345     /***
346      * Creates a new server.
347      */
348     private class NewAction extends AbstractAction {
349 
350         public NewAction() 
351 		{
352             putValue(Action.NAME, XNap.tr("New"));
353             putValue(Action.SHORT_DESCRIPTION,
354 					 XNap.tr("Creates a new server."));
355 			putValue(IconHelper.XNAP_ICON, "filenew.png");
356         }
357 
358         public void actionPerformed(ActionEvent event) 
359 		{
360 			PircBotServerData data = new PircBotServerData();
361 			PircBotServer server = getSelectedServer();
362 			if (server != null) {
363 				data.network = server.getNetwork();
364 			}
365 			else {
366 				data.network = getSelectedNetwork();
367 			}
368 			server = new PircBotServer(data);
369 
370 			PircBotNewServerDialog d = new PircBotNewServerDialog(server);
371 			d.setNetworks(tmServers.getNetworks());
372 			d.show(PircBotPanel.this);
373 		}
374 
375     } 
376 
377     /***
378      * Edit selected server.
379      */
380     private class EditAction extends AbstractAction {
381 
382         public EditAction() 
383 		{
384             putValue(Action.NAME, XNap.tr("Edit"));
385             putValue(Action.SHORT_DESCRIPTION,
386 					 XNap.tr("Edits the selected server."));
387 			putValue(IconHelper.XNAP_ICON, "edit.png");
388         }
389 
390         public void actionPerformed(ActionEvent event) 
391 		{
392 			PircBotServer server = getSelectedServer();
393 			if (server != null) {
394 				PircBotServerDialog d = new PircBotServerDialog(server);
395 				d.setNetworks(tmServers.getNetworks());
396 				d.show(PircBotPanel.this);
397 			}
398 		}
399 
400     } 
401 
402     /***
403      * Remove selected server.
404      */
405     private class RemoveAction extends AbstractAction {
406 
407         public RemoveAction() 
408 		{
409             putValue(Action.NAME, XNap.tr("Remove"));
410             putValue(Action.SHORT_DESCRIPTION,
411 					 XNap.tr("Removes the selected server."));
412 			putValue(IconHelper.XNAP_ICON, "eraser.png");
413         }
414 
415         public void actionPerformed(ActionEvent event) 
416 		{
417 			PircBotServer server = getSelectedServer();
418 			if (server != null) {
419 				tmServers.remove(server);
420 			}
421 		}
422 
423     } 
424 
425     /***
426      * Used by {@link #NewAction}.
427      */
428     private class PircBotNewServerDialog extends PircBotServerDialog
429     {
430 
431 		public PircBotNewServerDialog(PircBotServer server)
432 		{
433 			super(server);
434 		}
435 
436 		/***
437 		 * Adds server to table model, if successful.
438 		 */
439 		public boolean apply()
440 		{
441 			super.apply();
442 
443 			tmServers.add(getServer());
444 			return true;
445 		}
446 
447     }
448 
449 }