/*
* Copyright (c) 2014 tabletoptool.com team.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* rptools.com team - initial implementation
* tabletoptool.com team - further development
*/
package com.t3.client.ui;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.DecimalFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import net.tsc.servicediscovery.AnnouncementListener;
import net.tsc.servicediscovery.ServiceFinder;
import yasb.Binder;
import com.t3.client.AppConstants;
import com.t3.client.TabletopTool;
import com.t3.client.swing.AbeillePanel;
import com.t3.client.swing.GenericDialog;
import com.t3.language.I18N;
import com.t3.networking.registry.RegisteredServer;
import com.t3.networking.registry.T3Registry;
import com.t3.swing.SwingUtil;
/**
* @author trevor
*/
public class ConnectToServerDialog extends AbeillePanel<ConnectToServerDialogPreferences> implements AnnouncementListener {
private static ServiceFinder finder;
static {
finder = new ServiceFinder(AppConstants.SERVICE_GROUP);
}
private boolean accepted;
private GenericDialog dialog;
private int port;
private String hostname;
/**
* This is the default constructor
*/
public ConnectToServerDialog() {
super("com/t3/client/ui/forms/connectToServerDialog.xml");
setPreferredSize(new Dimension(400, 400));
panelInit();
}
@Override
protected void preModelBind() {
Binder.setFormat(getPortTextField(), new DecimalFormat("####"));
}
public int getPort() {
return port;
}
public String getServer() {
return hostname;
}
public void showDialog() {
dialog = new GenericDialog(I18N.getText("ConnectToServerDialog.msg.title"), TabletopTool.getFrame(), this);
bind(new ConnectToServerDialogPreferences());
getRootPane().setDefaultButton(getOKButton());
dialog.showDialog();
}
public JButton getOKButton() {
return (JButton) getComponent("okButton");
}
@Override
public void bind(ConnectToServerDialogPreferences model) {
finder.addAnnouncementListener(this);
updateLocalServerList();
updateRemoteServerList();
super.bind(model);
}
@Override
public void unbind() {
// Shutting down
finder.removeAnnouncementListener(this);
finder.dispose();
super.unbind();
}
public JButton getCancelButton() {
return (JButton) getComponent("cancelButton");
}
public void initCancelButton() {
getCancelButton().addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
accepted = false;
dialog.closeDialog();
}
});
}
public void initOKButton() {
getOKButton().addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
handleOK();
}
});
}
public boolean accepted() {
return accepted;
}
public JComboBox<String> getRoleComboBox() {
return (JComboBox<String>) getComponent("@role");
}
public void initRoleComboBox() {
getRoleComboBox().setModel(new DefaultComboBoxModel<String>(new String[] { "Player", "GM" }));
}
public void initLocalServerList() {
getLocalServerList().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
getLocalServerList().addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
handleOK();
}
};
});
}
public JList<RegisteredServer> getLocalServerList() {
return (JList<RegisteredServer>) getComponent("localServerList");
}
private void updateLocalServerList() {
finder.find();
}
private void updateRemoteServerList() {
new SwingWorker<Object, Object>() {
RemoteServerTableModel model = null;
@Override
protected Object doInBackground() throws Exception {
model = new RemoteServerTableModel(T3Registry.findAllInstances());
return null;
}
@Override
protected void done() {
if (model != null) {
getRemoteServerTable().setModel(model);
}
TableColumn column = getRemoteServerTable().getColumnModel().getColumn(1);
column.setPreferredWidth(70);
column.setMaxWidth(70);
column.setCellRenderer(new DefaultTableCellRenderer() {
{
setHorizontalAlignment(RIGHT);
}
});
}
}.execute();
}
public void initRemoteServerTable() {
getRemoteServerTable().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
getRemoteServerTable().setModel(new RemoteServerTableModel(Collections.EMPTY_LIST));
getRemoteServerTable().addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
JTable rem = getRemoteServerTable();
getServerNameTextField().setText(rem.getModel().getValueAt(rem.getSelectedRow(), 0).toString());
if (e.getClickCount() == 2)
handleOK();
}
};
});
}
public JTable getRemoteServerTable() {
return (JTable) getComponent("aliasTable");
}
public JButton getRescanButton() {
return (JButton) getComponent("rescanButton");
}
public JButton getRefreshButton() {
return (JButton) getComponent("refreshButton");
}
public void initRescanButton() {
getRescanButton().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
((DefaultListModel<RegisteredServer>) getLocalServerList().getModel()).clear();
finder.find();
}
});
}
public void initRefreshButton() {
getRefreshButton().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateRemoteServerList();
}
});
}
public JTextField getUsernameTextField() {
return (JTextField) getComponent("@username");
}
public JTextField getPortTextField() {
return (JTextField) getComponent("@port");
}
public JTextField getHostTextField() {
return (JTextField) getComponent("@host");
}
public JTextField getServerNameTextField() {
return (JTextField) getComponent("@serverName");
}
public JTabbedPane getTabPane() {
return (JTabbedPane) getComponent("tabPane");
}
private void handleOK() {
String username = getUsernameTextField().getText().trim();
if (username.length() == 0) {
TabletopTool.showError("ServerDialog.error.username"); //$NON-NLS-1$
return;
}
getUsernameTextField().setText(username);
String externalAddress = "Unknown";
try {
externalAddress = T3Registry.getAddress();
} catch (Exception e) {
// Oh well, might not be connected
}
// System.out.println("External address is: " + externalAddress);
JComponent selectedPanel = (JComponent) getTabPane().getSelectedComponent();
if (SwingUtil.hasComponent(selectedPanel, "lanPanel")) {
if (getLocalServerList().getSelectedIndex() < 0) {
TabletopTool.showError("ServerDialog.error.server"); //$NON-NLS-1$
return;
}
// OK
RegisteredServer info = getLocalServerList().getSelectedValue();
port = info.getPort();
hostname = info.getAddress();
}
if (SwingUtil.hasComponent(selectedPanel, "directPanel")) {
// TODO: put these into a validation method
if (getPortTextField().getText().length() == 0) {
TabletopTool.showError("ServerDialog.error.port");
return;
}
int portTemp = -1;
try {
portTemp = Integer.parseInt(getPortTextField().getText());
} catch (NumberFormatException nfe) {
TabletopTool.showError("ServerDialog.error.port");
return;
}
String host = getHostTextField().getText().trim();
if (host.length() == 0) {
TabletopTool.showError("ServerDialog.error.server");
return;
}
getHostTextField().setText(host);
// OK
port = portTemp;
hostname = host;
}
if (SwingUtil.hasComponent(selectedPanel, "tabletoptoolPanel")) {
int row=getRemoteServerTable().getSelectedRow();
RegisteredServer rs=((RemoteServerTableModel)getRemoteServerTable().getModel()).servers.get(row);
hostname = rs.getAddress();
try {
port = rs.getPort();
} catch (NumberFormatException nfe) {
TabletopTool.showError("ServerDialog.error.portNumberException");
return;
}
}
try {
InetAddress server = InetAddress.getByName(hostname);
InetAddress extAddress = InetAddress.getByName(externalAddress);
if (extAddress != null && extAddress.equals(server)) {
boolean yes = TabletopTool.confirm("ConnectToServerDialog.warning.doNotUseExternalAddress", I18N.getString("menu.file"), I18N.getString("action.showConnectionInfo"));
if (!yes)
return;
}
} catch (UnknownHostException e) {
// If an exception occurs, don't bother doing the comparison. But otherwise it's not an error.
}
if (commit()) {
accepted = true;
dialog.closeDialog();
}
}
@Override
public boolean commit() {
ConnectToServerDialogPreferences prefs = new ConnectToServerDialogPreferences();
// Not bindable .. yet
prefs.setTab(getTabPane().getSelectedIndex());
return super.commit();
}
private static class RemoteServerTableModel extends AbstractTableModel {
private final List<RegisteredServer> servers;
public RemoteServerTableModel(List<RegisteredServer> servers) {
// Simple but sufficient
Collections.sort(servers, new Comparator<RegisteredServer>() {
@Override
public int compare(RegisteredServer s1, RegisteredServer s2) {
return String.CASE_INSENSITIVE_ORDER.compare(s1.getName(), s2.getName());
}
});
this.servers = servers;
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return I18N.getText("ConnectToServerDialog.msg.headingServer");
case 1:
return I18N.getText("ConnectToServerDialog.msg.headingVersion");
case 2:
return I18N.getText("ConnectToServerDialog.msg.numberOfPlayers");
}
return "";
}
@Override
public int getColumnCount() {
return 3;
}
@Override
public int getRowCount() {
return servers.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch(columnIndex) {
case 0:
return servers.get(rowIndex).getName();
case 1:
return servers.get(rowIndex).getT3Version();
case 2:
return servers.get(rowIndex).getNumberOfPlayers();
}
return "";
}
}
// ANNOUNCEMENT LISTENER
@Override
public void serviceAnnouncement(String type, InetAddress address, int port, byte[] data) {
((DefaultListModel<RegisteredServer>) getLocalServerList().getModel()).addElement(new RegisteredServer(new String(data), address.getHostAddress(), port,"unknown",0));
}
}