package net.sf.colossus.webclient; import java.awt.BorderLayout; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Date; import java.util.LinkedList; import java.util.logging.Logger; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingUtilities; import net.sf.colossus.util.HTMLColor; import net.sf.colossus.webcommon.FormatWhen; import net.sf.colossus.webcommon.IWebServer; public class ChatHandler { private static final Logger LOGGER = Logger.getLogger(ChatHandler.class .getName()); private final static String chatSubmitButtonText = "Submit"; private final static int textAreaHeight = 20; private final String id; private final String title; private String username; private IWebServer server = null; private final JPanel chatTab; private final JButton chatSubmitButton; private final JTextArea displayArea; private final JScrollPane displayScrollPane; private final JScrollBar displayScrollBar; private final JTextField newMessage; private final FormatWhen whenFormatter; private boolean loginState = false; private long lastMsgWhen = -1; private boolean resentMode = false; private long afterResentWhen = -1; private String afterResentSender = null; private String afterResentMessage = null; private final static String dashes = "--------------------"; private final static String doubledashes = "========================="; private final LinkedList<String> history = new LinkedList<String>(); private static final int MAX_HISTORY = 100; private int posInHistory = -1; private String unsentMessage = ""; public ChatHandler(String id, String title, IWebServer server, String username) { this.id = id; this.title = title; this.server = server; this.username = username; whenFormatter = new FormatWhen(); chatTab = new JPanel(new BorderLayout()); displayArea = new JTextArea(); displayArea.setRows(textAreaHeight); displayArea.setEditable(false); displayArea.setLineWrap(false); displayArea.setBackground(HTMLColor.white); displayScrollPane = new JScrollPane(displayArea); displayScrollBar = displayScrollPane.getVerticalScrollBar(); chatTab.add(displayScrollPane, BorderLayout.CENTER); Box submitPane = new Box(BoxLayout.X_AXIS); newMessage = new JTextField(60); ActionListener submitListener = new ActionListener() { public void actionPerformed(ActionEvent e) { submitText(e.getSource()); } }; KeyListener keyListener = new KeyListener() { public void keyReleased(KeyEvent e) { int kc = e.getKeyCode(); if (kc == KeyEvent.VK_UP || kc == KeyEvent.VK_KP_UP) { historyUp(); } if (kc == KeyEvent.VK_DOWN || kc == KeyEvent.VK_KP_DOWN) { historyDown(); } } public void keyTyped(KeyEvent e) { // not needed } public void keyPressed(KeyEvent e) { // not needed } }; newMessage.addActionListener(submitListener); newMessage.addKeyListener(keyListener); newMessage.setEnabled(false); chatSubmitButton = new JButton(chatSubmitButtonText); chatSubmitButton.addActionListener(submitListener); chatSubmitButton.setEnabled(false); submitPane.setPreferredSize(chatSubmitButton.getMinimumSize()); submitPane.add(newMessage); submitPane.add(chatSubmitButton); chatTab.add(submitPane, BorderLayout.SOUTH); } private void historyUp() { if (posInHistory == -1) { unsentMessage = newMessage.getText(); posInHistory = history.size(); } if (posInHistory > 0) { posInHistory--; newMessage.setText(history.get(posInHistory)); } } private void historyDown() { if (posInHistory == -1) { // not in history, do nothing } else if (posInHistory == history.size() - 1) { posInHistory = -1; newMessage.setText(unsentMessage); unsentMessage = ""; } else if (posInHistory < history.size() - 1) { posInHistory++; newMessage.setText(history.get(posInHistory)); } } public String getId() { return this.id; } public String getTitle() { return this.title; } public JComponent getTab() { return this.chatTab; } public void setLoginState(boolean loggedIn, IWebServer server, String username) { this.server = server; if (loggedIn != loginState) { // when logged in, button/field are enabled and vice versa newMessage.setEnabled(loggedIn); chatSubmitButton.setEnabled(loggedIn); long now = new Date().getTime(); String txt = (loggedIn ? " logged in " : " logged out "); if (!loggedIn) { // logout show immediately chatDisplay(now, username, dashes + txt + dashes); } else { this.username = username; afterResentWhen = now; afterResentSender = username; afterResentMessage = dashes + txt + dashes; } } loginState = loggedIn; } public void submitText(Object source) { if (source == chatSubmitButton || source == newMessage) { String chatId = IWebServer.generalChatName; String message = newMessage.getText(); if (message.equals("")) { message = " "; } server.chatSubmit(chatId, username, message); addToHistory(message); posInHistory = -1; newMessage.setText(unsentMessage); unsentMessage = ""; } else { LOGGER.warning(""); } } private void addToHistory(String message) { if (!message.trim().equals("")) { history.add(message); if (history.size() > MAX_HISTORY) { history.removeFirst(); } } } public void chatDeliver(long when, String sender, String message, boolean resent) { if (resent) { // null, null on sender side, signals end of resending if (sender.equals("null") && message.equals("null")) { if (resentMode) { chatDisplayInEDT(dashes + " end of redisplaying older messages " + dashes + "\n"); } else { chatDisplayInEDT(dashes + " (no messages to redisplay) " + dashes + "\n"); } resentMode = false; if (afterResentSender != null) { chatDisplay(afterResentWhen, afterResentSender, afterResentMessage); afterResentWhen = -1; afterResentSender = null; afterResentMessage = null; } } else if (when <= lastMsgWhen) { // skip display message -- older than lastMsgWhen } else { if (!resentMode) { chatDisplayInEDT("\n" + dashes + " redisplaying last " + "(currently up to 50) messages " + dashes + "\n"); } resentMode = true; lastMsgWhen = when; chatDisplay(when, sender, message); } } else { lastMsgWhen = when; chatDisplay(when, sender, message); } } private void chatDisplay(long when, String sender, String message) { String whenTime = whenFormatter.timeAsString(when); String dateChange = whenFormatter.hasDateChanged(); String doubleDashLine = ""; if (dateChange != null) { doubleDashLine = "\n" + doubledashes + " " + dateChange + " " + doubledashes + "\n"; } String textToAppend = doubleDashLine + whenTime + " " + sender + ": " + message + "\n"; chatDisplayInEDT(textToAppend); } private void chatDisplayInEDT(final String textToAppend) { if (SwingUtilities.isEventDispatchThread()) { appendToDisplayArea(textToAppend); } else { SwingUtilities.invokeLater(new Runnable() { public void run() { appendToDisplayArea(textToAppend); } }); } } private void appendToDisplayArea(final String textToAppend) { displayArea.append(textToAppend); displayArea.setCaretPosition(displayArea.getDocument().getLength()); if (displayArea.getLineCount() - 2 > displayArea.getRows()) { displayScrollBar.setValue(displayScrollBar.getMaximum()); } } public void setBackgroundColor(Color color) { displayArea.setBackground(color); } } // END class ChatHandler