flash on 2010-1-28

by itou_hiroki
-*- coding:utf-8-unix -*-
Copyright (c) 2010 Itou Hiroki
キーボード作成を2つしようとした。うまくいかない
キーボード作成をカスタムクラスにした
「入力文字を下に表示する shift対応 IME対応 dropshadow Shiftの右と左を判断する 入力した最後の文字が赤くなる」
Todo
- Shiftの右と左を両方押して離すとShift残りが発生するが、両方押すことはないとしよう
♥0 | Line 300 | Modified 2010-01-28 16:40:17 | MIT License
play

ActionScript3 source code

/**
 * Copyright itou_hiroki ( http://wonderfl.net/user/itou_hiroki )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/swLA
 */

// -*- coding:utf-8-unix -*-
// Copyright (c) 2010 Itou Hiroki
// キーボード作成を2つしようとした。うまくいかない
// キーボード作成をカスタムクラスにした
// 「入力文字を下に表示する shift対応 IME対応 dropshadow Shiftの右と左を判断する 入力した最後の文字が赤くなる」
// Todo
// - Shiftの右と左を両方押して離すとShift残りが発生するが、両方押すことはないとしよう


package {
    import flash.display.Sprite;
    import flash.display.*;
    import flash.events.*;
    import flash.text.*;
    import flash.system.IME;
    import flash.filters.*;
    
    [SWF(width="465",height="465",backgroundColor="0x888888",frameRate="60")]
    
    public class FlashTest extends Sprite {
        var mykbd1:TheKeyboard = new TheKeyboard(10, 10);
        var mykbd2:TheKeyboard = new TheKeyboard(10, 275);
    }
}



import flash.display.Sprite;
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.system.IME;
import flash.filters.*;
class TheKeyboard extends Sprite {
    private const STAGE_PADDING:uint= 3;
    private const KEY_PADDING:uint = 2;
    private const KEY_AREA:uint = 30;
    private const KEY_COLOR:int = 0xeee8e8;
    private const KEY_TRANCEPARENCY:Number = 1.0;
    private const KEY_HIT_COLOR:int = 0xffcc00;
    private const KEY_HIT_TRANCEPARENCY:Number = 0.5;
    private const KEY_COLOR_OUTLINE:int = 0x333333;
    private const KEY_CHAR_COLOR:int = 0x333333;
    private const MAX_BOARD_LENGTH:int = 10;
    private const KEYCODE_SHIFT_RIGHT:int = 255;
    private var keyCodes:Array = new Array();
    private var keys:Array = new Array();
    private var brd:TextField = new TextField();

    public function TheKeyboard(_x:int, _y:int) {
        var i:int;
        // write as3 code here..
        if (IME.enabled){
            IME.enabled = false;
        }
        make_japanese_keyboard_obj(_x, _y);
        make_board(_x, _y);

        stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
    }

    private function onKeyDown(e:KeyboardEvent):void {
        var kc:uint = e.keyCode;
        var i:int;
        //trace('onKeyDown:', e.keyCode);
        //IMEをONにしようとしたなら、OFFにする
        if (IME.enabled){
            IME.enabled = false;
        }
        // '229' is HanZen or IME enable key
        if (keys[kc] === null || kc === 229){ return; }
        //右shift
        //trace('down keyloc=',e.keyLocation);
        if (kc === 16 && e.keyLocation === 2) { kc = KEYCODE_SHIFT_RIGHT; }

        keys[kc].pushed = true;
        addChild(keys[kc].hit);

        //16 or KEYCODE_SHIFT_RIGHT is 'Shift'
        if (keys[16].pushed || keys[KEYCODE_SHIFT_RIGHT].pushed){
            for (i=0; i<keyCodes.length; i++){
                keys[keyCodes[i]].textfield.text = keys[keyCodes[i]].char_display_shift;
            }
            put_char_on_board(keys[kc].char_input_shift);
        }else{
            put_char_on_board(keys[kc].char_input);
        }
    }

    private function onKeyUp(e:KeyboardEvent):void {
        var kc:uint = e.keyCode;
        var i:int;
        //trace('onKeyUp:', e.keyCode);
        //IMEをONにしようとしたなら、OFFにする
        if (IME.enabled){
            IME.enabled = false;
        }
        // '243' is HanZen key up code
        if (keys[kc] === null || kc === 243){ return ; }
        //右shift
        if (kc === 16){
            //trace('up keyloc=',e.keyLocation);
            //右シフト押したまま文字キーを押して離して、それから右シフト離したときに
            // e.keyLocationが2にならず0になるのはなぜだAdobe in FlashPlayer10.0.42.34
            if (e.keyLocation === 2 || keys[KEYCODE_SHIFT_RIGHT].pushed) {
                kc = KEYCODE_SHIFT_RIGHT;
            }
        }

        if (keys[kc].pushed){
            removeChild(keys[kc].hit);
            keys[kc].pushed = false;
        }

        //16 or KEYCODE_SHIFT_RIGHT is 'Shift'
        if (! keys[16].pushed && ! keys[KEYCODE_SHIFT_RIGHT].pushed){
            for (i=0; i<keyCodes.length; i++){
                keys[keyCodes[i]].textfield.text = keys[keyCodes[i]].char_display;
            }
        }
        // '229' is HanZen or IME enable key
        if (keys[229].pushed){
            removeChild(keys[229].hit);
            keys[229].pushed = false;
        }
    }

    private function make_board(_x:int, _y:int):void {
        //make board
        brd.x = 20 + _x;
        brd.y = 200 + _y;
        brd.width = stage.stageWidth - 20*2;
        trace(brd.width);
        //brd.y = Math.floor(stage.stageHeight / 3 * 2 );
        brd.height = 50;
        //brd.border = true;
        //brd.multiline = true;
        //brd.wordWrap = true;
        brd.autoSize = TextFieldAutoSize.RIGHT;
        //brd.antiAliasType = flash.text.AntiAliasType.NORMAL;
        var tfm:TextFormat = new TextFormat();
        tfm.font = 'Verdana';
        tfm.size = 84;
        tfm.color=0xeeeeee;
        brd.defaultTextFormat = tfm;
        var flt:DropShadowFilter = new DropShadowFilter(8,45,0.2, 12,12, 20);
        brd.filters = [flt];
        addChild(brd);
    }

    private function put_char_on_board(_char:String):void {
        var tfm_new:TextFormat = new TextFormat();
        tfm_new.color = 0xff3333;
        if (_char === 'NULL') { return; }
        else if (_char === 'Space') { _char = ' '; }
        var str:String = brd.text + _char;
        if (str.length > MAX_BOARD_LENGTH) {
            brd.text = str.substr(str.length - MAX_BOARD_LENGTH);
        }else{
            brd.text = str;
        }
        brd.setTextFormat(tfm_new, brd.text.length-1);
    }

    private function add_text_on_key(_tfd:TextField, _char:String, _x:int,_y:int):void {
        var tfm:TextFormat = new TextFormat();
        tfm.font = "Verdana";
        if (_char.length > 1){
            tfm.size = 12;
            _tfd.x = _x+STAGE_PADDING;
            _tfd.y = _y+STAGE_PADDING;
        }else{
            tfm.size = 18;
            _tfd.x = _x+STAGE_PADDING + KEY_PADDING;
            _tfd.y = _y+STAGE_PADDING - KEY_PADDING;
        }
        tfm.color = KEY_CHAR_COLOR;
        //_tfd.antiAliasType = flash.text.AntiAliasType.ADVANCED;
        _tfd.autoSize = TextFieldAutoSize.LEFT;
        _tfd.defaultTextFormat = tfm;
        if (_char != 'Space'){
            _tfd.text = _char;
        }
    }

    private function make_japanese_keyboard_obj(_x:int, _y:int):void {
        var i:int;
        var tfd:TextField;
        var key_str:String = '';
        var key_ary:Array  = [];

        //http://livedocs.adobe.com/flex/3_jp/langref/flash/events/KeyboardEvent.html
        key_str  = '27 ';
        key_str += '229 49 50 51 52 53 54 55 56 57 48 189 222 220 8 ';
        key_str += '9 81 87 69 82 84 89 85 73 79 80 192 219 13 ';
        key_str += '20 65 83 68 70 71 72 74 75 76 187 186 221 ';
        key_str += '16 90 88 67 86 66 78 77 188 190 191 226 ' + KEYCODE_SHIFT_RIGHT + ' ';
        key_str += '17 29 32 28';
        keyCodes = key_str.split(' ');

        key_str  = 'Esc ';
        key_str += 'HanZen Num1 Num2 Num3 Num4 Num5 Num6 Num7 Num8 Num9 Num0 Minus Accent Yen BackSpace ';
        key_str += 'Tab Q W E R T Y U I O P AtMark LeftBracket Enter ';
        key_str += 'Eisuu A S D F G H J K L SemiColon Colon RightBracket ';
        key_str += 'Shift Z X C V B N M Comma Period Slash Backslash RightShift ';
        key_str += 'Ctrl NoConvert Space Convert';
        var charNameJP:Array = key_str.split(' ');

        key_str  = 'Esc ';
        key_str += '半全 1 2 3 4 5 6 7 8 9 0 - ^ ¥ BS ';
        key_str += 'Tab q w e r t y u i o p @ [ Enter ';
        key_str += '英数 a s d f g h j k l ; : ] ';
        key_str += 'Shift z x c v b n m , . / \\ Shift ';
        key_str += 'Ctrl 無変換   変換'; //全角空白使ってます
        var dispCharJP:Array = key_str.split(' ');

        key_str  = 'Esc ';
        key_str += '半全 ! " # $ % & \' ( )   = ~ | BS '; //全角空白使ってます
        key_str += 'Tab Q W E R T Y U I O P ` { Enter ';
        key_str += '英数 A S D F G H J K L + * } ';
        key_str += 'Shift Z X C V B N M < > ? _ Shift ';
        key_str += 'Ctrl 無変換   変換'; //全角空白使ってます
        var dispCharJP_shift:Array = key_str.split(' ');

        key_str  = 'NULL ';
        key_str += 'NULL 1 2 3 4 5 6 7 8 9 0 - ^ ¥ NULL ';
        key_str += 'Space q w e r t y u i o p @ [ NULL ';
        key_str += 'NULL a s d f g h j k l ; : ] ';
        key_str += 'NULL z x c v b n m , . / \\ NULL ';
        key_str += 'NULL NULL Space NULL';
        var inputCharJP:Array = key_str.split(' ');

        key_str  = 'NULL ';
        key_str += 'NULL ! " # $ % & \' ( ) NULL = ~ | NULL ';
        key_str += 'Space Q W E R T Y U I O P ` { NULL ';
        key_str += 'NULL A S D F G H J K L + * } ';
        key_str += 'NULL Z X C V B N M < > ? _ NULL ';
        key_str += 'NULL NULL Space NULL';
        var inputCharJP_shift:Array = key_str.split(' ');

        var w:uint = KEY_AREA;
        key_ary = [];

        //ESC
        var y:int = 0;
        var x:int = 0;
        key_ary.push([x,y,w]);

        //数字の段 (半角全角とBackSpace含む)(含めていいのは幅が同じだから)
        //    キーボード横幅は 数字段で、15個。
        //    (画面横幅pixel)465÷15=31 余白を考えて1key 30pxで使う
        y = w*1;
        x = 0;
        key_ary.push(
            [x,y,w],[x+w,y,w],[x+w*2,y,w],[x+w*3,y,w],[x+w*4,y,w],
            [x+w*5,y,w],[x+w*6,y,w],[x+w*7,y,w],[x+w*8,y,w],[x+w*9,y,w],
            [x+w*10,y,w],[x+w*11,y,w],[x+w*12,y,w],[x+w*13,y,w],[x+w*14,y,w]
            );

        //TAB
        y = w*2;
        x = 0;
        key_ary.push([x,y,w+w/2]);
        //QWERTYの段
        x = w+w/2;
        key_ary.push(
            [x,y,w],[x+w,y,w],[x+w*2,y,w],[x+w*3,y,w],[x+w*4,y,w],
            [x+w*5,y,w],[x+w*6,y,w],[x+w*7,y,w],[x+w*8,y,w],[x+w*9,y,w],
            [x+w*10,y,w],[x+w*11,y,w]
            );
        //Enter (日本語キーボードの場合ここに来る)(英語キーボードならもう一つ下なんだけど)
        x = x+w*12;
        key_ary.push([x,y,'ENTER']);

        //Eisuu
        y = w*3;
        x = 0;
        key_ary.push([x,y,w+w/2+Math.floor(w/4)]);
        //ASDFの段
        x = w+w/2+Math.floor(w/4);
        key_ary.push(
            [x,y,w],[x+w,y,w],[x+w*2,y,w],[x+w*3,y,w],[x+w*4,y,w],
            [x+w*5,y,w],[x+w*6,y,w],[x+w*7,y,w],[x+w*8,y,w],[x+w*9,y,w],
            [x+w*10,y,w],[x+w*11,y,w]
            );

        //Shift
        y = w*4;
        x = 0;
        key_ary.push([x,y, w+w/2+Math.floor(w/4)+w/2]);
        //ZXCVの段
        x = w+w/2+Math.floor(w/4)+w/2;
        key_ary.push(
            [x,y,w],[x+w,y,w],[x+w*2,y,w],[x+w*3,y,w],[x+w*4,y,w],
            [x+w*5,y,w],[x+w*6,y,w],[x+w*7,y,w],[x+w*8,y,w],[x+w*9,y,w],
            [x+w*10,y,w]
            );
        //RightShift
        var x_shift_rightside:int = x+w*11;
        x = x+w*11;
        key_ary.push([x,y, w*15 - x_shift_rightside]);

        //Ctrl
        y = w*5;
        x = 0;
        key_ary.push([x,y,w+w/2]); //Tabと同じ幅
        //NoConvert
        x = w+w/2+Math.floor(w/4)+w/2 + w + w - Math.floor(w/4);
        key_ary.push([x,y,w+w/2]); //Tabと同じ幅
        //Space
        x = w+w/2+Math.floor(w/4)+w/2 + w + w - Math.floor(w/4) + w+w/2;
        key_ary.push([x,y,w+w+w/2]); //2.5キーぶんの幅
        //Convert
        x = w+w/2+Math.floor(w/4)+w/2 + w + w - Math.floor(w/4) + w+w/2 + w+w+w/2;
        key_ary.push([x,y,w+w/2]); //Tabと同じ幅

        for (i=0; i<keyCodes.length; i++) {
            x = key_ary[i][0] + _x;
            y = key_ary[i][1] + _y;

            tfd = new TextField();
            var spr_key:Sprite = new Sprite();
            var spr_hit:Sprite = new Sprite();

            if (key_ary[i][2]==='ENTER') {
                make_enterkey_image(spr_key, x,y, KEY_COLOR,KEY_TRANCEPARENCY);
                addChild(spr_key);

                add_text_on_key(tfd, dispCharJP[i], x,y);
                addChild(tfd);

                make_enterkey_image(spr_hit, x,y, KEY_HIT_COLOR,KEY_HIT_TRANCEPARENCY);

            }else{
                make_key_image(spr_key, x,y, key_ary[i][2], KEY_COLOR,KEY_TRANCEPARENCY);
                addChild(spr_key);

                add_text_on_key(tfd, dispCharJP[i], x,y);
                addChild(tfd);

                make_key_image(spr_hit, x,y, key_ary[i][2], KEY_HIT_COLOR,KEY_HIT_TRANCEPARENCY);
            }
            keys[keyCodes[i]] = [];
            keys[keyCodes[i]].x = x;
            keys[keyCodes[i]].y = y;
            keys[keyCodes[i]].key = spr_key;
            keys[keyCodes[i]].hit = spr_hit;
            keys[keyCodes[i]].textfield = tfd;
            keys[keyCodes[i]].name = charNameJP[i];
            keys[keyCodes[i]].char_display = dispCharJP[i];
            keys[keyCodes[i]].char_display_shift = dispCharJP_shift[i];
            keys[keyCodes[i]].char_input = inputCharJP[i];
            keys[keyCodes[i]].char_input_shift = inputCharJP_shift[i];
            keys[keyCodes[i]].pushed = false;
        }
        for (i=0; i<=255; i++) {
            if (keys[i] === undefined){
                keys[i] = null;
            }
        }
    }

    private function make_key_image(_obj:Sprite, _x:int,_y:int, _w:int, _col:int,_tp:Number):void {
        //http://livedocs.adobe.com/flex/3_jp/langref/flash/display/Graphics.html
        _obj.graphics.lineStyle(1,KEY_COLOR_OUTLINE);
        _obj.graphics.beginFill(_col,_tp);
        _obj.graphics.drawRect(_x+STAGE_PADDING,_y+STAGE_PADDING,
                               _w-KEY_PADDING*2,KEY_AREA-KEY_PADDING*2);
        _obj.graphics.endFill();
    }
    private function make_enterkey_image(_obj:Sprite, _x:int,_y:int, _col:int,_tp:Number):void {
        _obj.graphics.lineStyle(0,KEY_COLOR_OUTLINE);
        _obj.graphics.beginFill(_col,_tp);
        _obj.graphics.moveTo(_x+STAGE_PADDING,_y+STAGE_PADDING);
        //→
        _obj.graphics.lineTo(_x+STAGE_PADDING + KEY_AREA*15 - (_x+STAGE_PADDING)-KEY_PADDING*2 + 3,
                             _y+STAGE_PADDING);
        //↓
        _obj.graphics.lineTo(_x+STAGE_PADDING + KEY_AREA*15 - (_x+STAGE_PADDING)-KEY_PADDING*2 + 3,
                             _y+STAGE_PADDING + KEY_AREA-KEY_PADDING*2 + KEY_AREA-KEY_PADDING*2 + (KEY_PADDING*2));
        //←
        _obj.graphics.lineTo(_x+STAGE_PADDING+Math.floor(KEY_AREA/4),
                             _y+STAGE_PADDING + KEY_AREA-KEY_PADDING*2 + KEY_AREA-KEY_PADDING*2 + (KEY_PADDING*2));
        //↑
        _obj.graphics.lineTo(_x+STAGE_PADDING+Math.floor(KEY_AREA/4),
                             _y+STAGE_PADDING + KEY_AREA-KEY_PADDING*2);
        //←
        _obj.graphics.lineTo(_x+STAGE_PADDING,
                             _y+STAGE_PADDING + KEY_AREA-KEY_PADDING*2);
        //↑
        _obj.graphics.lineTo(_x+STAGE_PADDING,_y+STAGE_PADDING);
        _obj.graphics.endFill();
    }
}//class