/** * Copyright (C) 2002-2012 The FreeCol Team * * This file is part of FreeCol. * * FreeCol 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. * * FreeCol 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 FreeCol. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.freecol.client.gui.panel; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.logging.Logger; import org.freecolandroid.repackaged.java.awt.Component; import org.freecolandroid.repackaged.java.awt.event.ActionEvent; import org.freecolandroid.repackaged.java.awt.event.ActionListener; import org.freecolandroid.repackaged.javax.swing.JButton; import org.freecolandroid.repackaged.javax.swing.JScrollPane; import org.freecolandroid.repackaged.javax.swing.JTable; import org.freecolandroid.repackaged.javax.swing.ListSelectionModel; import org.freecolandroid.repackaged.javax.swing.table.AbstractTableModel; import org.freecolandroid.repackaged.javax.swing.table.DefaultTableCellRenderer; import net.miginfocom.swing.MigLayout; import net.sf.freecol.FreeCol; import net.sf.freecol.client.FreeColClient; import net.sf.freecol.client.control.ConnectController; import net.sf.freecol.client.gui.GUI; import net.sf.freecol.client.gui.i18n.Messages; import net.sf.freecol.common.ServerInfo; /** * This panel is used to display the information received from the meta-server. */ public final class ServerListPanel extends FreeColPanel implements ActionListener { private static final Logger logger = Logger.getLogger(ServerListPanel.class.getName()); private static final int CONNECT = 0, CANCEL = 1; private final ConnectController connectController; private final JTable table; private final ServerListTableModel tableModel; private String username; private JButton connect; /** * The constructor that will add the items to this panel. * * @param parent The parent of this panel. * @param connectController The controller responsible for creating new * connections. */ public ServerListPanel(FreeColClient freeColClient, GUI gui, ConnectController connectController) { super(freeColClient, gui); this.connectController = connectController; JButton cancel = new JButton("Cancel"); JScrollPane tableScroll; setCancelComponent(cancel); connect = new JButton(Messages.message("connect")); tableModel = new ServerListTableModel(new ArrayList<ServerInfo>()); table = new JTable(tableModel); DefaultTableCellRenderer dtcr = new DefaultTableCellRenderer() { public Component getTableCellRendererComponent(JTable t, Object o, boolean isSelected, boolean hasFocus, int row, int column) { setOpaque(isSelected); return super.getTableCellRendererComponent(t, o, isSelected, hasFocus, row, column); } }; for (int i = 0; i < table.getColumnModel().getColumnCount(); i++) { table.getColumnModel().getColumn(i).setCellRenderer(dtcr); } table.setRowHeight(22); table.setCellSelectionEnabled(false); table.setRowSelectionAllowed(true); table.setColumnSelectionAllowed(false); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tableScroll = new JScrollPane(table); table.addNotify(); tableScroll.getViewport().setOpaque(false); tableScroll.getColumnHeader().setOpaque(false); connect.setActionCommand(String.valueOf(CONNECT)); connect.addActionListener(this); cancel.setActionCommand(String.valueOf(CANCEL)); cancel.addActionListener(this); setLayout(new MigLayout("", "", "")); add(tableScroll, "width 400:, height 350:"); add(connect, "newline 20, split 2"); add(cancel, "tag cancel"); setSize(getPreferredSize()); } public void requestFocus() { connect.requestFocus(); } /** * Initializes the data that is displayed in this panel. * * @param username The username to be used when connecting to a server. * @param arrayList A list of <code>ServerInfo</code>-objects to be * displayed. */ public void initialize(String username, ArrayList<ServerInfo> arrayList) { this.username = username; // TODO: This should be added as a filtering rule: // Remove servers with an incorrect version from the list: Iterator<ServerInfo> it = arrayList.iterator(); while (it.hasNext()) { ServerInfo si = it.next(); if (!si.getVersion().equals(FreeCol.getVersion())) { it.remove(); } } tableModel.setItems(arrayList); setEnabled(true); if (arrayList.size() == 0) { connect.setEnabled(false); } else { table.setRowSelectionInterval(0, 0); } } /** * Sets whether or not this component is enabled. It also does this for its * children. * * @param enabled 'true' if this component and its children should be * enabled, 'false' otherwise. */ public void setEnabled(boolean enabled) { super.setEnabled(enabled); Component[] components = getComponents(); for (int i = 0; i < components.length; i++) { components[i].setEnabled(enabled); } table.setEnabled(enabled); } /** * This function analyses an event and calls the right methods to take care * of the user's requests. * * @param event The incoming ActionEvent. */ public void actionPerformed(ActionEvent event) { String command = event.getActionCommand(); try { switch (Integer.valueOf(command).intValue()) { case CONNECT: ServerInfo si = tableModel.getItem(table.getSelectedRow()); connectController.joinMultiplayerGame(username, si.getAddress(), si.getPort()); break; case CANCEL: getGUI().removeFromCanvas(this); getGUI().showNewPanel(); break; default: logger.warning("Invalid Actioncommand: invalid number."); } } catch (NumberFormatException e) { logger.warning("Invalid Actioncommand: not a number."); } } /** * Refreshes the table. */ public void refreshTable() { tableModel.fireTableDataChanged(); } } class ServerListTableModel extends AbstractTableModel { private static final String[] columnNames = { Messages.message("name"), Messages.message("host"), Messages.message("port"), Messages.message("players"), Messages.message("gameState"), }; private List<ServerInfo> items; public ServerListTableModel(List<ServerInfo> items) { this.items = items; } /** * Sets the items that should be contained by this model. * * @param items The <code>ArrayList</code> containing the items. */ public void setItems(List<ServerInfo> items) { this.items = items; } /** * Gets the given item. * * @param row The row-number identifying a <code>ServerInfo</code>-line. * @return The <code>ServerInfo</code>. */ public ServerInfo getItem(int row) { return items.get(row); } /** * Returns the amount of columns in this statesTable. * * @return The amount of columns in this statesTable. */ public int getColumnCount() { return columnNames.length; } /** * Returns the name of the specified column. * * @return The name of the specified column. */ public String getColumnName(int column) { return columnNames[column]; } /** * Returns the amount of rows in this statesTable. * * @return The amount of rows in this statesTable. */ public int getRowCount() { return items.size(); } /** * Returns the value at the requested location. * * @param row The requested row. * @param column The requested column. * @return The value at the requested location. */ public Object getValueAt(int row, int column) { if ((row < getRowCount()) && (column < getColumnCount()) && (row >= 0) && (column >= 0)) { ServerInfo si = items.get(row); switch (column) { case 0: return si.getName(); case 1: return si.getAddress(); case 2: return Integer.toString(si.getPort()); case 3: return Integer.toString(si.getCurrentlyPlaying()) + "/" + Integer.toString(si.getCurrentlyPlaying() + si.getSlotsAvailable()); case 4: return Messages.message("gameState." + Integer.toString(si.getGameState())); default: return null; } } return null; } }