236 lines
6.8 KiB
ActionScript
236 lines
6.8 KiB
ActionScript
//
|
|
// Nenya library - tools for developing networked games
|
|
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
|
// http://code.google.com/p/nenya/
|
|
//
|
|
// 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.flex {
|
|
|
|
import flash.display.DisplayObjectContainer;
|
|
|
|
import flash.events.Event;
|
|
import flash.events.FocusEvent;
|
|
import flash.events.KeyboardEvent;
|
|
import flash.events.MouseEvent;
|
|
|
|
import flash.ui.Keyboard;
|
|
|
|
import mx.containers.HBox;
|
|
|
|
import mx.core.Application;
|
|
|
|
import mx.controls.TextInput;
|
|
|
|
import mx.events.FlexEvent;
|
|
|
|
import com.threerings.util.Arrays;
|
|
import com.threerings.util.DelayUtil;
|
|
import com.threerings.util.StringUtil;
|
|
|
|
import com.threerings.flex.CommandButton;
|
|
|
|
import com.threerings.crowd.chat.client.ChatDirector;
|
|
import com.threerings.crowd.chat.data.ChatCodes;
|
|
|
|
import com.threerings.crowd.util.CrowdContext;
|
|
|
|
/**
|
|
* The chat control widget.
|
|
*/
|
|
public class ChatControl extends HBox
|
|
{
|
|
/**
|
|
* Request focus for the oldest ChatControl.
|
|
*/
|
|
public static function grabFocus () :void
|
|
{
|
|
if (_controls.length > 0) {
|
|
(_controls[0] as ChatControl).setFocus();
|
|
}
|
|
}
|
|
|
|
public function ChatControl (
|
|
ctx :CrowdContext, sendButtonLabel :String = "send",
|
|
height :Number = NaN, controlHeight :Number = NaN)
|
|
{
|
|
_ctx = ctx;
|
|
_chatDtr = _ctx.getChatDirector();
|
|
|
|
this.height = height;
|
|
styleName = "chatControl";
|
|
|
|
addChild(_txt = new ChatInput());
|
|
_txt.addEventListener(FlexEvent.ENTER, sendChat, false, 0, true);
|
|
_txt.addEventListener(KeyboardEvent.KEY_UP, handleKeyUp);
|
|
|
|
_but = new CommandButton(sendButtonLabel, sendChat);
|
|
addChild(_but);
|
|
|
|
if (!isNaN(controlHeight)) {
|
|
_txt.height = controlHeight;
|
|
_but.height = controlHeight;
|
|
}
|
|
|
|
addEventListener(Event.ADDED_TO_STAGE, handleAddRemove);
|
|
addEventListener(Event.REMOVED_FROM_STAGE, handleAddRemove);
|
|
}
|
|
|
|
/**
|
|
* Provides access to the text field we use to accept chat.
|
|
*/
|
|
public function get chatInput () :ChatInput
|
|
{
|
|
return _txt;
|
|
}
|
|
|
|
/**
|
|
* Provides access to the send button.
|
|
*/
|
|
public function get sendButton () :CommandButton
|
|
{
|
|
return _but;
|
|
}
|
|
|
|
override public function set enabled (en :Boolean) :void
|
|
{
|
|
super.enabled = en;
|
|
if (_txt != null) {
|
|
_txt.enabled = en;
|
|
_but.enabled = en;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Request focus to this chat control.
|
|
*/
|
|
override public function setFocus () :void
|
|
{
|
|
_txt.setFocus();
|
|
}
|
|
|
|
/**
|
|
* Configures the chat director to which we should send our chat. Pass null to restore our
|
|
* default chat director.
|
|
*/
|
|
public function setChatDirector (chatDtr :ChatDirector) :void
|
|
{
|
|
_chatDtr = (chatDtr == null) ? _ctx.getChatDirector() : chatDtr;
|
|
}
|
|
|
|
/**
|
|
* Configures the background color of the text entry area.
|
|
*/
|
|
public function setChatColor (color :uint) :void
|
|
{
|
|
_txt.setStyle("backgroundColor", color);
|
|
}
|
|
|
|
/**
|
|
* Handles FlexEvent.ENTER and the action from the send button.
|
|
*/
|
|
protected function sendChat (... ignored) :void
|
|
{
|
|
var message :String = StringUtil.trim(_txt.text);
|
|
if ("" == message) {
|
|
return;
|
|
}
|
|
|
|
var result :String = _chatDtr.requestChat(null, message, true);
|
|
if (result != ChatCodes.SUCCESS) {
|
|
_chatDtr.displayFeedback(null, result);
|
|
return;
|
|
}
|
|
|
|
// If there was no error, clear the entry area in prep for the next entry event
|
|
DelayUtil.delayFrame(function () : void {
|
|
// WORKAROUND
|
|
// Originally we cleared the text immediately, but with flex 3.2 this broke
|
|
// for *some* people. Weird! We're called from the event dispatcher for the
|
|
// enter key, so it's possible that the default action is booching it?
|
|
// In any case, this could possibly be removed in the future by the ambitious.
|
|
// Note also: Flex's built-in callLater() doesn't work, but DelayUtil does. WTF?!?
|
|
_txt.text = "";
|
|
});
|
|
_histidx = -1;
|
|
}
|
|
|
|
protected function scrollHistory (next :Boolean) :void
|
|
{
|
|
var size :int = _chatDtr.getCommandHistorySize();
|
|
if ((_histidx == -1) || (_histidx == size)) {
|
|
_curLine = _txt.text;
|
|
_histidx = size;
|
|
}
|
|
|
|
_histidx = (next) ? Math.min(_histidx + 1, size)
|
|
: Math.max(_histidx - 1, 0);
|
|
var text :String = (_histidx == size) ? _curLine : _chatDtr.getCommandHistory(_histidx);
|
|
_txt.text = text;
|
|
_txt.setSelection(text.length, text.length);
|
|
}
|
|
|
|
/**
|
|
* Handles Event.ADDED_TO_STAGE and Event.REMOVED_FROM_STAGE.
|
|
*/
|
|
protected function handleAddRemove (event :Event) :void
|
|
{
|
|
if (event.type == Event.ADDED_TO_STAGE) {
|
|
// set up any already-configured text
|
|
_txt.text = _curLine;
|
|
_histidx = -1;
|
|
|
|
// request focus
|
|
callLater(_txt.setFocus);
|
|
_controls.push(this);
|
|
|
|
} else {
|
|
_curLine = _txt.text;
|
|
Arrays.removeAll(_controls, this);
|
|
}
|
|
}
|
|
|
|
protected function handleKeyUp (event :KeyboardEvent) :void
|
|
{
|
|
switch (event.keyCode) {
|
|
case Keyboard.UP: scrollHistory(false); break;
|
|
case Keyboard.DOWN: scrollHistory(true); break;
|
|
}
|
|
}
|
|
|
|
/** Our client-side context. */
|
|
protected var _ctx :CrowdContext;
|
|
|
|
/** The director to which we are sending chat requests. */
|
|
protected var _chatDtr :ChatDirector;
|
|
|
|
/** The place where the user may enter chat. */
|
|
protected var _txt :ChatInput;
|
|
|
|
/** The current index in the chat command history. */
|
|
protected var _histidx :int = -1;
|
|
|
|
/** The button for sending chat. */
|
|
protected var _but :CommandButton;
|
|
|
|
/** An array of the currently shown-controls. */
|
|
protected static var _controls :Array = [];
|
|
|
|
/** The preserved current line of text when traversing history or carried between instances of
|
|
* ChatControl. */
|
|
protected static var _curLine :String;
|
|
}
|
|
}
|