Software Woes

Rants, tips and tricks



Tuesday, September 16, 2008



wxGrid with virtual storage and multirow or multicolumn cells

I'm working on a project that uses wxWidgets as a GUI library. In it, I have a grid (wxGrid class) that has some of the cells that span multiple columns. Now, it's very simple to make it work when you have a regular wxGrid. But, when you use virtual storage, you need to go through some steps to make sure multi-column span is done right.

There is no documentation on how to do this, so I first googled, and failing to find the explanation like the one I'm about to write now, I experimented. Finally, when some things just didn't work right, I had to dig into the wxGrid code to find out what is the correct way to do it.

If you ever used virtual grid, you know that you need to have a class that derives from wxGridTableBase. I have it, and in my class I override the function GetAttr to get various effects at runtime (saving both on memory and speed). In this function you can set the cell attributes (color, font style, etc.) by reading the info from your own virtual storage (this can be very useful if you want, say, negative numbers to be red). Anyway, in this class you use an object of class wxGridCellAttr, set its attributes and return pointer to it. Make sure you use cellAttriM->IncRef(); before exiting, since the caller will call DecRef() after using the info to render the cell on screen.

Now, on to the cells that span multiple columns or rows. To create a cell like that, you need to set the attribute for that cell, but also for all cells it 'covers'. All this is done via SetSize() function on wxGridCellAttr object.

Let's take for example a cell that spans one column and two rows: a cell at coordinates (3,5). This means that cell at coordinate (3,6) would be covered by this. So, for the cell at (3,5) you need to use:

cellAttr->SetSize(2, 1);

and for the cell at (3,6), you need to use:

cellAttr->SetSize(-1, 0);

This -1 and 0 is crucial for selection and cursor movement to work correctly. If your cell spans even more cells, you need to SetSize for all of them. For example, if the cell in above example would span 3 rows, the row at (3,7) would need to use:

cellAttr->SetSize(-2, 0);

etc.

Hopefully, something like this will be added to wx manual one day. Until that happens, read my blog ;)

2 Comments:

At 6:12 PM, Blogger Simon said...

Randy, can u post your code? And how to use it with database

 
At 7:51 PM, Blogger Randy White said...

For a complete working example with a database, see the FlameRobin source code:

http://sourceforge.net/p/flamerobin/flamerobin-git/ci/118620002b20d46b1e852cf690468f4bd59b6d4e/tree/src/gui/controls/

DataGrid* classes contain it all.

To extend this to multicell logic, see to code I wrote in the blog post.

 

Post a Comment

<< Home