/*
* XNap
*
* A pure java file sharing client.
*
* See AUTHORS for copyright information.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package xnap.plugin.nap.gui;
import xnap.*;
import xnap.plugin.nap.*;
import xnap.gui.*;
import xnap.gui.event.PopupListener;
import xnap.gui.table.*;
import xnap.io.*;
import xnap.net.IChannel;
import xnap.plugin.nap.gui.table.*;
import xnap.plugin.nap.net.*;
import xnap.plugin.nap.net.msg.MessageHandler;
import xnap.plugin.nap.util.*;
import xnap.util.*;
import xnap.util.event.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
import java.beans.*;
public class ServerPanel extends AbstractPanel implements StatusListener {
// --- Data Field(s) ---
private Preferences prefs = Preferences.getInstance();
private NapPreferences napPrefs = NapPreferences.getInstance();
private JScrollPane jsp;
private JTable jta;
private ServerTableModel stm;
private JLabel jlMyStatus;
private NapigatorAction acNapigator = new NapigatorAction();
private UseAutoConnectorAction acUseAutoConnector
= new UseAutoConnectorAction();
private ConnectAction acConnect = new ConnectAction();
private DisconnectAction acDisconnect = new DisconnectAction();
private AddServerAction acAddServer = new AddServerAction();
private EditServerAction acEditServer = new EditServerAction();
private RemoveServerAction acRemoveServer = new RemoveServerAction();
private OpenHostsFileAction acOpenHostsFile = new OpenHostsFileAction();
private SaveHostsFileAction acSaveHostsFile = new SaveHostsFileAction();
private OpenWSXFileAction acOpenWSXFile = new OpenWSXFileAction();
private SaveWSXFileAction acSaveWSXFile = new SaveWSXFileAction();
// --- Constructor(s) ---
public ServerPanel()
{
initialize();
}
// --- Method(s) ---
private void initialize()
{
setLayout(new java.awt.BorderLayout());
// popup-context menu
JPopupMenu popup = new JPopupMenu();
popup.add(acConnect);
popup.add(acDisconnect);
popup.addSeparator();
popup.add(new BrowseAction());
popup.add(new ChatAction());
popup.addSeparator();
popup.add(acEditServer);
popup.addSeparator();
popup.add(acAddServer);
popup.add(acRemoveServer);
// server table
stm = new ServerTableModel(Connector.getInstance());
jta = stm.createJTable();
jta.setShowGrid(false);
// double click listener
jta.addMouseListener(new TableDataListener());
MouseListener popupListener = new PopupListener(popup);
jta.addMouseListener(popupListener);
jta.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
acConnect);
jta.getActionMap().put(acConnect, acConnect);
// table scroll panel
jsp = new JScrollPane();
jsp.setViewportView(jta);
// button panel
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
JButton jbGetNap = new JButton(acNapigator);
buttonPanel.add(jbGetNap);
JCheckBox jcbAutoConnect = new JCheckBox(acUseAutoConnector);
jcbAutoConnect.setSelected(napPrefs.getUseAutoconnector());
buttonPanel.add(jcbAutoConnect);
JCheckBox jcbRemoveServers
= new JCheckBox(new RemoveFailedServersAction());
jcbRemoveServers.setSelected(napPrefs.getRemoveFailedServers());
buttonPanel.add(jcbRemoveServers);
// status line
jlMyStatus = new JLabel(XNap.tr("Not connected"));
// add containers to panel
add(jlMyStatus, BorderLayout.NORTH);
add(jsp, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
// stats updates
Connector.getInstance().addStatsListener(new StatsListener());
Connector.getInstance().setStatusListener(this);
}
public void doLoadServersFile(final String filename, boolean isWSX)
{
if (isWSX) {
(new Thread("LoadWSXFile")
{
public void run()
{
try {
Server[] servers;
WSXServerFile wsxfile = new WSXServerFile();
servers = wsxfile.readServerlist(new File(filename));
for (int i = 0; i < servers.length; i++) {
Connector.getInstance().addServer(servers[i]);
}
} catch (IOException e) {
setStatus(XNap.tr("Could not read") + " "
+ filename + ": " + e.getMessage());
}
}
}
).start();
}
else {
(new Thread("LoadServersFile")
{
public void run()
{
try {
Connector.getInstance().addFromFile(filename, false);
}
catch (IOException e) {
setStatus(XNap.tr("Could not read") + " " + filename +
": " + e.getMessage());
}
}
}
).start();
}
}
public void doSaveServersFile(final String filename, boolean asWSX)
{
if (asWSX) {
(new Thread("SaveWSXFile")
{
public void run()
{
try {
Server[] servers;
WSXServerFile wsxfile = new WSXServerFile();
servers = Connector.getInstance().getServers();
wsxfile.writeServerlist(new File(filename),
servers);
} catch (IOException e) {
setStatus(XNap.tr("Could not read") + " "
+ filename + ": " + e.getMessage());
}
}
}
).start();
}
else {
(new Thread("SaveServersFile")
{
public void run()
{
try {
Connector.getInstance().saveToFile(filename, false);
}
catch (IOException e) {
setStatus(XNap.tr("Could not save") + " " + filename
+ ": " + e.getMessage());
}
}
}
).start();
}
}
public AbstractAction getAskNapigatorAction()
{
return acNapigator;
}
public AbstractAction getUseAutoConnectorAction()
{
return acUseAutoConnector;
}
public void doAskNapigator()
{
setStatus(Plugin.tr("Downloading list of servers") + "...");
(new Thread("AskNapigator")
{
public void run()
{
Connector.getInstance().fetchServerLists();
}
}
).start();
}
public AbstractAction[] getActions()
{
return new AbstractAction[] {
acConnect, acDisconnect, null, acEditServer, null, acAddServer,
acRemoveServer, null, acOpenHostsFile, acSaveHostsFile, null,
acOpenWSXFile, acSaveWSXFile };
}
protected class StatsListener implements StatusListener
{
public void setStatus(String newValue)
{
jlMyStatus.setText(" " + newValue);
}
}
/**
*
*/
private class UseAutoConnectorAction extends AbstractAction {
public UseAutoConnectorAction()
{
putValue(Action.NAME, Plugin.tr("Connect automatically"));
putValue(Action.SHORT_DESCRIPTION,
Plugin.tr("Automatically connect to servers"));
putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_A));
putValue(Action.SMALL_ICON, XNapFrame.getEmptyIcon());
}
public void actionPerformed(ActionEvent event)
{
AbstractButton ab = (AbstractButton)event.getSource();
Connector.getInstance().setEnabled(ab.isSelected());
}
}
/**
*
*/
private class RemoveFailedServersAction extends AbstractAction {
public RemoveFailedServersAction()
{
putValue(Action.NAME, Plugin.tr("Remove Unreachable Servers"));
putValue(Action.SHORT_DESCRIPTION,
Plugin.tr("Automatically remove unreachable servers"));
putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_R));
}
public void actionPerformed(ActionEvent event)
{
AbstractButton ab = (AbstractButton)event.getSource();
napPrefs.setRemoveFailedServers(ab.isSelected());
}
}
/**
* NapigatorAction class handles the command to retrieve server entries
* from the Napigator services. It calls ServerPanel.doAskNapigator().
*/
private class NapigatorAction extends AbstractAction {
public NapigatorAction()
{
putValue(Action.NAME, Plugin.tr("Ask Napigator"));
putValue(Action.SHORT_DESCRIPTION, Plugin.tr("Ask Napigator for a list of servers"));
putValue(Action.SMALL_ICON,
XNapFrame.getIcon("connect_creating.png"));
putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_A));
putValue(Action.ACCELERATOR_KEY,
KeyStroke.getKeyStroke(KeyEvent.VK_N, Event.CTRL_MASK));
}
public void actionPerformed(ActionEvent event)
{
doAskNapigator();
}
} // class NapigatorAction
private class BrowseAction extends AbstractAction {
public BrowseAction()
{
putValue(Action.NAME, Plugin.tr("Browse User") + "...");
putValue(Action.SHORT_DESCRIPTION, Plugin.tr("Browse any User"));
putValue(Action.SMALL_ICON, XNapFrame.getIcon("filefind.png"));
}
public void actionPerformed( ActionEvent event )
{
int i = jta.getSelectedRow();
if (i != -1) {
Server s = stm.get(i);
String nick = JOptionPane.showInputDialog
(ServerPanel.this, Plugin.tr("Nick"),
Plugin.tr("Browse User"), JOptionPane.QUESTION_MESSAGE);
if (nick != null) {
Browse b = new Browse(s.getUser(nick));
SearchManager.getInstance().browse(b);
}
}
}
}
private class ChatAction extends AbstractAction {
public ChatAction()
{
putValue(Action.NAME, Plugin.tr("Chat with User") + "...");
putValue(Action.SHORT_DESCRIPTION, Plugin.tr("Private Chat with any User."));
putValue(Action.SMALL_ICON, XNapFrame.getIcon("mail_generic.png"));
putValue(Action.MNEMONIC_KEY, new Integer('H'));
}
public void actionPerformed( ActionEvent event )
{
int i = jta.getSelectedRow();
if (i != -1) {
Server s = stm.get(i);
String nick = JOptionPane.showInputDialog
(ServerPanel.this, "Nick", Plugin.tr("Chat with User"),
JOptionPane.QUESTION_MESSAGE);
if (nick != null) {
IChannel c = s.getUser(nick).getPrivateChannel();
ChatManager.getInstance().addChannel(c);
}
}
}
}
/**
* ConnectAction class handles the command to connect to the selected
* server(s). For each selected server it calls
* ServerPanel.doLogin()
*/
private class ConnectAction extends AbstractAction {
public ConnectAction()
{
putValue( Action.NAME, Plugin.tr("Connect"));
putValue( Action.SHORT_DESCRIPTION,
Plugin.tr("Connect to the selected server(s)"));
putValue(Action.SMALL_ICON,
XNapFrame.getIcon("connect_established.png"));
putValue( Action.MNEMONIC_KEY, new Integer('C') );
}
public void actionPerformed( ActionEvent event ) {
int rowC = jta.getSelectedRowCount();
int[] rows = jta.getSelectedRows();
for (int i = 0; i < rowC; i++) {
Connector.getInstance().login(stm.get(rows[i]));
}
}
} // class ConnectAction
/**
* DisconnectAction class handles the command to disconnect from the
* selected server(s). For each selected server it calls
* from the Napigator services. It calls ServerPanel.doAskNapigator().
*/
private class DisconnectAction extends AbstractAction {
public DisconnectAction() {
putValue( Action.NAME, Plugin.tr("Disconnect"));
putValue( Action.SHORT_DESCRIPTION,
Plugin.tr("Disconnect from the selected server(s)"));
putValue(Action.SMALL_ICON, XNapFrame.getIcon("connect_no.png"));
putValue( Action.MNEMONIC_KEY, new Integer('D') );
}
public void actionPerformed( ActionEvent event ) {
int rowC = jta.getSelectedRowCount();
int[] rows = jta.getSelectedRows();
for (int i = 0; i < rowC; i++) {
Connector.getInstance().logout(stm.get(rows[i]));
}
}
} // class DisconnectAction
/**
* AddServerAction class handles the command to add a user defined
* server to the list. It calls ServerPanel.addRow().
*/
private class AddServerAction extends AbstractAction {
public AddServerAction()
{
putValue(Action.NAME, Plugin.tr("Add Server") + "...");
putValue(Action.SHORT_DESCRIPTION, Plugin.tr("Add a server to the list"));
putValue(Action.SMALL_ICON, XNapFrame.getIcon("filenew.png"));
putValue(Action.MNEMONIC_KEY, new Integer('A'));
}
public void actionPerformed( ActionEvent event ) {
Server s = new Server();
ServerEditorDialog d = new ServerEditorDialog(s);
d.setLocationRelativeTo(ServerPanel.this);
d.setModal(true);
d.show();
if (d.isOkay()) {
Connector.getInstance().addServer(s);
}
}
} // class AddServerAction
/**
* RemoveServerAction class handles the command to remove the selected
* server(s) from the list. For each selected server it calls
* stm.removeServer(server).
*/
private class EditServerAction extends AbstractAction {
public EditServerAction()
{
putValue(Action.NAME, Plugin.tr("Edit Server") + "...");
putValue(Action.SHORT_DESCRIPTION, Plugin.tr("Change server properties"));
putValue(Action.SMALL_ICON, XNapFrame.getIcon("edit.png"));
putValue(Action.MNEMONIC_KEY, new Integer('E'));
}
public void actionPerformed( ActionEvent event )
{
int row = jta.getSelectedRow();
if (row != -1) {
Server server = stm.get(row);
ServerEditorDialog.showDialog(ServerPanel.this, server);
}
}
}
/**
* RemoveServerAction class handles the command to remove the selected
* server(s) from the list. For each selected server it calls
* stm.removeServer(server).
*/
private class RemoveServerAction extends AbstractAction {
public RemoveServerAction() {
putValue(Action.NAME, Plugin.tr("Remove Server"));
putValue(Action.SHORT_DESCRIPTION,
Plugin.tr("Remove the selected server(s) from the list"));
putValue(Action.SMALL_ICON, XNapFrame.getIcon("eraser.png"));
putValue(Action.MNEMONIC_KEY, new Integer('R'));
}
public void actionPerformed( ActionEvent event ) {
int[] rows = jta.getSelectedRows();
Server[] servers = new Server[rows.length];
for (int i = 0; i < rows.length; i++) {
servers[i] = stm.get(rows[i]);
}
for (int i = 0; i < servers.length; i++) {
Connector.getInstance().removeServer(servers[i]);
}
}
}
/**
* OpenHostsFileAction class handles the command to open a user-specified
* file containing a list of hosts. Once the user selects a file the
* ServerPanel.doLoadServersFile() method is called.
*/
private class OpenHostsFileAction extends AbstractAction {
public OpenHostsFileAction() {
putValue( Action.NAME, Plugin.tr("Import Hosts File"));
putValue( Action.SHORT_DESCRIPTION,
Plugin.tr("Imports a list of servers from a file"));
putValue(Action.SMALL_ICON, XNapFrame.getIcon("fileopen.png"));
putValue( Action.MNEMONIC_KEY, new Integer('O') );
}
public void actionPerformed( ActionEvent event ) {
JFileChooser chooser = new JFileChooser();
chooser.setSelectedFile(new File(FileHelper.getHomeDir() + "hosts"));
if (chooser.showOpenDialog(ServerPanel.this)
== JFileChooser.APPROVE_OPTION) {
String filename = chooser.getSelectedFile().getAbsolutePath();
doLoadServersFile(filename, false);
}
}
}
/**
* SaveHostsFileAction class handles the command to save the current
* list of servers to a user-specified file. Once the user chooses a file
* ServerPanel.doSaveServersFile() method is called.
*/
private class SaveHostsFileAction extends AbstractAction {
public SaveHostsFileAction()
{
putValue(Action.NAME, Plugin.tr("Export Hosts File") + "...");
putValue(Action.SHORT_DESCRIPTION,
Plugin.tr("Export a file with the servers you want to save for latter use"));
putValue(Action.SMALL_ICON, XNapFrame.getIcon("filesave.png"));
putValue(Action.MNEMONIC_KEY, new Integer('S'));
}
public void actionPerformed(ActionEvent event)
{
JFileChooser chooser = new JFileChooser();
chooser.setSelectedFile(new File(FileHelper.getHomeDir() + "hosts"));
if (chooser.showSaveDialog(ServerPanel.this)
== JFileChooser.APPROVE_OPTION)
{
String filename = chooser.getSelectedFile().getAbsolutePath();
doSaveServersFile(filename, false);
}
}
}
/**
* OpenWSXFileAction class handles the command to import a file in WSX
* format containing a list of hosts.
*/
private class OpenWSXFileAction extends AbstractAction {
public OpenWSXFileAction() {
putValue( Action.NAME, Plugin.tr("Import WSX File"));
putValue( Action.SHORT_DESCRIPTION,
Plugin.tr("Imports a lists of servers from a file in WSX format"));
putValue(Action.SMALL_ICON, XNapFrame.getIcon("fileimport.png"));
putValue( Action.MNEMONIC_KEY, new Integer('O') );
}
public void actionPerformed( ActionEvent event ) {
JFileChooser chooser = new JFileChooser();
if (chooser.showOpenDialog(ServerPanel.this)
== JFileChooser.APPROVE_OPTION) {
String filename = chooser.getSelectedFile().getAbsolutePath();
doLoadServersFile(filename, true);
}
}
}
/**
* OpenWSXFileAction class handles the command to export a list of servers
* in WSX format
*/
private class SaveWSXFileAction extends AbstractAction {
public SaveWSXFileAction()
{
putValue(Action.NAME, Plugin.tr("Export WSX File") + "...");
putValue(Action.SHORT_DESCRIPTION,
Plugin.tr("Exports a lists of servers into a file in WSX format"));
putValue(Action.SMALL_ICON, XNapFrame.getIcon("fileexport.png"));
putValue(Action.MNEMONIC_KEY, new Integer('S'));
}
public void actionPerformed(ActionEvent event)
{
JFileChooser chooser = new JFileChooser();
chooser.setSelectedFile(new File(FileHelper.getHomeDir() + "hosts.wsx"));
if (chooser.showSaveDialog(ServerPanel.this)
== JFileChooser.APPROVE_OPTION)
{
String filename = chooser.getSelectedFile().getAbsolutePath();
doSaveServersFile(filename, true);
}
}
}
/**
* TableDataListener class handles the mouse events invoked by clicking
* on the data portion of the JTable.
*/
private class TableDataListener extends MouseAdapter {
public void mouseClicked( MouseEvent event ) {
if (event.getClickCount() == 2) {
int row = jta.rowAtPoint(event.getPoint());
if(row > -1) {
jta.getSelectionModel().setSelectionInterval(row, row);
Connector.getInstance().login(stm.get(row));
}
}
}
}
}