Repackaging these into nenya.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4519 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,82 +0,0 @@
|
|||||||
package com.threerings.mx.controls {
|
|
||||||
|
|
||||||
import flash.display.DisplayObjectContainer;
|
|
||||||
|
|
||||||
import flash.events.Event;
|
|
||||||
|
|
||||||
import mx.controls.TextArea;
|
|
||||||
|
|
||||||
import com.threerings.crowd.chat.client.ChatDirector;
|
|
||||||
import com.threerings.crowd.chat.client.ChatDisplay;
|
|
||||||
import com.threerings.crowd.chat.data.ChatMessage;
|
|
||||||
import com.threerings.crowd.chat.data.UserMessage;
|
|
||||||
import com.threerings.crowd.util.CrowdContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A very simple chat display.
|
|
||||||
*/
|
|
||||||
public class ChatDisplayBox extends TextArea
|
|
||||||
implements ChatDisplay
|
|
||||||
{
|
|
||||||
public function ChatDisplayBox (ctx :CrowdContext)
|
|
||||||
{
|
|
||||||
_ctx = ctx;
|
|
||||||
this.editable = false;
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
width = 400;
|
|
||||||
height = 150;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface ChatDisplay
|
|
||||||
public function clear () :void
|
|
||||||
{
|
|
||||||
this.htmlText = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface ChatDisplay
|
|
||||||
public function displayMessage (
|
|
||||||
msg :ChatMessage, alreadyDisplayed :Boolean) :Boolean
|
|
||||||
{
|
|
||||||
if (!_scrollBot) {
|
|
||||||
_scrollBot = (verticalScrollPosition == maxVerticalScrollPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
// display the message
|
|
||||||
if (msg is UserMessage) {
|
|
||||||
this.htmlText += "<font color=\"red\"><" +
|
|
||||||
(msg as UserMessage).speaker + "></font> ";
|
|
||||||
}
|
|
||||||
this.htmlText += msg.message;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function parentChanged (p :DisplayObjectContainer) :void
|
|
||||||
{
|
|
||||||
super.parentChanged(p);
|
|
||||||
|
|
||||||
var chatdir :ChatDirector = _ctx.getChatDirector();
|
|
||||||
if (p != null) {
|
|
||||||
chatdir.addChatDisplay(this);
|
|
||||||
} else {
|
|
||||||
chatdir.removeChatDisplay(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
override protected function updateDisplayList (uw :Number, uh :Number) :void
|
|
||||||
{
|
|
||||||
super.updateDisplayList(uw, uh);
|
|
||||||
|
|
||||||
if (_scrollBot) {
|
|
||||||
verticalScrollPosition = maxVerticalScrollPosition;
|
|
||||||
_scrollBot = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The giver of life. */
|
|
||||||
protected var _ctx :CrowdContext;
|
|
||||||
|
|
||||||
protected var _scrollBot :Boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
package com.threerings.mx.controls {
|
|
||||||
|
|
||||||
import flash.events.MouseEvent;
|
|
||||||
|
|
||||||
import mx.controls.Button;
|
|
||||||
|
|
||||||
import com.threerings.mx.events.CommandEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A command button simply dispatches a Controller command (with an optional
|
|
||||||
* argument) when it is clicked.
|
|
||||||
*/
|
|
||||||
public class CommandButton extends Button
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Create a command button.
|
|
||||||
*/
|
|
||||||
public function CommandButton (cmd :String = null, arg :Object = null)
|
|
||||||
{
|
|
||||||
setCommand(cmd, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the command and argument to be issued when this button is pressed.
|
|
||||||
*/
|
|
||||||
public function setCommand (cmd :String, arg :Object = null) :void
|
|
||||||
{
|
|
||||||
_cmd = cmd;
|
|
||||||
_arg = arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
override protected function clickHandler (event :MouseEvent) :void
|
|
||||||
{
|
|
||||||
super.clickHandler(event);
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
// stop the click event
|
|
||||||
event.stopImmediatePropagation();
|
|
||||||
|
|
||||||
// dispatch the command event
|
|
||||||
// if the arg is null and we're a toggle button, dispatch our state
|
|
||||||
var arg :Object = _arg;
|
|
||||||
if (arg == null && toggle) {
|
|
||||||
arg = selected;
|
|
||||||
}
|
|
||||||
CommandEvent.dispatch(this, _cmd, arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The command to submit when clicked. */
|
|
||||||
protected var _cmd :String;
|
|
||||||
|
|
||||||
/** The argument that accompanies our command. */
|
|
||||||
protected var _arg :Object;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
package com.threerings.mx.controls {
|
|
||||||
|
|
||||||
import flash.display.DisplayObject;
|
|
||||||
import flash.display.DisplayObjectContainer;
|
|
||||||
|
|
||||||
import flash.geom.Rectangle;
|
|
||||||
|
|
||||||
import mx.controls.Menu;
|
|
||||||
import mx.core.mx_internal;
|
|
||||||
import mx.core.ScrollPolicy;
|
|
||||||
import mx.events.MenuEvent;
|
|
||||||
|
|
||||||
import com.threerings.mx.events.CommandEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A pretty standard menu that can submit CommandEvents if menu items
|
|
||||||
* have "command" and possibly "arg" properties. Commands are submitted to
|
|
||||||
* controllers for processing. Alternatively, you may specify
|
|
||||||
* "callback" properties that specify a function closure to call, with the
|
|
||||||
* "arg" property containing either a single arg or an array of args.
|
|
||||||
*
|
|
||||||
* Example dataProvider array:
|
|
||||||
* [ { label: "Go home", icon: homeIconClass,
|
|
||||||
* command: Controller.GO_HOME, arg: homeId },
|
|
||||||
* { type: "separator"},
|
|
||||||
{ label: "Crazytown", callback: setCrazy, arg: [ true, false ] },
|
|
||||||
* { label: "Other places", children: subMenuArray }
|
|
||||||
* ];
|
|
||||||
*
|
|
||||||
* See "Defining menu structure and data" in the Flex manual for the
|
|
||||||
* full list.
|
|
||||||
*/
|
|
||||||
public class CommandMenu extends Menu
|
|
||||||
{
|
|
||||||
public function CommandMenu ()
|
|
||||||
{
|
|
||||||
super();
|
|
||||||
|
|
||||||
addEventListener(MenuEvent.ITEM_CLICK, itemClicked);
|
|
||||||
// addEventListener(MenuEvent.MENU_SHOW, handleMenuShown);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to create a command menu.
|
|
||||||
*
|
|
||||||
* @param parent The parent of this menu.
|
|
||||||
* @param items an array of menu items.
|
|
||||||
*/
|
|
||||||
public static function createMenu (
|
|
||||||
parent :DisplayObjectContainer, items :Array) :CommandMenu
|
|
||||||
{
|
|
||||||
var menu :CommandMenu = new CommandMenu();
|
|
||||||
menu.tabEnabled = false;
|
|
||||||
menu.showRoot = true;
|
|
||||||
Menu.popUpMenu(menu, parent, items);
|
|
||||||
return menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Actually pop up the menu. This can be used instead of show().
|
|
||||||
*/
|
|
||||||
public function popUp (
|
|
||||||
trigger :DisplayObject, popUpwards :Boolean = false) :void
|
|
||||||
{
|
|
||||||
var r :Rectangle = trigger.getBounds(trigger.stage);
|
|
||||||
|
|
||||||
if (popUpwards) {
|
|
||||||
show(r.x, 0);
|
|
||||||
// then, reposition the y once we know our size
|
|
||||||
y = r.y - getExplicitOrMeasuredHeight();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// simply position it below the trigger
|
|
||||||
show(r.x, r.y + r.height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for MenuEvent.ITEM_CLICK.
|
|
||||||
*/
|
|
||||||
protected function itemClicked (event :MenuEvent) :void
|
|
||||||
{
|
|
||||||
var arg :Object = getItemArgument(event.item);
|
|
||||||
var cmd :String = getItemCommand(event.item);
|
|
||||||
var fn :Function;
|
|
||||||
if (cmd == null) {
|
|
||||||
fn = getItemCallback(event.item);
|
|
||||||
}
|
|
||||||
if (cmd != null || fn != null) {
|
|
||||||
event.stopImmediatePropagation();
|
|
||||||
if (cmd != null) {
|
|
||||||
CommandEvent.dispatch(mx_internal::parentDisplayObject, cmd, arg);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
var args :Array = (arg as Array);
|
|
||||||
if (args == null && arg != null) {
|
|
||||||
args = [ arg ];
|
|
||||||
}
|
|
||||||
fn.apply(null, args);
|
|
||||||
|
|
||||||
} catch (err :Error) {
|
|
||||||
Log.getLog(this).warning("Unable to call menu callback: " +
|
|
||||||
event.item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Callback for MenuEvent.MENU_SHOW.
|
|
||||||
// */
|
|
||||||
// protected function handleMenuShown (event :MenuEvent) :void
|
|
||||||
// {
|
|
||||||
// // just ensure that every menu can scroll
|
|
||||||
// event.menu.verticalScrollPolicy = ScrollPolicy.ON;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the command for the specified item, if any.
|
|
||||||
* Somewhat similar to bits in the DefaultDataDescriptor.
|
|
||||||
*/
|
|
||||||
protected function getItemCommand (item :Object) :String
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (item is XML) {
|
|
||||||
return (item.@command as String);
|
|
||||||
|
|
||||||
} else if (item is Object) {
|
|
||||||
return (item.command as String);
|
|
||||||
}
|
|
||||||
} catch (e :Error) {
|
|
||||||
// fall through
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the callback function for the specified item, if any.
|
|
||||||
*/
|
|
||||||
protected function getItemCallback (item :Object) :Function
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (item is XML) {
|
|
||||||
return (item.@callback as Function);
|
|
||||||
|
|
||||||
} else if (item is Object) {
|
|
||||||
return (item.callback as Function);
|
|
||||||
}
|
|
||||||
} catch (e :Error) {
|
|
||||||
// fall through
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the command for the specified item, if any.
|
|
||||||
* Somewhat similar to bits in the DefaultDataDescriptor.
|
|
||||||
*/
|
|
||||||
protected function getItemArgument (item :Object) :Object
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (item is XML) {
|
|
||||||
return item.@arg;
|
|
||||||
|
|
||||||
} else if (item is Object) {
|
|
||||||
return item.arg;
|
|
||||||
}
|
|
||||||
} catch (e :Error) {
|
|
||||||
// fall through
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
package com.threerings.mx.controls {
|
|
||||||
|
|
||||||
import flash.display.DisplayObject;
|
|
||||||
import flash.display.Graphics;
|
|
||||||
import flash.display.Sprite;
|
|
||||||
|
|
||||||
import flash.events.Event;
|
|
||||||
import flash.events.MouseEvent;
|
|
||||||
|
|
||||||
import flash.geom.Matrix;
|
|
||||||
import flash.geom.Rectangle;
|
|
||||||
|
|
||||||
import mx.containers.Canvas;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A control for scrolling some component separately.
|
|
||||||
*/
|
|
||||||
public class ScrollBox extends Canvas
|
|
||||||
{
|
|
||||||
public function ScrollBox (
|
|
||||||
target :DisplayObject, maxWidth :int, maxHeight :int)
|
|
||||||
{
|
|
||||||
_target = target;
|
|
||||||
_maxWidth = maxWidth;
|
|
||||||
_maxHeight = maxHeight;
|
|
||||||
|
|
||||||
opaqueBackground = 0xFFFFFF;
|
|
||||||
|
|
||||||
_box = new Sprite();
|
|
||||||
rawChildren.addChild(_box);
|
|
||||||
|
|
||||||
recheckBounds();
|
|
||||||
|
|
||||||
// TODO: only when something changes
|
|
||||||
addEventListener(Event.ENTER_FRAME, enterFrame);
|
|
||||||
|
|
||||||
_box.addEventListener(MouseEvent.MOUSE_DOWN, spritePressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function setActualSize (w :Number, h :Number) :void
|
|
||||||
{
|
|
||||||
super.setActualSize(w, h);
|
|
||||||
|
|
||||||
recheckBounds();
|
|
||||||
|
|
||||||
graphics.clear();
|
|
||||||
graphics.lineStyle(1, 0);
|
|
||||||
graphics.drawRect(0, 0, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function enterFrame (vent :Event) :void
|
|
||||||
{
|
|
||||||
if (!_dragging) {
|
|
||||||
recheckBounds();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the bounds of the scrollable area. Broken-out for easy overridding.
|
|
||||||
*/
|
|
||||||
protected function getScrollBounds () :Rectangle
|
|
||||||
{
|
|
||||||
var bounds :Rectangle = _target.transform.pixelBounds;
|
|
||||||
// var m :Matrix = _target.transform.concatenatedMatrix;
|
|
||||||
// bounds.topLeft = m.transformPoint(bounds.topLeft);
|
|
||||||
// bounds.bottomRight = m.transformPoint(bounds.bottomRight);
|
|
||||||
return bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function recheckBounds () :void
|
|
||||||
{
|
|
||||||
var bounds :Rectangle = getScrollBounds();
|
|
||||||
|
|
||||||
// see what's visible, what's not..
|
|
||||||
var scroller :Rectangle = _target.scrollRect;
|
|
||||||
if (scroller == null) {
|
|
||||||
scroller = bounds.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((_bounds != null) && _bounds.equals(bounds) &&
|
|
||||||
(_scroller != null) && _scroller.equals(scroller)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_bounds = bounds.clone();
|
|
||||||
_scroller = scroller;
|
|
||||||
|
|
||||||
_scale = Math.min(1,
|
|
||||||
Math.min(_maxWidth / _bounds.width, _maxHeight / _bounds.height));
|
|
||||||
width = _scale * _bounds.width;
|
|
||||||
height = _scale * _bounds.height;
|
|
||||||
|
|
||||||
drawBox(_box, _scroller.width * _scale, _scroller.height * _scale);
|
|
||||||
|
|
||||||
_box.x = (_scroller.x - _bounds.x) * _scale;
|
|
||||||
_box.y = (_scroller.y - _bounds.y) * _scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function drawBox (box :Sprite, ww :Number, hh :Number) :void
|
|
||||||
{
|
|
||||||
var g :Graphics = _box.graphics;
|
|
||||||
g.clear();
|
|
||||||
g.beginFill(0x0000FF);
|
|
||||||
g.drawRect(0, 0, ww, hh);
|
|
||||||
g.endFill();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function spritePressed (evt :MouseEvent) :void
|
|
||||||
{
|
|
||||||
_box.addEventListener(Event.ENTER_FRAME, boxUpdate);
|
|
||||||
_box.startDrag(true,
|
|
||||||
new Rectangle(0, 0, width - _box.width, height - _box.height));
|
|
||||||
stage.addEventListener(MouseEvent.MOUSE_UP, spriteReleased);
|
|
||||||
_dragging = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function spriteReleased (evt :MouseEvent) :void
|
|
||||||
{
|
|
||||||
stage.removeEventListener(MouseEvent.MOUSE_UP, spriteReleased);
|
|
||||||
_box.stopDrag();
|
|
||||||
_box.removeEventListener(Event.ENTER_FRAME, boxUpdate);
|
|
||||||
_dragging = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function boxUpdate (evt :Event) :void
|
|
||||||
{
|
|
||||||
var r :Rectangle = _target.scrollRect;
|
|
||||||
r.x = (_box.x / _scale) + _bounds.x;
|
|
||||||
r.y = (_box.y / _scale) + _bounds.y;
|
|
||||||
_target.scrollRect = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected var _dragging :Boolean;
|
|
||||||
|
|
||||||
protected var _target :DisplayObject;
|
|
||||||
|
|
||||||
protected var _maxWidth :int;
|
|
||||||
protected var _maxHeight :int;
|
|
||||||
|
|
||||||
protected var _box :Sprite;
|
|
||||||
|
|
||||||
protected var _scale :Number;
|
|
||||||
|
|
||||||
protected var _bounds :Rectangle;
|
|
||||||
protected var _scroller :Rectangle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package com.threerings.mx.effects {
|
|
||||||
|
|
||||||
import mx.effects.IEffectInstance;
|
|
||||||
import mx.effects.Effect;
|
|
||||||
|
|
||||||
public class FunctionEffect extends Effect
|
|
||||||
{
|
|
||||||
/** The function to call. */
|
|
||||||
public var func :Function;
|
|
||||||
|
|
||||||
/** The arguments to pass to the function. */
|
|
||||||
public var args :Array;
|
|
||||||
|
|
||||||
public function FunctionEffect (target :Object = null)
|
|
||||||
{
|
|
||||||
super(target);
|
|
||||||
|
|
||||||
instanceClass = FunctionEffectInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
|
||||||
override protected function initInstance (instance :IEffectInstance) :void
|
|
||||||
{
|
|
||||||
super.initInstance(instance);
|
|
||||||
|
|
||||||
var fe :FunctionEffectInstance = (instance as FunctionEffectInstance);
|
|
||||||
fe.func = func;
|
|
||||||
fe.args = args;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.threerings.mx.effects {
|
|
||||||
|
|
||||||
import mx.effects.effectClasses.ActionEffectInstance;
|
|
||||||
|
|
||||||
public class FunctionEffectInstance extends ActionEffectInstance
|
|
||||||
{
|
|
||||||
public function FunctionEffectInstance (target :Object)
|
|
||||||
{
|
|
||||||
super(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The function to call. */
|
|
||||||
public var func :Function;
|
|
||||||
|
|
||||||
/** The args to pass. */
|
|
||||||
public var args :Array;
|
|
||||||
|
|
||||||
override public function play () :void
|
|
||||||
{
|
|
||||||
super.play();
|
|
||||||
|
|
||||||
// call the function!
|
|
||||||
func.apply(null, args);
|
|
||||||
|
|
||||||
// and we're done
|
|
||||||
finishRepeat();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
package com.threerings.mx.events {
|
|
||||||
|
|
||||||
import flash.errors.IllegalOperationError;
|
|
||||||
|
|
||||||
import flash.events.Event;
|
|
||||||
import flash.events.IEventDispatcher;
|
|
||||||
|
|
||||||
public class CommandEvent extends Event
|
|
||||||
{
|
|
||||||
/** The event type for all controller events. */
|
|
||||||
public static const TYPE :String = "commandEvt";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this method to dispatch CommandEvents.
|
|
||||||
*/
|
|
||||||
public static function dispatch (
|
|
||||||
disp :IEventDispatcher, cmd :String, arg :Object = null) :void
|
|
||||||
{
|
|
||||||
// Create the event
|
|
||||||
var event :CommandEvent = create(cmd, arg);
|
|
||||||
|
|
||||||
// Dispatch it. A return value of true means that the event was
|
|
||||||
// never cancelled, so we complain.
|
|
||||||
if (disp == null || disp.dispatchEvent(event)) {
|
|
||||||
Log.getLog(CommandEvent).warning("Unhandled controller command " +
|
|
||||||
"[cmd=" + cmd + ", arg=" + arg + "].");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The command. */
|
|
||||||
public var command :String;
|
|
||||||
|
|
||||||
/** An optional argument. */
|
|
||||||
public var arg :Object;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Command events may not be directly constructed, use the dispatch
|
|
||||||
* method to do your work.
|
|
||||||
*/
|
|
||||||
public function CommandEvent (command :String, arg :Object)
|
|
||||||
{
|
|
||||||
super(TYPE, true, true);
|
|
||||||
if (_blockConstructor) {
|
|
||||||
throw new IllegalOperationError();
|
|
||||||
}
|
|
||||||
this.command = command;
|
|
||||||
this.arg = arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark this command as handled, stopping its propagation up the
|
|
||||||
* hierarchy.
|
|
||||||
*/
|
|
||||||
public function markAsHandled () :void
|
|
||||||
{
|
|
||||||
preventDefault();
|
|
||||||
stopImmediatePropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function clone () :Event
|
|
||||||
{
|
|
||||||
return create(command, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function toString () :String
|
|
||||||
{
|
|
||||||
return "CommandEvent[" + command + " (" + arg + ")]";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A factory method for privately creating command events.
|
|
||||||
*/
|
|
||||||
protected static function create (cmd :String, arg :Object) :CommandEvent
|
|
||||||
{
|
|
||||||
var event :CommandEvent;
|
|
||||||
_blockConstructor = false;
|
|
||||||
try {
|
|
||||||
event = new CommandEvent(cmd, arg);
|
|
||||||
} finally {
|
|
||||||
_blockConstructor = true;
|
|
||||||
}
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Used to prevent unauthorized construction. */
|
|
||||||
protected static var _blockConstructor :Boolean = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,301 +0,0 @@
|
|||||||
package com.threerings.mx.managers {
|
|
||||||
|
|
||||||
import flash.display.DisplayObject;
|
|
||||||
import flash.display.InteractiveObject;
|
|
||||||
import flash.display.Sprite;
|
|
||||||
import flash.events.MouseEvent;
|
|
||||||
import flash.text.TextField;
|
|
||||||
import flash.text.TextFieldType;
|
|
||||||
import flash.ui.Mouse;
|
|
||||||
|
|
||||||
import mx.core.Application;
|
|
||||||
import mx.managers.SystemManager;
|
|
||||||
import mx.styles.CSSStyleDeclaration;
|
|
||||||
import mx.styles.StyleManager;
|
|
||||||
|
|
||||||
import com.threerings.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A better CursorManager.
|
|
||||||
*/
|
|
||||||
public class CursorManager
|
|
||||||
{
|
|
||||||
public static const SYSTEM_CURSOR :int = 0;
|
|
||||||
|
|
||||||
public static const BUSY_CURSOR :int = 1;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Class methods
|
|
||||||
//
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes the cursor visible.
|
|
||||||
* Cursor visibility is not reference-counted.
|
|
||||||
* A single call to the <code>showCursor()</code> method
|
|
||||||
* always shows the cursor regardless of how many calls
|
|
||||||
* to the <code>hideCursor()</code> method were made.
|
|
||||||
*/
|
|
||||||
public static function showCursor () :void
|
|
||||||
{
|
|
||||||
if (_currentCursorId == SYSTEM_CURSOR) {
|
|
||||||
Mouse.show();
|
|
||||||
} else {
|
|
||||||
_cursorHolder.visible = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes the cursor invisible.
|
|
||||||
* Cursor visibility is not reference-counted.
|
|
||||||
* A single call to the <code>hideCursor()</code> method
|
|
||||||
* always hides the cursor regardless of how many calls
|
|
||||||
* to the <code>showCursor()</code> method were made.
|
|
||||||
*/
|
|
||||||
public static function hideCursor () :void
|
|
||||||
{
|
|
||||||
_cursorHolder.visible = false;
|
|
||||||
Mouse.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getCurrentCursorId () :int
|
|
||||||
{
|
|
||||||
return _currentCursorId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new cursor.
|
|
||||||
*
|
|
||||||
* @param cursorClass Class of the cursor to display.
|
|
||||||
*
|
|
||||||
* @param xOffset Number that specifies the x offset
|
|
||||||
* of the cursor, in pixels, relative to the mouse pointer.
|
|
||||||
* The default value is 0.
|
|
||||||
*
|
|
||||||
* @param yOffset Number that specifies the y offset
|
|
||||||
* of the cursor, in pixels, relative to the mouse pointer.
|
|
||||||
* The default value is 0.
|
|
||||||
*
|
|
||||||
* @return The ID of the cursor.
|
|
||||||
*/
|
|
||||||
public static function addCursor (
|
|
||||||
cursorClass :Class, xOffset :int = 0, yOffset :int = 0) :int
|
|
||||||
{
|
|
||||||
var cursorId :int = _nextCursorId++;
|
|
||||||
|
|
||||||
var rec :CursorRecord = new CursorRecord(cursorClass);
|
|
||||||
rec.x = xOffset;
|
|
||||||
rec.y = yOffset;
|
|
||||||
|
|
||||||
_cursors.put(cursorId, rec);
|
|
||||||
|
|
||||||
return cursorId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the current cursor.
|
|
||||||
*/
|
|
||||||
public static function setCursor (id :int) :void
|
|
||||||
{
|
|
||||||
if (id == _currentCursorId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_initialized) {
|
|
||||||
// oh, let's set it up
|
|
||||||
_systemManager = Application.application.systemManager;
|
|
||||||
|
|
||||||
// set up the busy cursor
|
|
||||||
var cursorManagerStyleDeclaration :CSSStyleDeclaration =
|
|
||||||
StyleManager.getStyleDeclaration("CursorManager");
|
|
||||||
var busyCursorClass :Class =
|
|
||||||
cursorManagerStyleDeclaration.getStyle("busyCursor");
|
|
||||||
_busyCursor = new CursorRecord(busyCursorClass);
|
|
||||||
|
|
||||||
// The first time a cursor is requested of the CursorManager,
|
|
||||||
// create a Sprite to hold the cursor symbol
|
|
||||||
_cursorHolder = new Sprite();
|
|
||||||
_cursorHolder.mouseEnabled = false;
|
|
||||||
_systemManager.cursorChildren.addChild(_cursorHolder);
|
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// figure out what the new cursor will be like
|
|
||||||
var rec :CursorRecord;
|
|
||||||
if (id == BUSY_CURSOR) {
|
|
||||||
rec = _busyCursor;
|
|
||||||
|
|
||||||
} else if (id != SYSTEM_CURSOR) {
|
|
||||||
rec = (_cursors.get(id) as CursorRecord);
|
|
||||||
if (rec == null) {
|
|
||||||
// a bogus id was specified
|
|
||||||
// TODO: throw an error?
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rec != null && (rec.cursor is Class)) {
|
|
||||||
// go ahead and instantiate the class
|
|
||||||
try {
|
|
||||||
var disp :DisplayObject = new (rec.cursor as Class);
|
|
||||||
rec.cursor = disp;
|
|
||||||
if (disp is InteractiveObject) {
|
|
||||||
(disp as InteractiveObject).mouseEnabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (err :Error) {
|
|
||||||
// this cursor is not usable, bail
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// always remove any custom cursors from the hierarchy
|
|
||||||
if (_cursorHolder.numChildren > 0) {
|
|
||||||
_cursorHolder.removeChildAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id != SYSTEM_CURSOR) {
|
|
||||||
Mouse.hide();
|
|
||||||
var currentCursor :DisplayObject = (rec.cursor as DisplayObject);
|
|
||||||
_cursorHolder.addChild(currentCursor);
|
|
||||||
_cursorHolder.x = _systemManager.mouseX + rec.x;
|
|
||||||
_cursorHolder.y = _systemManager.mouseY + rec.y;
|
|
||||||
|
|
||||||
_currentXOffset = rec.x;
|
|
||||||
_currentYOffset = rec.y;
|
|
||||||
_systemManager.stage.addEventListener(
|
|
||||||
MouseEvent.MOUSE_MOVE, mouseMoveHandler);
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
_currentXOffset = 0;
|
|
||||||
_currentYOffset = 0;
|
|
||||||
_systemManager.stage.removeEventListener(
|
|
||||||
MouseEvent.MOUSE_MOVE, mouseMoveHandler);
|
|
||||||
|
|
||||||
Mouse.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
_currentCursorId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a cursor from the cursor list.
|
|
||||||
* If the cursor being removed is the currently displayed cursor,
|
|
||||||
* the CursorManager displays the next cursor in the list, if one exists.
|
|
||||||
* If the list becomes empty, the CursorManager displays
|
|
||||||
* the default system cursor.
|
|
||||||
*
|
|
||||||
* @param cursorID ID of cursor to remove.
|
|
||||||
*/
|
|
||||||
public static function removeCursor (id :int) :void
|
|
||||||
{
|
|
||||||
var rec :CursorRecord = (_cursors.remove(id) as CursorRecord);
|
|
||||||
|
|
||||||
if (rec != null && id == _currentCursorId) {
|
|
||||||
setCursor(SYSTEM_CURSOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all of the cursors from the cursor list
|
|
||||||
* and restores the system cursor.
|
|
||||||
*/
|
|
||||||
public static function removeAllCursors () :void
|
|
||||||
{
|
|
||||||
_cursors.clear();
|
|
||||||
|
|
||||||
if (_currentCursorId != BUSY_CURSOR) {
|
|
||||||
setCursor(SYSTEM_CURSOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Class event handlers
|
|
||||||
//
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
private static function mouseMoveHandler (event :MouseEvent) :void
|
|
||||||
{
|
|
||||||
_cursorHolder.x = _systemManager.mouseX + _currentXOffset;
|
|
||||||
_cursorHolder.y = _systemManager.mouseY + _currentYOffset;
|
|
||||||
|
|
||||||
var target :Object = event.target;
|
|
||||||
|
|
||||||
// Do target test.
|
|
||||||
if (!_overTextField &&
|
|
||||||
target is TextField && target.type == TextFieldType.INPUT) {
|
|
||||||
_overTextField = true;
|
|
||||||
_showSystemCursor = true;
|
|
||||||
|
|
||||||
} else if (_overTextField &&
|
|
||||||
!(target is TextField && target.type == TextFieldType.INPUT)) {
|
|
||||||
_overTextField = false;
|
|
||||||
_showCustomCursor = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle switching between system and custom cursor.
|
|
||||||
if (_showSystemCursor) {
|
|
||||||
_showSystemCursor = false;
|
|
||||||
_cursorHolder.visible = false;
|
|
||||||
Mouse.show();
|
|
||||||
}
|
|
||||||
if (_showCustomCursor) {
|
|
||||||
_showCustomCursor = false;
|
|
||||||
_cursorHolder.visible = true;
|
|
||||||
Mouse.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A mapping of all assigned cursor ids. */
|
|
||||||
private static const _cursors :HashMap = new HashMap();
|
|
||||||
|
|
||||||
private static var _currentCursorId :int = 0; // SYSTEM_CURSOR
|
|
||||||
|
|
||||||
private static var _nextCursorId :int = 2; // skip BUSY
|
|
||||||
|
|
||||||
private static var _initialized :Boolean = false;
|
|
||||||
|
|
||||||
private static var _cursorHolder :Sprite;
|
|
||||||
|
|
||||||
private static var _currentXOffset :int = 0;
|
|
||||||
private static var _currentYOffset :int = 0;
|
|
||||||
|
|
||||||
/** A record for the busy cursor (where it can't be removed). */
|
|
||||||
private static var _busyCursor :CursorRecord;
|
|
||||||
|
|
||||||
private static var _overTextField :Boolean = false;
|
|
||||||
|
|
||||||
private static var _overLink :Boolean = false;
|
|
||||||
|
|
||||||
private static var _showSystemCursor :Boolean = false;
|
|
||||||
|
|
||||||
private static var _showCustomCursor :Boolean = false;
|
|
||||||
|
|
||||||
private static var _systemManager :SystemManager = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
class CursorRecord extends Object
|
|
||||||
{
|
|
||||||
public function CursorRecord (clazz :Class)
|
|
||||||
{
|
|
||||||
cursor = clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The class, or instantiated cursor. */
|
|
||||||
public var cursor :Object
|
|
||||||
|
|
||||||
/** The x/y offset for the hotspot. */
|
|
||||||
public var x :Number;
|
|
||||||
public var y :Number;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user