Chat tools
/**
* Copyright bkzen ( http://wonderfl.net/user/bkzen )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/e0RA
*/
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.EventDispatcher;
import net.wonderfl.utils.WonderflAPI;
/**
* いつか使うかも
* @author jc at bkzen
*/
[SWF (backgroundColor = "0xFFFFFF", frameRate = "30", width = "465", height = "465")]
public class ChatTools extends Sprite
{
private var tools: Tools;
private var api: WonderflAPI;
public function ChatTools()
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e: Event = null): void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
api = new WonderflAPI(loaderInfo.parameters);
addChild(tools = new Tools()).addEventListener(ChatEvent.SEND, onChatSend);
}
private function onChatSend(e: ChatEvent): void
{
tools.addLog(api.viewerDisplayName, e.value);
}
}
}
import com.bit101.components.VScrollBar;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
import flash.geom.Rectangle;
import flash.text.AntiAliasType;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.Expo;
class ChatEvent extends Event
{
public static const SEND: String = "send";
private var _value: String = "";
private var _name: String = "";
function ChatEvent(type: String, value: String, name: String = "", bubbles: Boolean = false, cancelable: Boolean = false)
{
_name = name, _value = value;
super(type, bubbles, cancelable);
}
public function get value(): String { return _value; }
public function get name(): String { return _name; }
}
/// コンポーネントのベース
class Comp extends Sprite
{
function Comp() { visible = false, addEventListener(Event.ADDED_TO_STAGE, init); }
private function init(e: Event): void { removeEventListener(Event.ADDED_TO_STAGE, init), initialize(), visible = true; }
protected function initialize(): void { }
public function resize(sw: int, sh: int): void { }
}
/// ツール全体
class Tools extends Comp
{
internal static const downFilter: Array = [new DropShadowFilter(2, 45, 0x777777, 1, 2, 2, 1, 1, true)];
private var input: ChatBar;
private var log: LogView;
public static const FONT: String = "Verdana";
function Tools() { }
public function send(res: String): void
{
dispatchEvent(new ChatEvent(ChatEvent.SEND, res));
}
public function addLog(name: String, value: String):void
{
log.addLog(name, value);
}
override protected function initialize(): void
{
addChild(log = new LogView()), addChild(input = new ChatBar(this));
stage.addEventListener(Event.RESIZE, onResize);
}
private function onResize(e: Event): void
{
var w: int = stage.stageWidth, h: int = stage.stageHeight; log.resize(w, h), input.resize(w, h);
}
}
/// ログ表示エリア
class LogView extends Comp
{
private var txt: TextField, btn: LogBtn, resizeJog: ResizeJog, scrollBar: VScrollBar;
private var _tx: Number = 0, _tw: int = 150;
private var sRect: Rectangle = new Rectangle();
private var maxlog: uint = 200;
private var logs: Array = [];
function LogView() { }
override protected function initialize(): void
{
var w: int = 150, h: int = stage.stageHeight;
addChild(txt = new TextField());
addChild(btn = new LogBtn());
addChild(resizeJog = new ResizeJog());
scrollBar = new VScrollBar(this, w - 13, 2, onScroll);
txt.defaultTextFormat = new TextFormat(Tools.FONT, 9, 0x777777);
txt.antiAliasType = AntiAliasType.ADVANCED;
txt.borderColor = 0x777777, txt.backgroundColor = 0xFFFFFF;
txt.wordWrap = txt.border = txt.background = true;
txt.x = txt.y = 2, btn.x = -18;
resize(stage.stageWidth, h);
btn.addEventListener(MouseEvent.CLICK, onClick);
resizeJog.addEventListener(MouseEvent.MOUSE_DOWN, onJogDown);
addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
txt.addEventListener(Event.SCROLL, onTextScroll);
}
public function addLog(name: String, log: String): void
{
if (logs.push(name + ":\n" + log) >= maxlog) logs.shift();
txt.text = logs.join("\n------------\n");
txt.scrollV = txt.maxScrollV;
}
private function updateScrollbar(): void { callLater(_updateScrollbar); }
private function _updateScrollbar(): void
{
var vl: int = txt.numLines - txt.maxScrollV + 1;
var p: Number = vl / txt.numLines;
scrollBar.setSliderParams(1, txt.maxScrollV, txt.scrollV);
scrollBar.setThumbPercent(p);
scrollBar.pageSize = vl;
}
private function onTextScroll(e:Event):void
{
scrollBar.value = txt.scrollV;
updateScrollbar();
}
private function onScroll(e: Event):void { txt.scrollV = Math.round(scrollBar.value); }
private function onMouseWheel(e: MouseEvent): void
{
scrollBar.value -= e.delta, txt.scrollV = Math.round(scrollBar.value);
}
private function onJogDown(e: MouseEvent): void {
stage.addEventListener(MouseEvent.MOUSE_UP, onJogUp), resizeJog.startDrag(false, sRect);
}
private function onJogUp(e: MouseEvent): void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, onJogUp), resizeJog.stopDrag();
_tw = _tw - resizeJog.x, resizeJog.x = 0, resize(stage.stageWidth, stage.stageHeight);
}
private function onClick(e: MouseEvent): void { BetweenAS3.to(this, { tx: btn.isOpen ? 0 : _tw }, 0.5, Expo.easeIn).play(); }
override public function resize(sw: int, sh: int): void
{
var w: int = _tw, h: int = sh - 27;
var g: Graphics = graphics; g.clear();
g.beginFill(0x777777), g.drawRect(0, 0, w, h), g.drawRoundRectComplex(- 20, h - 30, 20, 30, 4, 0, 0, 0);
g.beginFill(0xFFFFFF), g.drawRect(1, 1, w - 2, h - 2), g.drawRoundRectComplex(- 19, h - 29, 19, 28, 4, 0, 0, 0);
scrollBar.setSize(11, h - 4);
txt.width = w - 17, txt.height = sh - 32, btn.y = h - 28, show(sw);
callLater(updateScrollbar);
}
public function get tx(): Number { return _tx; }
public function set tx(value: Number): void { _tx = value, show(stage.stageWidth); }
private function show(sw: int): void { x = sw + _tx - _tw, scrollBar.x = _tw - 13, sRect.width = sw - 85, sRect.x = _tw - sw; }
}
/// リサイズ用のじょぐ
class ResizeJog extends Comp
{
function ResizeJog() { }
override protected function initialize(): void
{
alpha = 0, buttonMode = true, resize(stage.stageWidth, stage.stageHeight);
addEventListener(MouseEvent.MOUSE_DOWN, onDown);
addEventListener(MouseEvent.ROLL_OVER, onOver);
addEventListener(MouseEvent.ROLL_OUT, onUp)
}
private function onOver(e: MouseEvent): void { alpha = .2; }
private function onDown(e: MouseEvent): void { alpha = .5, stage.addEventListener( MouseEvent.MOUSE_UP, onUp); }
private function onUp(e: MouseEvent): void { alpha = 0, stage.removeEventListener(MouseEvent.MOUSE_UP, onUp); }
override public function resize(sw:int, sh:int):void
{
var g: Graphics = graphics, h: int = sh - 30;
g.clear(), g.beginFill(0, 0.2), g.drawRect(0, 0, 10, sh);
g.beginFill(0), g.drawRect(3, h - 20 >> 1, 1, 20), g.drawRect(5, h - 20 >> 1, 1, 20), g.drawRect(7, h - 20 >> 1, 1, 20);
}
}
/// ログの閉じる/開くボタン
class LogBtn extends Comp
{
private var close: Shape, open: Shape;
public var isOpen: Boolean = true;
function LogBtn() { }
override protected function initialize(): void
{
var g: Graphics = graphics;
g.beginFill(0x777777), g.drawRoundRectComplex(0, 0, 19, 28, 4, 0, 0, 0);
g.beginFill(0xFFFFFF), g.drawRoundRectComplex(1, 1, 17, 26, 4, 0, 0, 0);
close = new Shape(), g = close.graphics;
g.beginFill(0x777777), g.drawTriangles(Vector.<Number>([ -5, -5, 5, 0, -5, 5]));
open = new Shape(), g = open.graphics;
g.beginFill(0x777777), g.drawTriangles(Vector.<Number>([ 5, 5, -5, 0, 5, -5]));
addEventListener(MouseEvent.MOUSE_DOWN, onDown);
addEventListener(MouseEvent.CLICK, onClick);
addChild(close);
buttonMode = true, open.x = close.x = 10, open.y = close.y = 15;
}
private function onClick(e: MouseEvent): void
{
if ((isOpen = !isOpen)) removeChild(open), addChild(close);
else removeChild(close), addChild(open);
}
private function onDown(e: MouseEvent): void
{
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
filters = Tools.downFilter, open.x = close.x = 11, open.y = close.y = 16;
}
private function onUp(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
filters = null, open.x = close.x = 10, open.y = close.y = 15;
}
}
/// チャットのテキスト入力エリアを含むバー
class ChatBar extends Comp
{
private var txt: TextField;
private var btn: ChatBtn;
private var _tools:Tools;
function ChatBar(tools: Tools) { _tools = tools; }
override protected function initialize():void
{
var w: int = stage.stageWidth, h: int = 28;
addChild(txt = new TextField());
txt.y = 5, txt.x = 8, txt.width = stage.stageWidth - 80, txt.height = h - 8, txt.type = TextFieldType.INPUT;
txt.defaultTextFormat = new TextFormat(Tools.FONT, 12, 0x777777);
addChild(btn = new ChatBtn());
resize(w, stage.stageHeight);
txt.addEventListener(KeyboardEvent.KEY_DOWN, onKeydown);
btn.addEventListener(MouseEvent.CLICK, onClick);
}
private function onClick(e: MouseEvent): void { send(); }
private function onKeydown(e: KeyboardEvent): void { if (e.keyCode == Keyboard.ENTER) send(); }
private function send():void
{
var res: String = txt.text;
if (res != "") txt.text = "", _tools.send(res);
}
override public function resize(sw: int, sh: int): void
{
var g: Graphics = graphics, w: int = sw, h: int = 28; g.clear();
g.beginFill(0x777777), g.drawRoundRectComplex(0, 0, w, h, 4, 0, 0, 0);
g.beginFill(0xFFFFFF), g.drawRoundRectComplex(1, 1, w - 2, h - 2, 4, 0, 0, 0);
g.beginFill(0x777777), g.drawRoundRectComplex(3, 3, w - 68, h - 6, 4, 0, 0, 0);
g.beginFill(0xFFFFFF), g.drawRoundRectComplex(4, 4, w - 70, h - 8, 4, 0, 0, 0);
btn.x = w - 63, btn.y = 3, y = sh - h;
}
}
/// チャットのSENDボタン
class ChatBtn extends Comp
{
private var txt:TextField;
function ChatBtn() { }
override protected function initialize():void
{
var g: Graphics = graphics;
g.beginFill(0x777777), g.drawRect(0, 0, 60, 22);
g.beginFill(0xFFFFFF), g.drawRect(1, 1, 58, 20);
addChild(txt = new TextField());
txt.autoSize = TextFieldAutoSize.LEFT;
txt.defaultTextFormat = new TextFormat(Tools.FONT, 12, 0x777777, true);
txt.text = "SEND", txt.mouseEnabled = false, buttonMode = true;
txt.x = 60 - txt.width >> 1, txt.y = 22 - txt.height >> 1;
addEventListener(MouseEvent.MOUSE_DOWN, onDown);
}
private function onDown(e: MouseEvent): void
{
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
filters = Tools.downFilter, txt.x = 62 - txt.width >> 1, txt.y = 24 - txt.height >> 1;
}
private function onUp(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
filters = null, txt.x = 60 - txt.width >> 1, txt.y = 22 - txt.height >> 1;
}
}
//package com.bkzen.utils {
/**
* あとで一回呼ぶ関数。
* @author jc at bk-zen.com
*/
function callLater(closure: Function): void
{
Ticker.add(closure);
}
//}
internal class Ticker
{
import flash.display.Shape;
import flash.events.Event;
internal static function add(closure: Function): void
{
if (handlers.indexOf(closure) < 0) handlers[cnt++] = closure;
}
private static var ticker: Shape;
private static var cnt: int;
private static var handlers: Array;
{
handlers = [];
ticker = new Shape();
ticker.addEventListener(Event.ENTER_FRAME, enter);
}
private static function enter(e: Event): void
{
if (cnt == 0) return;
var arr: Array = handlers;
handlers = [], cnt = 0;
var n: uint = arr.length;
for (var i: uint = 0; i < n; i++)
{
arr[i]();
}
}
}