Wednesday, November 4, 2009

Pass ...rest as a parameter to another function

I recently needed to have a function that accepted a variable number of parameters. This can easily be accomplished using the function myFunction(...rest) syntax. This way I can pass in no parameters (in which case rest is an empty array), one parameter, or multiple parameters.

But, then I wanted to pass those same parameters on to another function that also accepted a variable number of parameters (e.g. ExternalInterface.call(jsFunctionName, ...args)). If you simply call the other function and pass in rest as a parameter then it won't work as expected. E.g.
    public function sayHello(...rest):void {
        // this won't work as expected
        callMe(rest);
    }
    
    private function callMe(...rest):void {
        trace(rest.length + ": ['" + rest.join("' | '""']");
    }

What happens in callMe(...rest) is rest is an array that actually contains only one item - another array which has the rest parameters that were originally passed into sayHello(...rest).
So if you made a call like this:
    sayHello("Hello""World""!");
Then the traced output would be 1: ['Hello,World,!'].
Notice that there is only 1 parameter!

The way to get around this is to use Function.apply(null, args) to call the function instead, like this:
    public function sayHello2(...rest):void {
        // use Function.apply to pass in the rest parameters properly
        var func:Function = callMe; 
        func.apply(null, rest);
    }

So if you made this call now:
    sayHello2("Hello""World""!");
Then the traced output would be 3: ['Hello' | 'World' | '!'].
Now there are 3 parameters as expected.

I found some help on this topic from The Joy Of Flex Blog by David Colleta.

Friday, October 23, 2009

LineChart with CheckBox Legend (Filter Series)

The following example shows a LineChart with a custom Legend that has CheckBoxes next to each LegendItem which allows you to filter the Chart to only show certain series (in this case lines).

I've created a custom class called CheckBoxLegend which extends Legend. It sets the legendItemClass to be the flex.utils.ui.charts.CheckBoxLegendItem class which extends the default LegendItem to add the CheckBox on the left side of the legend item.

Clicking on the legend item toggles the CheckBox and updates the Chart to show or hide the corresponding series. The series is hidden by setting the alpha value to 0.

Here is a snippet of how you use it in MXML:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:charts="flex.utils.ui.charts.*">

<mx:LineChart id="linechart" ... />
<charts:CheckBoxLegend dataProvider="{linechart}"
    color="#000000" direction="horizontal"/>

</mx:Application>

Here is the example, right click to view source:


Note that the minimum and maximum values of the vertical axis don't get updated when you uncheck one or more series. The Axis calculates these values but doesn't take into account the visibility of the Series. So I've added a new Update Vertical Axis Min/Max CheckBox that will go through all the y axis number values and calculate the minimum and maximum values for the visible series. I haven't tested this out on complicated datasets or different chart types, but hopefully it will be a good starting point.

Originally I played around with actually removing the series from the chart (instead of hiding it), but that caused more problems because when you remove a series the chart will automatically re-color any of the remaining series (unless you specified the stroke/color/fill styles) and the legend gets re-populated without the unchecked series. So it was easiest to just hide the series.

Thursday, October 22, 2009

Elevation Map using USGS and Yahoo Maps

** January 2012 Update
Yahoo has officially shut down support for Flex maps, so this example no longer works. For other options try the Google Flash Maps component (which is also deprecated now too)


This example combines two different services:
  • Flex Yahoo Maps - shows an interactive map component similar to Google Maps (Flex 3).
  • USGS Elevation Service - gets the elevation at a given Latitude and Longitude.

  • The Flex application below has the Yahoo Maps component on top and an AreaChart below which will show the elevation.
    Click on the map to add a marker. When you click again in a different location another marker is added, and the elevation chart at the bottom will show the elevation profile for the two points. If you want a more fine-grained elevation profile you can use the drop-down menu above the elevation chart to adjust how frequently the elevation is looked up (every KM, every 500m, every 200m). Keep in mind that the more elevations you look up the slower it is.

    You can also search for an address too using the search bar. The elevation at the search location will be displayed in the toolbar to the right of the search button. You can also show kilometer markers as well by checking the Show KM Markers checkbox in the top toolbar.

    Feel free to use this code for your own purposes. All you have to do is sign up for a Yahoo Maps key here:
    https://developer.apps.yahoo.com/wsregapp/
    And then edit the ElevationMapFunctions.as file and put your key in the APPID constant.
    Here is the Yahoo Maps API.

    There are also a few custom markers included in the source code that you can use and/or modify for your own needs.

    Use the mouse scroll wheel to zoom in or out (or use the +/- control on the map).

    This is a very simple example and a lot more could be done with it. It's really just to show how to get elevation data from the USGS Web Service, and how to add markers to a Yahoo Map.


    ** November 2009 Update
    I've updated the example to include another custom marker - the TitleMarker. This marker shows a label on the marker when it is collapsed. I've also added the option of Showing KM Markers which are displayed as TitleMarkers.
    I also separated the Elevation code into separate packages, and added some operations to allow querying for multiple elevations in sequence. When an elevation is returned from the USGS web service it is cached in the ElevationService class to speed things up.

    ** January 2010 Update
    I've restricted the number of elevations that can be looked up at one time to 30. This is to prevent someone trying to lookup the elevation every 200m between Canada and Europe. If you download the source code, and get your own yahoo maps application id then you can do what you like!

    ** January 2012 Update
    Yahoo has officially shut down support for Flex maps, so this example no longer works. For other options try the Google Flash Maps component (which is also deprecated now too)


    Friday, September 25, 2009

    Helper Classes in ActionScript

    I've had a few people ask me recently if you can have multiple classes defined in the same file in ActionScript. This is something that Java developers are probably very familiar with.

    Well the answer is yes, you can. They are called Helper Classes, but they are defined a little bit differently from how you might expect, and from how it is done in Java.

    Here's a simple example of a helper class:
    package helper
    {
        public class MainClass
        {
            public function MainClass() {
                var helperCls:HelperClass1 = new HelperClass1();
            }
        }
    }
        
    import mx.controls.TextInput;

    class HelperClass1 extends TextInput 
    {
        public function HelperClass1() {
        }
    }
    Notice that the helper class is defined outside of the package wrapper. And yes, multiple helper classes are allowed in the same file. One thing that surprised me was how the helper class has its own separate section for imports that are also outside of the package block.

    Note that helper classes are only available to the main class, and cannot be accessed outside of that file. Even a subclass can't use helper classes belonging to its superclass.

    Here is another website which has some more information on this topic:
    Class syntax in ActionScript 3.0.

    Thursday, September 10, 2009

    Image Splitter in AIR


    I haven't played with Adobe AIR much, and thought I'd give it a try. I have a whole bunch of sprites - images that contain many different smaller images all side by side - that I wanted to split up into separate images.

    So I decided to use Adobe AIR to solve this simple problem. The WindowedApplication lets you choose an input image file and an output directory. The image is loaded into the window and then you can choose the column width and row height for how you want to split the image up. Alternatively you can specify the number of rows and columns. This will draw a gray grid on top of the input image showing you how the image will be split up.

    Click on the images on the right side of the page to see the full size image. The top screenshot shows the input image being split into 6 columns and 4 rows. The middle screenshot shows how the background color can be made transparent. And the bottom example shows the output images.

    You can also choose between using the JPEGEncoder or the PNGEncoder (PNG supports transparency). If you choose PNG then you can also optionally choose a color that you want to make transparent (e.g. the background color). You can click on the input image to choose the color you want transparent, or you can use the ColorPicker.

    There is a filename prefix textbox too for choosing how you want the output files named. After the prefix a number will be appended (e.g. mario1.png, mario2.png) for each output image. Output images will not overwrite existing images unless you check the Overwrite checkbox.

    Feel free to modify for you own use. Because it's an AIR application I've only attached screenshots.

    - DOWNLOAD SOURCE ZIP FILE -

    - VIEW SOURCE -

     
    Input Image

    Transparent background

    Output Images



    Tuesday, August 11, 2009

    Tour de Flex and Flex Component Explorer

    If you haven't already seen this awesome Flex website then check it out.

    Tour de Flex


    It has examples (including source code) of all the common Flex 3 components (DataGrid, Tree, Button, Canvas, etc) as well as a TON of other examples (269 at the last count) from various open source projects including Flex Yahoo Maps, advanced Data Visualizations (3D charts, gantt charts, calendar views, etc), Cloud APIs (searching Amazon, eBay, Flickr, etc) and much more.

    There is also the original Adobe Flex 3 Component Explorer which contains examples of just the core Flex 3 components.

    For examples on styling components check out the Flex 3 Style Explorer site. I also find this list of all the styles for each Flex component useful: Flex 3.0 CSS Properties List.

    Friday, August 7, 2009

    Counting Words, StringWordValidator

    I was recently required to limit the number of words in a TextArea. It's easy to limit the number of characters by using the TextArea.maxChars property, but how do you restrict the number of words?

    The way I solved this problem was to make a new class that extends mx.validators.StringValidator and adds the following properties:
    • maxWords - the maximum number of words allowed
    • minWords - the minimum number of words allowed
    • tooManyWordsError - the error string to be displayed when too many words are entered
    • tooFewWordsError - the error string when not enough words are entered
    • trim - trims the input string before the validation occurs

    Here is the utility function I wrote for counting how many words are in a string:
        /**
         * Splits the text into words and returns the number of words found.
         * If the text is null or blank (trimmed) then 0 is returned.
         * The regular expression used is /\s+/g which splits the text into
         * words based on whitespace.
         */
        public static function countWords(txt:String):uint {
            var count:uint = 0;
            if (txt != null) {
                txt = StringUtil.trim(txt);
                if (txt.length > 0) {
                    count = txt.split(/\s+/g).length;
                }
            }
            return count;
        }

    And here is it in action (view source). The validator will run when the TextArea loses focus (that is the default behavior), so try typing in one word and then pressing tab. You can also adjust the minimum and maximum number of words allowed and the validation will be updated immediately.

  • StringWordValidator source
  • ErrorTipManager source (see previous blog post on Always showing error tips)

  • I also included the ResizableTextArea class too just for fun.

    Thursday, August 6, 2009

    Always showing error tips (validators)


    Many people have complained about how Flex 3's error validation messages are not shown unless you hover your mouse over the input field that is invalid. See the image on the right and you'll probably know what I'm talking about. If not, then when you use a mx.validators.Validator on an input field such as a TextInput or TextArea and the user enters invalid data then the input control gets a red border indicating an error. But the error message (e.g. "This field is required") is ONLY displayed when the user hovers the mouse over the input field.

    After reading a few other posts on the subject, including a bug report that is in the Adobe Bug Tracker I decided to see if I could come up with a nice easy solution.

    I made a new class called ErrorTipManager that has a bunch of public static functions that lets you easily attach your validators (or your own validation functions). The code is documented, so view the sample below and right click view source to get the source code. The error tips should stay in the correct position even when the input moves (from a window resize or layout).



    A lot of credit goes to Aral Balkin's blog entry on Better form validation in Flex. I also got help from this blog on how to show error tooltips.

    Note that if you use the ErrorTipManager as described above and you set the validator.enabled = false; then the error tip will still be displayed. The validator does not fire an event when the enabled value changes, so it isn't possible to automatically update the visibility of the error tip. Instead you can do it manually by calling ErrorTipManager.hideErrorTip(validator.source, true). See the source code of the example above - I've added in a CheckBox that controls the second validator's enabled state.

    August 26th, 2009 update
    Fixed a problem where the error tip wasn't being position properly.

    November 2nd, 2009 update
    Added two new functions to ErrorTipManager for handling error tips in popup windows:
    • registerValidatorOnPopUp(validator, popUp, hideExistingErrorTips) - registers the validator and adds move and resize listeners on the popUp. It can also hide any existing error tips (this is a good idea because the existing error tips appear on top of the popUp window which doesn't look good).
    • unregisterPopUpValidators(popUp, validateExistingErrorTips) - unregisters all the validators associated with the popUp and removes the move and resize listeners that were added to the popUp. It can also validate all the remaining validators which will cause the error tips to re-appear now that the popUp has closed.

    March 24th, 2010 update
    Fixed a problem where the error tip wasn't being positioned properly when the parent container was scrolled. It will also hide the error tip if the source component gets scrolled out of the view. I also now move the error tip in front of other error tips when it gets positioned.

    July 14th, 2010 update
    Added two more event listeners in the ErrorTipManager to listen for when the input is hidden (visible="false") and when it gets removed from its parent (input.parent.removeChild(input)).
    This still does not solve the problem where the error tip remains visible when the parent is hidden or removed (e.g. if the input is inside a TabNavigator and the tab changes). In this case I'd suggest manually hiding or removing the error tip. Listen for the appropriate event like "change" and then call ErrorTipManager.hideErrorTip(input).

    March 2011 update
    I've posted an alternate approach to displaying validation error messages that doesn't involve the rather hacky approach above. You can view the blog post here.

    Wednesday, July 29, 2009

    DataGridColumn header tooltips

    I really thought that something as simple as putting a tooltip on a DataGridColumn header would be easy to do in Flex.

    If you want to make your own headerRenderer, then it is obviously very simple to just set the toolTip property in your renderer. But I was curious if it could easily be done with out a custom header renderer. My solution was to create a new class which extended DataGridColumn and adds three new properties: headerToolTip, headerToolTipPosition, and headerTextTruncate (which adds the "..." if the headerText is too long to fit).

    Here is the simplified version of the MXML code:
    <mx:DataGrid x="10" y="10" width="500" height="130" dataProvider="{employees}">
      <mx:columns>
        <ui:DataGridToolTipColumn headerText="Phone" dataField="phone" width="90"
          headerToolTip="Phone Number (tooltip above)" headerToolTipPosition="above"/>
      </mx:columns>
    </mx:DataGrid>

    The headerToolTipPosition property can have the following values:
  • above - positions the tooltip above the header
  • below - positions the tooltip below the header
  • left - positions the tooltip to the left of the header
  • right - positions the tooltip to the right of the header
  • inline - positions the tooltip on top of the header
  • default - positions the tooltip slightly below and to the right of the header (this is the default value if headerToolTipPosition isn't specified.

  • And here is the example (right-click View Source for the full source code):

    Feel free to use this code or modify it to your own needs.

    ** Updated on September 16th 2009
  • Fixed it so that setting headerWordWrap="true" now works as expected.
  • When the headerToolTip isn't defined then no tooltip is shown.
  • Added a new property: headerTextTruncate which will truncate the headerText and add the ellipsis ("...") if the headerText doesn't fit inside the renderer. Note that this property doesn't work if the headerWordWrap property is set to true.


  • Tuesday, June 30, 2009

    Loading Remote SWFs and parameters

    Here is another example of one SWF loading another SWF and how parameters can be passed through the url.

    The main application (called Loader1) has a panel which displays information about the current application, parameters, url etc.

    The main application loads a remote application SWF (called Loader2) which also has the same panel displaying information about the application, parameters, url, etc. The differences are highlighted in bold.

    Here is the code for loading a remote swf - notice how parameters are passed into the url:
    private function loadRemoteSWF():void {
        var remoteSwfUrl:String = 
            "http://keg.cs.uvic.ca/flexdevtips/loaders/Loader2.swf?loaderurl=hello";
        var loader:SWFLoader = new SWFLoader();
        loader.addEventListener(Event.COMPLETE, remoteSWFLoaded);
        loader.load(remoteSwfUrl);
    }

    private function remoteSWFLoaded(event:Event):void {
        var loader:SWFLoader = event.currentTarget as SWFLoader;
        ui.addChild(loader.content); // ui is a UIComponent
    }

    In the remote application you can access the parameters that were passed in from the main application through the SWFLoader by the parameters property, but you MUST be inside the remote application MXML (e.g. in this case in Loader2.mxml), otherwise if you use Application.application.parameters this will refer to the parameters from the main application and not the ones that were passed in using the SWFLoader.


    Source Code:

    Monday, June 22, 2009

    Default stylesheet in an SWC (Flex Library Project), and embedded font rotation

    For ages now I've been trying to figure out how I can use a StyleSheet from inside my Flex Library Project in ActionScript. I kept reading that it is very resource intensive to be calling UIComponent.setStyle(...) at runtime, so I wanted to set all my styles using a StyleSheet. The LiveDocs on the subject seem to say that there are two ways to load a StyleSheet:
    1. From inside MXML in your Application using the <Style source="assets/styles.css"/> tag
    2. By loading an external stylesheet SWF file (compiled from a CSS file) using the
      StyleManager. loadStyleDeclarations(url)

    Then I finally found the solution in this article (right near the bottom of the page in the comment by Henk). And that pointed me to this LiveDoc - Applying styles to your custom component which solved the problem. Scroll most of the way down until you get to the part called "Applying styles from a defaults.css file".

    If you don't want to read the articles above, here is my brief summary.

    Using a StyleSheet in your FlexLibrary Project:
    1. create a StyleSheet in the src directory of your project, and call it defaults.css
    2. open the project Properties > Flex Library Build Path and check the src/defaults.css file under the Assets tab
    3. define your styles inside the defaults.css StyleSheet
    Restrictions:
    • You can include only a single style sheet in the SWC file
    • The file must be named defaults.css
    • The file must be in the top-most directory of the SWC file
    *Note: it appears that having a defaults.css file in your Flex Application project (swf) also works without having to specify the stylesheet in the mxml (e.g. <mx:Style source="defaults.css"/> is not needed).


    Using Embedded Fonts inside Flex Library Project/SWC:
    If you want to use an embedded font inside your library project you have two ways of doing this:
    1. Embed the font inside an ActionScript file like this (the font is inside the project src/assets directory):
      [Embed(source='/assets/verdana.ttf'fontName='localVerdana'
             mimeType='application/x-font')]
      public var verdanaFont:Class;
      ...
      setStyle("fontFamily""localVerdana");
    2. Or put your embedded ttf font in your project's src directory and embed the fond using the defaults.css file (the font must be in the src directory for this to work - see this Adobe Bug for more details):
      defaults.css:
      @font-face {
        font-family: localVerdana;
        font-weight: normal;
        src: url("verdana.ttf");
      }
      .label {
        /* must use embedded font for label rotation to work */
        font-family: localVerdana;
        /* must specifically set the font weight */
        font-weight: normal;
      }
    Note that if you want to set the DisplayObject.rotation property then you have to use an embedded font otherwise it doesn't work.

    Here is a simple example of font/label rotation (right click "View Source" for the code).
    In this example I actually included three fonts - Verdana plain, Verdana bold, and Comic Sans.

    * Note that fonts can greatly increase the size of your SWF. The three fonts that I used above are all about 150 KB each. One way to reduce the size of your SWF is to restrict the unicode character range (meaning that only part of the font set is included in your SWF). Here is the LiveDoc on Using Fonts and Setting Character Ranges.

    Ben Stucki's blog helped me figure out how to embed a bold and plain font in CSS.

    Saturday, June 20, 2009

    Error: Could not find resource bundle rpc

    I ran into this runtime error "Error: Could not find resource bundle rpc" when running my application which loads a remote SWF file. After a few futile Google searches (which turned up this bug report) I realized that I had compiled the remote SWF using the Flex 2.0.1 compiler instead of the default Flex 3.2. Once I changed my remote SWF to be compiled using the 3.2 compiler (this can be done under the project
    Properties > Flex Compiler > Use default SDK (currently "Flex 3.2") then it all worked as expected. So I'm guessing that Flex 3 and Flex 2 SWFs don't play nicely...

    Wednesday, June 17, 2009

    Creating a BevelFilter

    It is remarkably simple to add a bevel filter to any DisplayObject using the filters property. You can also apply a bevel filter to a BitmapData object by calling the applyFilter() function.

    The two classes that you can use are: BevelFilter or GradientBevelFilter. In the example below I use the BevelFilter because it is slightly more simple. Almost all the properties are the same, except that the GradientBevelFilter class lets you choose more than 2 colors, as well as the ratios and alpha values. Here is a GradientBevelFilter example.

    Here is an example that lets you set all the BevelFilter properties and see how it affects the image on to which the filter is applied.


    Most of the properties are quite self explanatory. The quality property can be set using constants defined in the BitmapFilterQuality class (high = 3, medium = 2, and low = 1). But the documentation also says that the allowed quality values are from 0 - 15, but you decrease the performance by setting the quality value higher than 3.
    There are also constants for the bevel type using the BitmapFilterType class.

    Adobe LiveDocs:
    I'm also using the BindingUtils class to bind the bevel filter properties to the inputs (so that when the inputs change, the filter properties change too).

    Tuesday, June 16, 2009

    Unable to export SWC oem

    Ever seen this error? I just came across it today. Thankfully the solution is very simple, but it took a few minutes of Google searches to find the solution.

    The problem is caused by having invalid assets selected in your Flex Library Project. Probably you've removed one or more asset files, but the project properties didn't get updated.
    To fix this open your project Properties > Flex Library Build Path > Assets, then de-select all your assets, and then re-select the assets. Click OK and it should update your project properties with the correct assets.

    Credits go to this useful website: FlexGarden.net

    Saturday, June 13, 2009

    Full Screen support in Flex

    I recently learned that you can make your Flex application full screen. Here are the steps to accomplish it:

    First edit your project's html-template/index.template.html file and add the following allowFullScreen property to the JavaScript code:
    else if (hasRequestedVersion) {
      AC_FL_RunContent(
        ...
        "allowFullScreen","true",
        ...
    );

    You can also add the <param name="allowFullScreen" value="true"/> to the <object> tag, and allowFullScreen="true" to the <embed> tag for compatibility.

    Next in your ActionScript code when the application has finished loading (when the stage isn't null) you can make your application full screen like this:
    Application.application.stage.displayState = StageDisplayState.FULL_SCREEN;

    I found this out from the The Adobe Flex 3 Programming ActionScript 3 PDF on page 547.

    Thursday, June 11, 2009

    Flex Amazon Image Search

    Here's a sample application that queries the Amazon Web Services to retrieve images for CDs, DVDs, books, video games, software, etc. E.g. if you want to find the album cover for a music CD.

    Here is my example - it lets you search for music, dvds, books, etc by title (and an artist for music cds, and an author for books) and then shows the resulting images ordered into 5 different image sizes. Double click an image to open the jpg in a new window.
    ** As Amazon keeps updating their web service this example will stop working. Please view the source code to see how it used to work!


    Here are the steps to get it working in your Flex Builder:
    1. Download the source code from the example above (Right click "View Source", then click the download link in the bottom left corner of the page)
    2. Sign up for an Amazon Web Service Account
    3. Copy your Access Key ID and put it in the services/AmazonItemSearch.as file
    4. Full details and the API for the Amazon Web Services are located here

    I found this website which helped me get started:
    Finding cover art with Flex and Amazon WebServices.


    ** August 24th, 2009 Update **
    As of August 15th Amazon now requires that all requests are signed. The example above has been updated to include this change, so you can View Source to see the code.

    Here are some links that I found very useful in fixing the problem:** One final note
    When signing the request, I tried using the com.adobe.crypto.HMAC and com.adobe.crypto.SHA256 classes that come with the as3corelib project to create the signature, but it didn't work because the signature needs to be Base64 encoded. So instead I modified those two classes very slightly to make it work.

    I also included a TestSignature.mxml application which was useful to make sure that the signature matched what the Signed Request Helper output.

    Thursday, June 4, 2009

    Repairing my Creative Zen Vision:M 60GB (not Flex related)


    I've spent many hours this year trying to fix my Creative Zen Vision:M 60GB. It died in January after I connected it to my laptop to charge it up (using a cheap adapter that I bought on ebay). Ever since it wouldn't turn on, just had a solid blue light (or a blinking blue light when it was plugged in to the computer or wall charger). And it was not recognized by the computer either.

    My first thought was that the motherboard had died (probably because of my cheap usb adapter cable), but motherboards are quite expensive to replace, so instead I bought a new battery (off ebay too!) just to make sure. When the battery arrived I installed it and nothing changed - exactly the same scenario. So then I went back on ebay and bought a motherboard (not as expensive as I thought - only $20 USD plus shipping). The motherboard arrived this week and I took the old one out and put the new one in. See below for links on how to disassemble the ZVM. It isn't that difficult as long as you have a tiny Phillips screw driver, and steady hands.

    After the new motherboard was installed I first connected it to the computer with the real cables that came with the player and charged it up. The computer instantly recognized mp3 player, and installed the drivers for it. But when I went to the properties in Windows Explorer it said it was only 50mb (instead of 60gb!). After searching google it appears that many other people have had this scenario. The reason for it is the firmware isn't correctly loaded, or is out of date, or the hard drive is faulty.

    When I turned on the mp3 player the screen then showed an error message saying incorrect firmware version (0.0.15) and gave me the option to clean , format, reload firmware, and reboot. Cleaning did nothing - the screen said "scan disk..." forever. So I tried to reload the firmware. I downloaded the latest version from the Creative support website (linked at the top) and ran the exe (version 1.21.02), but every time it said "Your player is not connected. Please connect your player." even though my player was connected AND was recognized by Windows Explorer. A few people mention that this error happens on Windows XP when you have Windows Media Player 11 installed, so I rolled back to Windows Media Player 10 and still the same problem.

    So, next step was to find a way to get the firmware onto the player with out using Creative's default firmware updater. I came across a support forum on www.epizenter.net mentioning that some people had hacked/cracked the Zen Vision:M firmware and had been able to change the fonts, colors, themes etc. So after days of searching I finally found some tools which helped me fix my zen. I haven't been able to find an original version of my 60gb firmware, so instead I'm using a modified version that uses a different font (Comic Sans MS). It works, so I don't care :)

    Here are the steps I followed:
    1. Download the hacked Firmware Updater (it is for the ZVM 30gb but also works with the 60gb)
    2. Download the modified firmware nk.bin and put it in this directory (on Windows) C:\CtJbFW\newbin
    3. Connect your zen, and run the updater. All being well it will update the firmware and reboot your zen and it will work!


    Links:
    I've recently bought the new Creative Zen X-Fi2 mp3 player, with the touchscreen interface. At first it was a little sluggish (the touchscreen), but Creative has released a few patches that greatly improve the performance.






    Wednesday, May 27, 2009

    Blogger source code syntax highlighting

    If you've read my last few blog posts you might have noticed that my code snippets now have syntax highlighting that looks similar to Flex Builder.

    I've found many people asking how to get syntax highlighting to work on source code that is pasted into Blogger. Most solutions use CSS and Javascript to accomplish that with varying levels of success. I've chosen to go a different route and am using a parser to turn ActionScript text into html which I then paste right into a blog post (under "Edit Html").

    I'm using a slightly modified version of this amazing free parser called Java2Html created by Markus Gebhard (GNU License). It is a Java Swing application (or Applet) that takes in input text and outputs html which you can easily copy and paste into a blog. The original version (which I believe is last updated in 2006) has three different style options - Eclipse, Kawa, and Monochrome. I've added a fourth option FlexBuilder that uses the default syntax highlighting styles found in ActionScript.

    If you want to try out my version, I've posted the applet here: java2html

    Here are some of the options you can use (in the panel on the right side):
  • Style - choose one of the 4 code styles (use FlexBuilder for ActionScript)
  • Line numbers - shows line numbers in the html
  • Table border - draws a 2 pixel gray border around the code block
  • Background color - if checked then a white background color is set on the code block
  • Include <html> and <body> tags - if false then the output html doesn't inclde the <html> and <body> tags, only the content.
  • Use <br> at the end of lines - if false then the html won't contain <br> tags
  • Include new lines ("\n") - if false then the html won't contain new line characters. Turn this off if you want to paste your code into Blogger since it treats new lines as breaks!
  • CSS Class - by default the code block is wrapped inside a <div class="java"> tag. This option configures the class="java" part.

  • Again I can't take much credit for this. All I've really done is add a few of the options mentioned above and changed the parser slightly to work with ActionScript keywords (such as function, var, etc).

    Here is an example of a very simple code snippet with and without styling:
    private function get string():String {
    var str:String = "String";
    return str;
    }
    private function get string():String {
        var str:String = "String";
        return str;

                

    One more thing, I haven't tested the various Target options, I only use the default "XHTML 1.0 Transitional (inlined fonts)".

    Tuesday, May 26, 2009

    Sorting string characters alphabetically

    In Java if you want to sort the characters in a String alphabetically it is very easy:
    String test = "sorting";
    char[] chars = test.toCharArray();
    Arrays.sort(chars);
    System.out.println(new String(chars))// prints out "ginorst"

    But how can we do this in Flex/ActionScript? Perhaps there is an easier way than this, but here are my utility functions that sorts the characters in a String by putting each character into an array, sorting the array, then joining the array back into a String.
    /**
     * Converts the string's characters into an array.
     @param string the string to convert into an array
     @param unique if true then only unique characters are added to the array
     @param ignoreCase only applies if the unique property is set to true
     */
    public static function toCharArray(string:String, unique:Boolean = false
           ignoreCase:Boolean = false):Array {
        var array:Array = new Array();
        if ((string != null&& (string.length > 0)) {
            // for tracking unique letters
            var seen:Object = new Object();
            // add each character to the array
            for (var i:int = 0; i < string.length; i++) {
                var char:String = string.charAt(i);
                if (unique) {
                    // unique characters only, possibly ignoring case 
                    // use the character code as the key (could just use the letter too) 
                    var key:String = (ignoreCase ? char.toUpperCase() : char);
                    key = key.charCodeAt(0).toString(10);
                    if (!seen.hasOwnProperty(key)) {
                        seen[keytrue;
                        array.push(char);
                    }
                else {
                    array.push(char);
                }
            }
        }
        return array;
    }

    /**
     * Sorts the characters in the string alphabetically. 
     @param ignoreCase if false (default) upper case letters come first then lowercase
     @param descending if true then the String is sorted in reverse
     @param unique if true then only unique characters are sorted and returned
     */
    public static function sort(string:String, ignoreCase:Boolean = false
                descending:Boolean = false, unique:Boolean = false):String {
        // no point in sorting
        if ((string == null|| (string.length <= 1)) {
            return string;
        }
        var chars:Array = toCharArray(string, unique, ignoreCase);
        var options:uint = 0;
        if (ignoreCase) {
            options = options | Array.CASEINSENSITIVE;
        }
        if (descending) {
            options = options | Array.DESCENDING;
        }
        chars.sort(function(s1:String, s2:String):int {
            return ObjectUtil.stringCompare(s1, s2, ignoreCase);
        }, options);
        
        var sorted:String = chars.join("");
        return sorted;
    }

    Feel free to comment if you know of a simpler way to sort characters in a String.

    Wednesday, May 20, 2009

    Using Flex and AMFPHP without a services-config.xml file

    I've been working a bit with amfphp, sending data between Flex and PHP using the RemoteObject class. Initially I put the generic services-config.xml file in my application's src directory:
    <services-config>
    <services>
    <service id="amfphp-flashremoting-service"
    class="flex.messaging.services.RemotingService"
    messageTypes="flex.messaging.messages.RemotingMessage">
    <destination id="amfphp">
    <channels>
    <channel ref="my-amfphp"/>
    </channels>
    <properties>
    <source>*</source>
    </properties>
    </destination>
    </service>
    </services>
    <channels>
    <channel-definition id="my-amfphp" class="mx.messaging.channels.AMFChannel">
    <endpoint uri="http://localhost/amfphp/gateway.php"
    class="flex.messaging.endpoints.AMFEndpoint"/>
    </channel-definition>
    </channels>
    </services-config>
    And changed my project properties to add this line to the Flex Compiler page:
    -services services-config.xml

    But I just came across this post which shows how to get around having to have an XML file by defining the channel at runtime.

    So here is my simplified Flex code:
    import mx.rpc.events.ResultEvent;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.remoting.RemoteObject;
    import mx.messaging.ChannelSet;
    import mx.messaging.channels.AMFChannel;


    var url:String = "http://localhost/amfphp/gateway.php";
    var channel:AMFChannel = new AMFChannel("my-amfphp", url);
    var channelSet:ChannelSet = new ChannelSet();
    channelSet.addChannel(channel);
    var ro:RemoteObject = new RemoteObject("amfphp");
    ro.channelSet = channelSet;
    // Specify the PHP class
    ro.source = "TestService";
    ro.addEventListener(FaultEvent.FAULT, function(event:FaultEvent):void {
        trace("Fault: " + event.fault);
    });
    ro.addEventListener(ResultEvent.RESULT, function(event:ResultEvent):void {
        trace("Result: " + event.result);
    });
    // the TestService class must have a public helloWorld function
    ro.helloWorld();

    You could also do the same in MXML:
    <mx:ChannelSet id="channelSet">
    <mx:channels>
    <mx:AMFChannel uri="http://localhost/amfphp/gateway.php"/>
    </mx:channels>
    </mx:ChannelSet>
    <mx:RemoteObject source="TestService" destination="amfphp"
    channelSet="{channelSet}" id="remoteObject"
    fault="trace('Fault: '+event.fault)"
    result="trace('Result: '+event.result)"/>

    And the corresponding PHP code (put the php file inside your webroot/amfphp/services directory):
    <?php
    class TestService {
        public function helloWorld() {
            return "Hello from PHP";
        }
    }
    ?>

    So what are the benefits of this approach? Well, I'm not sure. In my case it was better because I have one logging class that does all the remoting, and is used by many different Flex applications. So instead of having to duplicate the services-config.xml file in every flex application this way I could define my endpoint url (http://localhost/amfphp/gateway.php) in one place.

    Here is another site that is useful when getting started with amfphp:
  • amfphp video tutorials
  • Wednesday, April 29, 2009

    FlashVars - passing parameters into Flash/Flex

    I'm sure most people are familiar with how to pass parameters into Flex using FlashVars. If you edit your project's html-template/index.template.html file and add in the flashVars parameter into the JavaScript like this:

    ...
    } else if (hasRequestedVersion) {
    // if we've detected an acceptable version
    // embed the Flash Content SWF when all tests are passed
    AC_FL_RunContent(
    "src", "FlashVarsTest",
    "width", "100%",
    "height", "100%",
    "align", "middle",
    "id", "FlashVarsTest",
    "quality", "high",
    "bgcolor", "#ffffff",
    "name", "FlashVarsTest",
    "allowScriptAccess","always",
    "type", "application/x-shockwave-flash",
    "flashVars", "hello=world&another=one",
    "pluginspage", "http://www.adobe.com/go/getflashplayer"
    );
    }...

    This adds two parameters which can be accessed from inside Flex using the Application.application.parameters variable. E.g. Application.application.parameters.hello gives you the value "world".

    But if you don't want to use JavaScript (which I wouldn't recommend, but is necessary in a few cases) then you can use the old loading method (also included in the index.template.html file) like this. The important thing to note is that Internet Explorer loads the parameters in differently than all other browsers (that I've tested).

    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
    id="FlashVarsTest" width="100%" height="100%"
    codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
    <param name="movie" value="FlashVarsTest.swf" />
    <param name="quality" value="high" />
    <param name="bgcolor" value="#ffffff" />
    <param name="flashVars" value="FlashParameters=Internet Explorer only"/>
    <param name="allowScriptAccess" value="always" />
    <embed src="FlashVarsTest.swf" quality="high" bgcolor="#ffffff"
    width="100%" height="100%" name="FlashVarsTest" align="middle"
    play="true"
    loop="false"
    allowScriptAccess="always"
    type="application/x-shockwave-flash"
    flashVars="FlashParameters=FireFox,Safari,Chrome"
    pluginspage="http://www.adobe.com/go/getflashplayer">
    </embed>
    </object>
    And the same thing applies to the other tags: bgcolor, width, height. Internet Explorer reads in the values that are in the <object> tag, while all other browsers (FireFox, Chrome, Safari, ...) read in the values from inside the <embed> tag. So you have to make sure to duplicate all the values.

    Friday, April 24, 2009

    Tree Lines

    In Flex I've seen how you can configure Trees by changing the disclosure (expand/collapse) icon, the folder/leaf icons, background colors, indentation, etc. But I've never seen the option for rendering tree lines like you can in Java, C# and most other languages.

    I've created a custom TreeItemRenderer that does renderer tree lines. It has these properties:
    <ui:TreeItemLinesRenderer
    Styles
    lineAlpha="1"
    lineColor="#808080"
    lineThickness="1"
    lineStyle="dotted"/>
    And here is an example of it in action (right click to view source):


    If you know of any other solutions out there I'd be interested to see them.

    ** September 28th 2009 Updated **
    I've added another example application showing how to render tree lines in an AdvancedDataGrid control.
  • Flex Example Application
  • AdvancedDataGrid API
  • AdvancedDataGridGroupItemRenderer API

  • Flex 4/Spark Version
    Here is a very similar version written in Flex 4. It uses a lot of the same code, but uses a Spark item renderer instead. There is probably a much nicer way to do this using the new Spark Path or Line controls, but since the code was already written I went with this solution.

    An example of tree lines in an AdvancedDataGrid with a Flex 4 itemRenderer is on my newer blog post.

    Wednesday, April 22, 2009

    AdvancED Flex 3 Book


    Does anyone own this book? It covers some good material but the code samples in it are terrible! I've never seen so many typos and so much code that does not even compile.

    Here's my favorite code example from the book, see if you can count how many different compile errors and warnings you get from this snippet (page 172 of the book, copyright 2008, ...):
    private var myVariable:String;
    public get myVariable():void {
        return myVariable;
    }
    [Bindable]
    public set myVariable(value:String) {
        myVariable = value;
    }
    It seems like after almost every page I read in it I have to type the code into Flex Builder to verify that in fact no, you can't do it that way because it doesn't even compile.

    Anyways, hopefully not too many people buy this book... Or maybe by the next edition they will have fixed up the many errors.

    Another Flex/ActionScript book that I bought and think quite highly of is this one: