/*
(C) 2007-2012 yura.net
This file is part of Lobby.
Lobby 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 3 of the License
Lobby 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, see <http://www.gnu.org/licenses/>.
*/
package net.yura.lobby.client;
import java.applet.Applet;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.Vector;
import java.util.prefs.Preferences;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.AbstractCellEditor;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.OverlayLayout;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.event.MouseInputAdapter;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import net.yura.lobby.client.eyecandy.TranslucentJButton;
import net.yura.lobby.client.eyecandy.TranslucentJPanel;
import net.yura.lobby.client.eyecandy.TranslucentJScrollPane;
import net.yura.lobby.client.eyecandy.TranslucentJTable;
import net.yura.lobby.client.eyecandy.TranslucentJTree;
import net.yura.lobby.model.Game;
import net.yura.lobby.model.GameType;
import net.yura.lobby.model.Player;
import net.yura.lobby.util.TimeoutUtil;
public class LobbyClientGUI extends JPanel implements ActionListener,LobbyClient,TreeSelectionListener { // ,MouseListener,KeyListener
private static final String appName = "LobbySwingGUI";
private static final String appVersion = "1";
private static String CONFIG_FILENAME = "LobbyClient.conf";
private static final String NOTLOGGEDIN_PANEL = "notlogged";
private static final String LOGGEDIN_PANEL = "logged";
private CardLayout cardlayout;
private JPanel playersactions;
private BufferedImage backpic;
private BufferedImage logopic;
private ImageIcon backpicIcon;
private Color themeColor;
private JTree gameTypes;
private JTable games;
private GameTableModel gamesModel;
private JComponent glass;
private JInternalFrame logbox;
private JInternalFrame loadingbox;
private JTextArea connectlog;
private Connection mycom;
private Map lobbyGamePool;
// map of ALL games by gameType stored in vectors
// ALL games are in the pool
// the ones with getLobbyGameMoveListener()==null can be got and reused
private Map activegames;
// this is a map of avtive games, by game id
private Map privatechats;
private String myusername;
private int playerType;
private JLabel myusernameLabel;
private ChatBox chatwindow;
private PlayerList playerswindow;
private JPanel messages;
private static Applet applet;
private static URL codeBase;
private Preferences prefs=null;
private final int GAME_COL = 1;
private Properties config;
private static Thread loadFileThread;
private static URL inputFileName;
private static InputStream inputFileStream;
public LobbyClientGUI(Applet a,URL cb) {
applet = a;
codeBase = cb;
loadFileThread = new Thread() {
public void run() {
synchronized(this) {
try { this.wait(); }
// this happens when the applet is told to shut down
catch(InterruptedException ex) { ex.printStackTrace(); return; }
}
while(true) {
try {
inputFileStream = inputFileName.openStream();
}
catch(Throwable ex) {
//ex.printStackTrace();
}
synchronized(this) {
synchronized(inputFileName) {
inputFileName.notify();
}
try { this.wait(); }
catch(InterruptedException ex){ ex.printStackTrace(); return; }
}
}
}
};
loadFileThread.start();
super.setVisible(false);
config = new Properties();
config.setProperty("default.port","1964");
config.setProperty("default.host","lobby.yura.net");
config.setProperty("default.mode","debug");
String uuid;
try {
// TODO load and store for user.home instead of app dir.
config.load( new URL( cb, CONFIG_FILENAME ).openStream() );
uuid = config.getProperty("uuid");
if (uuid == null) {
if (applet == null) {
throw new RuntimeException("config file has no uuid");
}
else {
// TODO in applet mode create temp uuid, find a better way to do this
uuid = UUID.randomUUID().toString();
}
}
}
catch (Exception ex) {
// create new client uuid and store it
uuid = UUID.randomUUID().toString();
config.setProperty("uuid",uuid);
// can not find file, no problem, try and make it
try {
config.store( new FileOutputStream( CONFIG_FILENAME ), "Lobby Client Config file" );
}
catch (Exception ex2) {
// cant make it, no problem
}
}
// load the default images first!
try {
backpic = ImageIO.read( this.getClass().getResource( "back.jpg" ) );
logopic = ImageIO.read( this.getClass().getResource( "logo.png" ) );
backpicIcon = new ImageIcon(backpic);
themeColor = Color.RED;
}
catch (Exception e) {
throw new RuntimeException("cant find default images",e);
}
// now check if there are any custom images to load from the config file
setLobbyArt( config.getProperty("default.back"),config.getProperty("default.logo"),config.getProperty("default.color") );
try {
prefs = Preferences.userNodeForPackage( getClass() );
}
catch(Exception e) {
// it must be in applet mode
}
lobbyGamePool = new HashMap();
activegames = new HashMap();
privatechats = new HashMap();
setLayout(new BorderLayout());
JSplitPane top = new JSplitPane();
JSplitPane bottom = new JSplitPane();
JSplitPane main = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
main.setTopComponent(top);
main.setBottomComponent(bottom);
main.setResizeWeight(0.5);
add(main);
getRidOfColor(main);
getRidOfColor(top);
getRidOfColor(bottom);
//top.setDividerSize(20);
//bottom.setDividerSize(20);
//main.setDividerSize(20);
//setBackground(Color.BLUE);
//top.setBackground(null);
//bottom.setBackground(null);
//main.setBackground(null);
//top.setOpaque(false);
//bottom.setOpaque(false);
//main.setOpaque(false);
//((BasicSplitPaneUI) top.getUI()).getDivider().setBackground(null);
//((BasicSplitPaneUI) bottom.getUI()).getDivider().setBackground(null);
//((BasicSplitPaneUI) main.getUI()).getDivider().setBackground(null);
// System.out.println( ((BasicSplitPaneUI)main.getUI()).getDivider() );
// System.out.println( main.isOpaque() +" " +
// ((BasicSplitPaneUI)main.getUI()).getDivider().isOpaque() );
// System.out.println( findParentFrame(
// ((BasicSplitPaneUI)main.getUI()).getDivider() ) );
//lobbyPlayersList = new DefaultListModel();
//gamesModel = new GamesModel()
gameTypes = new TranslucentJTree(0.4f);
gameTypes.setRootVisible(false);
gameTypes.addTreeSelectionListener(this);
gameTypes.setCellRenderer(new TreeRenderer());
gamesModel = new GameTableModel();
games = new TranslucentJTable(gamesModel,0.5f) {
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
if (c instanceof JComponent) {
JComponent jc = (JComponent) c;
Game game = (Game)gamesModel.getDataVector().get(row);
StringBuffer buffer = new StringBuffer();
buffer.append( "<html>" );
buffer.append("Description: ");
buffer.append( getLobbyGame(game.getType(),false).getGameDescription(game.getOptions()) );
buffer.append("<br>");
buffer.append("ID: ");
buffer.append(game.getId());
buffer.append("<br>");
buffer.append("WhosTurn: ");
buffer.append(game.getWhosTurn());
buffer.append("<br>");
buffer.append("Players: ");
buffer.append(game.getPlayers());
buffer.append("<br>");
// Iterator it = game.getPlayers().iterator();
// while (it.hasNext()) {
// buffer.append( ( (Player)it.next() ).getName() );
// buffer.append( "<br>" );
// }
jc.setToolTipText( buffer.toString() );
if (!(jc instanceof TranslucentJButton) && game.getWhosTurn()!=null && !"".equals(game.getWhosTurn()) && !game.getPlayers().contains(new Player(game.getWhosTurn(), 0))) {
jc.setBackground(Color.RED);
jc.setOpaque(true);
}
}
return c;
}
};
/*
{
public Component prepareRenderer(TableCellRenderer renderer,int row, int col) {
Component comp = super.prepareRenderer(renderer, row, col);
JComponent jcomp = (JComponent)comp;
if (comp == jcomp) {
jcomp.setToolTipText((String)getValueAt(row, col));
}
return comp;
}
};
*/
gamesModel.addTableModelListener(games);
games.getTableHeader().setReorderingAllowed(false);
games.getTableHeader().setOpaque(false);
games.getTableHeader().setDefaultRenderer(new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(JTable table,Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c = super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
if(c instanceof JLabel) {
//We get a better looking font if we do not use the default table font.
JLabel label = new JLabel(((JLabel)c).getText());
label.setOpaque(false);
label.setHorizontalAlignment(SwingConstants.CENTER);
if(column==table.getColumnCount()) {
label.setBorder(BorderFactory.createLineBorder(Color.BLACK ));
}
else {
label.setBorder(BorderFactory.createMatteBorder(1,0,1,1,Color.BLACK ));
}
return label;
}
return c;
}
});
games.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
//games.addColumn(new javax.swing.table.TableColumn(0, 32));
games.getColumnModel().getColumn(0).setMaxWidth(32);
games.getColumnModel().getColumn(2).setMaxWidth(50);
games.getColumnModel().getColumn(3).setMaxWidth(50);
games.getColumnModel().getColumn(4).setMaxWidth(50);
games.getColumnModel().getColumn(5).setMaxWidth(50);
games.getColumn("Action").setCellRenderer(new ButtonRenderer());
games.getColumn("Action").setCellEditor(new ButtonEditor());
String DELETE = "del";
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = games.getInputMap(condition);
ActionMap actionMap = games.getActionMap();
// DELETE is a String constant that for me was defined as "Delete"
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), DELETE);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), DELETE);
actionMap.put(DELETE, new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if (playerType >= Player.PLAYER_MODERATOR) {
int[] selections = games.getSelectedRows();
Game[] gamesToRemove = new Game[selections.length];
int startedGameCount = 0;
for (int c = 0; c < selections.length; c++) {
Game game = gamesToRemove[c] = gamesModel.getGame(selections[c]);
if (game.getNumOfPlayers() == game.getMaxPlayers()) {
startedGameCount++;
}
}
if (startedGameCount > 0) {
int result = JOptionPane.showConfirmDialog(LobbyClientGUI.this,
"are you sure, " + startedGameCount + " game is started!",
"Delete Game?", JOptionPane.OK_CANCEL_OPTION);
if (result != JOptionPane.OK_OPTION) {
return;
}
}
for (int c = 0; c < gamesToRemove.length; c++) {
mycom.delGame(gamesToRemove[c].getId());
}
}
}
});
//games.setAutoCreateColumnsFromModel(false);
games.setRowHeight(20);
//gamesModel.addRow( getTableRow( new Game("myname",null,1,2,"ID STRING", Game.STATE_CAN_LEAVE) ) );
JPanel gametypewindow = new TranslucentJPanel(new BorderLayout(),0.5f);
gametypewindow.add( new JLabel(" Game Types:"),BorderLayout.NORTH );
gametypewindow.add( new TranslucentJScrollPane(gameTypes,0.0f));
JButton newgamebutton = new JButton("New Game");
newgamebutton.setActionCommand("newgame");
newgamebutton.addActionListener(this);
JPanel gameactionspanel = new TranslucentJPanel(0.0f);
gameactionspanel.add(newgamebutton);
JPanel gameswindow = new TranslucentJPanel(new BorderLayout(),0.5f);
gameswindow.add( new JLabel(" Games:"),BorderLayout.NORTH );
gameswindow.add(new TranslucentJScrollPane(games,0.2f));
gameswindow.add( gameactionspanel,BorderLayout.SOUTH );
JButton loginbutton = new JButton("Login");
loginbutton.setActionCommand("login");
loginbutton.addActionListener(this);
JButton registerbutton = new JButton("Register");
registerbutton.setActionCommand("register");
registerbutton.addActionListener(this);
JButton setnick = new JButton("Set Nick");
setnick.setActionCommand("setnick");
setnick.addActionListener(this);
JButton setnick2 = new JButton("Set Nick");
setnick2.setActionCommand("setnick");
setnick2.addActionListener(this);
JButton logoutButton = new JButton("Logout");
logoutButton.setActionCommand("logout");
logoutButton.addActionListener(this);
JButton editmyinfoButton = new JButton("Admin");
editmyinfoButton.setActionCommand("admin");
//JButton editmyinfoButton = new JButton("My Info");
//editmyinfoButton.setActionCommand("editinfo");
editmyinfoButton.addActionListener(this);
playersactions = new TranslucentJPanel(0.0f);
cardlayout = new CardLayout();
playersactions.setLayout( cardlayout );
JPanel notloggedinPanel = new JPanel();
notloggedinPanel.setOpaque(false);
notloggedinPanel.add(loginbutton);
notloggedinPanel.add(registerbutton);
notloggedinPanel.add(setnick);
JPanel loggedinPanel = new JPanel();
loggedinPanel.setOpaque(false);
loggedinPanel.add( logoutButton );
loggedinPanel.add( editmyinfoButton );
loggedinPanel.add(setnick2);
playersactions.add( notloggedinPanel , NOTLOGGEDIN_PANEL );
playersactions.add( loggedinPanel , LOGGEDIN_PANEL );
playerswindow = new PlayerList(this);
playerswindow.add( playersactions,BorderLayout.SOUTH );
top.setLeftComponent(gametypewindow);
top.setRightComponent(gameswindow);
mycom = new LobbyCom(uuid, appName, appVersion);
String wait = config.getProperty("wait");
if (wait!=null) {
mycom.setWait( Integer.parseInt(wait) );
}
mycom.addEventListener(this);
chatwindow = new ChatBox(this, null, -1); // TODO magic number
//chatwindow.addActionListener(mycom);
bottom.setLeftComponent(chatwindow);
bottom.setRightComponent(playerswindow);
bottom.setResizeWeight(1.0);
top.setDividerLocation(250);
bottom.setDividerLocation(500);
setBorder(javax.swing.BorderFactory.createEmptyBorder(20, 20, 20, 20));
main.setBorder(javax.swing.BorderFactory.createEmptyBorder(20, 0, 20, 0));
myusernameLabel = new JLabel();
JPanel topInfoPanel = new TranslucentJPanel(0.5f);
topInfoPanel.add( new JLabel("you are logged in as:") );
topInfoPanel.add( myusernameLabel );
JPanel topPanel = new JPanel();
topPanel.setOpaque(false);
topPanel.setLayout( new BorderLayout() );
topPanel.add( javax.swing.Box.createHorizontalStrut(330), BorderLayout.WEST );
topPanel.add( topInfoPanel );
topPanel.setPreferredSize( new Dimension(10, 30) );
add(topPanel, BorderLayout.NORTH);
messages = new TranslucentJPanel(0.5f);
messages.setLayout( new FlowLayout(FlowLayout.LEADING ) );
messages.add( new JLabel("Messages:") );
//messages.setMinimumSize( new Dimension(10, 40) );
messages.setPreferredSize( new Dimension(10, 40) );
add(messages, BorderLayout.SOUTH);
/*
{
public void paintComponent(Graphics g) {
Color oldColor = g.getColor();
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
Composite oldComp = g2d.getComposite();
Composite alphaComp = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, 0.5f);
g2d.setComposite(alphaComp);
g2d.fillRect(0, 0, getWidth(), getHeight());
g.setColor(oldColor);
}
};
games.setOpaque(false);
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {
boolean isSelected = false;
Color selectionColor;
{
selectionColor = games.getSelectionBackground();
setOpaque(false);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
this.isSelected = isSelected;
setOpaque(false);
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
public void paintComponent(Graphics g) {
if (isSelected) {
g.setColor(selectionColor);
g.fillRect(0, 0, getWidth(), getHeight());
}
super.paintComponent(g);
}
};
games.setDefaultRenderer(Object.class, renderer);
playersactions.setOpaque(false);
playerswindow.setOpaque(false);
gameswindow.setOpaque(false);
gametypewindow.setOpaque(false);
inchat.setOpaque(false);
chatwindow.setOpaque(false);
gameactionspanel.setOpaque(false);
//messages.setOpaque(false);
chat.setOpaque(false);
*/
}
private LobbyGameChatListener makeListener(final int id) {
return new LobbyGameChatListener() {
public void sendGameMessage(String message) {
LobbyClientGUI.this.sendGameMessage(id, message);
}
public void sendChat(String text) {
LobbyClientGUI.this.sendChat(id, text);
}
public void join() {
LobbyClientGUI.this.join(id);
}
public void leave() {
LobbyClientGUI.this.leave(id);
}
public void closeGame() {
LobbyClientGUI.this.closeGame(id);
}
public String whoAmI() {
return LobbyClientGUI.this.whoAmI();
}
};
}
// have to use this coz of
// http://forum.java.sun.com/thread.jspa?threadID=5279969
// http://bugs.sun.com/view_bug.do?bug_id=6593830
public static InputStream openStream(String file) throws IOException {
return openStream( new URL(codeBase,file) );
}
public static synchronized InputStream openStream(URL file) throws IOException {
if (applet != null) {
inputFileName = file;
inputFileStream = null;
synchronized (inputFileName) {
synchronized (loadFileThread) {
loadFileThread.notify();
}
try { inputFileName.wait(); }
catch(InterruptedException ex){ex.printStackTrace();}
}
if (inputFileStream==null) {
throw new IOException("cant load file: "+file);
}
return inputFileStream;
}
else {
return file.openStream();
}
}
public static void openURL(URL url) throws Exception {
System.out.println("OPEN URL: "+url);
}
public void paintComponent(Graphics g) {
int w = backpic.getWidth();
int h = backpic.getHeight();
for (int i = 0; i < getWidth(); i += w) for (int j = 0; j < getHeight(); j += h) {
g.drawImage(backpic, i, j, this);
}
g.drawImage(logopic, 0, 0, this);
}
public void setHostName(String host, int port) {
config.setProperty("default.host",host);
config.setProperty("default.port",String.valueOf(port));
}
public void setLobbyArt(String back, String logo,String color) {
if (back!=null && logo!=null && color!=null) {
// not needed to put them in, as here is where they are used
//config.setProperty("default.back",back);
//config.setProperty("default.logo",logo);
//config.setProperty("default.color",logo);
//Gui Stuff
try {
backpic = ImageIO.read(new URL( codeBase, back )); // config.getProperty("default.back")
logopic = ImageIO.read(new URL( codeBase, logo )); // config.getProperty("default.logo")
backpicIcon = new ImageIcon(backpic);
themeColor = Color.decode( color ); // config.getProperty("default.color")
}
catch (Exception e) {
e.printStackTrace();
}
}
}
private void connect() {
connect( config.getProperty("default.host"), Integer.parseInt(config.getProperty("default.port")));
}
public void valueChanged(TreeSelectionEvent e) {
GameType node = getCurrentGameType();
if (node == null) { return; }
mycom.getGames( node );
gamesModel.setDataVector(new Vector());
games.setModel(gamesModel);
}
private GameType getCurrentGameType() {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)gameTypes.getLastSelectedPathComponent();
return (node == null) ? null : (GameType)node.getUserObject();
}
private void makeLoginDialog() {
glass = new JPanel() {
public void paintComponent(Graphics g) {
//super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
g2.setComposite(ac);
g2.setColor( themeColor );
g2.fillRect(0,0,getWidth(),getHeight());
}
};
glass.setOpaque(false);
glass.addMouseListener( new MouseInputAdapter() {} );
getRootPane().getLayeredPane().setLayout( new OverlayLayout( getRootPane().getLayeredPane() ) );
loadingbox = new JInternalFrame("loading...");
JProgressBar loadingbar = new JProgressBar();
loadingbar.setIndeterminate(true);
loadingbox.getContentPane().add( loadingbar );
logbox = new JInternalFrame("connecting...");
JPanel cancelpanel = new JPanel();
JButton cancel = new JButton("Cancel");
cancel.addActionListener(this);
cancel.setActionCommand("exit");
cancelpanel.add( cancel );
connectlog = new JTextArea();
connectlog.setEditable(false);
logbox.getContentPane().add( new JScrollPane( connectlog ) );
logbox.getContentPane().add( cancelpanel , BorderLayout.SOUTH );
//logbox.setSize(400,300);
Dimension d = new Dimension(300, 200);
logbox.setMinimumSize(d);
logbox.setMaximumSize(d);
logbox.setPreferredSize(d);
d = new Dimension(300, 50);
loadingbox.setMinimumSize(d);
loadingbox.setMaximumSize(d);
loadingbox.setPreferredSize(d);
glass.setVisible(false);
logbox.setVisible(false);
loadingbox.setVisible(false);
getRootPane().getLayeredPane().add( glass, JLayeredPane.PALETTE_LAYER );
getRootPane().getLayeredPane().add(logbox , JLayeredPane.MODAL_LAYER);
getRootPane().getLayeredPane().add(loadingbox , JLayeredPane.MODAL_LAYER);
}
private static void getRidOfColor(JSplitPane a) {
a.setBorder( BorderFactory.createEmptyBorder() );
a.setOpaque(false);
a.setDividerSize(20);
a.setContinuousLayout(true);
a.setUI( new BasicSplitPaneUI() {
public BasicSplitPaneDivider createDefaultDivider() {
return new BasicSplitPaneDivider(this) {
public void paint(Graphics g) { }
};
}
} );
//((BasicSplitPaneUI)a.getUI()).getDivider().setBorder(null);
}
public void setUsername(String username,int type) {
myusername = username;
myusernameLabel.setText(username);
playerType = type;
if (type == Player.PLAYER_GUEST) {
cardlayout.show(playersactions,NOTLOGGEDIN_PANEL);
}
else {
cardlayout.show(playersactions,LOGGEDIN_PANEL);
}
/*
TODO:
needs to close the login or register box
as the setUsername indicated a good login, otherwise we would get errors
also save settings from those boxes if needed
if (prefs!=null) {
prefs.put( "username", username );
if (((JCheckBox)message[4]).isSelected()) {
prefs.put( "password", password );
}
else {
prefs.remove( "password");
}
}
*/
}
public void actionPerformed(ActionEvent ae) {
String ac = ae.getActionCommand();
if (ac.equals("exit")) {
exit();
}
else if (ac.equals("login")) {
String username="";
String password="";
if (prefs!=null) {
prefs = Preferences.userNodeForPackage( getClass() );
username = prefs.get( "username" , null);
password = prefs.get( "password" , null);
}
Object[] message = new Object[5];
message[0] = "user name:";
message[1] = new JTextField( username );
message[2] = "password:";
message[3] = new JPasswordField( password );
message[4] = new JCheckBox("save password");
if (prefs==null) { ((JCheckBox)message[4]).setEnabled(false); }
if (password!=null && !"".equals(password)) {
((JCheckBox)message[4]).setSelected(true);
}
String[] options = { "OK", "cancel" };
int result = JOptionPane.showOptionDialog(
this, // the parent that the dialog blocks
message, // the dialog message array
"Login", // the title of the dialog window
JOptionPane.OK_CANCEL_OPTION, // option type
JOptionPane.QUESTION_MESSAGE, // message type
null, // optional icon, use null to use the default icon
options, // options string array, will be made into buttons
options[0] // option that should be made into a default button
);
if (result == JOptionPane.OK_OPTION ) {
username = ((JTextField)message[1]).getText();
password = new String( ((JPasswordField)message[3]).getPassword() );
mycom.login(username,password);
}
}
else if (ac.equals("setnick")) {
String username="";
if (prefs!=null) {
prefs = Preferences.userNodeForPackage( getClass() );
username = prefs.get( "username" , null);
}
Object[] message = new Object[2];
message[0] = "Nick name:";
message[1] = new JTextField( username );
String[] options = { "OK", "cancel" };
int result = JOptionPane.showOptionDialog(
this, // the parent that the dialog blocks
message, // the dialog message array
"Set Nick", // the title of the dialog window
JOptionPane.OK_CANCEL_OPTION, // option type
JOptionPane.QUESTION_MESSAGE, // message type
null, // optional icon, use null to use the default icon
options, // options string array, will be made into buttons
options[0] // option that should be made into a default button
);
if (result == JOptionPane.OK_OPTION ) {
mycom.setNick( ((JTextField)message[1]).getText() );
}
}
else if (ac.equals("register")) {
String username = "";
String email = "";
String password1 = "";
String password2 = "";
boolean savepassword = false;
while (true) {
Object[] message = new Object[9];
message[0] = "user name:";
message[1] = new JTextField( username );
message[2] = "email:";
message[3] = new JTextField( email );
message[4] = "password:";
message[5] = new JPasswordField( password1 );
message[6] = "retype password:";
message[7] = new JPasswordField( password2 );
message[8] = new JCheckBox("save password",savepassword);
if (prefs==null) { ((JCheckBox)message[8]).setEnabled(false); }
String[] options = { "OK", "cancel" };
int result = JOptionPane.showOptionDialog(
this, // the parent that the dialog blocks
message, // the dialog message array
"Register", // the title of the dialog window
JOptionPane.OK_CANCEL_OPTION, // option type
JOptionPane.QUESTION_MESSAGE, // message type
null, // optional icon, use null to use the default icon
options, // options string array, will be made into buttons
options[0] // option that should be made into a default button
);
if (result == JOptionPane.OK_OPTION ) {
username = ((JTextField)message[1]).getText();
email = ((JTextField)message[3]).getText();
password1 = new String( ((JPasswordField)message[5]).getPassword() );
password2 = new String( ((JPasswordField)message[7]).getPassword() );
savepassword = ((JCheckBox)message[8]).isSelected();
//if (!password1.equals(password2)) {
// throw new NotAllowedException("passwords do not match");
//}
//if ("".equals(username) || "".equals(password1) || "".equals(email)) {
// throw new NotAllowedException("can not leave blank fields");
//}
mycom.register(username,email,password1);
break;
}
else {
break;
}
}
}
else if (ac.equals("logout")) {
mycom.logout();
}
else if (ac.equals("editinfo")) {
showInfoDialog(myusername);
}
else if (ac.equals("admin")) {
showAdminWindow();
}
else if (ac.equals("newgame")) {
GameType gametype = getCurrentGameType();
if (gametype!=null) {
LobbyGame lg;
startLoading();
try {
lg = getLobbyGame(gametype,false);
}
finally {
stopLoading();
}
Game newGameOptions = lg.newGameDialog(
(java.awt.Frame)javax.swing.SwingUtilities.getAncestorOfClass(java.awt.Frame.class, this),
gametype.getOptions(),
myusername
);
if (newGameOptions!=null) {
newGameOptions.setType(gametype);
// uncomment for testing private game creation
//newGameOptions.getPlayers().add(new Player(whoAmI(), 0));
mycom.createNewGame(newGameOptions);
}
}
}
else {
System.err.println("unknown command: "+ac);
}
}
private Map playerinfo;
public void setUserInfo(String user,List info) {
PlayerInfoWindow infoWindow = (PlayerInfoWindow)playerinfo.get(user);
infoWindow.updateInfo(info);
}
public void showInfoDialog(String user) {
if (playerinfo==null) {
playerinfo = new HashMap();
}
PlayerInfoWindow infoWindow = (PlayerInfoWindow)playerinfo.get(user);
if (infoWindow == null) {
infoWindow = new PlayerInfoWindow(
this,
user,false);
playerinfo.put(user,infoWindow);
infoWindow.setSize(300,250);
}
infoWindow.setVisible(true);
// mycom.getPlayerInfo(user);
/*
boolean edit = user.equals(myusername);
try {
PlayerInfo info = mycom.getPlayerInfo(user);
Object[] message = new Object[2];
message[0] = new JLabel("Info:");
message[1] = new JTextField( info.getInfo() );
String[] options = {
"OK",
"cancel"
};
int result = JOptionPane.showOptionDialog(
this, // the parent that the dialog blocks
message, // the dialog message array
"info for "+user, // the title of the dialog window
edit?JOptionPane.OK_CANCEL_OPTION:JOptionPane.OK_OPTION, // option type
JOptionPane.PLAIN_MESSAGE, // message type
null, // optional icon, use null to use the default icon
edit?options:new String[] {options[0]}, // options string array, will be made into buttons
options[0] // option that should be made into a default button
);
info.setInfo( ((JTextField)message[1]).getText() );
if (edit && result == JOptionPane.OK_OPTION ) {
mycom.setMyPlayerInfo(info);
}
}
catch(IOException ex) {
disconnected();
}
*/
}
void showAdminWindow() {
Object[] message = {
makeAdminPanel("resignUserFromAllGames",ProtoAccess.REQUEST_RESIGN_FROM_ALL_GAMES, new Param("username",String.class)),
makeAdminPanel("renameUser",ProtoAccess.REQUEST_RENAME_USER, new Param("oldName",String.class),new Param("newName",String.class))
};
JOptionPane.showOptionDialog(this, message, "admin", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
}
private JPanel makeAdminPanel(String label, final String command, final Param... param) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JButton action = new JButton(label);
panel.add(action);
panel.add(new JLabel("("));
final JTextField[] boxes = new JTextField[param.length];
for (int c=0;c<param.length;c++) {
if (c!=0) {
panel.add(new JLabel(","));
}
panel.add(new JLabel(param[c].name+"="));
JTextField box = new JTextField();
box.setMinimumSize(new Dimension(100, box.getMinimumSize().height));
box.setPreferredSize(new Dimension(100, box.getPreferredSize().height));
boxes[c] = box;
panel.add(box);
}
panel.add(new JLabel(")"));
action.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Map params = new HashMap();
for (int c=0;c<param.length;c++) {
params.put(param[c].name, boxes[c].getText());
}
mycom.sendAdminCommand(command, params);
}
});
return panel;
}
static class Param {
public final String name;
public final Class clas;
public Param(String name, Class clas) {
this.name = name;
this.clas = clas;
}
}
private LobbyGame makeLobbyGame(GameType gametype) {
try {
ClassLoader ucl = gametype.getClassLoader( codeBase.toString() );
return (LobbyGame)Class.forName( gametype.getClassName() ,true,ucl).newInstance();
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
}
List getGamePool(GameType gametype) {
List a = (Vector)lobbyGamePool.get(gametype);
// if no games of this type then make a vector and put at least 1 in it
if (a==null) {
a = new Vector();
lobbyGamePool.put(gametype,a);
}
return a;
}
private LobbyGame getLobbyGame(GameType gametype,boolean fresh) {
List a = getGamePool(gametype);
if (a.isEmpty()) {
a.add( makeLobbyGame(gametype) );
}
if (!fresh) {
return (LobbyGame)a.get(0);
}
else {
for (int c=0;c<a.size();c++) {
LobbyGame z = (LobbyGame)a.get(c);
if (z.getLobbyGameMoveListener() == null) {
return z;
}
}
}
LobbyGame game = makeLobbyGame(gametype);
a.add(game);
return game;
}
public static URL getCodeBase() {
return codeBase;
}
public ClassLoader getClassLoader(GameType gameType) {
return gameType.getClassLoader(codeBase.toString());
}
public void savePlayerInfo(String name, List info) {
// mycom.setPlayerInfo(name, info);
}
private void stopLoading() {
glass.setVisible(false);
loadingbox.setVisible(false);
}
/*
public void mouseClicked(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mousePressed(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public void keyPressed(KeyEvent e){}
*/
public void error(String s) {
JOptionPane.showMessageDialog(this, s, "Error", JOptionPane.ERROR_MESSAGE);
}
private void exit() {
if (mycom!=null) { try { mycom.disconnect(); }catch(Exception e) {} }
if (applet==null) {
System.exit(0);
}
}
public void showConnectingDialog(boolean a) {
if (glass == null) { makeLoginDialog(); }
glass.setVisible(a);
logbox.setVisible(a);
}
public void disconnected() {
showConnectingDialog(true);
for (Iterator games = new HashSet(activegames.values()).iterator();games.hasNext();) {
// TODO then will in tern call leavegame, is this ok?
((LobbyGame)games.next()).closegame();
}
}
public void connected() {
mycom.getGameTypes();
// mycom.getMainRoomList();
showConnectingDialog(false);
}
private String server;
private int port;
public void connect(String s,int p) {
server = s;
port = p;
//TODO: Change these strings to global string constants.
if ("debug".equalsIgnoreCase(config.getProperty("default.mode") )) {
// mycom.setLogging(true);
}
else {
// mycom.setLogging(false);
}
mycom.connect(server, port);
}
public void connecting(String a) {
connectlog.append(a+"\n");
connectlog.setCaretPosition(connectlog.getDocument().getLength());
}
private void loadGame(Game game) {
LobbyGame lg = (LobbyGame)activegames.get( new Integer(game.getId()) );
if(lg==null) {
startLoading();
try {
int gameId = game.getId();
GameType gametype = game.getType();
lg = getLobbyGame(gametype,true);
activegames.put(new Integer(gameId),lg);
ChatBox cb = new ChatBox(this,null,gameId);
PlayerList pl = new PlayerList(this);
lg.addLobbyGameMoveListener( makeListener(gameId) );
lg.joinGame(game ,cb,pl);
mycom.playGame(game.getId());
}
finally {
stopLoading();
}
}
else {
System.out.println("game already open: "+game);
// TODO, bring to front, this does not seem to work
//((java.awt.Frame)javax.swing.SwingUtilities.getAncestorOfClass(java.awt.Frame.class, lg.getPlayerList() )).toFront();
}
}
private void startLoading() {
glass.setVisible(true);
loadingbox.setVisible(true);
}
public ChatBox findAndFlashPrivate(final String name,boolean pop) {
ChatBox cb = (ChatBox)privatechats.get(name);
if (cb==null) {
cb=new ChatBox(this,name,-1); // TODO magic number, it will be ignored anyway
//cb.addActionListener(mycom);
privatechats.put(name,cb);
JFrame d = new JFrame("IM with "+name);// (java.awt.Frame)javax.swing.SwingUtilities.getAncestorOfClass(java.awt.Frame.class, this),
cb.setBorder( BorderFactory.createMatteBorder(20, 20, 20, 20, backpicIcon ) );
d.getContentPane().add(cb);
d.setSize(250,300);
}
final JFrame dialog = (JFrame)javax.swing.SwingUtilities.getAncestorOfClass(JFrame.class, cb);
if (dialog.isVisible()) {
if (!dialog.isFocused()) { dialog.requestFocus(); }
}
else if (pop) {
dialog.setVisible(true);
dialog.requestFocus();
}
else {
addNewMessage( new Message( name, "Message from player, click to view" ) {
public void action() {
dialog.setVisible(true);
dialog.requestFocus();
}
} );
}
return cb;
}
abstract class Message {
private String name;
private String tooltip;
public Message(String n,String t) {
name = n;
tooltip = t;
}
public String getName() {
return name;
}
public String getTooltip() {
return tooltip;
}
abstract public void action();
public boolean equals(Object obj) {
return ( name.equals( ((Message)obj).getName() ) );
}
}
private Vector messagesVector = new Vector();
public void addNewMessage(final Message m) {
if (messagesVector.contains(m)){ return; }
final JButton message = new JButton( m.getName() );
message.setToolTipText( m.getTooltip() );
message.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ae) {
m.action();
messages.remove(message);
messages.revalidate();
messages.repaint();
messagesVector.remove(m);
}
} );
messages.add(message);
messages.revalidate();
messages.repaint();
messagesVector.add(m);
((java.awt.Frame)javax.swing.SwingUtilities.getAncestorOfClass(java.awt.Frame.class, this)).requestFocus();
}
// ########################################################
// ######################### interface LobbyGameChatListener
// ########################################################
public void sendGameMessage(int gameid,String message) {
mycom.sendGameMessage(gameid,message);
}
public void sendPrivateChat(String name,String text) {
// mycom.sendPrivateChat(name,text);
}
public void sendChat(int id,String text) {
mycom.sendChat(id,text);
}
/**
* this is called by the open game when the user clicks on the close button
* the user can be a player OR a spectator
*/
public void closeGame(int gameid) {
killGame(gameid);
mycom.closeGame(gameid);
}
void killGame(int gameid) {
LobbyGame gameToLeave = (LobbyGame)activegames.remove( new Integer(gameid) );
// we remove the listener to indicate that it can be reused now
gameToLeave.removeLobbyGameMoveListener(gameToLeave.getLobbyGameMoveListener());
// it is already in the game pool and can now be reused when needed
}
public String whoAmI() {
return myusername;
}
// ########################################################
// ######################### interface LobbyClient ########
// ########################################################
public synchronized void incomingChat(int chatid, String player, String message) {
LobbyGame lg = (LobbyGame)activegames.get(new Integer(chatid));
if (lg!=null) {
lg.getChatBox().incomingChat(player,message);
}
else {
System.out.println("ERROR!!!! chat comming in but there is no active game with that id");
}
}
public void incomingChat(String player, String message) {
chatwindow.incomingChat(player,message);
}
public void privateMessage(String player, String message) {
// @todo: first create a message that we have a message
//pop up a chat window
ChatBox cb = findAndFlashPrivate(player,false);
cb.incomingChat(player,message);
}
public synchronized void addOrUpdateGame(final Game game) {
LobbyGame lobbyGame = ((LobbyGame)activegames.get( new Integer(game.getId()) ));
if (lobbyGame!=null) {
lobbyGame.gameUpdate(game);
}
// TODO remove this
else if ( game.getState(myusername) == Game.STATE_CAN_PLAY) {
addNewMessage( new Message( game.toString(), "New Game Started, click to play" ) {
public void action() {
loadGame( game );
}
} );
}
if (game.getType().equals( getCurrentGameType() )) {
List gameList = gamesModel.getDataVector();
int index = Collections.binarySearch(gameList, game);
if (index >= 0) {
gameList.set(index, game);
gamesModel.fireTableRowsUpdated(index,index);
}
else {
int row = -index -1;
int selected = games.getSelectedRow();
gameList.add(row, game);
// if we added a item before the selection we need to move the selection down
if (selected >= row) {
games.setRowSelectionInterval(selected+1, selected+1);
}
}
games.revalidate();
games.repaint();
}
}
// TODO, get rid of synchronized, and put SwingWorker
public synchronized void addGameType(List list) {
GameType current = getCurrentGameType();
TreePath found=null;
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
for (int c=0;c<list.size();c++) {
GameType gt = (GameType)list.get(c);
DefaultMutableTreeNode gtNode = new DefaultMutableTreeNode(gt);
root.add(gtNode);
if (gt.equals(current)) {
found = new TreePath(gtNode.getPath());
}
//System.out.println("Added: "+gt.toString()+" to the game types");
}
DefaultTreeModel gameTypesModel = new DefaultTreeModel(root);
gameTypes.setModel(gameTypesModel);
if (found!=null) {
gameTypes.setSelectionPath(found);
}
}
public synchronized void removeGame(int gameid) {
Vector gameList = gamesModel.getDataVector();
for(int c = 0;c<gameList.size();c++) {
if( ((Game)gameList.get(c)).getId()==gameid ) {
int selection = games.getSelectedRow();
gamesModel.removeRow(c);
if (selection == c) {
games.clearSelection();
}
else if (selection > c) {
games.setRowSelectionInterval(selection-1, selection-1);
}
games.revalidate();
games.repaint();
return;
}
}
}
@Override
public void gameStarted(int gameId) {
List<Game> games = gamesModel.getDataVector();
for (Game game: games) {
if (game.getId() == gameId) {
loadGame(game);
return;
}
}
}
public void addPlayer(Player player) {
playerswindow.addPlayer(player);
}
public void addPlayer(int chatid, Player player) {
LobbyGame lg = (LobbyGame)activegames.get(new Integer(chatid));
if (lg!=null) {
lg.getPlayerList().addPlayer(player);
}
else {
// create the room and add it to the messages
System.out.println("ERROR!!!! trying to add player when list is not found");
}
}
public void removePlayer(String player) {
playerswindow.removePlayer(player);
}
public void removePlayer(int chatid, String player) {
LobbyGame lg = (LobbyGame)activegames.get(new Integer(chatid));
if (lg!=null) {
lg.getPlayerList().removePlayer(player);
}
else {
System.out.println("Got Nullpointer while removing player from list[LobbyClientGUI->removePlayer()]");
}
}
public void messageForGame(int gameid,Object object) {
LobbyGame lg = (LobbyGame)activegames.get(new Integer(gameid));
if (lg!=null) {
lg.gameMessage(object);
}
else {
System.out.println("got command for game "+gameid+" but that game is not open");
}
}
public void setVisible(boolean a) {
super.setVisible(a);
if (a) {
// this is to say that currently we r NOT connected
disconnected();
connect();
}
else {
exit();
}
}
public void renamePlayer(String oldname, String newname,int newType) {
playerswindow.renamePlayer(oldname,newname,newType);
Iterator games = activegames.values().iterator();
for (LobbyGame game;games.hasNext();) {
game = (LobbyGame)games.next();
game.renamePlayer(oldname, newname, newType);
}
// TODO, this sould NOT be synchronized
// instead should be in the SwingWorker.invokelater thread!
synchronized(privatechats) {
ChatBox cb = (ChatBox)privatechats.remove(oldname);
if(cb != null) {
cb.setChatRoomName(newname,-1); // TODO magic number
privatechats.put(newname,cb);
}
}
}
public void join(int gameid) {
mycom.joinGame( gameid );
}
public void leave(int gameid) {
mycom.leaveGame( gameid );
}
// ########################################################
// ######################### static void main #############
// ########################################################
public static void main(String[] argv) throws Exception {
try {
net.yura.grasshopper.BugManager.intercept();
}
catch(Throwable th) {
System.out.println("Grasshopper not loaded");
}
if (argv.length==1) {
CONFIG_FILENAME = argv[0];
}
// set up system Look&Feel
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {
e.printStackTrace();
}
JFrame gui = new JFrame("yura.net Lobby");
gui.setSize(800, 600);
final LobbyClientGUI mt = new LobbyClientGUI( null, new java.io.File(".").toURI().toURL() );
gui.setContentPane(mt);
// gui.setIconImage(Toolkit.getDefaultToolkit().getImage(
// this.class.getResource("icon.gif") ));
// gui.setResizable(false);
gui.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
// gui.pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = gui.getSize();
frameSize.height = ((frameSize.height > screenSize.height) ? screenSize.height
: frameSize.height);
frameSize.width = ((frameSize.width > screenSize.width) ? screenSize.width
: frameSize.width);
gui.setLocation((screenSize.width - frameSize.width) / 2,
(screenSize.height - frameSize.height) / 2);
gui.setVisible(true);
// THIS IS CRAZY CONNECT DISCONNECT STUFF
gui.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(WindowEvent evt) {
//mt.exit();
mt.setVisible(false);
}
});
//mt.connect();
mt.setVisible(true);
//mt.connect("localhost", 1964);
//mt.connect("192.168.1.80",1964);
//mt.connect("colbertff.selfip.org", 1964);
}
public static JButton setupButton(JButton button, int a) {
switch( a ) {
case Game.STATE_CAN_JOIN: button.setActionCommand("J"); button.setText("join"); button.setBackground( Color.GREEN ); break;
case Game.STATE_CAN_LEAVE: button.setActionCommand("L"); button.setText("leave"); button.setBackground( Color.RED ); break;
case Game.STATE_CAN_WATCH: button.setActionCommand("W"); button.setText("watch"); button.setBackground( Color.WHITE ); break;
case Game.STATE_CAN_PLAY: button.setActionCommand("W"); button.setText("play"); button.setBackground( Color.BLUE ); break;
}
return button;
}
class TreeRenderer implements TreeCellRenderer {
public Component getTreeCellRendererComponent(JTree tree,Object value,final boolean selected,boolean expanded,boolean leaf,int row, boolean hasFocus) {
JLabel label = new JLabel(value.toString()) {
public void paintComponent(Graphics g) {
if(selected) {
Color oldColor = g.getColor();
Graphics2D g2d = (Graphics2D)g;
Composite oldComp = g2d.getComposite();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f));
g2d.setColor(getBackground());
g2d.fillRect(0,0,getWidth(),getHeight());
g2d.setColor(oldColor);
g2d.setComposite(oldComp);
super.paintComponent(g);
}
else {
super.paintComponent(g);
}
}
};
if(leaf) {
label.setIcon((Icon)UIManager.get("Tree.leafIcon"));
}
else {
if(expanded) {
label.setIcon((Icon)UIManager.get("Tree.openIcon"));
}
else {
label.setIcon((Icon)UIManager.get("Tree.closedIcon"));
}
}
return label;
}
}
class GameTableModel extends DefaultTableModel {
private final String[] colnames = new String[] {"Icon","Name","In Game","Timeout","Players","Action"};
public GameTableModel() {
setColumnIdentifiers( colnames );
}
public boolean isCellEditable(int row, int column) {
if (column == 1) {
return playerType >= Player.PLAYER_MODERATOR;
}
return (column== (colnames.length-1) );
}
public void setDataVector(Vector objects) {
dataVector = objects;
games.revalidate();
games.repaint();
}
public Class getColumnClass(int c) {
//System.out.println(c+" "+ getValueAt(0, c).getClass() );
//return getValueAt(0, c).getClass();
// changed to get fid of nullpointer sometimes
if (c==0) {
return javax.swing.ImageIcon.class;
}
return String.class;
}
public String getColumnName(int column) {
return colnames[column];
}
public int getColumnCount() {
return colnames.length;
}
public Object getValueAt(int row, int column) {
Game game = getGame(row);
switch (column) {
case 0: return getLobbyGame(game.getType(),false).getIcon(game.getOptions());
case 1: return game;
case 2: return new Integer( game.getInGame() );
case 3: return TimeoutUtil.formatPeriod( game.getTimeout()*1000L );
case 4: return game.getNumOfPlayers()+"/"+game.getMaxPlayers();
case 5: return new Integer( game.getState(myusername) );
default: throw new RuntimeException();
}
}
@Override
public void setValueAt(Object aValue, int row, int column) {
if (column == 1) {
if (playerType >= Player.PLAYER_MODERATOR) {
Game game = getGame(row);
String newName = (String) aValue;
if (!game.getName().equals(newName)) {
game.setName(newName);
mycom.createNewGame(game);
}
}
}
else {
super.setValueAt(aValue, row, column);
}
}
public Game getGame(int row) {
return (Game)dataVector.get(row);
}
}
class ButtonRenderer implements TableCellRenderer {
private JButton button;
public ButtonRenderer() {
button = new TranslucentJButton(0.6f);
button.setMargin( new Insets(0,0,0,0) );
button.setBorder(BorderFactory.createEmptyBorder());
button.setContentAreaFilled(false);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
JButton button2 = setupButton( button, ((Integer)value).intValue() );
return button2;
}
}
class ButtonEditor extends AbstractCellEditor implements TableCellEditor,ActionListener {
private JButton button = new TranslucentJButton(0.6f);
private Game game;
public ButtonEditor() {
button.addActionListener(this);
button.setMargin( new Insets(0,0,0,0) );
}
public void actionPerformed(ActionEvent ae) {
String a = ae.getActionCommand();
if (a.equals("J")) {
join( game.getId() );
}
else if (a.equals("L")) {
leave( game.getId() );
}
else if (a.equals("W")) {
loadGame(game);
}
else {
System.err.println("unknown command "+a);
}
cancelCellEditing();
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
// editing started, need to know what game object we r editing, so the button can use it
game = (Game)table.getValueAt(row,GAME_COL);
JButton button2 = setupButton( button, ((Integer)value).intValue() );
return button2;
}
public Object getCellEditorValue() {
throw new RuntimeException(); // editing should always get cancelled
}
public boolean stopCellEditing() { // when ever it stops, just cancel it so no update happens
cancelCellEditing();
return true;
}
}
}