Posts in Category "General"

Faster DataGrid Horizontal Scrolling

Lately, I’ve heard many complaints about horizontal scrolling performance in DataGrid. Vertical scrolling has been optimized, but horizontal has not. I found a bit of time to put together how to subclass DataGrid and try to optimize horizontal scrolling. I’m sure there’s bugs and I don’t know if I’ll have time to fix them and the usual caveats apply.
Hope it helps. It should work with any Flex 3 SDK version.
Download Source
In the example, the top DataGrid is not optimized, the bottom one is. Make the screen bigger and you’ll start to see and feel the difference.
Run Example

Flex Authority Magazine

I think I can finally say I got something published! Gordon Smith and I contributed to the first issue of Flex Authority, a new magazine (made of actual paper!) that focuses on Flex and AIR. We hope to be regular contributors. The link to find out more is: http://www.flex-authority.com/. Buy your subscription today. We won’t make any money from it, but this post is to thank them for working with us and to help them get the word out so they can make some money.

Custom ArrayCollections, Adding New Items to DataGrid

The previous posts used custom ILists to merge or concatenate other ILists. This example uses a custom subclass of ArrayCollection to fake an empty object at the end of the actual ArrayCollection which can be used to add new entries to the DataGrid.
If the user fills out the new entry, it is added to the actual collection and another new entry is faked. Additional logic dictates that if the user strips all information out of an entry, that entry is removed from the actual collection.
Usual caveats apply
Download Source
Run Demo

Custom ILists, ComboBox Prompts

Following up on the last post which showed how to use custom ILists to merge two collections, this post shows how to use a custom IList to concatenate or append two collections.
Such a thing might be useful in a situation where you want to add more than one prompt to a ComboBox. In the example, I have the days of the week to choose from, but also want to add “Every Day”, “Weekdays” and “Weekends” without modifying the original days of the week collection. Of course, if you concatenate the two collections, it offsets your selectedIndex.
Download Source
Run Demo

Custom ILists, CheckBoxDataGrid, Merged Arrays

Earlier I published how to do a CheckBoxDataGrid where the selection model uses CheckBoxes instead of mouse clicks. I should have mentioned that the example used the DataGrid’s selection logic which meant that the dataprovider item’s selected state was not stored in the dataProvider and thus you couldn’t sort by whether an item was selected or not.
If you have a selected field in your data, then the code to handle checkbox selection is quite different. You basically shut down the DataGrid’s selection code and update the collection instead. You can see that in the source code for this example.
This example goes one step further, however. It assumes that you want to store selection in the dataProvider, but the dataProvider items don’t have a selected field and are “immutable”. The example code shows how to use a custom IList to merge two arrays or ArrayCollections into one merged collection where the data objects contain fields from both arrays. By doing that you can “add” a selected field to each item.
Custom ILists are a powerful way to change data without having to process each data item. The example code merges the items on-demand instead of up-front thus saving startup time. It would be wasteful to process 1000 items if you only show 7 and the user doesn’t scroll past 20.
Anyway, here’s the code. Usual caveats apply.
Download Source
Run Demo

DataGrid Double-Click To Edit

Several people have asked about changing the default editing behavior of a DataGrid so that starting an edit session requires a double-click instead of the default single-click.
Here’s my approach:
Download Source
Run Demo

Smooth Scrolling List

One of the features that got cut from 3.0 was “smooth scrolling”. List and other list-related classes scroll by row/column which can be a bit choppy at times. We tried to leave the hooks in to allow someone to do it, but we ran out of time to finish the job.
It’s too bad we didn’t finish the job as there are some difficult things to workaround in trying to get smooth scrolling to work, but I cooked this prototype up to give you a sense for how you might be able to get it working in your apps. Note that the prototype assumes that all rows are the same height. If you have variableRowHeight, that’s a whole different problem.
Usual caveats apply, and no, I don’t currently have time to make examples for TileList and DataGrid. Maybe some one else will have the time.
Download Source
Run Demo

SelectedItem and ComboBox

Seems like it is once a month where someone is having trouble setting the selectedItem of a ComboBox. The key is that the ComboBox does an exact reference match on the items in the dataProvider. It doesnt take the time to compare values within the dataProvider items with the values in the item you are setting as the selectedItem.
In other words, if you have an array of objects:

[{ firstName: “Alex”, lastName: “Harris” }, { firstname: “Alex”, lastName: “Harui”}, {firstName: “Alex”, lastName: “Trebek”}]

you can’t just set:

selectedItem = { firstName: “Alex”, lastName: “Harui }

as that assigns the selectedItem to a different Object instance with the same values. The ComboBox class will simply look to see if there is a reference to that instance in its dataProvider, which there is not. Instead, you have to scan the dataprovider and match up values.
So many folks are doing this, that I decided to post an example so we don’t have to keep writing that scan-the-dataprovider loop. This example tries for an exact match first, so if you know you’ll never have an exact match you can save more time by cutting out that first call to super.selectedItem = value;
Source for ComboBox subclass
Test file source
Helper class source for Test file
Test file
Usual caveats apply.

Threads in Actionscript 3

Every once in a while, someone decides they would like to see threading or background processing in Actionscript. While the underlying Flash Player and Operating System use threads, the execution model for Actionscript does not.
For those who don’t know, ‘threading’ is essentially the ability to have the code do something in the background while the UI is doing something else. Because Actionscript is single-threaded, if you spend lots of time doing heavy computation, the UI cannot be updated while you’re doing that computation so your application appears stuck or effects don’t run smoothly.
Similarly, there is no yielding or blocking in Actionscript either. If the next line of code is supposed to run, you cannot prevent the next line of code from running. That means that when you call Alert.show(), the next line of code following that runs right away. In many other runtimes, the Alert window has to be closed before the next line of code continues.
Threading may be a feature of Actionscript some day, but until then, you have to live with the fact that there is no such thing right now.
In other single-threaded environments, you can get something like threads via ‘pseudo-threading’, which involves dividing up the heavy computation into small chunks on your own. (There is no solution to allow for blocking or yielding other than refactoring the application to be even-driven). Pseudo-threading is painful, but doable in most situations. Iterative tasks are easier than recursive ones, the chunk size has to be small enough to not degrade the UI response time and restoration of the execution context must be efficient otherwise you’ll spend too much time saving and restoring your state and not get anything done.
Someone asked me how I would generalize such a thing. I put this together in a couple of hours. It represents my first thoughts, not some deep thinking on the subject. A PseudoThread instance takes a callback function and a context object and calls the callback function with the context object as mahy times as it thinks it can get away with it within the frame interval. The callback function should update the context object before returning and return false when done and the PseudoThread instance dispatches an event and destroys itself.
PseudoThread.as
The following is the a test that loads an image, and adds a red tint to a copy of the image one row at a time. I purposefully slowed it down with trace statements so you can see that it doesn’t do it all at once and doesn’t seem to affect the rotating button.
PseudoThreadTest.swf
These two links are the source file and the test image.
PseudoThreadTest.mxml
the test image
The usual caveats apply (there are probably bugs, limitations, etc). Hope it helps.

HTML and Flex

In case you didn’t know, the Flash Player is not very good at displaying HTML content. Since the Flash Player is the foundation for Flex, Flex apps deployed on the Web aren’t very good at displaying HTML either. In the Adobe AIR Player, essentially a full browser is built in and HTML content is rendered faithfully. However, the amount of code required to display HTML in AIR is measured in megabytes and is too large to be included in the Flash Player download at this time.
Various folks have made reasonable attempts to get something to work in Flash. There is the DENG project . And popular among many Flex developers is the third-party HTMLComponent which uses the IFrame trick to display HTML “over” chosen areas in your Flex application. FABridge lets you integrate your Ajax application with Flex widgets.
None of these solutions are fully-integrated with Flex in the sense that the HTML is part of the Flex DOM. Right after 2.0 shipped, I was doing some testing on how fast Flash Player 9 and ActionScript 3 was and hacked together a little test which grabs an XHTML file, parses it using E4X, and creates a UIComponent for every HTML tag and one or more TextFields for every run of text. It ran suprisingly fast. I put it down to get on to Flex 3 work and poked at it a bit since then. I finally found time to fix post this code. You’ll see that there are many bugs and missing features.
To fully finish off HTML rendering and CSS, fix bugs, etc in this code is outside of the scope of Adobe’s focus at this time. It might make a great community project if some of you want to take on the effort. I’m no expert in HTML so you may or may not want to start with the code attached here. This test just proves the feasiblity of mapping HTML tags to UIComponents so there is better integration with Flex and better HTML rendering than you can currently get in the Flash Player.
Source Code for flex.html.*
Source Code for test files for flex.html.*
SWFs, HTML, etc for test files for flex.html.*
The zips can be imported into FlexBuilder 3. I didn’t post the SWFs because you need to run out of your local sandbox to get around security restrictions, so it is best to download the files, import the projects, build them and run them.
Personally, I don’t believe most of you need a full browser. You probably just have ‘plain’ HTML documents that don’t run scripts, don’t do fancy DIV stuff like wrapping text around images, etc. So you might be able to fix a few bugs and get what you want to work in relatively short order. You probably also don’t need to wade through hand-authored HTML and ‘bad’ HTML. All of that sutff adds weight to the code.
For example, htmltest3 in the test zip is test for the superscript/subscript tags. Maybe all you need is a few tags like those plus bold and italic.
The hmltest2 test also shows the principle of dynamic UI. You can send your UI over as XHTML and by wrapping your Flex component appropriately, you can generate the UI from the XHTML description. Notice the DataGrid in the document.
The code has an IHTMLElement interface so you can talk to it in DHTML/AJAX-like ways. There’s even the beginnings of an XMLHTTPRequest class. There is also a class that tries to clean up bad HTML.
Have fun, hope it helps, and DO NOT REPORT BUGS. I will probably delete all comments reporting bugs as this is totally unsupported by me.