Monday, July 19, 2010

DataGrid Filter example

One of the powerful additions to Revolution 3.5 is the DataGrid - a custom control group that allows you to display any type of data with astonishing flexibility. Recently, I had to add filtering capabilities to a data grid for one of my projects. In this post, I will explain how I accomplished it, thanks to the DataGrid lessons available on the website.

Here's a screenshot of the example stack:

Execute the following steps, if you want to follow along:
- Create a new stack
- Drag a button to the topleft of the card and set its name to "Fill"
- Drag a text field to the topright of the card
- Drag a label field next to the text field and set its content to "Filter:"
- Drag a data grid onto the card and configure it using the Object Inspector
-> In the 'Basic Properties' panel, turn off the checkbox "Allow Text Editing"
-> Switch to the 'Columns' panel, and add 2 columns "index" and "name"
-> Edit the script of the DataGrid, and set it to the following:

local sOriginalData
local sIndexMap
local sFilter

setProp dgData pData
put pData into sOriginalData
end dgData

setProp dgFilter pFilter
put pFilter into sFilter
end dgFilter

private command RebuildMap
local tKeys, tKey, tIndex
put 0 into tIndex
put the keys of sOriginalData into tKeys
sort tKeys numeric
repeat for each line tKey in tKeys
if sFilter is empty \
or sFilter is in sOriginalData[tKey]["name"] \
add 1 to tIndex
put tKey into sIndexMap[tIndex]
end if
end repeat
set the dgNumberOfRecords of me to tIndex
dispatch "ResetList" to me
end RebuildMap

on GetDataForLine pLine, @pData
local tKey
put sIndexMap[pLine] into tKey
put sOriginalData[tKey] into pData
end GetDataForLine

on SortDataGridColumn pColumn
-- prevent column sorting
end SortDataGridColumn

The above data grid script will take care of filtering the data. Now it's just a matter of wiring up the text field.
-> Edit the script of the text field and set it to the following:

local sUpdateMsg

on keyUp pKey
pass keyUp
end keyUp

on deleteKey
pass deleteKey
end deleteKey

on backspaceKey
pass backspaceKey
end backspaceKey

on pasteKey
pass pasteKey
end pasteKey

on cutKey
pass cutKey
end cutKey

command ScheduleUpdate
if sUpdateMsg is empty then
send "UpdateFilter" to me in 100 milliseconds
put the result into sUpdateMsg
end if
end ScheduleUpdate

on UpdateFilter
set the dgFilter of group "DataGrid 1" \
to the text of me
put empty into sUpdateMsg
end UpdateFilter

By trapping the different key events, we can update the data grid filter as we go along. Note that I used the ScheduleUpdate helper command to try and minimize the number of refreshes for quick typers. Play around with the interval until you find the sweet spot of responsive user interface.

Finally, it is time to fill the data gird with some data for testing, so edit the script of the button and set it to the following:

on mouseUp
local tData, tIndex, tName
put 0 into tIndex
repeat for each line tName in the functionNames
add 1 to tIndex
put tIndex into tData[tIndex]["index"]
put tName into tData[tIndex]["name"]
end repeat
set the dgData of group "DataGrid 1" to tData
end mouseUp

This simple script will fill our data grid with a list of the built-in functions that revTalk has to offer. Click the button, and type away in the filter text field to see the effect. Here's what happens when I type "cos":

Looks pretty good, doesn't it? It certainly was good enough for my use, but there are a few things to bear in mind about this implementation:
- I didn't have to edit the data in the grid.
- I didn't have to support sorting for my particular project.
Both of these limitations can be overcome, but I'll leave that for another time...

No comments: