Question

I'm trying to change the color of all 4-letter words in a spark.components.Label.

It is a chat-like program, where user enters words into the TextInput field, presses ENTER and the lines are appended to the Label (or Text or TextArea or RichText - whatever is suitable here).

I have prepared this simple test case below, it will run instantly in your Flash Build 4.6 and the code to find the words and their indices is already there.

My problem is to figure out how to change the color of text parts programmatically (i.e. by ActionScript 3) and repeatedly, I just can't figure it out despite reading the docs again and again.

Screenshot:

screenshot

Test.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    minWidth="400" minHeight="300">

    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;

            private const WORD:RegExp = /\b[a-z]{4}\b/i; 

            public function chat(event:FlexEvent):void {
                var line:String = _input.text;
                var start:int = 0;

                do {
                    var rest:String = line.substr(start);
                    var found:int = rest.search(WORD);
                    // no more 4-letter words found
                    if (found < 0)
                        break;
                    var word:String = rest.substr(found, 4);
                    trace('word=' + word + ' @ index=' + (start + found));
                    start += found + 4;
                } while (start + 4 <= line.length);

                _output.text += (line + "\n"); 
                _input.text = '';
            }
        ]]>
    </fx:Script>

    <s:Label id="_output" left="4" top="4" right="4" bottom="24" backgroundColor="0xFFFFCC" />
    <s:TextInput id="_input" bottom="4" right="4" enter="chat(event)" />
</s:Application>

UPDATE: I'm trying RichText + the code below as suggested by Georgi and see that the pattern replacement has worked (by looking at the trace() output), but get the error:

TypeError: Error #1034: Type Coercion failed: cannot convert "[object TextFlow][object TextFlow]" to flashx.textLayout.elements.TextFlow.

<?xml version="1.0" encoding="utf-8"?>
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    minWidth="400" minHeight="300">

    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;
            import flashx.textLayout.conversion.TextConverter;

            private const WORD:RegExp = /\b[a-z]{4}\b/ig; 

            public function chat(event:FlexEvent):void {
                var line:String = _input.text.replace(WORD, '<font color="#FF0000">$&</font>') + '<br>';
                trace('line=' + line);
                // XXX how to append text here? XXX
                _output.textFlow += TextConverter.importToFlow(line, TextConverter.TEXT_FIELD_HTML_FORMAT); 
                _input.text = '';
            }
        ]]>
    </fx:Script>

    <s:RichText id="_output" left="4" top="4" right="4" bottom="24" />
    <s:TextInput id="_input" bottom="4" right="4" enter="chat(event)" />

</s:Application>

UPDATE 2: If I use _output.textFlow = above then the TypeError goes away. But I need to append the text somehow...

Was it helpful?

Solution

I don't think it's possible with a s:Label component. You may try using s:RichText (which, luckily, isn't very different from s:Label) with appropriate HTML formatting. You'll have to keep the produced HTML and set the textFlow every time, by using TextConverter first. Something like this:

<?xml version="1.0" encoding="utf-8"?>
<s:Application 
   xmlns:fx="http://ns.adobe.com/mxml/2009" 
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx" 
   minWidth="400" minHeight="300">

<fx:Script>
    <![CDATA[
        import flashx.textLayout.conversion.TextConverter;

        import mx.events.FlexEvent;

        private const WORD:RegExp = /\b([a-z]{4})\b/ig; 

        private var output:String = "";

        public function chat(event:FlexEvent):void {                
            output += _input.text.replace(WORD, '<font color="0xFF0000">$1</font>') + '<br>';

            _output.textFlow = TextConverter.importToFlow(output, TextConverter.TEXT_FIELD_HTML_FORMAT);

            _input.text = "";
        }
    ]]>
</fx:Script>

    <s:RichText id="_output" left="4" top="4" right="4" bottom="24" backgroundColor="0xFFFFCC" />
    <s:TextInput id="_input" bottom="4" right="4" enter="chat(event)" />
</s:Application>

The code above is not working perfectly, but seems enough to demonstrate the concept.

Edit: Note the "g" flag in the regex to match all the four-letter words.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top