Everything started when I should make a property editor using the Firemonkey TGrid. After my searches on the net, I have seen that no working code for this is provided but only some code which shows how to make your own column which is for a different cell type. But in this case, I needed a grid which I can host different types of cells in one column. I have seen that it’s not that easy so I designed a new column class TVariantColumn which can host different cell types in a performant way. Here is the story and the code.
Firemonkey grid is a powerful one which has some major differences as it was in VCL. The grid doesn’t have got its own render engine for cells, instead it hosts other controls in the cells and these controls all make the drawing themselves. These controls show their data not from the grid but from our own data objects using the OnGetData event. To be able to make all these in a performant way only the controls for the visible cells are created. The responsible code for this is in TColum class which is the proxy for cells, it creates the cell control (say TEdit) when it is needed and locates it on the grid. Each column can create cells of its type. The cell controls are reserved in an array, so when the amount of the visible rows exceed, more controls are created. So any control in the array doesn’t belong to a specific row, it can be showed in any row when it is visible.
Now let us think, what we should do if we want to show a different cell type in each row of a column. According to the current TColumn design, this is not possible. Because the controls in the array aren’t for specific rows, but any visible row in the column. So we should change the cell update logic of the TColumn, which will not directly create the control but make some other class create the control which is responsible for that kind of cell. The new logic will be handled in our new column class TVariantColumn and the TCellProxy class with its descendants will be inter proxies that will be responsible for the cells of one kind.
This class is inherited from TColumn class, and what is mostly changed is the logic in UpdateCells. This function calls the CreateCellControl for each row in the visible area. The CreateCellControl doesn’t create the cells itself but first finds out which proxy should be responsible for the cell (through event) and then asks the proxy to create the cell. The proxy checks its que when asked, if there is any non-reserved cell it gives it directly otherwise create a new one. So the possible amount of cells in one proxy is the possible number of that type of cells visible together in the grid. All these makes the control creation and usage performant.
To use this class, just create it and add it to your grid in runtime when you need it. Before adding to the grid be sure that you set the OnGetCellProxyIndex event property.
vColumn := TVariantColumn.Create(Self); vColumn.Header := 'Variant Column'; vColumn.OnGetCellProxyIndex := GetCellProxyIndex; Grid1.AddObject(vColumn);
After this, you will need to create the proxies for each type you will use in this column. We have got 13 type of proxies that are all inherited from TCellProxy.
When you create a cell proxy like
the proxy will be created by the vColumn using the class type passed and will be added to its list. The first proxy created will have an index 0 and the second will have 1 and goes on. So you should give this index for a specific row when asked by OnGetCellProxyIndex event.
The list includes almost all types of editors that is available as standalone in Firemonkey. I will code a few more proxies in near future like for example TComboTrackbar control, but the good news is that you can use any other control using the TCustomProxy. With this class, the controls are created and handled in your own code through the events. All of the cell proxies use a cell type class inherited from the native control class like TEdit, TCombobox. The same strategy is used in TColumn and cell relation. These cell type classes use standard styling so when your stylebook uses a different style every cell in VariantColumn will obey the change.
If you want to have your own proxy, just inherit one from TCellProxy. You can see how it’s done from my code. To get the source code of the FMX.VariantColumn.pas with the project source of demo application use this SVN link. The class code is in the Utils folder. For non-programmers the compiled Win32, Win64, MacOSX (Thanks to Firemonkey) demo applications are also available to download.