how can I write a generic property modification function in Flex/Actionscript3? - apache-flex

I'm new to Flex, although not new to programming. I want to write a generic event handler that will be called by all my textinput boxes when they receive focus. When they have focus, I want to change the colour of the textinput box. When they lose focus, I want to restore the "inactive" color profile. I could write an ActionScript event handler for each textinput box, but we all know that's lame. :o) What I need, then, is a way to access the object which is calling the event handler.
In Delphi, I'd have written a function which passes in the Sender object, allowing me to access the calling object's properties. I'm guessing ActionScript/Flex has a completely different architecture, which is why I'm having difficulty doing this.
Thanks in anticipation!

You should subclass TextInput and handle the focus events in there. I think this would be the simplest way to achieve what you are looking for without having any complex code.

I hope I'm understanding what you're asking for... are you talking about event delegation?
This worked for me:
// 'focusOut' for blur
stage.addEventListener('focusIn', function(e:Event):void {
// The focused control is e.target
});

If you want to change the look of the focused input box, you can do this by setting the focusSkin property. If you want this to happen globally, you can put a style declaration in your CSS file.
In this CSS example I'm replacing the default focusSkin (mx.skins.halo.HaloFocusRect) with an embedded PNG file.
TextInput {
focusSkin: Embed(source="focus.png");
}
TextInput has a few properties for altering the look of the focus, like changing the opacity of the focus skin (focusAlpha property). Check the TextInput documentation for more info.

Related

JavaFX - Keeping Focus on a "Default" Component

I'm looking for the most concise way to deal with focus in an application which renders a map in a canvas component. You can pan the map location using arrow keys or ASWD keys. So far, I've been giving the canvas focus at startup and handling key pressed events via canvas.setOnKeyPressed().
This works fine, but I've always known that a problem was on the horizon when other components enter the picture. Once you interact with another component, it gains focus, and you're unable to scroll around the canvas map. I can prevent this from happening with some components like Hyperlinks or Buttons (I don't need tab-navigation) with something like this for those components:
sidePanel.getChildren().forEach(node -> node.setFocusTraversable(false));
But, when we get to things like TextArea or TextField, those do need to hold focus while they're being edited. And I'll need some way to return focus back (or at least unfocus those components) without being an annoyance to the user. (I don't want to have to click the canvas for it to regain focus.)
The options I see for returning focus back to the canvas after the user is done with those fields seem to be:
Add a key handler (ex. ESC or ENTER keypress) on EACH of these components which returns focus back to the canvas.
Maybe not so concise, and a bit of a pain... also feels a bit fragile; if I miss something and the canvas loses focus, it would fail - I need a 100% reliable solution.
Extend each of these components and add similar code to return focus back to Canvas
Even nastier and requires using custom components in Scene Builder, which
is not ideal.
Add a global event handler on the Scene and transmit events to the controller which owns the canvas
I believe an event filter would accomplish this - but on the other hand if the user is simply using arrow keys to move around a TextArea, I wouldn't want the Canvas map to move!
To solve the above problem, possibly the global event handler could ignore ASWD and arrow keypresses if the focus is on certain types of components? Is this worth trying, or am I neglecting a problem this would create?
Are there any other simple options out there that I've missed - and what would you suggest as the best option here? I'd like an automatic solution that doesn't require remembering to add some workaround code every time a UI component is added.

Flex - change and focusOut in one event?

I need to be able to trigger an event on change, but only when user focus out of the input text.
Is there any one event I can use?
I guess I can use a combination of both, by finding out which of them triggers last, and only use that, if the other has been called, but that introduces some complexity and clutters the code.
There's no single event that combines both of these concepts. You'll need to write some custom logic to do what you're describing.
Using the mx.managers.FocusManager getFocus() method you can find the component that currently has focus. In the change handler on the TextInput you can check if this TextInput currently is the component with focus. If not, you can go about your business.

NavigatorContent onSelect

Is there any shortcut way to add an eventListener to something like a select event for NavigatorContent.
I am aware I can add a listener for a change event on the ViewStack and identify the selected NavigatorContent through that handler.
The ViewStack component dispatch a CREATION_COMPLETE event on the new selectedChild
As2 has shortcuts for what you want, im afraid as3 doesnt as AS3 wants to know exactly whats needed to care for at what time.
an update /enterframe function can reduce some code but apply more load on the swf over all as its waitng for a call.
throw some code up in your question so we all know exactly what your talking about.

setting the default button in preinitialization

I have a more than one container in a view. I am trying to set default button at the moment page is loaded so that when I press enter, function that handles keydown event called. If I simply set default button in preinit() function, it does not work.
How can I do this ?
It's tough to debug "Does not work" sometimes. But, in this case I suspect you get a "Null value" style error.
The preinitialize event is fired before createChildren() so most likely the button you want make the "Default" doesn't exist yet. More info about the Flex Component LifeCycle.
You can move your code to the initialize event.
I assume that by "setting the default" you mean you are using the FocusManager to give your button focus?
Assuming I understand your question correctly, you need to do two things to make this work.
Set the defaultButton
Set focus to the container or some child of the container
As #Flextras said, preinit may also not be the best choice for this.
If the container is declared in MXML, I recommend setting the defaultButton property in the MXML declaration, and setting focus on creationComplete.

Flex: Modify an embedded icon and use it in a button?

Just that, if you embed an icon:
[Embed(source='icons/checkmark.png')]
private static var CheckMark:Class;
You end up with a dynamic class. You can pretty easily assign the icon to a button at runtime by calling the setStyle method:
var btn:Button = new Button();
btn.setStyle("icon", CheckMark);
But what if you wanted to alter the icon at runtime, like changing it's alpha value or even redrawing pixels, before assigning it to the button?
So far I can't find a satisfactory answer...
This is the only answer I could find that seemed close: Dynamic Icons (example with View Source)
His solution involves a custom "DynamicIcon" class which is used in the button's icon setting, and a custom Button class which adds one method to the Button class to draw dynamic icons.
The end result is that you are able to send BitmapData to the DynamicIcon class, which will show up in the button. So, embed your image, instantiate your asset class, get the bitmapasset and modify it however you need to and send the bitmapData to the icon.
It's an interesting problem and it seems like there should be an easier solution, but this works without a lot of hassle.
The way I'd solve this is to implement a programmatic skin class that draws the icon itself manually. There's probably more work you'll have to do to ensure the button calculates the correct size as if it has an icon even though it doesn't. You may have to poke through the Button source code to look at how the reference to the icon is stored.
I love just creating programmatic skins that do exactly what I want and then using interesting CSS declarations to modify states - for instance:
button.setStyle("customIconAlpha", .4);
and then of course the skin or the custom button class would have:
var alpha:Number = getStyle("customIconAlpha") as Number;
(not sure if you have to typecast that one)
The big problem I found with programmatic skins is that the button refuses to measure the width/height. I easily got around this by overriding the get methods for each:
override public function get width():Number { return WIDTH; }
override public function get height():Number { return HEIGHT; }
In my case I needed to modify buttons in a TabNavigator, hence no easy way to subclass the button. Thankfully, the parent of each skin is the button, so using static methods within your skin, you can identify the instance of the Button to which the icon skins belong.
If you're using the cover-all "icon" style, a new skin object will be created for each state. So you'll need to keep this in mind when changing the state of the icons.

Resources