TextEngineMouseDrag on 2011-8-12

by momolab
♥0 | Line 293 | Modified 2011-08-12 15:42:23 | MIT License
play

ActionScript3 source code

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

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFieldType;
    import flash.text.TextFormat;
    
    import flash.display.Loader;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.net.URLRequest;
    import flash.text.TextFormat;
    import flash.text.engine.ContentElement;
    import flash.text.engine.ElementFormat;
    import flash.text.engine.FontDescription;
    import flash.text.engine.FontPosture;
    import flash.text.engine.FontWeight;
    import flash.text.engine.GraphicElement;
    import flash.text.engine.GroupElement;
    import flash.text.engine.TextBlock;
    import flash.text.engine.TextElement;
    import flash.text.engine.TextLine;
    import flash.ui.Mouse;
    import flash.ui.MouseCursor;
    
    public class TestDaumTextEngine extends Sprite {
        private var _textField:TextField;
        
        private var _textBlock:TextBlock;
        private var fontDescription:FontDescription;
        private var elementFormat:ElementFormat;
        private var textEngineLayer:Sprite;
        private var contentCollection:Vector.<ContentElement>;
        
        private var _eventDispatcher:EventDispatcher;
        private var _selectionBeginIndex:int = -1;
        private var _selectionEndIndex:int = -1;
        
        public function TestDaumTextEngine() {
            // Test Text Engine
            var format:TextFormat = new TextFormat();
            format.font = "Malgun Gothic";
            format.size = 20;
            format.color = 0x333333;
            format.bold = false;
            format.italic = false;
            
            createTextField(format);
            
            fontDescription = new FontDescription();
            elementFormat = new ElementFormat();
            textLinesDefaultFormat(format);
            
            textEngineLayer = new Sprite();
            addChild(textEngineLayer);
            
            _eventDispatcher = new EventDispatcher();
            _eventDispatcher.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
            _eventDispatcher.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
            _eventDispatcher.addEventListener(MouseEvent.MOUSE_OVER, mouseOverOutHandler);
            _eventDispatcher.addEventListener(MouseEvent.MOUSE_OUT, mouseOverOutHandler);
        }
        
        private function mouseOverOutHandler(event:MouseEvent):void {
            Mouse.cursor = (event.type == MouseEvent.MOUSE_OVER || event.buttonDown) ? MouseCursor.IBEAM : MouseCursor.ARROW;
        }
        
        private function mouseMoveHandler(event:MouseEvent):void {
            if(!event.buttonDown)
                return;
            
            var line:TextLine;
            if (event.target is TextLine) {
                line = TextLine(event.target);
            }
            else {
                line = TextLine(event.target.parent);
            }
            _selectionEndIndex = line.textBlockBeginIndex + line.getAtomIndexAtPoint(event.stageX, event.stageY);
            drawBackground(_selectionBeginIndex, _selectionEndIndex);
        }
        
        private function mouseDownHandler(event:MouseEvent):void {
            stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
            graphics.clear();
            var line:TextLine;
            if (event.target is TextLine) {
                line = TextLine(event.target);
            }
            else {
                line = TextLine(event.target.parent);
            }
            _selectionBeginIndex = line.textBlockBeginIndex + line.getAtomIndexAtPoint(event.stageX, event.stageY);
        }
        
        private function mouseUpHandler(event:MouseEvent):void {
            stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
            
            var objs:Array = getObjectsUnderPoint(new Point(event.stageX, event.stageY));
            var obj:Object;
            var found:Boolean = false;
            while(objs.length) {
                if (objs.pop() is TextLine) {
                    found = true;
                    break;
                }
            }
            
            Mouse.cursor = found ? MouseCursor.IBEAM : MouseCursor.ARROW;
        }
        
        private function drawBackground(begin:int, end:int):void {
            var i:int, l:int;
            
            graphics.clear();
            
            if (begin > end) {
                var begin2:int = begin;
                begin = end;
                end = begin2;
            }
            
            var line:TextLine;
            for(i = 0, l = this.numChildren ; i < l ; i++) {
                line = this.getChildAt(i) as TextLine;
                if (line.textBlockBeginIndex <= begin && (line.textBlockBeginIndex + line.rawTextLength) >= begin) {
                    break;
                }
            }
            
            var startLine:TextLine = line;
            
            for(i = 0, l = this.numChildren ; i < l ; i++) {
                line = this.getChildAt(i) as TextLine;
                if(line.textBlockBeginIndex <= end && (line.textBlockBeginIndex + line.rawTextLength) >= end) {
                    break;
                }
            }
            
            var endLine:TextLine = line;
            line = startLine;
            var bounds:Rectangle;
            
            try {
                while(true) {
                    if (line == null) {
                        break;
                    }
                    
                    if (line == startLine) {
                        if (startLine == endLine) {
                            bounds = line.getAtomBounds(Math.min(Math.max(begin - line.textBlockBeginIndex, 0), line.rawTextLength - 1)).union(line.getAtomBounds(Math.min(Math.max(end - line.textBlockBeginIndex, 0), line.rawTextLength - 1)));
                        }
                        else {
                            bounds = line.getAtomBounds(Math.min(Math.max(begin - line.textBlockBeginIndex, 0), line.rawTextLength - 1)).union(line.getAtomBounds(line.rawTextLength - 1));
                        }
                        bounds.x += line.x;
                        bounds.y += line.y;
                    }
                    else if (line == endLine) {
                        bounds = line.getAtomBounds(Math.min(Math.max(end - line.textBlockBeginIndex, 0), line.rawTextLength - 1)).union(line.getAtomBounds(0));
                        bounds.x += line.x;
                        bounds.y += line.y;
                    }
                    else {
                        bounds = line.getBounds(line.parent);
                    }
                    
                    graphics.beginFill(0x6699ff, .2);
                    graphics.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
                    
                    if(line == endLine) {
                        break;
                    }
                    
                    line = line.nextLine;
                }
            }
            catch(e:Error) {
            }
        }
        
        private function createTextField(format:TextFormat):void {
            _textField = new TextField();
            _textField.type = TextFieldType.INPUT;
            _textField.autoSize = TextFieldAutoSize.LEFT;
            _textField.multiline = true;
            _textField.border = true;
            _textField.borderColor = 0;
            addChild(_textField);
            
            _textField.defaultTextFormat = format;
            
            _textField.addEventListener(Event.CHANGE, textFieldChangeHandler);
        }
        
        private function textFieldChangeHandler(event:Event):void {
            createTextLines(event.target.text);
            
            textEngineLayer.y = _textField.y + _textField.height;
        }
        
        private function createTextLines(value:String):void {
            var textLine:TextLine = null;
            var groupElement:GroupElement;
            var lineY:Number = 0;
            
            removeAllTextLine();
            
            var contentCollection:Vector.<ContentElement> = parseText(value);
            groupElement = new GroupElement(contentCollection, null, _eventDispatcher);
            
            _textBlock = new TextBlock();
            _textBlock.content = groupElement;
            
            while(textLine = _textBlock.createTextLine(textLine)) {
                textEngineLayer.addChild(textLine);
                lineY += textLine.height;
                textLine.y = lineY;
            }
        }
        
        private function parseText(value:String):Vector.<ContentElement> {
            var contentCollection:Vector.<ContentElement> = new Vector.<ContentElement>();
            var textElement:TextElement;
            var graphicElement:GraphicElement;
            var char:String;
            
            for(var i:int = 0, l:int = value.length; i < l; i++) {
                char = value.charAt(i);
                
                switch (char) {
//                    case "A" :
//                    case "B" :
//                    case "C" :
//                    case "D" :
//                    case "E" :
//                    case "F" :
//                        graphicElement = createGraphicElement(char, elementFormat, 64, 64);
//                        contentCollection.push(graphicElement);
//                        break;
                    case "1" :
                        graphicElement = createGraphicElementWithURL("http://cdn1.iconfinder.com/data/icons/animals/48/Panda.png", elementFormat, 48, 48);
                        contentCollection.push(graphicElement);
                        break;
                    case "2" :
                        graphicElement = createGraphicElementWithURL("http://cdn1.iconfinder.com/data/icons/animals/48/Elephant.png", elementFormat, 48, 48);
                        contentCollection.push(graphicElement);
                        break;
                    case "3" :
                        graphicElement = createGraphicElementWithURL("http://cdn1.iconfinder.com/data/icons/animals/48/Butterfly.png", elementFormat, 48, 48);
                        contentCollection.push(graphicElement);
                        break;
                    case "4" :
                        graphicElement = createGraphicElementWithURL("http://cdn1.iconfinder.com/data/icons/animals/48/Dolphin.png", elementFormat, 48, 48);
                        contentCollection.push(graphicElement);
                        break;
                    case "a" :
                        graphicElement = createGraphicElementWithURL("http://cdn1.iconfinder.com/data/icons/walle/64/my_computer.png", elementFormat, 64, 64);
                        contentCollection.push(graphicElement);
                        break;
                    case "b" :
                        graphicElement = createGraphicElementWithURL("http://cdn1.iconfinder.com/data/icons/walle/64/media_player.png", elementFormat, 64, 64);
                        contentCollection.push(graphicElement);
                        break;
                    case "c" :
                        graphicElement = createGraphicElementWithURL("http://cdn1.iconfinder.com/data/icons/walle/64/my_documents.png", elementFormat, 64, 64);
                        contentCollection.push(graphicElement);
                        break;
                    case "d" :
                        graphicElement = createGraphicElementWithURL("http://cdn1.iconfinder.com/data/icons/walle/64/basket_empty.png", elementFormat, 64, 64);
                        contentCollection.push(graphicElement);
                        break;
                    case "e" :
                        graphicElement = createGraphicElementWithURL("http://cdn1.iconfinder.com/data/icons/walle/64/search.png", elementFormat, 64, 64);
                        contentCollection.push(graphicElement);
                        break;
                    case "f" :
                        graphicElement = createGraphicElementWithURL("http://cdn1.iconfinder.com/data/icons/walle/64/network.png", elementFormat, 64, 64);
                        contentCollection.push(graphicElement);
                        break;
                    case "g" :
                        graphicElement = createGraphicElementWithURL("http://server2.iconfinder.com/data/icons/walle/64/basket_full.png", elementFormat, 64, 64);
                        contentCollection.push(graphicElement);
                        break;
                    case "h" :
                        graphicElement = createGraphicElementWithURL("http://server2.iconfinder.com/data/icons/walle/64/my_applications.png", elementFormat, 64, 64);
                        contentCollection.push(graphicElement);
                        break;
                    default :
                        textElement = createTextElement(char, elementFormat);
                        contentCollection.push(textElement);
                        break;
                }
            }
            
            return contentCollection;
        }
        
        private function textLinesDefaultFormat(format:TextFormat):void {
            fontDescription = fontDescription.clone();
            elementFormat = elementFormat.clone();
            
            fontDescription.fontName = (format.font) ? format.font : fontDescription.fontName;
            elementFormat.fontSize = (format.size) ? Number(format.size) : elementFormat.fontSize;
            elementFormat.color = (format.color) ? uint(format.color) : elementFormat.color;
            fontDescription.fontWeight = (format.bold) ? FontWeight.BOLD : fontDescription.fontWeight;
            fontDescription.fontPosture = (format.italic) ? FontPosture.ITALIC : fontDescription.fontPosture;
            
            elementFormat.fontDescription = fontDescription;
        }
        
        private function createGraphicElement(name:String, format:ElementFormat, elementWidth:Number = 15.0, elementHeight:Number = 15.0):GraphicElement {
            var graphicElement:GraphicElement = new GraphicElement(new this[name](), elementWidth, elementHeight);
            graphicElement.elementFormat = format;
            
            return graphicElement;
        }
        
        private function createGraphicElementWithURL(url:String, format:ElementFormat, elementWidth:Number = 15.0, elementHeight:Number = 15.0):GraphicElement {
            var tempGraphic:Shape = new Shape();
            tempGraphic.graphics.drawRect(0, 0, elementWidth, elementHeight);
            
            var graphicElement:GraphicElement = new GraphicElement(tempGraphic, elementWidth, elementHeight);
            graphicElement.elementFormat = format;
            
            var contentLoader:Loader = new Loader();
            var contentLoadCompleteHandler:Function = function(event:Event):void {
                graphicElement.graphic = contentLoader;
                contentLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, contentLoadCompleteHandler);
            };
            contentLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, contentLoadCompleteHandler);
            var request:URLRequest = new URLRequest(url);
            contentLoader.load(request);
            
            return graphicElement;
        }
        
        private function createTextElement(textData:String, format:ElementFormat):TextElement {
            var textElement:TextElement = new TextElement(textData, elementFormat);
            
            return textElement;
        }
        
        private function removeAllTextLine():void {
            while(textEngineLayer.numChildren) {
                textEngineLayer.removeChildAt(0);
            }
        }
    }
}