How Do I See All Events Fired by an Object? - apache-flex

I am having trouble wiring up an event listener to a fl.transitions.Transition.
Is it possible to somehow view all the events an object fires? That way I could check I am using the correct event (and possible view better ones to use).

The easiest is to override the dispatchEvent method in classes where you want to intercept events.
You can find the classes in %CS_ROOT%\Common\First Run\Classes\mx\transitions\easing\.
You can also create a subclass of EventDispatcher with a custom dispatchEvent-implementation and use that as a subclass for all classes where you'll be wanting to intercept events.
greetz
back2dos

The problem is, you have to have an event type to listen for. The only way to do this is to add listeners for all the possible events.
Now, you can add a handler with an indeterminate event type, such as:
private function myUniversalHandler(event:*) : void {
trace(event.type);
trace(event.constructor.toString());
}
And this will report any event passed to it. Nevertheless, it simply won't be called unless it is listening for an event of a particular type. And adding all those listeners is a lot of work to go through. Better to study the events available to you from whatever class you are dispatching the vent from.

I would look at TransitionManager, and the events allTransitionsOutDone and allTransitionsInDone which it dispatches. I haven't used these, but my understanding of their function matches what you seem to be looking for.

checkout the online reference, you should see there all events (and inherited events) of a Class.
On a side note if you are using flex you might be using mx.states.Transition

There is no way, at runtime, to find out all the events that fire from a component. You'll have to explore the component source code to get a complete list.
Reviewing the ASDocs, as others have suggested, is a good way to get a handle on the documented events of a component; and in most cases you'll be able to find one to suit your needs.

You cannot programmatically get a list of all events fired by any given object. You can however get a list of all events fired by a standard library object (that are part of it's public interface) from its documentation (cilck on the show inherited events link) and decide whether you're using the appropriate one.

I have scratched my head quite a bit on this issue as well.
The answer is this
you can get a list of all event listeners that an object is listening to only if attached though MXML
if not attached through MXML you cannot see the events an object is listening to (attached by AS)
if you want to see all the events an object is listening to you can check for hasEventListener although this is a long coding way
another efficient way (if you can use it, I couldn't) is to monkey patch the framework and create a dictionary of listeners for every object.
you can accomplish that by patching FlexSprite and overriding the addEventListener function.
you should keep in mind, this will not work when you are loading the framework through RSL.

Related

Easy way to tell if data is dirty

I am currently using databinding on a group of spark form elements and want to know if the data class I am bound to is dirty.
It might be nice if spark "Form" elements would trigger a change event that bubbled up to and was caught by a spark "Form". Then I could just add an event listener to the form. But I don't see something like that.
So besides comparing a copy of the original data class to the bound data class OR adding a change event to each form element and capturing that event, what's an easy way of knowing a class object has changed?
Make an extension of TextInput or whatever other input elements you'll have in your form then in your components creation complete register a listener for the change event, in the handler dispatch a bubbling event, then in your document that contains the form use your custom elements and add a listener via AS3 to the Form for the event you dispatched and stop it's propagation at that point.
Otherwise I think your second solution of change handler on each wouldn't be too bad. If you have a lot of elements in the form or it's dynamic you could write a function that steps through the form items of the form and checks their children then you just have to write a switch that deals with each class type (you can use http://www.actionscriptdeveloper.co.uk/getting-the-class-of-an-object-in-as3/on each of the child elements to determine what type it is, then if it's a TextInput or whatever register the appropriate event to call your commonly used function, just be sure it has a generic Event as it's parameter since all other Events will be sub-classes thereof).
So far as I know there is no easy way to listen for changes to the underlying data from the ArrayCollection or other wrapper ListCollectionView data structures. Part of the problem is the elements added a collection aren't required to implement any sort of interface to allow for listeners to be registered. That is, the data elements aren't necessarily event dispatchers, the only other way for this information to be communicated to the List would be if the data elements had a handle on all lists that contain that element and they mark something on the lists to indicate "dirty" when any property is set. These are all achievable within the constraints of the language but aren't provided out of the box as the usage for them is probably limited and could potentially unnecessarily bloat the cpu usage of the ListCollectionView in other cases.

Flex: DataGrid and the Command Pattern

I am using a command pattern, so any changes to object state need to happen within a command execution. A normal itemeditor in a DataGrid would just make its changes on the underlying bound object, but I need to intercept that change and make it use a command.
I'm pretty new to flex, so I'm looking for ideas of how to implement this. A basic example is that I have an object with a "date" field. In the datagrid I am using a flex "DateField" component as the itemeditor. When I select a new date, I don't want it to update the datasource, I want it to call a different method where I can access the newly selected value and pass it to a command to execute. Any tips would be greatly appreciated. Thanks in advance.
Use the itemEditBegin and/or itemEditEnd events on the DataGrid and build your command in the handler. This page has a few examples of capturing the edit operation with those events.
In my opinion, you're over-engineering this to hell, to the point that it becomes unusable. Why would you need a command to just change data on the fly? I've been doing Flex for 3 years and I yet to see it done this way. The only time commands are used is for receiving information from the server.
Either way, if you really want to implement it (against my recommendation), you would probably want to do event bubbling with a controller listening higher up the display list for the event, then from there trigger a command. From within the item renderer:
this.dispatchEvent(new Event('someEvent', true));
And then higher up the display list:
dataGrid.addEventListener('someEvent', someEventHandler);
And within the handler you can run the command.

Equivalent of describeType for Flex Component EVENTS

Using "introspection" In Flex I can say:
var classInfo:XML=describeType(SomeObject);
Which will list for me the Accessors, Methods And Variables.
(http://livedocs.adobe.com/flex/3/html/help.html?content=usingas_8.html)
But what is the equivalent to programmatically inspect all of an object's possible EVENTS?
(NOT JUST the events for which event listeners have been set, but to somehow step through a list of all VALID EVENTS for which event listeners may POTENTIALLY be set -- I realize that such lists are readily available online, and that's great for cases when I know the object's type at design type, but I require some way to inspect any given displayobject programmatically at runtime, and determine what events, if any, are or may be associated with it.)
There isn't a way.
The Event information defined using the event metadata tag is done only for the purposes of code hinting and documentation via ASDocs. It has no relevance to events that the component may or may not be firing.
At any point in time, a portion of code can call "dispatchEvent" and dispatch that event. This is used very commonly for "somePropertyChanged" events which are used for bindings. These events rarely, if ever, get documented using the event metadata. But, the component still fires them.
Bubbling confuses the issue; because if a component's child fires an event where the bubble property is true; then it is almost the same as that component firing the event. How, programmatically, would you figure that out without some sort of code analyzer?
That said, there is a compiler argument to retain metadata ( keep-as3-metadata at http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_14.html and http://jacwright.com/blog/72/using-your-own-custom-metadata-in-as3/ ).
I believe if you do that, then there is a way to get the event metadata from the component; I thought using describeType. But, remember that metadata is not the whole story in terms of events.

Please some details on the MXML tag <mx:SetEventHandler />

Can anyone give me some details on the proper use of the tag <mx:SetEventHandler /> used when switching states? The Flex documentation is not very elaborate on this subject.
Especially removing event handlers has my interest.
This question is a more specific formulation of my preceding post:
Howto removeEventListener with <mx:SetEventHandler />?
thanks
Bart
SetEventHandler pretty much does what it says on the tin. For a given state you can define an event handler for a chosen event. You provide arguments to it which define the event, the function which is to be caled in response to the event, and the target object which dispatches the event. The adobe docs are pretty clear about that much.
If I understand your question correctly you want to remove an event handler rather than set one for a different state. If that is the case then you have a couple of options, you can define a different handler for each state, some of which do nothing, or you can define nulls in the function definition in the SetEventHandler tax for a given state.
<mx:State name="hasHandler">
<mx:SetEventHandler name="click" handlerFunction="doClick" target="{myClickableObject}"/>
<mx:State/>
<mx:State name="hasNoHandler">
<mx:SetEventHandler name="click" target="{myClickableObject}"/>
<mx:State/>
leaving the handlerFunction undefined sets it to null.
However, what I would do would be to define SetEventHandlers for only those states that need them. You should be able to set up the logic of your states such that you never need to remove an event handler, only set them. I think this is closer to the intended use of SetEventHandler and saves you having to rely on setting nulls for some states.
HTH. If you google "Flex SetEventHandler" there are a lot of good resources about it.
P.S. Make sure your default state does not have the event specifically handled if you are going to use this method.

React to change on a static property

I'm re-writing an MXML item renderer in pure AS. A problem I can't seem to get past is how to have each item renderer react to a change on a static property on the item renderer class. In the MXML version, I have the following binding set up on the item renderer:
instanceProperty={callInstanceFunction(ItemRenderer.staticProperty)}
What would be the equivalent way of setting this up in AS (using BindingUtils, I assume)?
UPDATE:
So I thought the following wasn't working, but it appears as if Flex is suppressing errors thrown in the instanceFunction, making it appear as if the binding itself is bad.
BindingUtils.bindSetter(instanceFunction, ItemRenderer, "staticProperty");
However, when instanceFunction is called, already initialized variables on the given instance are all null, which was the cause of the errors referenced above. Any ideas why this is?
You have 2 options that I am aware of:
Option 1
You can dig into the code that the flex compiler builds based on your MXML to see how it handles binding to static properties. There is a compiler directive called -keep-generated-actionscript that will cause generated files to stick around. Sleuthing through these can give you an idea what happens. This option will involve instantiating Binding objects and StaticPropertyWatcher objects.
Option 2
There is staticEventDispatcher object that gets added at build time to classes containing static variables see this post http://thecomcor.blogspot.com/2008/07/adobe-flex-undocumented-buildin.html. According to the post, this object only gets added based on the presence of static variables and not getter functions.
Example of Option 2
Say we have a class named MyClassContainingStaticVariable with a static variable named MyStaticVariable and another variable someobject.somearrayproperty that we want to get updated whenever MyStaticVariable changes.
Class(MyClassContainingStaticVariable).staticEventDispatcher.addEventListener(
PropertyChangeEvent.PROPERTY_CHANGE,
function(event:PropertyChangeEvent):void
{
if(event.property == "MyStaticVariable")
{
someobject.somearrayproperty = event.newValue as Array;
}
});
I think you need to respond to the "PropertyChanged" event.
If you're going to do that, use a singleton instead of static. I don't think it will work on a static. (If you have to do it that way at all, there are probably a couple ways you could reapproach this that would be better).
var instance:ItemRenderer = ItemRenderer.getInstance();
BindingUtils.bindProperty(this, "myProperty", instance, "theirProperty");
After fiddling with this for a while, I have concluded that this currently isn't possible in ActionScript, not even with bindSetter. It seems there are some MXML-only features of data bindings judging by the following excerpt from the Adobe docs (though isn't it all compiled to AS code anyways)?
You cannot include functions or array
elements in property chains in a data
binding expression defined by the
bindProperty() or bindSetter() method.
For more information on property
chains, see Working with bindable
property chains.
Source: http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_7.html
You can create a HostProxy class to stand in for the funciton call. Sort of like a HostFunctionProxy class which extends from proxy, and has a getProperty("functionInvokeStringWithParameters") which will invoke the function remotely from the host, and dispatch a "change" event to trigger the binding in typical [Bindable("change")] Proxy class.
You than let the HostProxy class act as the host, and use the property to remotely trigger the function call. Of course, it'd be cooler to have some TypeHelperUtil to allow converting raw string values to serialized type values at runtime for method parameters (splitted by commas usually).
Example:
eg.
var standInHost:Object = new HostFunctionProxy(someModelClassWithMethod, "theMethodToCall(20,11)");
// With BindingUtils.....
// bind host: standInHost
// bind property: "theMethodToCall(20,11)"
Of course, you nee to create such a utlity to help support such functionality beyond the basic Flex prescription. It seems many of such (more advanced) Flex bindings are usually done at compile time, but now you have to create code to do this at runtime in a completely cross-platform Actionscript manner without relying on the Flex framework.

Resources