« January 2008 | Main | March 2008 »
February 29, 2008
Migrating from Flex 2 to Flex 3
Check this link before migrating your applications from Flex 2 to Flex 3. In my own experience the issues have been very minor and fixed within a few minutes. But your results will varying depending on what controls you've used and how large your application is.
http://learn.adobe.com/wiki/display/Flex/Backwards+Compatibility+Issues
Posted by pent at 12:05 PM
February 25, 2008
Adobe Releases Flex 3 and AIR
It's finally here: Adobe Flex 3 has offically been released. Check out the press release for all the details. Be sure to check the Flex Product Page. You'll find a product information, demos, tips, and more on the product pages.
If you have been using Flex 3 Beta - we can't thank you enough for helping us make the product better. Your Flex 3 Beta 3 licenses should work for a little while longer.
Tip: If you have been using Flex Builder 2 PLUGIN for Eclipse 3.2, and want to move to Flex 3 PLUGIN, I suggest you uninstall the Flex Builder 2 PLUGIN, upgrade to Eclipse 3.3, then install the Flex Builder 3 PLUGIN - a couple more steps but the transition will be cleaner.
If you don't intend to start using Flex 3 right away, it is still a good idea to move to Flex Builder 3. That's because Flex Builder 3 can also handle projects created with the Flex 2 SDK. That's right - Flex 3 can use multiple SDKs. This will allow you to continue to work on your Flex 2 projects AND allow you to explore Flex 3 and test your software with the new SDK.
Here are few more related announcements:
- opensource.adobe.com/flex & opensource.adobe.com/blazeds projects are live. In addition, we are announcing that we are joining the SQLite Consortium (http://www.sqlite.org).
- Big companies are launching production apps on Adobe AIR today, concurrent with our release. Press Release
- 30onAIR - Join in the launch fun by recording a 30-second video on Why Flex, Why AIR or Why CF.
Enjoy!
Posted by pent at 08:02 AM | Comments (0)
February 22, 2008
Gauge Revisited
I received a comment on my recent blog article about the Gauge component wanting to know how to use a graphic skin for the gauge's needle. I should have included that, but since I didn't I thought I would supplement the article. As it turns out, you can't just swap a graphic skin for the programmatic skin - in that version of the Gauge control. My bad.
It has to do with the rotation of the needle. I used the Flex Rotate effect to turn the needle and made it rotate the needle about the needle's (0,0) point.
The problem with using (0,0) is that in a graphic, you cannot have negative pixels. To center the needle you'd have to draw half of it with negative pixel coordinates. That's not possible, so I had to come up with another solution.
First, I changed my philosophy of using Rotate. Now, rather than rotating about (0,0) I let Rotate determine the center of the needle and rotate it about its own center point.
I then created another class for the Gauge called GaugeNeedle and it hosts the skin. The Gauge class creates an instance of GaugeNeedle, positions it at (0,0) - the upper left corner of the gauge, and sizes it to match the gauge. If the gauge face is a circle, picture the GaugeNeedle as floating in the center of a box with the box sized to fit the gauge's face inside of it.
The needle skins are now drawn under the assumption that their centers are aligned with the center of the Gauge. If you were drawing a programmatic needle skin, you'd determine the center point and draw from there. Suppose the Gauge is 200x200 pixels. The GaugeNeedle will be sized to fit 200x200 also. So the needle skin should draw its base at 100,100 and draw the point to the right.
A graphic skin does much the same: you'd make a 200x200 image with a transparent background (PNG works best) and put the needle's base at 100,100 and draw it pointing to the right.
![]() |
The needle graphic is positioned so that its base is in the center of the image. |
When the needlePlacement value is not "center", the box (GaugeNeedle) is positioned so its center point is shifted to where the needle's base should be. For instance, if needlePlacement is "left", then the GaugeNeedle is not positioned at (0,0) but somewhere to the left of that so its center point is drawn closer to the left edge of the Gauge face.
I think you'll find skinning this version of the Gauge a bit easier.
Posted by pent at 04:51 PM | Comments (4)
February 20, 2008
30 on AIR site launches
www.30onair.com site launches tomorrow - Feb 21 2008.
Posted by pent at 10:51 AM
February 15, 2008
Revised Gauge Control
I've been looking over my past posts and thought it was time to update the old Gauge control I introduced way-back-when. In looking over that code I thought it was time for a re-write and a simplification.
This is the result:
This gauge control is simplified in a couple of ways:
- First, there are just two parts: the face and the needle. Both of these are skins which you can change.
- Second, the skins are directly 'attached' to the control. In the previous versions of this component I had created classes which then held the skins. I wanted to show you a more simplified approach and it works well here.
I also made adjustments for the placement of the needle and the label as well as the start angle of the needle and its sweep from minimum to maximum value. If you play with the example above you'll see that as you change the needle's position the start and sweep angles reset to favored positions. You can change them, of course. For example, if you set the needle position to "top" the start and sweep angles reset to 45 and -90 respectively. This puts the minimum value on the left side. If you want the minimum value to appear on the right side and have the maximum value on the left, then set the start angle to 135 and set the sweep angle to (positive) 90.
This set of properties along with custom skins can give you very flexible gauges.
I did not in this version of the gauge control include interaction. You can basically copy the code from the previous version and use it here. I recommend you extend this control and create an InteractiveGauge control or something like that.
I hope you find the control useful, but more important, I hope you find this example of writing a Flex control simple and easy to follow.
View and download the source code.
Posted by pent at 10:57 AM | Comments (8)
February 06, 2008
creationPolicy vs Binding
I just read a comment on an article I wrote a few years ago, creationPolicy vs. Form Data. The commenter suggested that the Save button must be able to read the values from the controls, even if those controls haven't been created - probably to make the code easier to write or at least consistent.
I disagree with this, but after reading that article again, I see that I could have given more information to support my position.
The article suggests using a <mx:Model> to hold the data and then use data binding to transfer the information from the model to the UI controls. That's fine for presenting the information, but it doesn't help when you to save the information.
ActionScript 3 Approach
Here's a different approach that works better with ActionScript 3 (for Flex 2 or Flex 3). Let's suppose you have an Accordion with two forms: Payment Information and Shipping Address. Let's also suppose you have two ActionScript classes that correspond to these forms: PaymentInfo and ShippingAddress. Here's the definition of the PaymentInfo class:// file: PaymentInfo.as
package mydata
{
[Bindable]
public class PaymentInfo
{
public var cardType:String;
public var cardNumber:String;
public var expireDate:Date;
}
}
Here's the definition of the ShippingAddress class:
// file: ShippingAddress.as
package mydata
{
[Bindable]
public class ShippingAddress {
public var firstName:String;
public var lastName:String;
public var street:String;
public var city:String;
public var state:String;
public var zipCode:String;
}
}
These look like ordinary ActionScript classes, but notice the [Bindable] meta tag above the class definition? That tag tells the compiler that all public properties can be used in data-binding. It is a short-cut to putting [Bindable] before each public variable.
In the Form to be used for the Payment Information you may have controls like this one to get the credit card number:
<mx:TextInput id="creditCardNumber" />
Since you want the PaymentInfo's cardNumber property to appear in the TextInput, you can use data-binding to associate the property with the field:
<mx:TextInput id="creditCardNumber" text="{data.cardNumber}" />
That's great for showing the credit card number if the value already exists. But how about saving that information?
Binding Tag
What you want to do is a "reverse" data-binding. Right now the {data.cardNumber} binding is one-way: whatever appears in the PaymentInfo's cardNumber property appears in the TextInput control. What you'd like is that if you change the value in the UI control to be automatically copied back into the PaymentInfo.You can do this by using the <mx:Binding> tag. Here's how to do that for the card number:
<mx:Binding source="creditCardNumber.text" destination="data.cardNumber" />
Any change made to the text property of the creditCardNumber TextInput control is reflected back to the cardNumber property of the PaymentInfo class instance for this Form.
Note: You can also do this type of binding in ActionScript using the mx.binding.utils.BindingUtils class.
Example
Picture this: the Payment Information form appears (blank). You fill in the fields and pick Save. The Save button's code does not have to access the UI controls at all: it saves the contents of the PaymentInfo class because the Binding took care of transferring the data from the control back to the data class.<mx:Script><![CDATA[
[Bindable] private var payment:PaymentInfo; // remember to create an instance using the new operator
[Bindable] private var shipping:ShippingAddress; // remember to create an instance using the new operator
]]></mx:Script>
<mx:Accordion>
<forms:PaymentInfoForm data="{payment}" />
<forms:ShippingForm data="{shipping}" />
</mx:Accordion>
Now suppose the Shipping Address were used in the same way, but in this case, the user never opened that form. Since the Save button code is not accessing any of the UI controls on the form, only the ShippingAddress properties, it doesn't matter if the UI controls were ever created.
In the above code example, the Binding tags will transfer changes to the controls in the PaymentInfoForm to the payment variable. Changes to the controls in the ShippingForm (if created by the user visiting it in the Accordion) will likewise be transferred to the shipping variable.
The Save button code then saves the contents of the payment and shipping variables.
Summary
Using the Binding tag to "reverse" data-binding on editable controls will make your code easier to write, understand, and more reliable. You won't have to worry if user's never touch containers on controls like Accordion or TabNavigator. And if the user does visit a form, data binding will populate the UI controls and Binding will read them.And yes, if you have 100 UI controls and fields you will need 100 Binding tags.
Posted by pent at 08:50 AM | Comments (9)
