Archive for November, 2009
“Silverlight on the iPhone”: poetic license, or just plain dishonest?
A few days back, the web was a awash with headlines that Silverlight was coming to the iPhone. Behind those headlines was the story that Silverlight video was the only part of Silverlight that was coming to the iPhone. The details of the story appearing to be that IIS was going to support converting Silverlight video into a form that could be displayed on the iPhone.
Yesterday I got into a discussion with Aral Balkan on Twitter over whether or not it was appropriate to call it Silverlight video as the video is displayed using the <video/> HTML 5 tag. In order to better defend my stance that it was, I decided to investigate the matter further to gain a proper understanding of what was going on. In the process, I had to do an about-turn on my position, and conclude Aral was right. Read more
1 commentThe Muppets: Bohemian Rhapsody
Maybe there is hope for Ubuntu after all
In a clear bid to turn Ubuntu into a serious contender for the mainstream market, Gimp is to be removed from future releases. Gimp epitomises everything that is wrong about Linux, with its “feature rich” functionality taking precedence over usability (or “UX” as it’s fashionably called these days). I can honestly say Gimp is the single most difficult-to-use piece of software I’ve used and it was instrumental in driving me toward using Windows many years ago.
For Linux to become mainstream, it needs to ditch the quest for ever more complex features and instead become simple to use. This seems an alien concept to most Linux folk, but it is good to see that Canonical seem to have got it. Now if only they could ditch that shit-brown default theme and get a contemporary look and feel to compete with Windows 7 and OS X, then they just might break into the OS mass-market.
For more details on the reasoning behind ditching Gimp, see this excellent article on Ars Technica.
2 commentsAutoSortDataGrid: A simple extension to the DataGrid Flex component
In response to that, I have created a simple extension to the DataGrid component. It is called AutoSortDataGrid and it adds two properties to DataGrid: sortColumn and sortDirection. These simple additions enable one to specify the initial sort state of a datagrid, and no additional code is required on the user’s part. Read more
1 commentMake your WordPress blog smartphone-compatible with WPTouch
Whilst smartphones are great for accessing the web when out and about, their small screen size can be a problem at times. Having recently tried to look something up on my own blog with an iPhone, I realised it was a nightmare to navigate. So I figured it was time for a new theme that could support the iPhone. It turns out that the great people at Brave New Code have created a truly marvellous plugin that makes life even easier. Read more
No comments
I hate arrogant software!
There is a class of dialogue though that really riles me: the sort that says “You cannot do that”. Read more
No commentsFlex developer tip: initialising a datagrid with a sorted column
If you use Flex, then you are likely – sooner rather than later – to find yourself using the datagrid component. On the whole, it’s a really powerful and fairly easy to use component. There is one caveat to this though and that is the way column sorting occurs. Consider the following code:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" backgroundGradientColors="[#efefef, #E8e8e8]" width="450" height="350" horizontalAlign="left" borderColor="0" borderStyle="solid"> <mx:Script> <![CDATA[ import mx.collections.SortField; import mx.collections.Sort; private function start():void { var data:Array = [{name:"Red", red:255, green:0, blue:0}, {name:"Green", red:0, green:255, blue:0}, {name:"Blue", red:0, green:0, blue:255}, {name:"Yellow", red:255, green:255, blue:0}, {name:"Magenta", red:255, green:0, blue:255}, {name:"Cyan", red:0, green:255, blue:255}, {name:"White", red:255, green:255, blue:255}, {name:"Black", red:0, green:0, blue:0}]; dataGrid.dataProvider = data; } ]]> </mx:Script> <mx:Button label="Start" click="start()"/> <mx:DataGrid id="dataGrid" width="100%" height="100%"> <mx:columns> <mx:DataGridColumn headerText="Colour" dataField="name"/> <mx:DataGridColumn headerText="Red" dataField="red"/> <mx:DataGridColumn headerText="Green" dataField="green"/> <mx:DataGridColumn headerText="Blue" dataField="blue"/> </mx:columns> </mx:DataGrid> </mx:Application>
This results in the following SWF:
As you can see, the data is presented in the datagrid in the same order as the code defines it. Click on one of the column headers and it sorts that column. Click again and it reverse sorts the column. This is great, unless you want the datagrid to start up with on of the columns sorted. That’s when the fun starts.
An Automatically Sorted Datagrid
If you read through the API documentation for the datagrid, it is really vague on how sorting occurs and there is no obvious way of initialising a datagrid in a sorted state. In the past, I have tried all sorts of ways of ways, including simulating a click event on the column header to force a sort and even creating a datagrid subclass that overrides a lot of the sort arrow placement code to force a sort arrow to appear at start up. Such techniques though are messy, unreliable and there was always this nagging feeling that I’d missed something obvious.
Recently I applied a bit of lateral thinking – and a lot of googling – to the problem and I discovered the proper way to solve this problem. It wasn’t obvious, but it was far simpler than anything else I’d tried and it works properly. The key to it is realising that when one clicks on a column header, a sort is applied to the data source and – this is the non obvious bit – that sort is used to determine where the sort arrow appears and whether its an up-pointing or down-pointing arrow. So the solution to having a datagrid start up in a sorted state is to apply a sort to the datagrid’s data source at start up. Told you it wasn’t obvious!
Consider therefore the new version of the code. The key part is the contents of start(), which is responsible for initialising the datagrid with a sort.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" backgroundGradientColors="[#efefef, #E8e8e8]" width="450" height="350" horizontalAlign="left" borderColor="0" borderStyle="solid"> <mx:Script> <![CDATA[ import mx.collections.SortField; import mx.collections.Sort; private function start(column:String, descending:Boolean):void { var sort:Sort = new Sort(); var sortField:SortField = new SortField(column, true, descending); var data:Array = [{name:"Red", red:255, green:0, blue:0}, {name:"Green", red:0, green:255, blue:0}, {name:"Blue", red:0, green:0, blue:255}, {name:"Yellow", red:255, green:255, blue:0}, {name:"Magenta", red:255, green:0, blue:255}, {name:"Cyan", red:0, green:255, blue:255}, {name:"White", red:255, green:255, blue:255}, {name:"Black", red:0, green:0, blue:0}]; sort.fields = [sortField]; dataGrid.dataProvider = data; dataGrid.dataProvider.sort = sort; dataGrid.dataProvider.refresh(); } ]]> </mx:Script> <mx:HBox width="100%" horizontalAlign="center"> <mx:Button label="Start Colour Desc" click="start('name', true)"/> <mx:Button label="Start Red Asc" click="start('red', false)"/> <mx:Button label="Start Red Desc" click="start('red', true)"/> </mx:HBox> <mx:DataGrid id="dataGrid" width="100%" height="100%"> <mx:columns> <mx:DataGridColumn headerText="Colour" dataField="name"/> <mx:DataGridColumn headerText="Red" dataField="red"/> <mx:DataGridColumn headerText="Green" dataField="green"/> <mx:DataGridColumn headerText="Blue" dataField="blue"/> </mx:columns> </mx:DataGrid> </mx:Application> |
This results in the following SWF:
Applying a Compare Function to an Auto-Sort Datagrid
There is one final problem with initialising a datagrid in a sorted state and that is when columns have their own custom compare functions. When the titlebar is clicked, the custom function is applied to the sort. When we initialise the datagrid in a sorted state, we are supplying it with a presorted data source with a Sort object attached. Therefore the custom function is not applied. All is not lost though, as the function cane be manually attached to the Sort object. The following code demonstrates this with a function that sorts first the colour number, then the name for the red green and blue fields.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" backgroundGradientColors="[#efefef, #E8e8e8]" width="450" height="350" horizontalAlign="left" borderColor="0" borderStyle="solid"> <mx:Script> <![CDATA[ import mx.collections.SortField; import mx.collections.Sort; private function start(column:String, descending:Boolean, compareFunction:Function):void { var sort:Sort = new Sort(); var sortField:SortField = new SortField(column, true, descending); var data:Array = [{name:"Red", red:255, green:0, blue:0}, {name:"Green", red:0, green:255, blue:0}, {name:"Blue", red:0, green:0, blue:255}, {name:"Yellow", red:255, green:255, blue:0}, {name:"Magenta", red:255, green:0, blue:255}, {name:"Cyan", red:0, green:255, blue:255}, {name:"White", red:255, green:255, blue:255}, {name:"Black", red:0, green:0, blue:0}]; sortField.compareFunction = compareFunction; sort.fields = [sortField]; dataGrid.dataProvider = data; dataGrid.dataProvider.sort = sort; dataGrid.dataProvider.refresh(); } private function sortColour(field:String, obj1:Object, obj2:Object):int { var i1:int = obj1[field] as int; var i2:int = obj2[field] as int; var n1:String = obj1.name; var n2:String = obj2.name; return i1 > i2 ? 1 : i2 > i1 ? -1 : n1 > n2 ? 1 : n2 > n1 ? -1 : 0; } private function sortRed(obj1:Object, obj2:Object):int { return sortColour("red", obj1, obj2); } private function sortGreen(obj1:Object, obj2:Object):int { return sortColour("green", obj1, obj2); } private function sortBlue(obj1:Object, obj2:Object):int { return sortColour("blue", obj1, obj2); } ]]> </mx:Script> <mx:HBox width="100%" horizontalAlign="center"> <mx:Button label="Start Colour Desc" click="start('name', true, null)"/> <mx:Button label="Start Green Asc" click="start('green', false, sortGreen)"/> <mx:Button label="Start Green Desc" click="start('green', true, sortGreen)"/> </mx:HBox> <mx:DataGrid id="dataGrid" width="100%" height="100%"> <mx:columns> <mx:DataGridColumn headerText="Colour" dataField="name"/> <mx:DataGridColumn headerText="Red" dataField="red" sortCompareFunction="sortRed"/> <mx:DataGridColumn headerText="Green" dataField="green" sortCompareFunction="sortGreen"/> <mx:DataGridColumn headerText="Blue" dataField="blue" sortCompareFunction="sortBlue"/> </mx:columns> </mx:DataGrid> </mx:Application> |
And the two-column sorting behaviour can be observed in the resultant SWF below:
And there you have it. Sorting a datagrid at start up may not be intuitive, but it’s fairly straighforward once you know how.
1 comment
