1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.plugin.opennap.gui;
21
22 import javax.swing.AbstractAction;
23 import javax.swing.AbstractButton;
24 import javax.swing.Action;
25 import javax.swing.JCheckBox;
26 import javax.swing.JFileChooser;
27 import javax.swing.JLabel;
28 import javax.swing.JOptionPane;
29 import javax.swing.JPanel;
30 import javax.swing.JPopupMenu;
31 import javax.swing.JScrollPane;
32 import javax.swing.KeyStroke;
33 import javax.swing.SwingUtilities;
34 import javax.swing.event.TreeSelectionEvent;
35 import javax.swing.event.TreeSelectionListener;
36 import javax.swing.tree.TreePath;
37
38 import java.awt.BorderLayout;
39 import java.awt.FlowLayout;
40 import java.awt.event.ActionEvent;
41 import java.awt.event.KeyEvent;
42 import java.awt.event.MouseListener;
43 import java.io.File;
44 import java.text.SimpleDateFormat;
45 import java.util.Date;
46 import java.util.LinkedList;
47
48 import org.xnap.XNap;
49 import org.xnap.event.StatusListener;
50 import org.xnap.gui.ActionProvider;
51 import org.xnap.gui.StatusBar;
52 import org.xnap.gui.action.CollapseAllNodesAction;
53 import org.xnap.gui.action.ExpandAllNodesAction;
54 import org.xnap.gui.component.XNapButton;
55 import org.xnap.gui.component.XNapCheckBox;
56 import org.xnap.gui.component.XNapMenuItem;
57 import org.xnap.gui.event.DoubleClickListener;
58 import org.xnap.gui.event.PopupListener;
59 import org.xnap.gui.table.JTreeTable;
60 import org.xnap.gui.table.LeafTreeTableNode;
61 import org.xnap.gui.table.TreeTableNode;
62 import org.xnap.gui.tree.NetworkTreeCellRenderer;
63 import org.xnap.gui.util.FocusManager;
64 import org.xnap.gui.util.GUIHelper;
65 import org.xnap.gui.util.IconHelper;
66 import org.xnap.io.FileExtensionFilter;
67 import org.xnap.plugin.opennap.OpenNapPlugin;
68 import org.xnap.plugin.opennap.action.OpenNapGetServerListAction;
69 import org.xnap.plugin.opennap.net.OpenNapBrowse;
70 import org.xnap.plugin.opennap.net.OpenNapServer;
71 import org.xnap.plugin.opennap.util.OpenNapPreferences;
72 import org.xnap.search.DefaultSearchFilter;
73 import org.xnap.search.Search;
74 import org.xnap.search.SearchFilter;
75 import org.xnap.search.SearchManager;
76 import org.xnap.util.FileHelper;
77 import org.xnap.util.IllegalOperationException;
78
79 /***
80 * This class provides a {@link JTreeTable} that contains a list of
81 * {@link OpenNapServer} objects that are grouped by network.
82 */
83 public class OpenNapServerPanel extends JPanel
84 implements ActionProvider, TreeSelectionListener, StatusListener {
85
86
87
88 private OpenNapPreferences napPrefs = OpenNapPlugin.getPreferences();
89
90 private JTreeTable jttServers;
91 private OpenNapServerTableModel tmServers;
92 private JLabel jlStatus;
93
94 private JFileChooser jfcDefault = new JFileChooser();
95
96 private Action acConnect = new ConnectAction();
97 private Action acDisconnect = new DisconnectAction();
98 private Action acAddServer = new AddServerAction();
99 private Action acEditServer = new EditServerAction();
100 private Action acRemoveServer = new RemoveServerAction();
101 private Action acOpenServerFile = new OpenServerFileAction(jfcDefault);
102 private Action acSaveServerFile = new SaveServerFileAction(jfcDefault);
103 private Action acUseAutoConnector = new UseAutoConnectorAction();
104 private Action acCollapseAllNodes;
105 private Action acExpandAllNodes;
106 private Action browseAction = new BrowseAction();
107 private Action chatAction = new ChatAction();
108
109
110
111 public OpenNapServerPanel()
112 {
113 initialize();
114 }
115
116
117
118 private void initialize()
119 {
120 setLayout(new BorderLayout());
121
122
123 tmServers = new OpenNapServerTableModel();
124 jttServers = tmServers.createTreeTable(napPrefs, "server");
125 jttServers.getTree().getSelectionModel().addTreeSelectionListener(this);
126 jttServers.getTree().setCellRenderer
127 (new NetworkTreeCellRenderer(tmServers));
128 DoubleClickListener.install(jttServers, acConnect);
129 GUIHelper.bindEnterKey(jttServers, acConnect);
130
131 acCollapseAllNodes = new CollapseAllNodesAction(jttServers.getTree());
132 acExpandAllNodes = new ExpandAllNodesAction(jttServers.getTree());
133
134
135 JPopupMenu popup = new JPopupMenu();
136 popup.add(new XNapMenuItem(acConnect));
137 popup.add(new XNapMenuItem(acDisconnect));
138 popup.addSeparator();
139 popup.add(new XNapMenuItem(browseAction));
140 popup.add(new XNapMenuItem(chatAction));
141 popup.addSeparator();
142 popup.add(new XNapMenuItem(acAddServer));
143 popup.addSeparator();
144 popup.add(new XNapMenuItem(acEditServer));
145 popup.add(new XNapMenuItem(acRemoveServer));
146
147 MouseListener popupListener = new PopupListener(popup);
148 jttServers.addMouseListener(popupListener);
149
150 jttServers.getInputMap().put(KeyStroke.getKeyStroke
151 (KeyEvent.VK_ENTER, 0), acConnect);
152 jttServers.getActionMap().put(acConnect, acConnect);
153
154
155
156 JPanel jpButtons = new JPanel();
157 jpButtons.setLayout(new FlowLayout(FlowLayout.LEFT));
158
159 jpButtons.add(new XNapButton(new OpenNapGetServerListAction()));
160 jpButtons.add(new XNapButton(new FindWSXFiles()));
161
162 JCheckBox jcbAutoConnect = new JCheckBox(acUseAutoConnector);
163 jcbAutoConnect.setSelected(napPrefs.getUseAutoconnector());
164 jpButtons.add(jcbAutoConnect);
165
166 JCheckBox jcbRemoveServers
167 = new XNapCheckBox(new RemoveFailedServersAction());
168 jpButtons.add(jcbRemoveServers);
169
170
171 jlStatus = new JLabel(OpenNapPlugin.getServerManager().getStats());
172
173
174 add(jlStatus, BorderLayout.NORTH);
175 add(new JScrollPane(jttServers), BorderLayout.CENTER);
176 add(jpButtons, BorderLayout.SOUTH);
177
178
179
180
181
182
183 jfcDefault.setSelectedFile
184 (new File(FileHelper.getHomeDir() + "hosts"));
185 jfcDefault.addChoosableFileFilter(new FileExtensionFilter("wsx"));
186 jfcDefault.addChoosableFileFilter
187 (new FileExtensionFilter("hosts", XNap.tr("XNap Server")));
188
189 valueChanged();
190 }
191
192 public Action[] getActions()
193 {
194 return new Action[] {
195 acOpenServerFile, acSaveServerFile, null, acConnect, acDisconnect,
196 null, acAddServer, null, acEditServer, acRemoveServer, null,
197 acCollapseAllNodes, acExpandAllNodes
198 };
199 }
200
201 /***
202 * Returns the currently selected servers.
203 *
204 * @return null, if nothing is selected
205 */
206 public OpenNapServer[] getSelectedServers()
207 {
208 TreePath[] paths = jttServers.getTree().getSelectionPaths();
209 if (paths != null) {
210 LinkedList results = new LinkedList();
211 for (int i = 0; i < paths.length; i++) {
212 TreeTableNode node
213 = (TreeTableNode)paths[i].getLastPathComponent();
214 if (node instanceof LeafTreeTableNode) {
215 results.add((OpenNapServer)node.getData());
216 }
217 }
218 return (results.size() > 0)
219 ? (OpenNapServer[])results.toArray(new OpenNapServer[0]) : null;
220 }
221 return null;
222 }
223
224 public void setStatus(final String newValue)
225 {
226 Runnable runner = new Runnable()
227 {
228 public void run()
229 {
230 jlStatus.setText(newValue);
231 }
232 };
233 SwingUtilities.invokeLater(runner);
234 }
235
236 public void valueChanged(TreeSelectionEvent e)
237 {
238 valueChanged();
239 }
240
241 public void valueChanged()
242 {
243 boolean selected = (getSelectedServers() != null);
244 acConnect.setEnabled(selected);
245 acDisconnect.setEnabled(selected);
246 acEditServer.setEnabled(selected);
247 acRemoveServer.setEnabled(selected);
248 browseAction.setEnabled(selected);
249 chatAction.setEnabled(selected);
250 }
251
252
253
254 /***
255 * AddServerAction class handles the command to add a user defined
256 * server to the list.
257 */
258 private class AddServerAction extends AbstractAction {
259
260 public AddServerAction()
261 {
262 putValue(Action.NAME, XNap.tr("Add Server") + "...");
263 putValue(Action.SHORT_DESCRIPTION,
264 XNap.tr("Add a server to the list."));
265 putValue(IconHelper.XNAP_ICON, "filenew.png");
266 }
267
268 public void actionPerformed( ActionEvent event )
269 {
270 OpenNapServerEditorDialog d = new OpenNapServerEditorDialog();
271 d.setNetworks(tmServers.getNetworkNames());
272 d.show(OpenNapServerPanel.this);
273 }
274
275 }
276
277 private class BrowseAction extends AbstractAction {
278
279 public BrowseAction()
280 {
281 putValue(Action.NAME, XNap.tr("Browse User") + "...");
282 putValue(Action.SHORT_DESCRIPTION,
283 XNap.tr("Prompts for a nick."));
284 putValue(IconHelper.XNAP_ICON, "filefind.png");
285 }
286
287 public void actionPerformed( ActionEvent event )
288 {
289 OpenNapServer[] servers = getSelectedServers();
290 if (servers != null) {
291 for (int i = 0; i < servers.length; i++) {
292 String nick = JOptionPane.showInputDialog
293 (OpenNapServerPanel.this, XNap.tr("Nick"),
294 XNap.tr("Browse User"), JOptionPane.QUESTION_MESSAGE);
295
296 if (nick != null) {
297 OpenNapBrowse b
298 = new OpenNapBrowse(servers[i].getUser(nick));
299 SearchManager.getInstance().handle(b);
300 FocusManager.setFocusTo("search");
301 }
302 }
303 }
304 }
305
306 }
307
308 private class ChatAction extends AbstractAction {
309
310 public ChatAction()
311 {
312 putValue(Action.NAME, XNap.tr("Chat With User") + "...");
313 putValue(Action.SHORT_DESCRIPTION,
314 XNap.tr("Prompts for a nick."));
315 putValue(IconHelper.XNAP_ICON, "mail_generic.png");
316 }
317
318 public void actionPerformed( ActionEvent event )
319 {
320 OpenNapServer[] servers = getSelectedServers();
321 if (servers != null) {
322 for (int i = 0; i < servers.length; i++) {
323 String nick = JOptionPane.showInputDialog
324 (OpenNapServerPanel.this, XNap.tr("Nick"),
325 XNap.tr("Chat With User"),
326 JOptionPane.QUESTION_MESSAGE);
327
328 if (nick != null) {
329 OpenNapPlugin.getMessageHandler().getPrivateChannel
330 (servers[i].getUser(nick));
331 FocusManager.setFocusTo("chat");
332 }
333 }
334 }
335 }
336
337 }
338
339 /***
340 * This class connects the selected servers.
341 */
342 private class ConnectAction extends AbstractAction {
343
344 public ConnectAction()
345 {
346 putValue(Action.NAME, XNap.tr("Connect"));
347 putValue(Action.SHORT_DESCRIPTION,
348 XNap.tr("Connects to the selected servers."));
349 putValue(IconHelper.XNAP_ICON, "connect_creating.png");
350 }
351
352 public void actionPerformed(ActionEvent event)
353 {
354 OpenNapServer[] servers = getSelectedServers();
355 if (servers != null) {
356 for (int i = 0; i < servers.length; i++) {
357 try {
358 servers[i].connect();
359 }
360 catch (IllegalOperationException e) {
361 StatusBar.setText(e.getLocalizedMessage());
362 }
363 }
364 }
365 }
366
367 }
368
369 /***
370 * This class provides an action that disconnects the selected servers.
371 */
372 private class DisconnectAction extends AbstractAction {
373
374 public DisconnectAction()
375 {
376 putValue(Action.NAME, XNap.tr("Disconnect"));
377 putValue(Action.SHORT_DESCRIPTION,
378 XNap.tr("Disconnect from the selected servers."));
379 putValue(IconHelper.XNAP_ICON, "connect_no.png");
380 }
381
382 public void actionPerformed( ActionEvent event )
383 {
384 OpenNapServer[] servers = getSelectedServers();
385 if (servers != null) {
386 for (int i = 0; i < servers.length; i++) {
387 try {
388 servers[i].disconnect();
389 }
390 catch (IllegalOperationException e) {
391 StatusBar.setText(e.getLocalizedMessage());
392 }
393 }
394 }
395 }
396 }
397
398 /***
399 * This class provides an action that opens a
400 * {@link OpenNapServerEditorDialog} for each selected server.
401 */
402 private class EditServerAction extends AbstractAction {
403
404 public EditServerAction()
405 {
406 putValue(Action.NAME, XNap.tr("Edit Server") + "...");
407 putValue(Action.SHORT_DESCRIPTION,
408 XNap.tr("Opens a dialog with the server properties."));
409 putValue(IconHelper.XNAP_ICON, "edit.png");
410 }
411
412 public void actionPerformed( ActionEvent event )
413 {
414 OpenNapServer[] servers = getSelectedServers();
415 if (servers != null) {
416 for (int i = 0; i < servers.length; i++) {
417 OpenNapServerEditorDialog d
418 = new OpenNapServerEditorDialog(servers[i]);
419 d.setNetworks(tmServers.getNetworkNames());
420 d.show(OpenNapServerPanel.this);
421 }
422 }
423 else {
424 StatusBar.setText(XNap.tr("Please select a server."));
425 }
426 }
427
428 }
429
430 /***
431 * RemoveServerAction class handles the command to remove the selected
432 * server(s) from the list. For each selected server it calls
433 * tmServers.removeServer(server).
434 */
435 private class RemoveServerAction extends AbstractAction {
436
437 public RemoveServerAction()
438 {
439 putValue(Action.NAME, XNap.tr("Remove Server"));
440 putValue(Action.SHORT_DESCRIPTION,
441 XNap.tr("Remove the selected servers from the list"));
442 putValue(IconHelper.XNAP_ICON, "eraser.png");
443 }
444
445 public void actionPerformed( ActionEvent event )
446 {
447 OpenNapServer[] servers = getSelectedServers();
448 if (servers != null) {
449 for (int i = 0; i < servers.length; i++) {
450 OpenNapPlugin.getServerManager().remove(servers[i]);
451 }
452 }
453 else {
454 StatusBar.setText(XNap.tr("Please select a server."));
455 }
456 }
457
458 }
459
460 /***
461 *
462 */
463 private class UseAutoConnectorAction extends AbstractAction {
464
465 public UseAutoConnectorAction()
466 {
467 putValue(Action.NAME, XNap.tr("Connect automatically"));
468 putValue(Action.SHORT_DESCRIPTION,
469 XNap.tr("Automatically connect to servers"));
470 }
471
472 public void actionPerformed(ActionEvent event)
473 {
474 AbstractButton ab = (AbstractButton)event.getSource();
475 OpenNapPlugin.getServerManager().getConnector().setEnabled
476 (ab.isSelected());
477 }
478
479 }
480
481
482 /***
483 *
484 */
485 private class FindWSXFiles extends AbstractAction {
486
487 public FindWSXFiles()
488 {
489 putValue(Action.NAME, XNap.tr("Find WSX Files"));
490 putValue(IconHelper.XNAP_ICON, "editfind.png");
491 putValue(Action.SHORT_DESCRIPTION,
492 XNap.tr("Find servers file."));
493 }
494
495 public void actionPerformed(ActionEvent event)
496 {
497 SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
498
499 DefaultSearchFilter filter = new DefaultSearchFilter();
500 filter.put(SearchFilter.TEXT, "PUBLIC " + df.format(new Date()));
501 filter.put("nap.minBitrate", new Long(24));
502 filter.put("nap.maxBitrate", new Long(24));
503 filter.put("nap.minFrequency", new Long(16000));
504 filter.put("nap.maxFrequency", new Long(16000));
505
506 Search search = OpenNapPlugin.getSearchManager().search(filter);
507 SearchManager.getInstance().handle(search);
508
509 FocusManager.setFocusTo("search", event);
510 }
511
512 }
513
514 }