Category: Flex

Oct 21 2008

Groovy ate my Actionscript's semicolons!

I think I've been writing too much Groovy.  I was reworking some navigation in the Broadchoice Workspace this morning, and noticed that I had stopped using semicolons entirely.

It's a small thing, but I'm finding the code is just easier on the eyes.  At first, with Groovy, I had a hard time without semicolons - my brain is just programmed to see them.  After some adjustments, though, I'm living a happier life with less punctuation in my code (ha!  take that, perl and Ruby lovers!).

5 comments - Posted by Joe Rinehart at 10:57 AM - Categories: Flex

May 22 2008

Powerful MXML Bindings with Ternary (?:) Operators

One thing I've found myself doing more and more often in Flex applications is using Ternary operators within data bindings. Frequently, if I find myself with an event handler that updates visual state based on nothing more than a condition, I can replace the AS3 function entirely with such a binding.

A example over on the Flexexamples blog that was posted earlier today shows a good "before" picture of the situation. A change handler is assigned to a checkbox, and based on the state of the checkbox, an error string is set / nulled:

<mx:Script>
<![CDATA[
private function checkBox_change(evt:Event):void {
   if (checkBox.selected) {
      checkBox.errorString = "";
   } else {
      checkBox.errorString = "You must click here to continue";
   }
}
]]>
</mx:Script>

<mx:CheckBox
   id="checkBox"
   label="I have read and agreed to your license"
   errorString="You must click here to continue"
   change="checkBox_change(event);"
   width="100%"
/>
Full code available at Flexexamples.

What's the Ternary operator?

It's a shortcut to a conditional operator that uses a ?: combination as a quick "if / then / else" to return one of two values. It can replace the following code:

if (foo == bar)
{
   result = "success";
}
else
{
   result = "failure";
}

With this:

result = (foo == bar ? "success" : "failure");

What's important about it in this context is that it's legal to use it within a data binding expression.

Putting it all together

By using a ternary operator in a binding expression to control the CheckBox's error string, we can replace the AS3 event handler in the Flexexample code entirely, leaving us with nothing but MXML:

<mx:CheckBox
   id="checkBox"
   label="I have read and agreed to your license"
   errorString="{checkBox.selected ? null : checkBoxErrorString}"
   width="100%"
/>

Other uses

I find myself often using this to control whether or not a control is enabled/disabled while a server-side operation takes place:

<mx:Panel
   title="Edit User: John Doe"
   enabled="{this.saveStatus != AsynchonousStatus.WAITNG}"
/>

I'll also use it to show / hide elements when a full-bore state may not be necessary:

<mx:HBox>
   <mx:Button label="Home" />
   <mx:Button
      label="User Management"
      includeInLayout="{currentUser.isAdministrator}"
      visible="{currentUser.isAdministrator}"
   />

</mx:HBox>

Conclusion

Data binding allows us to work declaratively, and by using it to evaluate expressions as well as update data, we can avoid a good deal of manual event handling.

4 comments - Posted by Joe Rinehart at 9:00 AM - Categories: Flex

Mar 27 2008

Photoshop Express: Novice User Experience

I am by no means a designer. I do like to take pictures now and then, retouching them and sharing them with friends and family. While I've got CS3, it's an intimidating and complex product for my needs. This probably places my in the demographic targeted by Photoshop Express: nondesigners who want to do a little retouching and sharing.

I fired up the beta this morning, and here's the summary of my experience.

No custom loader?

If it's this high profile of a RIA, I'd expect a more branded version of the stock Flex application loader, even if it's just the Ps glyph over the progress bar.

Better-than-average Flex form validation

I'm not a huge fan of default Flex form validation, where you just glow the incorrect fields. I love how the signup form alerts you with what's wrong then returns you to the form with the incorrect fields highlighted, still showing intelligent messages on focus. The glowing fields did omit passwords not matching, though - probably a quick fix!

And is it a coincidence that my captcha contained "PDF"?

Verify account? What the heck?

Why am I taken to an HTML page asking me to verify my account instead of having this shown in the main Flex app? Why does this link take me to another HTML page that then links me to the Flex app? Kind of a wonky workflow that could've been done without ever leaving the app...

Quick Start -> Upload Photos

Oh my, this is slick. Someone really thought through getting a new user started. You want to get started immediately? Click Quick Start to drop to your library and be immediately prompted to upload a photo. Select a photo (or photos) and you get a great Flex UI showing you progress of your uploads. 54% and waiting...

Opening a photo

Ok, I see my photo..click. Nothing. We're so used to the Web that we've become single-click beings. Double-click...ok, now I'm editing. I guess I could've used the "Photo Options" or "Edit Photo" button, too, but some sort of action on single click would be nice.

Autocorrect and other basic tools

I expected to click "Autocorrect" and get a corrected image. What I got instead was a great surprise - it gives you its best guess as well as thumbnails of a few other correction candidates. Absolutely great for a nondesigner like myself! Rollover a thumb, and it'll show it to you in the large space. Click and hold "View Original" at any time to see what you started with. Sliiiick.

Ok, I'm all corrected and balanced...let's share this out so you can see what I've done.

Sharing Photos

Where's the Share button? Can't find it on the editing screen. Let's try Saving to see where I go...

Nothing saying "Share," but there's an E-Mail Photo and Create Album option. Maybe an Album is shareable to you?

Select two images (edited and an original copy I uploaded), create an album, and "Share Album," and it looks like we're good to go. Maybe a changing "Create Album" to "Create and Share Albums" would be good.

Anyhow, I'm now sharing the Album on My Gallery, but I'm not sure how to give you a URL to it. I could e-mail friends, but I'd rather have a link.

Ah, ok. Once in your gallery, you can choose an Album, click "Link" or "Embed," and you get some bits. Might be nice to just show these options on the prior screen as well as on the Album viewer itself.

Embed is cool! Here's a preview and link to the album

Summary

Absolutely great tool when it comes to allowing a nonphotographer / designer like myself to tweak pictures and catalog my photos. It took me a bit to learn how to use it, but I won't be forgetting what I found. I think there's a bit of room for making things easier on the user when it comes to sharing, but I dig it.

4 comments - Posted by Joe Rinehart at 8:19 AM - Categories: Flex | See Also

Mar 20 2008

Flex "RadioButton" ListItemRenderer

I'm becoming an ever increasing fan of the way the Flex visual components were built. Yeah, some things are private when protected would be nice, but for the kind of data-focused work I do I find myself rarely getting stuck. On top of that, building Flex widgets is the perfect 3:00AM brain exercise for when our 3 month old daughter wakes me up.

Anyhow, I needed a better way to show long lists of radio buttons in a UI. Using a repeater just kind of stank - I wanted something that worked like a normal list, but showed a RadioButton beside each item. Thirty minutes later, I was in business:

I decided to blog it as it's a dead simple example of how to extend a base Flex component, add additional visual children, and control both the layout and data-focused aspects through the UIComponent "lifecycle" methods and Flex events.

Here's the code for the renderer:

package com.firemoss.controls.list
{
   import mx.controls.RadioButton;
   import mx.controls.listClasses.BaseListData;
   import mx.controls.listClasses.ListBase;
   import mx.controls.listClasses.ListItemRenderer;
   import mx.events.ListEvent;
   
   public class RadioButtonListItemRenderer extends ListItemRenderer
   {
   
      /**
       * Radio button shown at left of control.
       */
      private var radioButton:RadioButton;
      
      /**
       * List owning this renderer.
       */
      private var list:ListBase;
      
      /**
       * Override createChildren() to create a radio button.
       */
      override protected function createChildren():void
      {
         super.createChildren();
         
         // Create our radio button and add it to the display list.          
         this.radioButton = new RadioButton();
         this.addChild(this.radioButton);
      }
      
      /**
       * Override updateDisplayList to position radio button
       * and shift label.
       */
      override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
      {
         // Shift what super thinks of width by our radio's width...          
         super.updateDisplayList(unscaledWidth - this.radioButton.width, unscaledHeight);
         
         // For my purposes, a hard width is fine.      
         
         this.radioButton.width = 25;
         
         // Place our radio          
         this.radioButton.x = 6;
         this.radioButton.y = this.height / 2 - this.radioButton.height / 2;

         // Slide that label over          
         this.label.x = this.radioButton.width;
         
      }
      
      /**
       * Override the listData setter to add listener for changes to the owner (List selection change)
       */
      override public function set listData(value:BaseListData):void
      {
         super.listData = value;
         
         // If we're in the right condition          
         if (value.owner is ListBase)
         {
            // Remove event listeners from any prior assigned list             
            if (this.list)
            {
               this.list.removeEventListener(ListEvent.CHANGE, ownerChangeHandler);
            }
   
            // Keep the list around             
            this.list = value.owner as ListBase;
            
            // Watch the list for changes to its selection             
            this.list.addEventListener(ListEvent.CHANGE, ownerChangeHandler, false, 0, true);
         }
      }
      
      
      /**
       * When the list's selection changes, update the state of the radio button.
       */
      private function ownerChangeHandler(event:ListEvent):void
      {
         // If the list has a selection and it's this renderer's data, check the button          
         this.radioButton.selected = (this.data != null && this.data == this.list.selectedItem);
      }
      
   }
}

Enjoy, and happy listing!

7 comments - Posted by Joe Rinehart at 2:44 PM - Categories: Flex

Feb 26 2008

Custom Flex ToolTips made easy with CustomToolTip

Over the past year, I've spent a good deal of my time reconciling what designers create with what Flex provides. One of the items I run into most frequently is the need for a seriously custom tooltip: images, formatted fonts, etc.

Until today, my approach matched many others, handling the toolTipCreate event and setting the tooltip to use manually. This got a bit repetitive, so I've wrapped up the logic in a CustomToolTip class (attached to this blog entry, download it here) that makes it a declarative process.

You simply state the component creating the tooltip (the "source") and what class to use (not instance, but class!) as a ToolTip (the "renderer"):

<tooltip:CustomToolTip source="{someButton}" renderer="{com.myapp.SomeToolTip}" />

<mx:Button id="someButton" label="Some Button with a Custom Tooltip" toolTip="someTooltipText" />

When the button is moused over, a new instance of com.myapp.SomeToolTip will be created.

If your renderer class implements ICustomToolTip (in the attached .zip), it'll have the source's instance set into its "source" property. This allows you to place a custom tooltip on something like an itemRenderer and access its underlying "data" property.

6 comments - Posted by Joe Rinehart at 7:30 AM - Categories: Flex

Feb 25 2008

Flex 3 SDK and BlazeDS in Subversion Repos!

How cool is this? It looks like Adobe's taking their Open Source stance pretty seriously. If you want to get your hands on BlazeDS or the Flex 3 SDK, they're using straight-up Subversion repositories that you can directly access!

For example, I'd like to look into why circular references are such a bear to serialize / resolve. Now, I can geek to my heart's content looking at the serialization code directly in the repo!

1 comments - Posted by Joe Rinehart at 8:38 AM - Categories: Flex

Feb 22 2008

Silverlight 2: Looks good!

Odd for me to say something positive about Silverlight. I tried 1.0, and sort of gave up. After reading Scott Guthrie's blog entry about Silverlight 2.0, I might have to give it another shot - I like C#, but just can't stand ASP.NET.

What I really like about the Silverlight 2.0 screenshots shown is the the darn thing looks good. Frankly, out of the box Flex looks pretty lousy next to it. It's got clean scroll bars, good-looking buttons, and I don't see anything that's the weird-shade-of-blue-green-not-found-in-nature that's all over default skinned Flex apps.

Odd to see a Microsoft product that's graphically more pleasing than something from Adobe. Maybe Flex 4 (or a 3.01) could bring about a real skin update that makes our default applications look halfway decent?

2 comments - Posted by Joe Rinehart at 12:47 PM - Categories: RIA Platforms | Flex