Flex: How to create an entirely new component? - apache-flex

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!

Related

Flex: Is it a good idea or design to include an MXML another MXML file?

I want to know if its a good idea to have an mxml file for each component, then inline these various components in one mxml file and able to communicate between these mxml files ?
For example I have a overView.mxml and in this, i inline the other mxml files which contains components like datagrid, another mxml contains may be a form. Will i be able to communicate to the grid data by accessing its id in the form mxml ?
Please let me know if my question is not clear. I will try to rephrase it.
Thanks so much.
Yes, this is a good idea. It's much better than creating one giant MXML or class that contains all of your functionality.
At the same time, it caries some overhead. To communicate between the classes (MXML files are just classes) you have to dispatch events. A parent component that contains child components, can set public properties of its child components (with or without data binding).
You should try to decouple your components as much as possible. Try not to write code where the child component is explicitly referring to the parent (ie: try not to use the parent property). Instead dispatch an event from the child component and make the parent listen for the event.
Regarding your example with a data grid and a form:
If these two objects will have a lot of interaction between them, it will be much easier to keep them in the same MXML file. This doesn't sound like a scenario where one is a parent component that contains a child component. Since these "siblings" are likely to communicate w/each other, it would be easier to have them in the same MXML file. However, if things get complex and the file grows to more than a couple hundred lines, you will likely benefit from separating them.
Let's say you plan to use the form component elsewhere in your project w/out the data grid, then it also makes sense to separate them.
Regarding your question: "will the form component be able to communicate w/the grid component by accessing it's id?":
Technically, yes, you could do that but only by tightly coupling your form component w/the grid component. The form component can use the parent property to go up one level and use the id of the grid. But since the parent property is typed as a DisplayObjectContainer you have to fool the compiler and you loose the benefits of strong typing (because the DisplayObjectContainer doesn't have a property that is the ID of your grid). So while this is possible, it's not good design and prevents you from reusing the form component elsewhere.
This tight coupling defeats the purpose of creating separate components. So you're back to either facilitating that communication through dispatching events, or putting the grid and form in the same document :)
TLDR:
You should generally be trying to create re-usable components. So I would generally lean in that direction. MXML files are just classes, all the usual things people talk about in object oriented programming apply.

How to use data from one mxml component in another mxml component? - Flex

I'm pretty new to Flex and I don't know how to solve this problem.
I have 3 mxml components. In Component 1, I let the users fill in some data. In Component 3 I want to use the data, but I can't find a way to make it work.
Can someone help me, please? :)
I can show you code, but I think it would complicate the things a lot because it is data coming from a slider and the code is pretty long.
I feel like I answer this question on a routine basis. What is your display hierarchy?
Here are a few common things:
If component3 is a child of component1; then just pass the data in using public variables
If component1 is a child of component3; then wrap the data in a custom event and dispatch that event from component1 up to component3.
If component1 and component3 have the same parent, then combine the previous two approaches. Wrap the data up in a custom event, dispatch it to the parent. Have the parent pass the data down into component3.
A lot of frameworks make use of singletons and/or dependency injection; to help share data between components in more complicated architectures.
A quick Google reveals these sources; which seem to cover similar ground and may help:
http://www.actionscript.org/forums/showthread.php3?t=120330
how to use mxml component in another actionscipt
Pass data between flex components

when should I override 1 of the lifecycle methods?

I've read in the flex developer guide that you sometimes need to override one
of the lifecycle methods like: commitProperties and updateDisplayList
but I've written a few flex apps without ever needing to implement them.
when do I need to override them?
First, I 100% recommend studying this presentation by EffectiveUI:
Diving Deep with the Flex Component Lifecycle
and this by Michael Labriola from Digital Primates:
Diving in the Data Binding Waters
They go into things you'll never find in the docs but that are super practical for understanding the Flex Component Lifecycle.
From my experience, the only time you need to worry about overriding core lifecycle methods is if you are creating components. I make a distinction between Application Views and the Components.
Components are things that need to be nearly perfect, highly optimized, and extremely versatile/abstract.
Views are things that you may only need in one Application, but could reuse if you so desired (LoginScreen, ContactForm, etc.).
Views, for the most part, are just adding things to the display list of a more generic component (Canvas, Group, Container, VBox, List, etc.). You, as a View/Application developer, don't really care about how the "dataProvider" creates it's itemRenderers, it just works.
Components are a different story though. When you create a component, you want it to fit perfectly into that system Flex has set up: the Component Lifecycle. It's pretty tough when you first try to build a component like they do, but after you wrap your head around it it's super easy. Here's how I think of the methods when I develop components:
createChildren()
Called once when component is constructed
Called top down. So if Panel calls createChildren, it's createChildren method will call addChild on all of it's children, which calls initialize, which calls createChildren.
If you created a custom component, say a StarRatingComponent, you might want to add 5 stars to the stage when the component is constructed. So you'd override createChildren() to do add stars to the component you're in. By default, though, all Container components in the Flex SDK add their children here (lists do it a bit differently), so you never have to do this if you're building MXML views or something not-to-be-extremeley-reusable.
The next 3 methods are called 1 frame after properties are set.
measure()
If the parent doesn't have any sizing (percent or explicit), it will need to be sized based on it's children's sizes. This can only happen from the bottom up (took me quite a while to really wrap my head around that).
If the parent has explicit or percent sizes, it skips this step.
You override measure if you want to:
Have measuredWidth or measuredHeight return a useful value. So if you build a custom CoverFlowContainer component, and measuredWidth/measuredHeight aren't set (because measure was not overriden), then if you don't specify any sizing on CoverFlowContainer, it would be 0 width 0 height. So instead, override measure and have it set measuredWidth to radius * 2 or something like that, and now you don't need to give it a size!
If the component does not have an explicit or percent size, measure will be used to size the component. Otherwise it's skipped.
commitProperties
Called after measure.
Applies all property changes (from setting properties on the component) to the component (they were stored in private variables for that first frame).
Called a frame after initial property settings.
This is the most important method to override in my opinion. So for your CoverFlowContainer, say you set the hypothetical distance, gap, selectedItem, and tilt properties. When you set them, store them in private variables. Flex will wait a frame, and call commitProperties. In your overridden commitProperties, you can then say layout.updateEverything(selectedItem, distance, gap, tilt); so to speak. So this is the method you override to make all property changes be applied at once.
updateDisplayList
Called after commitProperties
Called top down.
You only override this to set visible properties on the component, such as setActualSize, graphics, etc. But by now (because of `commitProperties), you have all your required variables to update the display set to the right values.
Overall
So from my experience, I worked a lot with these lifecycle methods when creating a component library for things I would use in a million projects:
TitleWindow (my own version)
View3D (for Away3D/Papervision)
Tree and Stack for Flex 4
TextArea (with prompt, expandable, etc.)
ToolTip (easier to skin tooltip)
I needed to make sure everything was updated and rendered perfectly according to the lifecycle. Reading and understanding the Flex 4 Spark Source Code really helps clarify when to override these methods. As does the Openflux Source Code (very simple, clear alternative to the Flex Framework. Not as feature rich so it shows how to bare-bone override those methods to accomplish some pretty advanced things).
When I develop applications and make things like AdvertismentView, MenuView and LoginView, I don't ever think about it because all the components I'm using have already solved those problems (ViewStack, Group, List, etc.). I'm basically just setting properties they've defined and updated in their own commitProperties override.
The only time I would start overriding lifecycle methods in a View would be when I need to access custom variables from outside the view. So say I had a custom RichTextEditor and I created some properties called showFontControls and showStylePanel. When I set those variables, I would probably do what they described in the Data Binding Presentation: accessor sets private variable and calls the invalidation methods, lifecycle methods execute a frame later and I have overridden commitProperties and updateDisplayList to show those panels and fonts. But in practice, that's probably overkill because it wouldn't offer that much of a performance gain for the amount of work it would take. I'd just set up some binding to a visible property in that case. Nevertheless....
The best thing to do to really get into this is to just download the Flex SDK Source and see what they're doing.
Hope that helps.
Lance
Here's another presentation by Deepa (from the Flex framework team) that goes over a lot of the same framework methods, including a nice explanation of why the whole invalidation model exists to begin with:
http://tv.adobe.com/watch/max-2008-develop/creating-new-components-in-flex-3-by-deepa-subramaniam/

Flex Component Lifecycle: validateNow, validateDisplayList, invalidateDisplalList, commitProperties, etc

I am extending VBox to make a Calendar component. What method should I override to add the code to draw itself? What is the difference between all these methods? Is there something I should be putting in each one, or is there a specific method I can just override, add my drawing code, and have it work?
Thanks!
This white-paper is perhaps the best source of information I have seen on the subject.
Deepa's MAX 2008 talk was easily the best and most easily understanding presentation on the topic. It shows exactly how to write components properly in Flex 3.
I also recommend this article:
http://maohao.wordpress.com/2009/02/02/6-steps-in-creating-custom-uicomponent-in-flex-halo-framework/
Briefly, if you're doing graphics operations to draw, you'll want to use override updateDisplayList() and call invalidateDisplayList() as necessary; if you're using subcomponents, you'll use commitProperties()/invalidateProperties(). If you're dynamically sized, you'll need measure() and invalidateSize().
Override updateDisplayList method of UIComponent and do your drawing in it. Use the component's unscaledWidth and unscaledHeight as the bounds for drawing.
From Adobe Flex 3 Live Docs Advanced Visual Components in ActionScript - great source.

Flex: Render an unrealized UIComponent to BitmapData?

What is the best way to render to a UIComponent which hasn't been added to the stage? (I'm using UIComponents as renderers for objects, and want to render new copies for image export, filtering, etc.)
Two strategies I've seen/used so far include realizing the component to ensure it calls all the lifecycle methods:
Add the component to Application.application, render with BitmapData.draw(), remove component. This is similar to what I've seen done for printing unrealized components as well.
Add the component to a pop up window, render with BitmapData.draw(), dismiss popup after rendering complete.
I believe both of these just rely on the UI not refreshing while the current thread/event is executing, though (1) could also rely on the component being realized out of view.
Is there a better way?
What I've used in the past with much success is the following:
Create a new instance of your component
Add an event listener for FlexEvent.CREATION_COMPLETE
Set visible=false on the component
Add the component as a child of the main Application
When the component is created, the event listener function will be invoked. The rest of the logic should be put in / invoked from your event listener function
Remove the event listener you added in step #2.
Use ImageSnapshot.captureImage() or captureBitmapData() to capture the visual representation of the component.
Remove the component from the main Application
Process the image data as you need to.
I've used this to snapshot various Flex charting components for use in PDF's generated on the server side. After getting the BitmapData I use the PNGEncoder or JPEGEncoder classes to compress the data, then encode it in Base64 before uploading to the server.
I'm pretty sure you can use the draw() method in BitmapData without having your component on the DisplayList.
For example is use it when I need to modify images I load with the Loader Class. In the init handler I create a BitmapData instance and draw the Bitmap from the loadInfo.content property, then copyPixels() or whatever I need to modify the loaded image
So much of a UIComponent's layout can be tied to it's context. This is especially true for a lot of its derivatives (e.g. HBox) since the fluidity of the layout is tied to it's parent's size and the number of siblings sharing its parents space.
Additionally Flex can be a real pain to get to visually update. Often critical render functions aren't done synchronously ... there are callLater, callLater2 and other hacky approaches that make dealing with the auto-magical layout properties of UIComponents a major headache. Not even calling validateNow or updateDisplayList can guarantee that the layout will be correct on the current frame (instead of a few frames in the future).
I suggest the best thing you can do is not use a UIComponent and try and use a Sprite or other.
Your approach to attach it but make it invisible (alpha = 0, mouseEnabled = false, mouseChildren = false) is decent. You should listen for the FlexEvent.CREATION_COMPLETE callback before you are certain it is properly laid out. Then you can bitmapData.draw it and then remove it from the stage. If you must use UIComponents then I know of no better way.
You can call the lifecycle function manually before using the BitmapData.draw(). Do the following.
createChildren().
commitProperties().
updateDisplayList().
bmd.draw().
The first 2 steps are not 100% necessary, you can put all codes into updateDisplayList(). Because you invoke the function manually, you don't have to worry this is invoked by Flex framework many times.

Resources