views:

52

answers:

1

Hi all,

I want to be able to write a paragraph in a textfield, and then click and hold, or do some similar gesture, and have the entire paragraph selected. I'm then going to drag it (using bitmapdata or whatever) to another textfield.

In order to do this, I need to be able to detect where a given paragraph ends. So I'm trying to do that with the following code, which searches for "\n" in the text. It isn't finding it. Can anyone see why (or suggest another technique for doing this)?

TIA,

David

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldType;

import view.controls.CustomButton;

public class Main extends Sprite
{
    private var bt:CustomButton;
    private var tf:TextField;

    public function Main()
    {
        tf = new TextField();
        tf.name = "tfield";
        tf.type = TextFieldType.INPUT;
        tf.width = 400;
        tf.height = 200;
        tf.x = 100;
        tf.y = 100;
        tf.selectable = true;
        tf.border = true;
        tf.background = true;
        tf.backgroundColor = 0xFFFFFF;
        tf.multiline = true;
        tf.text = "Like most of the things I get excited about and share with you, this technique really doesn’t have much to it, but I love its elegance, how it works in the background and gets out of your way. While it’s really simple I think this one is a real gem, ’cause when you look at a class that uses it, it looks like magic!\n\nOkay, so you know how when you’re writing a site or app that’s of a small to medium scale, you default to storing data in XML, and you map that XML to model classes, usually pretty directly? Or, maybe you use a configuration file for your site to load in some constants or something, and XML is a pretty easy choice for this. With E4X you can really parse through that XML quickly.";
        tf.wordWrap = true;
        addChild(tf);

        bt = new CustomButton("Detect", 0xFFFFFF, 0x000000,50,20);
        bt.x = 250;
        bt.y = 350;
        addChild(bt);
        addEventListener(Event.ADDED_TO_STAGE, init);

    }

    private function init(e:Event):void
    {
        bt.addEventListener(MouseEvent.CLICK, clickHandler);
    }

    private function clickHandler(e:MouseEvent):void
    {
        var lineBreak:int = tf.text.indexOf("\n");
        trace(lineBreak);
    }
}
}
//custom button class

package view.controls

{ import flash.display.GradientType; import flash.display.SimpleButton; import flash.display.Sprite; import flash.display.Stage; import flash.events.Event; import flash.geom.Matrix; import flash.text.TextField; import flash.text.TextFormat; import flash.text.TextFormatAlign;

public class CustomButton extends Sprite
{
    private var textColor:uint = 0x000000;
    private var myColor:uint = 0xFEEE9E9;
    private var btnWidth:Number;
    private var btnHeight:Number;

    public function CustomButton(buttonText:String, gradientColor:uint, borderColor:uint, myBtnWidth:Number, myBtnHeight:Number)
    {
        var colors:Array = new Array();
        var alphas:Array = new Array(1, 1);
        var ratios:Array = new Array(0, 255);
        var gradientMatrix:Matrix = new Matrix();
        var lineThickness:Number = 1;
        //var myColor:uint = 0xFF0000;
        gradientMatrix.createGradientBox(myBtnWidth, myBtnHeight, Math.PI/2, 0, 0);

        this.btnWidth = myBtnWidth;
        this.btnHeight = myBtnHeight;
        var ellipseSize:int = 20;
        var btnUpState:Sprite = new Sprite();
        colors = [0xFFFFFF, myColor];
        //btnUpState.graphics.lineStyle(1, brightencolor(myColor, -500));
        btnUpState.graphics.lineStyle(lineThickness, borderColor);
        btnUpState.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, gradientMatrix);
        btnUpState.graphics.drawRoundRect(0, 0, myBtnWidth, myBtnHeight, ellipseSize, ellipseSize);
        btnUpState.addChild(createButtonTextField(buttonText, textColor));
        //
        var btnOverState:Sprite = new Sprite();
        colors = [0xFFFFFF, brightencolor(myColor, 50)];
        //btnOverState.graphics.lineStyle(1, brightencolor(myColor, -50));
        btnOverState.graphics.lineStyle(lineThickness, borderColor);
        btnOverState.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, gradientMatrix);
        btnOverState.graphics.drawRoundRect(0, 0, myBtnWidth, myBtnHeight, ellipseSize, ellipseSize);
        btnOverState.addChild(createButtonTextField(buttonText, textColor))
        //
        var btnDownState:Sprite = new Sprite();
        //colors = [brightencolor(myColor, -15), brightencolor(myColor, 50)];
        btnDownState.graphics.lineStyle(lineThickness, borderColor);
        btnDownState.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, gradientMatrix);
        btnDownState.graphics.drawRoundRect(0, 0, myBtnWidth, myBtnHeight, ellipseSize, ellipseSize);
        btnDownState.addChild(createButtonTextField(buttonText, textColor))
        //
        this.btnWidth = myBtnWidth;
        this.btnHeight = myBtnHeight;

        var myButton:SimpleButton = new SimpleButton(btnUpState, btnOverState, btnDownState, btnOverState);
        myButton.name = buttonText;
        addChild(myButton);

    }


    private function createButtonTextField(Text:String, textcolor:uint):TextField {
        var myTextField:TextField = new TextField();
        myTextField.textColor = textcolor;
        myTextField.selectable = false;
        myTextField.width = btnWidth;
        myTextField.height = btnHeight;
        var myTextFormat:TextFormat = new TextFormat();
        myTextFormat.align = TextFormatAlign.CENTER;
        myTextFormat.font = "Arial";
        myTextFormat.size = 12;
        myTextField.defaultTextFormat = myTextFormat;

        myTextField.text = Text;
        myTextField.x = (btnWidth/2)-(myTextField.width/2);
        myTextField.y = 1;
        return myTextField;
    }

    private function brightencolor(color:int, modifier:int):int {
        var hex:Array = hexToRGB(color);
        var red:int = keepInBounds(hex[0]+modifier);
        var green:int = keepInBounds(hex[1]+modifier);
        var blue:int = keepInBounds(hex[2]+modifier);
        return RGBToHex(red, green, blue);
    }

    private function hexToRGB (hex:uint):Array {
        var colors:Array = new Array(); 
        colors.push(hex >> 16);
        var temp:uint = hex ^ colors[0] << 16;
        colors.push(temp >> 8);
        colors.push(temp ^ colors[1] << 8);
        return colors;
    }

    private function keepInBounds(number:int):int {
        if (number < 0)    number = 0;
        if (number > 255) number = 255;
        return number;
    }    
    private function RGBToHex(uR:int, uG:int, uB:int):int {
        var uColor:uint;
        uColor =  (uR & 255) << 16;
        uColor += (uG & 255) << 8;
        uColor += (uB & 255);
        return uColor;
    }
}
}
+1  A: 
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.display.Sprite;
import flash.events.MouseEvent;

var tf:TextField = new TextField();
tf.type = TextFieldType.INPUT;
tf.width = 400;
tf.height = 200;
tf.x = stage.stageWidth / 2 - tf.width / 2;
tf.y = stage.stageHeight / 2 - tf.height / 2;
tf.selectable = true;
tf.border = true;
tf.background = true;
tf.backgroundColor = 0xCCCCCC;
tf.multiline = true;
tf.wordWrap = true;
tf.text = "Enter text here, hit enter to create new paragraphs."
stage.addChild(tf);

var pushme:Sprite = new Sprite();
pushme.graphics.beginFill(0xCCCCCC, 1);
pushme.graphics.drawRect(0, 0, 100, 25);
pushme.graphics.endFill();
pushme.buttonMode = true;
pushme.addEventListener(MouseEvent.CLICK, pushedme);
pushme.x = tf.x + tf.width - pushme.width;
pushme.y = tf.y + tf.height + 15;
stage.addChild(pushme);

function pushedme(e:MouseEvent):void {
    var paragraphCounter:int = 1;
    var curParagraphOffset:int = -1;
    for (var i:int = 0; i < tf.numLines; i++) {
        if (tf.getFirstCharInParagraph(tf.getLineOffset(i)) == tf.getLineOffset(i) && tf.getFirstCharInParagraph(tf.getLineOffset(i)) > curParagraphOffset) {
            trace("Paragraph " + paragraphCounter + " text: \n" + tf.text.substr(tf.getFirstCharInParagraph(tf.getLineOffset(i)), tf.getParagraphLength(tf.getFirstCharInParagraph(tf.getLineOffset(i)))));
            paragraphCounter++;
            curParagraphOffset = tf.getFirstCharInParagraph(tf.getLineOffset(i));
        }
    }
}

Paragraph Detection

Paragraph Detection


Step by step

You can probably take it from here and ignore the empty paragraphs, but to explain:

  1. Setup textfield, input more text manually (as shown)
  2. Create the button to check for paragraphs
  3. Set paragraph counter to 1 so it outputs properly for the first detected paragraph
  4. Paragraph offset needs to be -1 for the if statement to be satisfied for the first iteration as the first paragraph should be at character 0
  5. If the first character in the paragraph is also the first character on this line and we're not part of the previous paragraph, we have a new paragraph on this line.
  6. Output the paragraph text based on the first character and the length of the paragraph by taking a substring of the tf.text property.
  7. Increment paragraphCounter and set the curParagraphOffset to the new first character index.

If you want to be able to click and hold on a given paragraph, all you need to do is call:

tf.getCharIndexAtPoint(x, y)

on click of your text field. You can then find the first character in that paragraph, grab the substring based on the paragraph length, and go from there.

Hope this helps!

Tegeril
Tremendous. Clear and concise. Thanks.
David
You're welcome!
Tegeril
Looking back over this, it is probably doable without the entire curParagraphOffset part, but I was being safe.
Tegeril
+1. Very nice answer.
Juan Pablo Califano