FormItem, adding an icon

Adding an icon to a form item is (yet another) one of those really annoying things in flex. I’m sure its something that loads of people wish to do but you can’t.

Well just to see if I could, I set about and extended the FormItem class so that I could add an image/icon.

After a quick look at the source code of the FormItem you can see that it only has two children. One, the label and two, the indicator. So if you do wish to add anything else you’re going to have to extend the FormItem.

Thankfully the FormItem is based on the Container which makes adding anything fairly straight forward. I prefer to do any extending in actionscript but you could do the below in MXML with a bit of actionscript code at the same time.

There are 3 steps you need to make.

  1. Override the createChildren method
  2. Set the image source
  3. Override the label

Override the createChildren

protected override function createChildren():void {
    super.createChildren();
    //you could move the image creation into a seperate function when and if the imagesource has been set
	//but for this example I've kept it simple.
	this.image = new Image();
	image.width = 16;
	image.height = 16;
	//again I've hardcoded these values for simplicity
	//You could if you wanted to create a versitile custom component load these values in from a CSS file
	image.setStyle('verticalCenter', 0 );
	image.setStyle('left', 5 );
	image.source = _imageSource;
	this.rawChildren.addChild(image);
	//bind the string property to the image source property.
	BindingUtils.bindProperty(image, 'source', this, 'imageSource');
}

from the above code you’ll see that all I’ve done is create an image, set its various properties and add it to the form.

most of this could and probably should be moved to a separate function (but for this demo I haven’t) so that you only add the image if it is actually required.  Also the style settings should come from a CSS file but for simplicity of the demo I haven’t done this.

Set the image source

private var _imageSource : String = '';
 
[Bindable]
public function get imageSource() : String {
	return _imageSource;
} 
 
//Sets the imageSource and I've added a number of spaces at the start to offset the 
//width of the image.
//The overall form width will be calculated from the width of the label (this is done inside the FormItem) 
public function set imageSource(str : String) : void {
  _imageSource = str;
  if(_imageSource.length > 0){//setting the label (not using _label) will resize the form/formItems
  //add spaces to the trimed version to make sure you don't end up with 100's of spaces at the start.
	label = "   " + StringUtil.trim(_label);
  } else {
	label = StringUtil.trim(_label);
  }
}

In the above code you can see that I set the variable _imageSource (which bound to the images source – see first snippet of code).  If the source is not “” then I add spaces to the label, make sure you set label and not _label.  This makes sure that the label width gets recalcualted.

Override the label

//Sets the label.
//If the imageSource has been set already then this will add spaces to the label
public override function set label(str : String) : void {
  _label = str;
  if(_imageSource.length > 0){
	_label = "   " + str;
  } else {
	_label = StringUtil.trim(str);
  }
  // call the super last, this will also force the remeausing of the formItem and Form
  super.label = _label;
}

The above code is very similar to the setter that set the imageSource but this time it sets _label then makes sure that the super function gets the new label.

Check out the simple demo here. (Right click for source)

[ad name=”ad-1″]

Exploding pie charts, part 2

In one of my first blogs I demoed a pie chart that made each of the wedges from the pie explode out the way when its item in the legend was rolled over by the mouse.
The pie chart also had a nice effect when it was shown in that it filled up in a circular manor.

You can check out the app here.

After a comment/question from the previous post asking about something I didn’t explain, I thought that it deservered its own post rather than just an edit of the original.

So the question was how do you get the circular effect, and how do you do ‘(… %)’ in the legend?

The effect

Firstly set up the effect

<mx:SeriesInterpolate id="doughnut" duration="1000" />

Then whatever ID you have given your pie series you’d do the following (I called my one ‘seriesOne’)

seriesOne.setStyle('showDataEffect', doughnut);

(I did this set up in the script block on creation complete or show + I nulled the effect/DP’s on hide so that you get the full effect each time)

If you wish to get the full opening of the circle effect then the data must be empty to start with as the effect just changes between the current and the new values.

The second part of the question was to do with the labels on the legend.  This one is all to do with how you set up your dataprovider for the pie chart.

The label

I start of with loading in the data from an XML file (if you use some HTTP tool you should be able to see the data).  It goes something like the following

<chartOne>
  <chartName>blah</chartName>
  <data>
    <section>
      <name>item 1</name>
      <value>37.55</value>
    </section>
    <section>
      <name>item 2</name>
      <value>13.33</value>
    </section>               
  </data>
</chartOne>

As you’ll see from the data there is no ‘%’. So what I do is when I load the data I construct an object VO (value object).

This VO contains the name, item and a label.  The label is just the name + ‘(‘ + value +’%)’.  Then the arrayCollection I use for the dataprovider is just a collection of these object VO’s.

Essentially my VO is this,

var obj : Object =new Object();
obj.name = 'item 1';
obj.value = 37.55;
obj.label = obj.name + '(' + obj.value +'%)';

The legend looks at the data for the pie chart and sees the label property and uses that as it is.

This may make you ask about the datatip for the actual pie chart as it doesn’t contain the brackets. Well for that I had to implement a dataTipFunction.

This function took the form,

private function returnToolTip(hitData:HitData):String {
    return hitData.item.name + ' ' +hitData.item.value + '%';
}

and you just can set this in the MXML of the pie chart.

Well hopefully thats explained in a reasonable way, I’d love to open the entire source for this but without reworking it (commercial reasons) I can’t.

Check out part one of the blog here.

[ad name=”ad-1″]

Dates, how many days? (DateValidator)

It’s been a while since I last looked at this, and it annoys me that there isn’t a simple function to do this. So if you are wishing to find out how many days are in a month for a given year then feel free to use the below.

Of course it’s going to be virtually the same result for most years, but I still think it should be a function inside the Date class (or maybe a DateUtil class).

Start off with a standard Switch statement as all months (apart from February) have a fixed number of days.  This of course isn’t exactly rocket science but how do we figure out how many days February has?

Well the solution still isn’t rocket science but I like it, if you create a DateValidator and you give it a date of 29/02/2003 (yes this is a UK date – date at the start) and get it to validate that, then it will fail as 2003 isn’t a leap year. So February for 2003 must only have 28 days.

That’s it.  You could of course just divide the year by 4 and check to see if there is a modulus of 0, if so then it is a leap year.  If you chose to use this approach you’d need to make sure that the date range you are using doesn’t include anything unusual (I’m not sure how constant the leap year really is, if it’s anything like the clocks going forward or back 1 or 2 hours then you’re best just using the internal date validation). The flash player gets its time from the operation system, so (AFAIK) its rules for working out if a date is valid is also comes from the operating system.

the below code also shows an example of using the DateValidator that doesn’t use the month/date/year input, which is another reason why I like it.

public function getNumberOfDaysInMonth(month : Number, year : Number) : Number{
 
  switch(month){
 
    case 0://January
    case 2://March
    case 4://May
    case 6://July
    case 7://August
    case 9://October
    case 11://December
    return 31;
    break;
 
    case 3://April
    case 5://June
    case 8://September
    case 10://November 
    return 30;
    break;
 
    case 1://February
    return getNumberOfDaysInFebruary(year);//
    break;
 
    default:
    return 0;//should never reach this - if it does then 0 is an error
  }
}
 
private function getNumberOfDaysInFebruary(year  : Number ) : Number {
 
  var isValid : DateValidator = new DateValidator();
  isValid.inputFormat = "DD/MM/YYYY";
  isValid.allowedFormatChars = "/";
  var result : ValidationResultEvent = isValid.validate("29/02/"+ year);
  if(result.results == null ){//29th is a valid date
    return 29;
  } else {//29th is NOT a valid date
    return 28;
  }
}

[ad name=”ad-1″]

Flex & Version control

Ever had a project where your client has some kind of odd/unusual caching issue with their servers that you have absoulutly zero control over?

Well if you have (which I have had) then the following swc file may help you to diagnose the problem. Its a very simple swc file that you can place inside your code and pass it a version number. Next time you build your app and deploy it to your clients servers you can type ‘version’ then whatever number you gave inside your code will appear inside an Alert box.

This has helped me sooooo many times, as after deploying some code, if they (client) appear to be seeing something different to what I’m seeing then I can get them to type ‘version’ and if it’s the old version number I have to tell them to clear their cache & wait for their internal servers to refresh (again I/they have no control over this), then a few hours later they will have the correct version.

So it just helps when you roll out a minor update and you say its fixed, then they come back and say that they can’t see the changes, you can then show that its the internal hardware and that they just have to wait to get the new swf.

As a little extra feature on the version SWC I’ve given it the ability to listen to your own functions should you wish. It works by listening to the keypress event on the stage (so their is nothing visual to worry about). By default the version number is shown by typing ‘version’ when the app has focus. If you wished it to do something else on a certain word or set of key presses (a-z, 0-9) then you would do the following:

 
//There is a addKeyListenerFunction and a removeKeyListenerFunction
addKeyListenerFunction('whateverSetOfKeyPressesYouWantToListenTo', someFunction);
//remove listener by passing in the word that you where listening for
removeKeyListenerFunction('whateverSetOfKeyPressesYouWantToListenTo');

Click here for runnable demo, right click for source code. (just make sure app has focus for it to work)

If you’re interested in file size, using the above example with and without the version SWC changed the file size by just under 3K (3057 bytes).

The version SWC is case insensitive, so if you ask it to listen to HELLOWORLD, this is the same as helloworld.

Get the SWC file here.

[ad name=”ad-1″]

Simple tip #1 – custom events

Today while coding I was creating some classes that required them to dispatch custom events. I know that this is a fairly common thing to do but sometimes it is these little things that can trip you up or take a while to find out how to do them.

So I thought that each time I come across something that is ‘simple’ (only simple after you know it!) that I’ll try to create a quick blog entry and take note of it.  Each time I create a new ‘tip’ post I’ll link it to the previous/next tip so that it will be quick and easy to browse through a load of tips.
 

Tip #1

So for my first tip, this is how to implement your own custom events.

First if you are firing the events from a custom MXML file then you need to create a metadata tag. I make this the first node inside the MXML file.  For example:

 

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
		width="500"
		height="300"
		>
 
<mx:Metadata>
<!-- 
First two event are plain string events, they do not pass any specific data with them -->
<!-- 
The last event is a custom class that extends Event and as such you need to give
it its package name + the class name as the type -->
	[Event('next')]
	[Event('previous')]
	[Event(name='jump', type='com.kennethsutherland.events.JumpEvent')]
</mx:Metadata>
...

If your custom class is an AS3 file then you would put something like the following are the imports

[Event(name="previous", type="flash.events.Event")]
[Event(name='jump', type='com.kennethsutherland.events.JumpEvent')]

Then inside the MXML file (script block) or anywhere in the AS3 file to fire the event I’d do the following:
 

//custom event, the extra value is handled by the JumpEvent class
dispatchEvent(new JumpEvent("jump", specificValueForTheJumpEventClass));
//standard event
dispatchEvent(new Event("next"));

If you do the above and lets just say your MXML/AS file is called ‘GreatComponent’ then in order to use the new custom event, its as simple as the below bit of code. 

<local:GreatComponent
    next="doSomething()"
    jump="doSomethingElse(event)"
/>

That’s it, now you can fire of any custom event that you wish and make sure that it gets listened to.

Next Tip

 

[ad name=”ad-1″]

Custom Class & Custom Itemrenderer

Today (not for the first time – but it’s been a while) I needed to create a custom class that took a custom itemRenderer.

Having used itemRenderers for ages I thought it was going to be straight forward, but I’d forgotten a few little bits of info needed to implement them from scratch (i.e. not using say a menu or datagrids itemRenderers). It’s all very well to just give a flex component a class name in the MXML but how does the class that contains the itemrenderer implement it?

Test app

So I created a very small test app to make sure that I could create a custom itemRenderer for my custom class.

  • Step 1, create the custom itemRenderer.  For the test I just made this a Canvas and made it 100% * 100% and the background colour was red.
  • step 2, display the class that you are going use as an itemRenderer as a normal display object (place custom class inside a Canvas)
  • step 3, create a custom class that will take and display an itemRenderer. Once created assign your new custom itemRenderer to the new custom class.
  • View the test app, all going well you should now see two instances of your itemRenderer. One is the actual class as a displayObject and the other as an itemRenderer inside your custom class.

I’ve placed my small test app here purely so that you can look at the source code (right click app).  The app does NOTHING and is not interactive, it’s just to show the source code and how to make sure you set things up correctly.

 

Once you’ve looked at the code this bit will make sense.

  • step 1 & 2, display a canvas in the top left. This canvas contains only the custom class that is to be used as an itemRenderer.  This just proves that the itemRender will display what you think it should.
  • step 3,  create a custom class that will contain your itemRenderer. Then place custom class into app and set the itemRenderer to your custom itemRenderer class.  

All you need to do now is create a itemRenderer slighty more complex than a red box, but as long as it’s a DisplayObject then its going to be the same.

That’s it, as ever feel free to comment (especially if you’ve found this helpful).

[ad name=”ad-1″]

Silverlight / AIR / NYT

Well this is slightly old news, and a lot of you may well know that the New York Times has released a very good AIR application for reading the news.  You may even recognize it from the demo that was given at Max 2008 (for the International Herald Tribune).

http://www.insideria.com/2009/05/new-york-times-air-reader-rele.html

Well what I didn’t know until today was at the same time the NYT have released a Silverlight kit so that developers can build an app using Silverlight and pull in various articles from the NYT.

http://www.infoq.com/news/2009/05/Times-Silverlight

This just seems like very bad timing and another kick in the teeth for Silverlight (don’t get me wrong I’d like to have as many RIA languages out there to give me a choice depending on the project requirements). So around the same week they release a kit for Silverlight they drop their Silverlight reader in favour of a AIR reader due to issues with Silverlight.

http://firstlook.blogs.nytimes.com/category/times-reader/

I think we still need to wait a while for Silverlight to mature a bit (which I’m sure it will) before using it fully.  

It would be interesting to find out how many of the major early adaptors of Silverlight are still using it. Every now and then you hear of a major Silverlight project being dropped in favour of flash/AIR.  Am I just not reading the MS blogs which have the opposite (i.e. flash/AIR projects being dropped for Silverlight)?

 

 [ad name=”ad-1″]

Tiles and the packing problem

On more than one occasion in the past I’ve been wishing to create a custom component that is totally dynamic so that I don’t have to worry about hardcoding any sizes.
So lets just say I have a list/tilelist and it contains pictures. Normally what I’d do is make sure that the pictures are a set size and I’d just make the list dynamic in one direction so it may end up showing 4.5 tiles which is normally fine as it’s a scrollable list.

But what if you have a list that will only ever contain say 10 items and you wish to use as much of the users screen as possible then each time the user changes the screen size you need to work out the optimal size of a tile/item.

Check out the demo here. This actually took me quiet a while to figure out how to do, I think the function to work out the size has gone through several iterations. (the example is based on the Tile class as that handles the layout and lets me do the nice animation moves when one tile moves around the screen on resize)

Here is the actionscript code that will work out the optimal size. I know that this function can be optimised further, but this will do to show you how its done. (possible optimisations: SQRT is not a nice function to call for the processor, use it sparingly, reducing number by just -1 each time isn’t great either, could reduce it by larger amounts then swing back a forth until I get the best fit).

//total number of tiles
var tile_count : Number = numberOfSlides;
//height of rectangle
var b : Number = unscaledHeight;
//width of rectanlge
var a : Number = unscaledWidth;
 
//divide the area but the number of tiles to get the max area a tile could cover
//this optimal size for a tile will more often than not make the tiles overlap, but
//a tile can never be bigger than this size
var maxSize : Number = Math.sqrt((b * a) / tile_count);
//find the number of whole tiles that can fit into the height
var numberOfPossibleWholeTilesH : Number = Math.floor(b / maxSize);
//find the number of whole tiles that can fit into the width
var numberOfPossibleWholeTilesW : Number = Math.floor(a / maxSize);
//works out how many whole tiles this configuration can hold
var total : Number = numberOfPossibleWholeTilesH * numberOfPossibleWholeTilesW;
 
//if the number of number of whole tiles that the max size tile ends up with is less than the require number of
//tiles, make the maxSize smaller and recaluate
while(total &lt; tile_count){
	maxSize--;
	numberOfPossibleWholeTilesH = Math.floor(b / maxSize);
	numberOfPossibleWholeTilesW = Math.floor(a / maxSize);
	total = numberOfPossibleWholeTilesH * numberOfPossibleWholeTilesW;
}
 
return maxSize;

If anyone else has a solution or knows of a better solution using actionscript (or anything else for that matter) I’d love to see it as although this works I’m thinking there must be a faster solution.

Looking at links like the following http://www.combinatorics.org/Surveys/ds7.html these problems can be pretty complicated!

[ad name=”ad-1″]

A – Z, custom search to firefox plugin

So you may have read my previous posts on the custom search that I created, well as suggested in a previous comment the information to create one then turn it into a open search search plugin and then into a firefox plugin is out there.  It’s just not all in the same place.

So I’m going to go through the process and try to make clear each step of the way. Here is what I’m going to cover.

  1. Create the custom search (hosted by Google)
  2. Take new custom search and insert into wordpress
  3. Create a OpenSearch plugin from code that’s compatible with the majority of browsers
  4. Turn OpenSearch plugin into a firefox plugin so that you can list it under firefoxes search plugins
  5. Make the browser automatically pick up the openSearch plugin to show user you have plugin available

So first you need to create the search.

1, Create Google custom search.

For this (AFAIK) you need a Google account and you then need to get a adSense account set up.  This is how I found the custom search as it is part of the options on the general screen.  I kind of expect that this option to create a custom search will be available elsewhere on the Google site but this is where I found it.

Once you go through the wizard that Google gives you, you get a choice.  I’ve gone with opening the result inside Google.  If you choose the last option then the end result will mean that you will get two bits of code to insert into your wordpress site. If this is the case then I’d have a look at a wordpress plugin to deal with the code. There are a few out there, but they may or may not work depending on your theme that you have.

 

I choose the hosted on Google option because – 1, should it (the search) be popular then it will not increase my bandwidth usage and 2, it makes it more offical if its hosted on a  google URL (just my opinion).

You should now have some code from Google, something along the following lines

<form action="http://www.google.com/cse" id="cse-search-box">
  <div>
    <input type="hidden" name="cx" value="partner-pub-7396620608505330:xjbbr6-w0cu" />
    <input type="hidden" name="ie" value="ISO-8859-1" />
    <input type="text" name="q" size="23" />
    <input type="submit" name="sa" value="Search" />
 
  </div>
</form>
 
<script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;lang=en"></script>

 

2, Insert code into wordpress

Now that you have your code you will need to find the searchform.php file from your theme. Should be inside wp-content->themes->{your theme} -> searchform.php

Open up that file and insert the new code.

I didn’t do anything to the Google code, just pasted it above the standard wordpress code so I now have 2 searchs on my site, one for the ‘Flex collection’ and one for my site.

Thats it, part 2 done.

3, Create OpenSearch plugin

First you need to get a URL that you can use for your search. So either do a search after installing your search in your wordpress blog or look at the code and put it all together to create one.

For example if you do a search on my site for ‘pie charts’, this is the URL that you end up with http://www.google.com/cse?cx=partner-pub-7396620608505330%3Axjbbr6-w0cu&ie=ISO-8859-1&q=pie+charts&sa=Search+-+Flex+Collection  

If you look at the above code from point 2 you’ll be able to see how its made up.

Now that you have a URL go to http://mycroft.mozdev.org/ and select to create a plugin.

Fill in all the boxes (they’re all pretty much self explanatory), but as an example the two main inputs that have to be correct are the ‘Search URL’ and the ‘Search Form URL’

Using the above URL, my ‘Search URL’ would be http://www.google.com/cse?cx=partner-pub-7396620608505330%3Axjbbr6-w0cu&ie=ISO-8859-1&q={searchTerms}&sa=Search+-+Flex+Collection 

and the ‘Search Form URL’ would be http://www.google.com/cse?cx=partner-pub-7396620608505330%3Axjbbr6-w0cu&ie=ISO-8859-1

Click ‘Generate Code’ then ‘Install Plugin’. Test the plugin and if all is good (copy the generated code), then submit plugin.

Take note of the URL that you can use to get at the plugin from mycroft.mozdev.org, you will need this for part 5.

4, Create firefox plugin

Take your code that you just copied from part 3 and save it to a XML file.

Open https://addons.mozilla.org/en-US/firefox

Login/register -> developers tools -> submit add-on.

Pick a licence, then it will ask you to upload a file. Upload the XML file that you just saved. Then its just a case of editing the appropriate sections and you are now done.

Do a quick search for your plugin and you can now get a URL such as https://addons.mozilla.org/en-US/firefox/addon/11823 and send this round friends etc to get some reviews. Once you have a few reviews you can submit your plugin to be made public.

Feel free to review my plugin, I need some reviews so that I can submit it.

Finally.

5, Make the browser pick up the openSearch plugin when your site is viewed


The above image shows what happens if a browser picks up that the site it is displaying has a custom search tool that can be installed. It highlights a small button beside the search box.
To do this I’ve placed the following code into the header file

<link rel="search" type="application/opensearchdescription+xml" title="Flex Collection" href="http://mycroft.mozdev.org/installos.php/30790/fx.xml"/>

Use the above but replace the href with whatever URL you saved from part 3 (the mycroft.mozdev link) and obviously replace the title with something relevant to your search.
Then place that line of code into the header.php for your theme (or somewhere that will always get served up on your site, I just choose the header as that seemed appropriate). Put it beside the other links if your header file has them otherwise just make sure it’s in the head tag.

That’s it.
Hope this is helpful.

[ad name=”ad-1″]

Flex and Google Maps

I started to try out some flex with Google maps and it’s refreshingly straight forward.

Virtually all of the information to do the below can be found here http://code.google.com/apis/maps/documentation/flash/reference.html

 

So I’m just going to highlight a couple of things I did that were not in the docs.

Panning

  • Panning, well there is an example on how to do panning in ‘tour de flex’ but it uses a very basic method to work out difference between 2 points, divide by 100 and just add difference to starting point using the timer function.

A much better way would be to use a Tween so that you can implement an easing function, but a tween will only do one value at a time and a point has two values.

So I used the Move class. It moves an object from point A to point B which is exactly what I was after, but I just wanted the values as I’m not moving an object.

 Here is the actionscript code to implement it

//The move effect needs a target  otherwise it will NOT tween
//so just create a temporary target
var uiTemp : UIComponent = new UIComponent();
moveEffect = new Move();
//set up the move effect
moveEffect.xFrom = currentLatLng.x;
moveEffect.yFrom = currentLatLng.y;
moveEffect.duration = 1500;
moveEffect.easingFunction = moveMap;
moveEffect.xTo = Number(mapDetails.lat);
moveEffect.yTo = Number(mapDetails.long);
 
//on each update move the map
//calls the map.setCenter method
moveEffect.addEventListener(TweenEvent.TWEEN_UPDATE, updateMapPosition, false, 0, true);
//at the end I open up the marker window
moveEffect.addEventListener(TweenEvent.TWEEN_END, showMarker, false, 0, true);
//Play effect, give it the target so that it actually plays
moveEffect.play([uiTemp]);

Marker Windows

  • The information window that pops up beside the marker on the map needed to be an image with some text.  I never noticed any examples in the docs for this but I did see an example online so I thought I’d stick into this post as well to increase its coverage.

    Again very straight forward (Google really makes it easy for developers) check out the code below.

 

//In order to open a window beside a marker you need a InfoWindowOptions
var options:InfoWindowOptions = new InfoWindowOptions({
    //This is the key line for making it into a custom window
    //uiHolder is a Canvas (but it can be any UIComponent) and I'm sure you know what you can put into
    //a UIComponent, anything you like :)
    customContent: uiHolder,
 
    padding : 7,
    width: 262,
    height: 262,
    drawDefaultFrame: true
});
//Take the marker that you wish the window to appear above and
//call openInfoWindow and pass in the InfoWindowOptions you just created
currentOpenMarker.openInfoWindow(options);

Click to open app in new window

Click to open app2 in new window

[ad name=”ad-1″]