Tuesday, October 18, 2011

Focus Flex App on start up


When a flex application loads it doesn't actually have focus until the user clicks on it.

So even though you can call setFocus() on a TextInput or Button and visually it appears that your control has focus (blue border), if you try to type you'll notice that nothing happens. This can be quite frustrating for a user.

One way to solve this is to edit the html file that loads your application (e.g. the index.template.html), and call the JavaScript focus() function on the flash element. I found this website explains it quite nicely:
http://www.appfoundation.com/blogs/giametta/2007/07/09/internet-explorer-setting-focus-on-flex-apps-flash-player/.

If for prefer to keep all your code in ActionScript you can accomplish the same thing by doing this:
 ExternalInterface.call("function() { var app = document.getElementById('"+id+"'); app.tabIndex = 0; app.focus(); }");

I usually put that line of code inside my applicationComplete event handler.

One other thing to note is that if you call setFocus on a component that isn't finished being initialized it won't always work. For best results call setFocus() in a creationComplete event handler.

I added the app.tabIndex = 0 after finding that the focus didn't work on Safari. This came from stackoverflow.

Tuesday, October 11, 2011

FXG Scale Grid

When working with FXG an important concept to understand is the Scale Grid. The scale grid determines how your FXG graphic scales. If your FXG element is used without an explicit width or height (e.g. <fxg:rounded_box/>) then the scale grid is not used. But if for example you define your FXG to have a width of 200 pixels and then in your MXML you use the FXG element and set its width to "100%" (e.g. <fxg:rounded_box width="100%"/>) or something other than 200 you'll see the graphic get scaled. The scale grid becomes important when you want to preserve aspect ratios (e.g. on rounded corners).

Here is the typical example used to illustrate the problem:

Here is the FXG source code (rounded_box_scale9.fxg) used to create this graphic. Notice the scaleGridLeft, scaleGridTop, scaleGridRight, and scaleGridBottom properties, these are what control the scaling.
<s:Graphic xmlns:s="http://ns.adobe.com/fxg/2008" version="2.0" 
	scaleGridTop="20" scaleGridLeft="20" scaleGridRight="130" scaleGridBottom="21">
	
	<s:Rect height="41" width="150" radiusX="20">
		<s:fill>
			<s:LinearGradient rotation="90">
				<s:GradientEntry color="#FFFFFF"/>
				<s:GradientEntry color="#C0C0C0"/>
				<s:GradientEntry color="#FFFFFF"/>
			</s:LinearGradient>
		</s:fill>
		<s:stroke>
			<s:SolidColorStroke color="#AAAAAA" weight="2"/>
		</s:stroke>
	</s:Rect>
	
</s:Graphic>

And here is the associated MXML (the rounded_box fxg doesn't have the scaleGrid properties):
<s:VGroup x="10" y="10" gap="10">
	<fxg:rounded_box/>
	<fxg:rounded_box width="100"/>
	<fxg:rounded_box width="200"/>
	<fxg:rounded_box_scale9 width="100"/>
	<fxg:rounded_box_scale9 width="200"/>
</s:VGroup>

I found this website quite useful in illustrating some of the scale grid limitations: http://www.adobe.com/devnet/flex/articles/mobile-skinning-part1.html.

And here is Adobe's page on FXG:
http://help.adobe.com/en_US/flex/using/WSda78ed3a750d6b8f26c150d412357de3591-8000.html.

But to summarize, here are the limitations I've found with scale grids:
  • Scale grid values must be inside the boundaries of the graphic and must not overlap
    (that is, left boundary < scaleGridLeft < scaleGridRight < right boundary).
  • Scale grids will not work if the graphic contains any Group elements.
  • Scale grids will not work if elements have alpha applied. Instead, apply alpha to the stroke and fill elements.
  • Scale grids will not work with filters (e.g. DropShadow, GlowFilter, etc). Instead add the filters inside the MXML.
I'm sure there are more restrictions, but these are what I've found so far.


Wednesday, September 21, 2011

Flex 4 Path Builder


April 2013 - added View Source to right click menu.

I got a little carried away making an application that lets you manipulate Flex Path objects. This application lets you easily design a path by double clicking to make each end point in your path. You can select each individual line, move, or curve segment and manipulate the end points () and the curve control points (). Click on the screenshot above to see it in action. I'm sure there will be bugs, so use at your own risk. There is no undo support either.

To use this tool, you can start by adding different kind of path segments - move, lines, and curves - by clicking on one of the 6 buttons along the top in the blue titlebar. This will cause the path segment to be appended to the currently displayed path. Each path segment also shows up in the list on the left side. Click on an individual path segment in this list to highlight it in the path. The red end points () are draggable - move them around to adjust the path. Note that the following path segment will be moved to start wherever the current path segment ends. You can also click and drag the circle control points () to adjust the quadratic and cubic Bezier Curves.
Alternatively you can use the new "Path Designer" option (which is explained in the top panel on the left side). The path designer lets you double click on the white graph area to create each segment of your path. Here are the instructions:
  • To create a line: Double-click on the graph
  • To create a straight line (horizontal, vertical, or at 45°): Shift + double-click on the graph
  • To create a quadradic curve: Ctrl(⌘) + double-click on the graph (you can edit the control point later)
  • To create a cubic bezier curve: Ctrl(⌘) + shift + double-click on the graph
  • If you check the Use relative positions checkbox the path segments will use relative positions instead of absolute (lower case letters like "l", "m", "c", "q", etc)
  • If you check the Snap To Grid checkbox, then the end points are all shifted to fit on a grid defined by the number of pixels you choose. This is a nice way to easily get nice round numbers like 20, 50, 100.

If you have an existing path you can paste the data string (e.g. "M 100 100 L 150 150 H 200") into the textbox at the top and click Update. This will render your path on the screen and allow you to manipulate it.

I've also added support for ActionScript GraphicsPath commands to be pasted in the same textbox in this format:
"1 2;10 10 20 20"
The first set of numbers before the semi-colon are the commands (defined by the constants in GraphicsPathCommand). The second set of numbers after the semi-colon are the coordinates of each path segment. In your program you can use a trace statements like this on your GraphicsPath object to output the correct format:
trace(path.commands.join(" ") + ";" + path.data.join(" "));

And finally, if you have a path created in ActionScript using a Graphics object or a GraphicsPath object like this:
var g:Graphics = uiComponent.graphics;
g.moveTo(10, 10);
g.lineTo(50, 10);
g.moveTo(50, 50);
g.lineTo(10, 50);
You can copy that code and paste it into the same textbox at the top. It will pick out the move, line, and quad curve commands. This will only work if you use all numbers in your code - no variables or constants.

The Translate X/Y option lets you move every single point on the screen by the given x and y offset values. This includes the control points. So think of it as shifting the entire path. Note that the points can't be moved into negative values (even though they are allowed), so unexpected things will happen if you try to do this.

On the right side of the app (not shown in the screenshot) there is an edit panel which lets you type in the exact numeric values that you want for each point in the selected path segment. This way you can easily tweak your path to look just right.

Below the Edit Panel is the Stroke & Fill Properties panel. This lets you define the path stroke and fill properties.

Below that is the MXML and FXG output windows which let you copy the MXML/FXG source code used to render the path, so you can paste it into your own application. If you are using FXG, then in Flash Builder choose "File > New > File". Then enter in the filename you want like "mypath.fxg". In the editor paste in the FXG, it has all the declaration xml that you should need.

Feedback welcome, have fun playing.

I haven't enabled view-source for this project yet, hopefully one day.

Monday, August 29, 2011

Can't type into Flex textbox on Mac Safari 5.1!

I recently ran into a problem on Mac Safari 5.1 where I couldn't type into any text boxes in my Flex App. Very frustrating! Anyway, I finally found a simple solution from the Adobe Forums.

First this problem only happens with the Debug Flash Player.

The fix is very simple - in Safari under the Develop menu (if you don't see the Develop menu it can be shown by going to Preferences > Advanced and checking the Show Develop menu in menu bar checkbox), change the User-Agent to Firefox or something other than the default. This will cause the page to reload, and should allow you to type again.

Bizarre.

Monday, June 27, 2011

Flash Builder 4.5 Mobile Application for Acer Iconia A500 Tablet

This blog post will discuss making a simple mobile application using Flash Builder 4.5. I will be targeting the Acer Iconia A500 Tablet because it is currently the only mobile device that I have access to, but it should be relevant to other mobile devices too. The Acer Iconia A500 Tablet runs on Google Android 3.0 (Honeycomb). For a full review of the tablet, read this article. It sells for around $450 for the 32GB version.

Step 1 - configure the tablet

On the tablet go to Settings - Applications - Development
Check the USB Debugging option. This allows Flash Builder to debug applications straight on to the tablet through USB. Next, connect the tablet to your computer using the USB cable provided.

Step2 - create a mobile project

Inside Flash Builder, create a new Flex Mobile Project.
Give it a name like TabletApp. Click Next.

Select the desired target platform(s). For the Acer Iconia and other Andoid tablets, check the Google Android checkbox. You can choose the mobile app template to use here as well.
Important: your mobile application might need to have access to the internet, the file system, the gps, etc. Under the Permissions tab, choose the Google Android platform, and check any of the permissions that your application needs.
For my sample application I chose the INTERNET, WRITE_EXTERNAL_STORAGE, and ACCESS_FINE_LOCATION (GPS) permissions.


Click next. Set up the build path if necessary, or leave it to the default values.

Once the project is created, Flash Builder will open the two main files - TabletApp.mxml (the main application file), and TabletAppHomeView.mxml (the default home view component). Add in some components to the home view like a button or a label.

Step 3 - Run the application on the tablet

Now, to test our your application on the Acer Iconia Tablet, make sure it is connected by USB, and that you followed the step above on the tablet to enable USB debugging.

Under the Run menu, choose Debug Configurations.... Add a new Mobile Application launch configuration. Choose your project and application, and the target platform (Google Android in this case).
Under where it says "Launch method", choose the On device radio button. If you have trouble connecting, then read the Device connection help page.

If all works as planned, you should see on the tablet the simple application that you created.

Step 3b - Run the application on the desktop

If you want to test out your application without running it on the tablet, you can run it on the desktop by choosing the other radio button option - On desktop. There is a list of pre-configured devices, but the Acer Iconia tablet isn't in the list. So click Configure... and then Add to add it to the list. Here are the specs:

I've put together a simple app that shows some of the properties available to mobile applications. Click the screenshot below to see the full size.
You can download the project file here. In Flash Builder choose "File - Import...", and then choose "Flash Builder - Flash Builder Project", and select the downloaded fxp file.

Thursday, May 19, 2011

Simple Animating Preloader and Throbber/Spinner

This is my fourth post on Flex preloaders. It shows how you can use a throbber or spinner as a
simple yet effective preloader. The throbber can also be used in your application in other places whenever you want to indicate that something is happening.

In the example below I've included two kinds of throbbers:
  • SimpleThrobber (extends Sprite) - ActionScript/Flash only, no Flex dependencies (good for preloaders)
  • Throbber (extends SkinnableContainer) - advanced throbber, skinnable and style-able
I've also included two skins to go with the Throbber class - ThrobberCirclesSkin and ThrobberLinesSkin.

Both throbbers work roughly the same way. The animation is performed every X milliseconds, and the lines or circles are drawn in a rotating manner so that the throbber animates. Both throbbers support an array of colors which define the appearance of the throbber, and a delay property which determines the speed of the animation.

Anyway, check out the code below (right click View Source to see the source), there is some documentation to explain the various styles, properties, and functions.


The other blog posts I've written on preloaders and spinners/throbbers can be found here:As mentioned in the comments, the just released Flex 4.5 SDK now contains a similar Spark BusyIndicator component. There is a nice blog post on it here.

Thursday, March 24, 2011

Spark Forms, Validation, and Errors

One of my previous posts on Always showing error tips (validators) presented one way of trying and improve the built-in validation error handling in Flex. It was a nice idea, but as many people have pointed out in the comments there are too many different use cases that causes the error tips to not show up properly.

Below is another alternative approach, and one that I hope is less of a hack.

I've created a class called InputControl which is very similar to the Flex 3 FormItem. It has a label property, and can contain one or more child elements.

What this control does that makes it useful is to listen for when the errorString property changes on an input control (such as a TextInput), and instead of displaying the default Flex error toolTip, it shows that errorString in a label that is always visible. It also immediately clears the input's errorString property so that the default error toolTip is not displayed.

The InputControl class is skinnable, and I've created two different skins. The default one InputControlSkin has the same layout as the FormItem (label on the left) and displays the error string on the right of the input.

The second skin is called InputControlVerticalSkin which displays the label, input, and error message in a vertical layout. This skin is more suited for large inputs like a TextArea.

There are definitely a few issues with this approach:
- longer error messages either don't show up properly or are truncated
- form label alignment is not customizable

Feel free to modify my code to make it work differently. Most properties are hard coded in the skins, and I didn't spend the time to extract them out into styles.

Here it is in action, right click to view source:

Tuesday, March 15, 2011

State Transitions

I've put together a little example of how you can use transitions to animate between the states in your application component.

There are many websites explaining Flex 3 states as well as the new and improved Flex 4 states.

If you don't already use states, I would highly recommend you become familiar with them. They are very powerful, and make it much easier to create complex user interfaces.

Transitions are effects that are played when your component changes from one state to another state. They are a nice way to smoothly animate changing content, for example fading out content being hidden, or resizing containers that have new elements being added.

In the example below, I've created an application that has 5 states:
  • Normal - default state
  • Resize - resizes the main panel using a Resize effect
  • Fade - fades in/out a Label using a Fade effect
  • AnimateColor - animates a gradient color using the AnimateColor effect
  • Easing - uses a Bounce easer with a Move transition

I've noticed that certain effects like Resize don't work properly with other effects like Fade. I haven't spent the time to try and figure out why not.

Anyway, here is the example. Right click to view source.

Wednesday, January 26, 2011

Animated Scrolling List

In Flex 4, the Spark List has a function called ensureIndexIsVisible(index). This function immediately scrolls the list to that index if it is not visible.

I've added a slight modification to this to animate the scrolling over half a second to make it much smoother. The animation is done using an AnimateProperty instance on the list's data group, and setting the property to verticalScrollPosition.

Here it is in action, as usual right click to view source:


For simplicity I am only scrolling the vertical scrollbar. If you are using a horizontal or tiled list, you'll want to animate the horizontal scrollbar too. In the tile case, you could use a Parallel instance to animate both the horizontal and vertical scrollbars.

Friday, January 14, 2011

Grayscale Preloader

Following on from my last post on grayscale images, I've made another preloader to illustrate how you can animate an image from grayscale to colour.

The preload consists of an image and a loading label. The image starts off gray, and as the preloader progress value increases it gradually becomes coloured. The alpha value also increases from 0.5 at the start to 1 at the end. To spice it up a little I also added in a GlowFilter and a DropShadowFilter.

Here it is in action, click the RELOAD button to show the preloader again.



For another example of a custom preloader, check out this blog post on Another Custom Preloader.

Friday, January 7, 2011

Grayscale Images, ProgressBar, Rating Control

I've been learning some neat tricks for working with images and graphics. One of them is how to take a color image (or a graphic like an ellipse that you've drawn using MXML/FXG) and make it grayscale.

Obviously if you have the image, you could just as easily open it up in your favorite image editor like Photoshop and make a grayscale copy of the image and save it to your Flex project.

Anyway, here is how you can do it dynamically. I've shown two different ways of doing it. Again I want to emphasize that all the images and graphics below are in color, they are simply modified at run time to appear in grayscale.

The first way is to set the UIComponent.blendMode or GraphicElement.blendMode property to "luminosity" on the image or graphic. This method works by blending the colours in the image with the color "behind" the image (usually the background color of the parent container or application). So if the color behind the image is white or light gray, then the image will become gray. If the color behind is green, then the image will be colourized to green. See the bottom part of example #6 where 4 red circles are drawn with various background colours.

The second way is to use a ColorMatrixFilter on the BitmapImage which converts the color image into grayscale.

To illustrate this, I've created 6 examples:
  1. Normal color image
  2. Color image turned into grayscale using the blendMode="luminosity" property
  3. Color image turned into grayscale using a ColorMatrixFilter
  4. Combination of a grayscale image (as the background) with part of the color image as the foreground. To draw only part of the color image, set the fillMode="clip" property on the image, and then set the width and height properties and then the image will be clipped.
  5. A custom ProgressBar
  6. A sample non-interactive rating control, as well as some luminosity examples
For more information on making skins for progress bars, see these two articles:
Creating a Custom Track Skin on an MX ProgressBar and Creating a Custom Bar Skin on an MX ProgressBar.

And finally, here are the examples. As always right click to view the source code.


The rating control in example #6 actually uses a Star graphic that is drawn with FXG (Adobe help on Using FXG). You could just as easily do this in MXML or simply use an image from your computer. I've noticed that Flash Builder doesn't really support FXG files properly (no autocomplete or new file wizards), so it's not that easy to create them unless you know the specifications well.

The rating control could easily be extended to be a fully functional user interactive rating control. You could also use the technique shown in example #4 to display fractional rating values (e.g. 2.5 out of 5).

Wednesday, December 22, 2010

Drawing 3D Shapes in Flex

I found this great 3-part article by Lee Burrows on how to draw semi 3D shapes in Flex:
  • Part 1
  • Part 2
  • Part 3

  • I highly recommend that you check them out.

    Expanding on those examples I've changed them slightly in the following ways:
  • Instead of rotating the shape based on mouse position, the rotation now happens when you drag your mouse
  • Added a 3D Triangle and a 3D Arrow (combines a triangle and a cube)
  • Added a 3D shape with 6 different hockey logos, one on each side


  • All credit goes to Lee for his excellent examples. If you want to understand the math behind it all, then definitely read his article. My examples don't have much in the way of comments.

    View Source is available for all the following examples, right click below to access the source.

    Example #1 - Simple Rotating Cube:


    Example #2 - Rotating Triangle:


    Example #3 - Rotating Arrow (with highlighting):


    Example #4 - Cube With Image/Bitmap Fill:

    You might notice a few tiny problems with the arrow. When rotating it in certain directions some lines show through that shouldn't be visible. It is most likely due to combining the two shapes (one cube and one triangle) to form the arrow.

    Also, the mouse dragging to rotate works as expected until you've rotated the shape 180 degrees, then it becomes backwards. I haven't spent the time to try and fix this.

    The fourth example uses Lee's Shape3D class which encapsulates the 3D functionality in one simple class. It is much cleaner this way.

    Thursday, November 25, 2010

    YouTube Videos in Flex

    Here is an example of how to get YouTube videos to be shown inside your Flex Application.

    The first thing to do is add an SWFLoader to your mxml file. The source property of the SWFLoader gets set to the url of the video that you want to show inside Flex.
    But you can't just use any YouTube url like this one:
    http://www.youtube.com/watch?v=owGykVbfgUE
    Instead you use a url in this form:
    http://www.youtube.com/v/VIDEO_ID?version=3

    The id of the video you want to play (e.g. owGykVbfgUE) must replace the VIDEO_ID portion of the url. This url actually redirects to an SWF file somewhere.

    The version=3 parameter is very important. This tells YouTube to load the ActionScript 3.0 version of the SWF file. Without this parameter it defaults to the AS2 version which doesn't not play nicely with AS3. I found that I could watch one video, but after that no other videos could be played (I found this blog post that explains why if you're interested). I also found this YouTube reference which is where I learned about using the version=3 parameter.

    There are a few other parameters that you can use like:
    • autoplay=1 - starts the video immediately without the user having to press play
    • fs=1 - allows full screen
    • rel=1 - shows related content after the video has finished playing
    For a full list of the parameters go here

    And finally, when you want to play another video, make sure you call the swfLoader.unloadAndStop() function otherwise you can get multiple videos playing at the same time, very confusing.

    Keep in mind that when you run this locally you will see a lot of SecurityExceptions in your console, this is expected and normal.

    And one last thing, some videos you will not be able to play inside Flex due to copyright restrictions. The owners of youtube videos must be able to specify whether the video can be played from a different website using an embedded player.

    Here is the example in action (right click to view-source):

    Wednesday, October 27, 2010

    Displaying Html text in Labels

    Displaying html content inside Flex labels is not as straight forward as it was in Flex 3 by simply setting the htmlText property. Here are the 3 Spark controls used for displaying text:
    • Label - lightweight plain text only
    • RichText - as the name says it provides support for rich text.
      Also allows html content to be imported (anchor tags <a> don't work)
    • RichEditableText - provides the same rich text support as the RichText control.
      Allows editing and anchor html tags work properly
    Here is a list of the supported HTML tags: <div>, <p>, <a>, <span>, <img>, <br>.

    As noted above, if you want to use anchor <a> tags, you must use a RichEditableText control. In this case you'd most likely want to also set the editable="false" property.
    The anchor href property can be set to a relative path like
    <a href="index.html">index</a>
    Or an absolute one like
    <a href="http://google.com" target="_blank">google</a>
    Note that you can set the target property to control whether the link is opened in a new window or not.
    If you want to listen for when the user clicks on an anchor it is possible, but involves a lot more work. Basically you import the html string into a TextFlow object. Then you iterate through all the child elements until you find the LinkElement (which represents the anchor tag), and then add a FlowElementMouseEvent.CLICK event listener.

    Here is some sample code that I use to achieve this:
    /**
     * Converts the html string (from the resources) into a TextFlow object
     * using the TextConverter class. Then it iterates through all the 
     * elements in the TextFlow until it finds a LinkElement, and adds a 
     * FlowElementMouseEvent.CLICK event handler to that Link Element.
     */
    public static function addLinkClickHandler(html:String, 
            linkClickedHandler:Function):TextFlow {
      var textFlow:TextFlow = TextConverter.importToFlow(html, 
        TextConverter.TEXT_FIELD_HTML_FORMAT);
      var link:LinkElement = findLinkElement(textFlow);
      if (link != null) {
        link.addEventListener(FlowElementMouseEvent.CLICK, 
              linkClickedHandler, false0true);
      else {
        trace("Warning - couldn't find link tag in: " + html);
      }
      return textFlow;
    }

    /**
     * Finds the first LinkElement recursively and returns it.
     */
    private static function findLinkElement(group:FlowGroupElement):LinkElement {
      var childGroups:Array = [];
      // First check all the child elements of the current group,
      // Also save any children that are FlowGroupElement
      for (var i:int = 0; i < group.numChildren; i++) {
        var element:FlowElement = group.getChildAt(i);
        if (element is LinkElement) {
          return (element as LinkElement);
        else if (element is FlowGroupElement) {
          childGroups.push(element);
        }
      }
      // Recursively check the child FlowGroupElements now
      for (i = 0; i < childGroups.length; i++) {
        var childGroup:FlowGroupElement = childGroups[i];
        var link:LinkElement = findLinkElement(childGroup);
        if (link != null) {
          return link;
        }
      }
      return null;
    }

    A simple control that I've created and use frequently is called HtmlLabel which extends the RichEditableText class to provide simple support for html text:
    <?xml version="1.0" encoding="utf-8"?>
    <s:RichEditableText xmlns:fx="http://ns.adobe.com/mxml/2009"
      xmlns:s="library://ns.adobe.com/flex/spark"
      xmlns:mx="library://ns.adobe.com/flex/mx"
      focusEnabled="false"
      selectable="false"
      editable="false">

      <fx:Script>
        <![CDATA[
          import flashx.textLayout.conversion.TextConverter;

          override public function set text(value:String):void {
            super.textFlow = TextConverter.importToFlow(value, 
              TextConverter.TEXT_FIELD_HTML_FORMAT);
          }
        ]]>
      </fx:Script>

    </s:RichEditableText>

    Spell Checking

    Here is a short example of how to get the Adobe Squiggly spell checking tool installed. Squiggly can be downloaded here.

    Squiggly files:
    • AdobeSpellingConfig.xml - put this file in your project's src folder. It defines the locations of the dictionaries and which language(s) to use.
    • en_US.aff, en_US.dic - these are the dictionary files. You'll need different ones for different languages of course. By default they go in the src/dictionaries/en_US folder.
    • AdobeSpellingEngine.swc - the main engine library - required, goes in project lib folder.
    • AdobeSpellingUI.swc - the ui library for Flex 3/MX components (e.g. <mx:TextArea>)
    • AdobeSpellingUIEx.swc - the ui library for Flex 4/Spark components (e.g. <s:TextArea>)
    ** Only use one of AdobeSpellingUI.swc or AdobeSpellingUIEx.swc.

    To integrate Spell Checking into a Spark TextArea (id="textArea"), all you have to do is add one line:

    SpellUI.enableSpelling(textArea, "en_US");

    I did notice one problem with using Squiggly with Spark controls. The default Cut/Copy/Paste/Select All context menu items were not available anymore. I found a workaround for this by getting the contextMenu (which gets set on the RichEditableText control, not the TextArea) and setting clipboardMenu = true. See the example below for more details (right click to View Source).

    Squiggly is still in prerelease, so a few bugs are expected. There is a forum here for discussions on Squiggly, and to report problems.

    Thursday, September 9, 2010

    Flex 4 Tree Lines

    I've updated my previous blog post on Tree Lines to include a Flex 4/Spark version which uses the MXTreeItemRenderer class.

    For more documentation on how to use it see the blog post linked above.


    I've also updated the AdvancedDataGrid example to show tree lines in the tree:

    Friday, August 27, 2010

    Detecting browser height

    Here is an example of one way to find out the height of the browser window from inside Flex. It is very easy to find this out if your have your Flex application set to height="100%". But if you use a fixed height like height="300" then stage.stageHeight and app.height both return 300.

    This example uses the ExternalInterface to determine the height of the browser by calling the eval javascript function (it is a built-in function).

    E.g.
    var browserHeight:Number = ExternalInterface.call("eval", "window.innerHeight");

    Different browsers (NS, FF, Chrome, IE, Safari) obviously don't all support this call. So far the window.innerHeight property works on all of them except IE. For IE you can use this one (IE 7 and above I think?):
    var browserHeight:Number = ExternalInterface.call("eval", "document.documentElement.clientHeight");

    And if your browser is older you can try this one:
    var browserHeight:Number = ExternalInterface.call("eval", "document.getElementsByTagName('body')[0].clientHeight");

    Browsers will also handle errors differently, so if you try to use one of those JavaScript functions in one browser you might get undefined return, and in another browser you might get an error dialog box.

    Here is an example of this in action, it opens in a new browser window to show it properly.
    If it was embedded on this page using an <iframe> tag then the size returned is that of the iframe, not the browser.

    - Browser Height Example -
    Click this image to open the real application


    Obviously if you were interested in the browser width then you could do exactly the same thing but replace innerHeight with innerWidth and clientHeight with clientWidth.

    Comments welcome.

    Wednesday, August 11, 2010

    Synchronized Scrollbars

    I recently had a need for two side-by-side TextAreas whose vertical scrollbars were synchronized. So if you drag the left scrollbar, the right one updates, and vice versa.

    I've written a utility class called LinkedScrollers that synchronizes the scrolling of two Scrollers. It has 5 public properties:
    • enabled (defaults to true) - set to false to allow scrollbars to move independently
    • scroller1 - the first Scroller
    • scroller2 - the second Scroller
    • component1 - the first SkinnableComponent, e.g. List, TextArea
    • component2 - the second SkinnableComponent (List, TextArea, etc)
    Originally I wanted to bind the scrollers directly to my LinkedScrollers in MXML like this:
    <spark:LinkedScrollers scroller1="{list.scroller}" scroller2="{textArea.scroller}"/>
    But unfortunately the scroller property on List/TextArea is not bindable, so that didn't work. You can still use the scroller1 and scroller2 in ActionScript (e.g. in the application's creationComplete handler) to set the scrollers.

    So another solution is to set the component1 and component2 properties to the two SkinnableComponents that you want to link (Lists, TextAreas, etc). It should work for any SkinnableComponent that contains a "scroller" skin part.
    E.g.
    <spark:LinkedScrollers component1="{list}" component2="{textArea}"/>

    Here it is in action, view source enabled (right click on the example below):


    As you might guess, this follows on from my previous post on Spark TextArea With Line Numbers.

    Friday, July 16, 2010

    Spark TextArea with Line Numbers

    Here is a skin that you can use on the Spark TextArea class to show line numbers down the left side of the text.
    The line numbers use the same size font as the TextArea.

    It is very simply to use, simply set the skinClass property in mxml like this:
    <s:TextArea skinClass="flex.utils.spark.TextAreaLineNumbersSkin"/>

    If you want a horizontal scroll bar on the TextArea, then set lineBreak="explicit" and the horizontal scrollbar will appear.

    Here is an example of it in action (right click to view source).


    It would be very easy to modify this skin to make it resizable by adding a resize handle in the bottom right corner. Look at the source code from my previous blog post on Resizable Controls, specifically the flex.utils.spark.resize.ResizableTextAreaSkin class, it uses a custom skin for the Scroller, which adds the resize handle.

    Monday, June 28, 2010

    Flex 4 Spark Resizable Controls

    Please go here for Flex 3 Resizable Containers.

    I've created a bunch of skins for many of the common Spark components that allows them to be resized. Each of these skins contains a resizeHandle that when dragged allows the control to be resized. There are two resize handle classes that you can use, the default is called flex.utils.spark.resize.ResizeHandleLines. You can replace every occurrence of that class with flex.utils.spark.resize.ResizeHandleDots if you prefer.

    Here are a list of resize skins:

    With the exception of the ResizableLabel class, all the others are Skins, and as such can be used very simply by setting the skinClass="flex.utils.spark.resize.___Skin" property to the appropriate skin.

    Another option is to create a CSS style for ALL spark.components.Scroller classes to use the flex.utils.spark.resize.ResizableScrollerSkin class like this:
    <fx:Style>
    @namespace "library://ns.adobe.com/flex/spark";
    @namespace mx "library://ns.adobe.com/flex/mx";
    @namespace spark "flex.utils.spark.*";
    @namespace resize "flex.utils.spark.resize.*";

    /* Make all Scroller's use the resizable scroller skin. */
    s|Scroller {
      skin-class: ClassReference("flex.utils.spark.resize.ResizableScrollerSkin");

    </fx:Style>

    ** Note that I've renamed the Flex3 package flex.utils.ui.resize.* to the new Flex4/Spark package name flex.utils.spark.resize.*.

    The most used skin is the ResizableScrollerSkin, it is used on TextAreas, Lists, DataGrids, Trees, ComboBoxes, DropDownLists, and anything else that uses a Scroller component. The way it works is to use a skin for the Scroller that adds the resize handle and uses custom HScrollBar and VScrollBar classes which leave room for the resize handle (the simplest way I could think to do it). Each of the resizable skins uses the ResizeManager class to handle the mouse events and resize the appropriate control.

    The resizable ComboBox and DropDownList skins are slightly different in that they both save the size of the drop down list since it gets destroyed and re-created each time. It also sets the popUpWidthMatchesAnchorWidth="false" after resizing since the width no longer matches the anchor.

    I've also added support for restricting the resize in only the vertical or horizontal direction. There are many ways you can do this, you can either set a style on the resize component:
    .resizePanel {
      resize-direction: vertical; /* or horizontal */
    }
    Or you can call a static method on the ResizeManager class:
    ResizeManager.setResizeDirection(resizePanel, "vertical"); // or "horizontal"
    Or if you can access the ResizeManager class (usually stored in the skin class), then you can set the resizeDirection property on the manager like this:
    resizeManager.resizeDirection = "vertical"; // or "horizontal";
    There are constants defined in the ResizeManager class for "vertical", "horizontal", and "both" (default).

    September 30th, 2010 Update:
    I've added a new skin called ResizableDraggableTitleWindowSkin that uses the MoveManager class to allow dragging the TitleWindow around the screen. It also adds a small drag handle in the titlebar too.
    The same could be done for other classes (e.g. Panel) by following the same procedure. All that is required is a dragComponent (the component that listens for mouse drag events) and a moveComponent (the component that gets moved - in this case it is the TitleWindow).

    Here is an example of most of the skins, view-source enabled.