diff --git a/src/java/com/threerings/crowd/chat/client/ChatDirector.java b/src/java/com/threerings/crowd/chat/client/ChatDirector.java
index 04b64b713..fc6b24fb0 100644
--- a/src/java/com/threerings/crowd/chat/client/ChatDirector.java
+++ b/src/java/com/threerings/crowd/chat/client/ChatDirector.java
@@ -154,21 +154,6 @@ public class ChatDirector extends BasicDirector
registerCommandHandlers();
}
- /**
- * Registers all the chat-command handlers.
- */
- protected void registerCommandHandlers ()
- {
- MessageBundle msg = _ctx.getMessageManager().getBundle(_bundle);
- registerCommandHandler(msg, "help", new HelpHandler());
- registerCommandHandler(msg, "clear", new ClearHandler());
- registerCommandHandler(msg, "speak", new SpeakHandler());
- registerCommandHandler(msg, "emote", new EmoteHandler());
- registerCommandHandler(msg, "think", new ThinkHandler());
- registerCommandHandler(msg, "tell", new TellHandler());
- registerCommandHandler(msg, "broadcast", new BroadcastHandler());
- }
-
/**
* Adds the supplied chat display to the front of the chat display list. It will subsequently
* be notified of incoming chat messages as well as tell responses.
@@ -599,6 +584,21 @@ public class ChatDirector extends BasicDirector
_auxes.remove(source.getOid());
}
+ /**
+ * Returns the history list containing a trailing window of messages that have passed through
+ * this chat director. The history list is created on demand so that systems which don't make
+ * use of chat history need not incur the overhead of tracking historical chat messages. Thus
+ * messages will only be added to the history after this method has been called at
+ * least once.
+ */
+ public HistoryList getHistory ()
+ {
+ if (_hlist == null) {
+ addChatDisplay(_hlist = new HistoryList());
+ }
+ return _hlist;
+ }
+
/**
* Run a message through all the currently registered filters.
*/
@@ -702,6 +702,21 @@ public class ChatDirector extends BasicDirector
_cservice = null;
}
+ /**
+ * Registers all the chat-command handlers.
+ */
+ protected void registerCommandHandlers ()
+ {
+ MessageBundle msg = _ctx.getMessageManager().getBundle(_bundle);
+ registerCommandHandler(msg, "help", new HelpHandler());
+ registerCommandHandler(msg, "clear", new ClearHandler());
+ registerCommandHandler(msg, "speak", new SpeakHandler());
+ registerCommandHandler(msg, "emote", new EmoteHandler());
+ registerCommandHandler(msg, "think", new ThinkHandler());
+ registerCommandHandler(msg, "tell", new TellHandler());
+ registerCommandHandler(msg, "broadcast", new BroadcastHandler());
+ }
+
/**
* Processes and dispatches the specified chat message.
*/
@@ -1443,6 +1458,9 @@ public class ChatDirector extends BasicDirector
/** Operation used to display chat messages. */
protected DisplayMessageOp _displayMessageOp = new DisplayMessageOp();
+ /** A rolling chat history, or null if {@link #getHistory} is never called. */
+ protected HistoryList _hlist;
+
/** Registered chat command handlers. */
protected static HashMap _handlers = Maps.newHashMap();
diff --git a/src/java/com/threerings/crowd/chat/client/HistoryList.java b/src/java/com/threerings/crowd/chat/client/HistoryList.java
new file mode 100644
index 000000000..304fa955e
--- /dev/null
+++ b/src/java/com/threerings/crowd/chat/client/HistoryList.java
@@ -0,0 +1,127 @@
+//
+// $Id$
+//
+// Narya library - tools for developing networked games
+// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
+// http://www.threerings.net/code/narya/
+//
+// This library is free software; you can redistribute it and/or modify it
+// under the terms of the GNU Lesser General Public License as published
+// by the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+package com.threerings.crowd.chat.client;
+
+import java.util.ArrayList;
+
+import com.samskivert.util.ObserverList;
+
+import com.threerings.crowd.chat.data.ChatMessage;
+
+/**
+ * Stores chat history.
+ */
+public class HistoryList extends ArrayList
+ implements ChatDisplay
+{
+ /** An interface for chat history observers. */
+ public interface Observer {
+ /** Called when messages have been added or removed from the chat history.
+ * @param adjustment the number of messages that have been added (+) or removed (-). */
+ void historyUpdated (int adjustment);
+ }
+
+ // documentation inherited from interface
+ public boolean displayMessage (ChatMessage msg, boolean alreadyDisplayed)
+ {
+ // see if we're full, and if so, clear out a bunch of old stuff
+ int adjusted;
+ if (size() == MAX_HISTORY) {
+ removeRange(0, PRUNE_HISTORY);
+ adjusted = PRUNE_HISTORY;
+
+ } else {
+ adjusted = 0;
+ }
+
+ // add the message to the history
+ add(msg);
+
+ // notify observers that something changed
+ notify(adjusted);
+
+ return true;
+ }
+
+ @Override
+ public void clear ()
+ {
+ // see how many entries we're clearing out..
+ int adjusted = size();
+ super.clear();
+
+ // and notify the chat displays of that fact
+ notify(adjusted);
+ }
+
+ /**
+ * Adds an {@link Observer} that wants to know about changes to the history.
+ */
+ public void addObserver (Observer obs)
+ {
+ _obs.add(obs);
+ }
+
+ /**
+ * Removes a {@link Observer} from hearing about changes to the history.
+ */
+ public void removeObserver (Observer obs)
+ {
+ _obs.remove(obs);
+ }
+
+ /**
+ * Notifies listening {@link Observer}s that there has been a change to this history.
+ */
+ protected void notify (int adjustment)
+ {
+ _historyUpdatedOp.setAdjustment(adjustment);
+ _obs.apply(_historyUpdatedOp);
+ }
+
+ protected static class HistoryUpdatedOp
+ implements ObserverList.ObserverOp
+ {
+ public void setAdjustment (int adjustment) {
+ _adjustment = adjustment;
+ }
+
+ public boolean apply (Observer obs) {
+ obs.historyUpdated(_adjustment);
+ return true;
+ }
+
+ protected int _adjustment;
+ }
+
+ /** A list of {@link Observer}s interested in history changes. */
+ protected ObserverList _obs = ObserverList.newFastUnsafe();
+
+ /** An operation used to notify observers of history updates. */
+ protected HistoryList.HistoryUpdatedOp _historyUpdatedOp = new HistoryUpdatedOp();
+
+ /** The maximum number of history entries we'll keep. */
+ protected static final int MAX_HISTORY = 2000;
+
+ /** The number of history entries we'll prune when we hit the max. */
+ protected static final int PRUNE_HISTORY = 200;
+}