I'm moving some Flex classes to pure Flash/AS3 to be part of a shared library. I have an event listener on FlexEvent.CREATION_COMPLETE to create and add display-objects once things are running, but I don't know the right way to do this in Flash?
edit: Maybe if my class subclasses Sprite rather than a Flex class, I can add children in the constructor, I don't need to wait for a "construction complete" event?
It depends on what you are trying to do: When you add children in the constructor, you will not be able to depend on any information about the stage and/or other elements on it. I have found it a better practice to add an event listener for Event.ADDED_TO_STAGE in the constructor, and have the handler method initialize the element.
You're really comparing apples and oranges here.
The Flex Framework is a UI Framework, and the CREATION_COMPLETE event is part of that framework.
Flash Professional is an IDE, primarily geared for creating animation. It has ActionScript support, but is not a framework and does not offer anything beyond native ActionScript other than libraries or classes you build, buy, create, or borrow.
If you want some parallel to creationComplete, you'll probably need to find--or create--a UI Framework. It is, in theory, possible (although not easy, nor something I'd recommend) to initialize the Flex Framework for use inside a Flash IDE created movie. After all, under the hood it is all ActionScript.
creationComplete Dispatched when the component, and all of its child components, and all of their children, and so on have been created, laid out, and are visible.
See more info on the flex life-cycle events and some that are plain flash here: also +1ed the added_to_stage as it's likely what you'll need in this case.
http://livedocs.adobe.com/flex/3/html/help.html?content=containers_intro_3.html
Related
I'm trying to implement a popup window (NativeWindowType.UTILITY) in an AIR 2.7 application that uses Swiz for dependency injection.
I have followed the Swiz guidelines that I've been able to find, and implemented ISwizAware on the class that creates the window, and I am calling _swiz.registerWindow() before opening the window, and dependency injection works fine on the window itself after this.
However, the problem I am running into is that I have a child view within that window, and I have a mediator that uses the [ViewAdded] and [ViewRemoved] tags. Neither the view added nor view removed functions are triggering. I'm thinking the issue is either:
The child view is not correctly registering with Swiz.
The swiz instance doesn't know about the beans (I have tried manually adding the bean however, which didn't have any effect).
The ViewAdded and ViewRemoved metadata tags simply aren't working because each NativeWindow object has its own stage instance.
Anyone know more about this?
Popups are a special case since they don't get added under the same display tree as your application. Under Stage (the main wrapper for Flash Player), you'll have Application where your code resides for Swiz, but Popup is in a separate layer above Application. Since they're siblings, Swiz cannot listen in for when the popup is being added to the Stage.
The way around this is to either set the properties of the popup manually (which is normally the easiest way) or manually add the popup to Swiz's awareness. For this you'll have to look at the documentation since I haven't touched Swiz in a long time.
I'm fairly experienced with Flex 4, but I still haven't needed frameworks yet (I like to do everything myself) and don't want to use them either, I know it's advantages and have learned how to use one of them, but still, no.
How can I dispatch an event in the main application and have a component inside a popupmanager to react to that event? All this dispatching the event within the main app and NOT aiming it to the popupmanager or the component instance, I want to be able to fire the event and not care about who gets it or if anyone reacts to it at all so if that is possible then I wouldn't care about keeping track of said popups.
I already dispatch an event from the component and receive it in the main application by bubbling the event and therefore being agnostic of each other, now I want it backwards.
Note: I have used singletons, but it's not the approach I need this time.
It sounds to me you are in desperate need of RobotLegs, you seem to be asking how to to create/use an event bus system in order to de-couple your components which is exactly what robotlegs is amazing at.
One thing you should definitely also look at is ActionScript 3 Signals. Signals is an approach to make strongly typed events like .NET Framework, instead of the magic strings event system, and is a fantastic easy bolt on addition to any Flash/Flex project.
Another way that is common is a mediator/controller singleton pattern. Let's say this is an automotive application, and we have a service layer that behind the scenes is receiving some data from the server, whilst at the same time our popup is behind displayed. One way we solve this problem is create a singleton based controller for our data like PartsController. It also has some public const Signals like SingalDataUpdated. The popup can now do something like PartsController.SignalDataUpdated.add(OnPartsUpdated). OnPartsUpdated is a local method inside the popup that can now react to the event as necessary and has no coupling to any other UI component. This is typically the approach we take and ensure that no UI component has explicit knowledge of any other UI component, and instead only talk to the controllers. One thing you need to ensure though is when the popup is closed remove the signal lister.
Again though, RobotLegs does most of all these for you and encourages some very great architecural best-pracitces. I would highly recommend you read through their documenation and get familiar with it. It will change your life when you realize how modular and maintainable it helps make your code.
Good luck!
Update regarding context and singletons
The idea regarding a context is to create a single singleton known as your application's context that stores the instances of what would be your other singletons. Inversion of control (IoC) and RobotLegs just wires things together so it dosen't look like absolute crap to work with, but you can just use a simple IoC injector like Swiz or SwiftSuspenders which RobotLegs is built upon. So, for example, you might hit a particular controller like:
AppContext.Instance.ProductController.SignalProductAdded.add(OnProductAdded);
But that is a bit ridiculous to try to access everything this way. Here comes RobotLegs to the rescue. Instead define injection rules in your RobotLegs context, so if a component asks for a UserController via an inject metadata tag, everything would get the same UserController. Exactly like a singleton, but correctly so in your component define;
[Inject] public var _objProductController:ProductController;
Now your component can work with the controller object as if it was its own, but instead it was injected in by RobotLegs on construction. For me and and most of my products I build a few base objects like GroupBase, PanelBase, PopupPanelBase, etc. that extend the proper component and already have all the controller injection properties so any component derived from these already connect to the proper controllers as needed.
For your simple project, it's like easier to roll your own and just create a single singleton for your context to hold your controllers and communicate with application's context that way. These are all pretty high level architecural decisions and everyone works differently at this level based on their experience, preference, or whatever. The most important thing is that it works for you, and you are comfortable with the architecture. RobotLegs helps make everything very decoupled which has some amazing unforseen benefits later.
Good luck!
If I understand the question:
how can I dispatch an event in the
main application and have a component
inside a popupmanager to react to that
event
Inside your pop up component, you can do something like this:
var app:Application = FlexGlobals.topLevelApplication as Application;
app.addEventListener('myCustomEvent',onMyCustomEvent);
Now any instances of the myCustomEvent that are dispatched by the main Application class will fire the handler in the popup. Also, any instance of the myCustomEvent that bubble up to to the main Application class will fire the handler in the popup.
I'm not sure if this is a good idea. Accessing the topLevelApplication will add external dependencies to your pop up which may reduce re-use of said component in the long term. Accessing the topLevelApplication is not a decision I would take on without thought.
If you were trying to ask a different question; it is unclear to me from your post, which I found kind of confusing.
Looking further into what Flextras.com said (Jeffry Houser I presume), this feat is impossible, events never bubble to children, only to parents.
Therefore, this has to be done in a central event repository approach, which is the way frameworks do it mostly.
This is indeed one of the problems solved by dependencies injection found in some frameworks as robotlegs.
I have an application in flex, it has some components out of the box and quite a few of custom components and events.
I want to get all event listeners on a specific component in runtime, I know how to do it with monkey-patching the framework but I do not want to use a monkey patch nor can I rely on this in production.
Is there a way?
The EventDispatcher has a pretty slim public interface:
addEventListener
dispatchEvent
hasEventListener
removeEventListener
willTrigger
This means the list of listeners isn't exposed. You can only tell if there is at least one event listener for a particular type of event.
I would re-examine why you need to do what you want to do. In a typical Observer Pattern the listener list isn't meant to be exposed. I have a strong feeling if you are trying to get that list then you are approaching a higher level problem from the wrong direction.
You can't. You could simply use custom components only and override addEventListener to gather the information. I don't really see why monkey patching wouldn't work. Flex is powerful in features but poor in design and I guess you'll have to just live with that.
I am having a problem with preloaders showing up in my flex apps. I never had this problem when developing flash apps so I got the idea to use a flash app as a shell with the sole purpose of showing a preloader while the flex app loads. I am not sure how to do this though, and I also need to ba able to pass the FlashVars from the shell flash app to the flex app. Does anyone know how this can be done?
Flex supports preloaders through the Application class, so you shoudn't have to resort to a hack. It's described in detail in the Flex 3 Developer Guide, Ch. 14 ("Application Container"). I never programmed a pure Flash preloader, but I figure it's different from what Flex does. Maybe the two of them conflict?
I am going to begin by agreeing with Simon, but there are ways to create the hack you're talking about.
Unfortunately, the parent layer to the Application in Flex overrides numChildren so that it always returns -1. This means that you are neither able to access the parent swf from flex, nor are you able to directly access the descendant SWF from Flash (amusingly, if a Flex App loads a Flash swf, this is not a problem).
The way around this:
Create a custom event. Set bubbling to true and cancelable to false.
Add an event listener for that event on the Flash layer.
Dispatch that from the Application layer of the Flex App.
The function which handles that event can now use the target property of the event to access the Application layer of the Flex App.
I'd like to develop a network graph application for Flex - imagine placing nodes on a Canvas and connecting them with links. The nodes should have editable text and other UI components.
I'm trying to find examples of creating an entirely new UI component from scratch, but all I've been able to find are trivial examples that extend existing components: a RedButton that extends Button, for example, or a ComboBox that has states to choose from.
My main question is, what ActionScript method defines the drawing of a component? What is the ActionScript equivalent of Java's paint() method?
You want to create a component that overrides the updateDisplayList method, and do your drawing in there:
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList( unscaledWidth, unscaledHeight );
// The drawing API is found on the components "graphics" property
graphics.clear();
graphics.lineTo( 0, unscaledWidth );
// etc
}
More information can be found here: http://livedocs.adobe.com/flex/3/html/help.html?content=ascomponents_advanced_3.html
I would suggest looking at the flexlib project if you need examples of custom components.
There's good general info in the livedocs here
Although you can create custom components in MXML and in ActionScript, I would recommend implementing them in ActionScript.
In short this is what you need to do:
When you create a custom component in ActionScript, you have to override the methods of the UIComponent class. You implement the basic component structure, the constructor, and the createChildren(), commitProperties(), measure(), layoutChrome(), and updateDisplayList() methods.
I recommend reading the 5-part tutorial series by Peter Ent on creating custom components.
Here is the link to Part 1.
Also recommended, tutorial series on ItemRenderers and ItemEditors.
Chapter 19 of Programming Flex 2 by Kazoun and Lott show the construction event model as well as the refresh event model.
In short, the Flex component structure assumes that you have properties of the object that affect its appearance. Instead of applying changes immediately, it allows property mutators to invalidate the component's "content" (e.g. text) via the inherited invalidateProperties() method. One also calls invalidateSize() when a property change will, ummm, change the size of the component, and invalidateDisplayList() when things need to be re-drawn (as opposed to just having different text).
This invalidation model optimizes the work of the component. It does not measure itself unless it knows it changed size; it does not place and draw itself unless something called invalidateDisplayList() since the last time it updated its layout; and it does not move its properties' values into its subcomponents unless it knows those values have changed.
Cheers
The typical behavior is to subclass an existing component, mainly because so much of the work of implementing the functionality of so many of the most typical kinds of components is already done for you -- you just have to know which component most resembles the one you want to create. (A challenge in its own right, given how many there are.)
If you like, though, you can create a pretty bare-bones UIComponent "from scratch" simply by extending UIComponent (which'll give you all the baseline stuff), or I suppose, if you're really going for minimalism, and you're up for a challenge, you can just implement IUIComponent, and define each interface method manually. If you do choose to go that second route, do yourself a favor and listen to this talk first -- it's an in-depth discussion of the Flex component architecture, given by one of the engineers on the Flex team. I recommend it often, and highly; it's excellent, and it clarifies a number of component-development details that still aren't all that well documented. Extremely valuable stuff if you're going to be building non-trivial custom components of the kind you're describing.
Hope it helps. Good luck!