views:

33

answers:

2

I'm new to Flex/Actionscript and have a very basic question.

Let's say I have about 100+ buttons. They all have the same label. Now I want to change the label for all with a click. I could give them IDs and then run a for loop, but I'm searching for a neater solution.

Thanks for help.

Update:

Hm, it doesn't work because label of buttons are modified during the run time. This is the code

public function changeButton(event:Event):void {
    if (event.target.label != 'X') {
    event.target.label ='X';
    } else {
    event.target.label ='';
    }
}

Now I need a button that will on click delete/replace this label with an empty one.

+3  A: 

If you're using Flex, you can use databinding:

[Bindable] myButtonLabel:String = "Default Label";

<mx:Label id="label1" text="{myButtonLabel}"/>
<mx:Label id="label2" text="{myButtonLabel}"/>

function buttonClick(evt:Event):void {
    myButtonLabel = "New Label";
}

Whenever you change the value of myButtonLabel all labels will change.

Jordan
From info given, this seems a good candidate to subclass Button and encapsulate this behaviour in the actual button using the technique above.
David Collie
+1  A: 

Off the top of my head I can offer you several solutions, depending on your definition of 'neat'. I guess the 'neatest' would be dispatching an event. But I will outline all three:

1.Have label itself be an event dispatcher or some object that can notify whatever "is labelled" with its particular value. This can be seen as a variation of solution #3 of course, but is NOT. Your buttons will register listeners on the label they are assigned, and by making the label change operation dispatch a change event your buttons will have a chance to update their label display. This is neat because you can have a reusable generic programming pattern along:

class Button
{
    var label_tf: TextField;

    public function Button(label: *)
    {
        if(label is IEventDispatcher)
        {
            label.addEventListener("change", on_label_change_event, false, 0, true);
        }

        label_tf.text = label;
    }

    function on_label_change_event(event: Event)
    {
        label_tf.text = event.target;
    }
}

dynamic class DynamicEventDispatcher extends EventDispatcher
{
}

var label = new DynamicEventDispatcher();
label.value = "Cancel"
label.toString = function() { return this.value; };

var button1 = new Button(label);
var button2 = new Button(label);
var buttonN = new Button(label);

/// Now make all buttons display 'Cancel' in Spanish ;-)
label.value = "Anular";
label.dispatchEvent(new Event("change"));

2.Another one, like what you thought of but thought was not neat enough, which I assume would be faster to update is keeping a track of buttons with the same label in a container that is easily iteratable, e.g. a dictionary (need weak keys, so a vector won't do!)

class Button
{
    static var buttons_by_label: Dictionary;

    static function init_class()
    {
        buttons_by_label = new Dictionary(true);
    }

    static function reset_identical_labels(old_value: String, new_value: String)
    {
        if(buttons_by_label[old_value] === undefined)
        {
            throw new Error("No buttons with specified label value.");
        }

        for(var button: Button in buttons_by_label[old_value])
        {
            button.label = new_value;
        }
    }

    var label_tf: TextField;

    public function Button(label: String)
    {
        this.label = label;
    }

    public function get label()
    {
        return label_tf.text;
    }

    public function set label(new_value: String)
    {
        var old_value: String = label_tf.text;

        if(buttons_by_label[old_value] !== undefined)
        {
            delete buttons_by_label[old_value][this];
        }

        if(buttons_by_label[new_value] === undefined)
        {
            buttons_by_label[new_value] = new Dictionary(true);
        }

        buttons_by_label[new_value][this] = true;

        label_tf.text = new_value;
    }
}

Button.init_class();

var button1 = new Button("Cancel");
var button2 = new Button("Cancel");
var buttonN = new Button("Cancel");

Button.reset_identical_labels("Cancel", "Anular");

3.Use the benefits of display list hierarchy and the event flow model to have Flash Player do most of the work for you:

class Button
{        
    var label_tf: TextField;

    public function Button(label: String)
    {
        this.label = label;

        stage.addEventListener("request.button.update_label", 
            on_update_label_request_event, 
            false, 0,true);
    }

    public function get label()
    {
        return label_tf.text;
    }

    public function set label(new_value: String)
    {            
        label_tf.text = new_value;
    }

    function on_update_label_request_event(event: LabelUpdateRequestEvent)
    {
        if(label == event.old_value)
        {
            label = event.new_value;
        }
    }
}

class LabelUpdateRequestEvent extends Event
{
    public var old_value: String;
    public var new_value: String;

    public function LabelUpdateRequestEvent(old_value: String, new_value: String)
    {
        super("request.button.update_label");

        this.old_value = old_value;
        this.new_value = new_value;
    }
}

var button1 = new Button("Cancel");
var button2 = new Button("Cancel");
var buttonN = new Button("Cancel");

stage.dispatchEvent(new LabelUpdateRequestEvent("Cancel", "Anular"));

What I suggest you do is examine the weaknesses and strengths of each - all of them DO have both - and use a hybrid solution. The first has the effect of separating the value of a label with a reference to the value, i.e. two different label objects both with "Cancel" as value will NOT change each other, even though the label is actually identical. The other two solutions don't separate value from reference. With them however you get the extra cost of adding too many event listeners with too many buttons, something the second solution does not do. This all was off the top of my head, but you have an interesting problem, use your fantasy now :-)

amn