package net.sf.colossus.webclient; import java.text.DateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; import java.util.TimeZone; import java.util.Vector; import javax.swing.table.AbstractTableModel; import net.sf.colossus.webcommon.GameInfo; import net.sf.colossus.webcommon.GameInfo.GameState; import net.sf.colossus.webcommon.User; public class GameTableModel extends AbstractTableModel { private final String[] columnNames = { "#", "state", "by", "when", "duration", "info", "Variant", "Viewmode", "Expire", "Options", "Teleport", "min", "target", "max", "actual", "players", "online" }; private final Vector<GameInfo> data = new Vector<GameInfo>(17, 1); private final HashMap<String, Integer> rowIndex = new HashMap<String, Integer>(); private final Locale myLocale; public GameTableModel(Locale myLocale) { super(); this.myLocale = myLocale; } public int getColumnCount() { return columnNames.length; } public int getRowCount() { return data.size(); } @Override public String getColumnName(int col) { return columnNames[col]; } public Object getValueAt(int row, int col) { int rows = data.size(); if (row >= rows) { return "-"; } GameInfo gi = data.get(row); if (gi == null) { return "-"; } Object o = null; switch (col) { case 0: o = gi.getGameId(); break; case 1: o = gi.getStateString(); break; case 2: o = gi.getInitiator(); break; case 3: if (gi.isScheduledGame()) { o = humanReadableTime(gi.getStartTime()); } else { o = "-instantly-"; } break; case 4: o = gi.getDuration().toString() + " min."; break; case 5: o = gi.getSummary(); break; case 6: o = gi.getVariant(); break; case 7: o = gi.getViewmode(); break; case 8: o = gi.getEventExpiring(); break; case 9: o = gi.getGameOptionsFlagsString(); break; case 10: o = gi.getTeleportOptionsFlagsString(); break; case 11: o = gi.getMin(); break; case 12: o = gi.getTargetInteger(); break; case 13: o = gi.getMax(); break; case 14: o = gi.getEnrolledCount(); break; case 15: o = gi.getPlayerListAsString(); break; case 16: o = Integer.valueOf(gi.getOnlineCount()); break; } return o; } @Override public Class<?> getColumnClass(int col) { Class<?> c = String.class; switch (col) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: c = String.class; break; case 9: case 10: // c = Boolean.class; c = String.class; break; case 11: case 12: case 13: case 14: case 16: c = Integer.class; break; case 15: c = String.class; break; } return c; } // TableModel forces us into casting @SuppressWarnings("unchecked") @Override public void setValueAt(Object value, int row, int col) { if (col == -1) { setRowAt(value, row); return; } GameInfo gi = data.get(row); if (gi == null) { gi = new GameInfo("", false); } switch (col) { case 0: gi.setGameId((String)value); break; /* case 0: String gameId = (String) value; gi.setGameId(gameId); rowIndex.put(gameId, new Integer(row)); break; */ case 1: GameState gameState = GameState.valueOf((String)value); gi.setState(gameState); break; case 2: gi.setInitiator((String)value); break; case 3: gi.setStartTime((String)value); break; case 4: gi.setDuration((String)value); break; case 5: gi.setSummary((String)value); break; case 6: gi.setVariant((String)value); break; case 7: gi.setViewmode((String)value); break; case 8: gi.setEventExpiring((String)value); break; case 9: gi.setUnlimitedMulligans(((Boolean)value).booleanValue()); break; case 10: gi.setUnlimitedMulligans(((Boolean)value).booleanValue()); break; case 11: gi.setMin((Integer)value); break; case 12: gi.setTarget((Integer)value); break; case 13: gi.setMax((Integer)value); break; case 14: gi.setEnrolledCount((Integer)value); break; case 15: gi.setPlayerList((ArrayList<User>)value); break; case 16: gi.setOnlineCount(((Integer)value).intValue()); break; } fireTableCellUpdated(row, col); } public String getOptionsTooltipText(int row) { return data.get(row).GetOptionsTooltipText(); } public String getTeleportOptionsTooltipText(int row) { return data.get(row).GetTeleportOptionsTooltipText(); } public int addGame(GameInfo gi) { int nextIndex = data.size(); data.add(gi); String gameId = gi.getGameId(); rowIndex.put(gameId, Integer.valueOf(nextIndex)); fireTableRowsUpdated(nextIndex, nextIndex); return nextIndex; } // Note that webclient state change code relies on the fact that calling // this for a game that is not in the table does not harm nor complain! public void removeGame(String gameId) { int index = this.findRowIndex(gameId); if (index != -1) { data.remove(index); rowIndex.remove(gameId); redoRowIndices(); fireTableRowsDeleted(index, index); } else { // no problem. For example on login client gets told all the // running games and client tries to remove them from pot table // but they are not there... } } public void resetTable() { int size = data.size(); if (size > 0) { data.clear(); rowIndex.clear(); fireTableRowsDeleted(0, size - 1); } } public void redoRowIndices() { rowIndex.clear(); int size = data.size(); int i = 0; while (i < size) { GameInfo gi = data.get(i); String gameId = gi.getGameId(); rowIndex.put(gameId, Integer.valueOf(i)); i++; } } public void setRowAt(Object value, int row) { GameInfo gi = (GameInfo)value; String gameId = gi.getGameId(); rowIndex.put(gameId, Integer.valueOf(row)); data.set(row, gi); fireTableRowsUpdated(row, row); } public int findRowIndex(String gameId) { Integer iI = rowIndex.get(gameId); if (iI == null) { return -1; } else { return iI.intValue(); } } public Integer getRowIndex(GameInfo gi) { Integer index = rowIndex.get(gi.getGameId()); if (index == null) { index = Integer.valueOf(data.size()); int row = index.intValue(); data.add(gi); rowIndex.put(gi.getGameId(), Integer.valueOf(row)); fireTableRowsInserted(row, row); } return index; } private String humanReadableTime(Long startTime) { String timeString = ""; DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, myLocale); df.setTimeZone(TimeZone.getDefault()); df.setLenient(false); timeString = df.format(startTime); return timeString; } }