Proposed Multi Column List Box API

BlitzMax Forums/MaxGUI Module/Proposed Multi Column List Box API

SebHoll(Posted 2009) [#1]
Alright, I've had a play around with this over the last few days and have been experimenting with various different API systems that could be employed. For me to implement this, I would want to make the API as simple and uncluttered as possible, and so propose having the following function set:

SetGadgetColumns( gadget:TGadget, strColumns$[], intWidths:Int[] = Null, intFlags:Int = Null )

SetGadgetColumn( gadget:TGadget, index, text$, width, flags )
GadgetColumnText$( gadget:TGadget, index )
GadgetColumnWidth( gadget:TGadget, index )
GadgetColumnFlags( gadget:TGadget, flags )

A character, say "~0" or "~t", is defined as being column separator for the text in the rows, and helper functions such as...

SetGadgetItemText( gadget:TGadget, rowIndex, text$, colIndex = -1 )

...will allow you to alter the text on a column by column basis if preferable.

Making a listbox multicolumn would be as simple as:
Global listbox:TGadget = CreateListBox( 0, 0, ClientWidth(window), ClientHeight(window), window )
SetGadgetColumns( listbox, ["First Column", "Second Column", "Third Column"] )
...or if you want to specify the column sizes at the same time...
Global listbox:TGadget = CreateListBox( 0, 0, ClientWidth(window), ClientHeight(window), window )
SetGadgetColumns( listbox, ["Column 1", "Column 2", "Column 3"], [100, 200, 100] )
Then items can be added like so:
AddGadgetItem listbox, "Yay!~tMulticolumn Support~tIs Cool!"
...and if I wanted to change just one of the cells, I could just do...
SetGadgetItemText listbox, 0, "Is Awesome!", 2   'set the third column in the first row.

How does this sound? For multi-column list boxes, this seems perfect - obviously any future table/property-grid gadget would have a more complex API.


Ked(Posted 2009) [#2]
Yes! This would be awesome for multi-column list boxes! I may have obscured my intention with bringing up the table gadget, so just forget that. :) I think it would be a great addition to MaxGUI to have a listbox with columns, no tables.

Also, maybe some of these?:

SetGadgetColumnText(gadget:TGadget, index:Int, newtext:String)
RemoveGadgetColumn(gadget:TGadget, index:Int) (this would also remove all cells associated with this column)


degac(Posted 2009) [#3]
Oh!! Great!


xlsior(Posted 2009) [#4]
Would you envision to be able to sort by column with such an implementation as well, or would you consider that a feature of the table/property-grid?

Also, text-only and no images, I presume?


SebHoll(Posted 2009) [#5]
Sorting - not sure yet. If I can think of a simple way to achieve this, possibly. Probably not though...

And yep, only supports one one icon per row (on the left hand side like a std. list box).


Mark Tiffany(Posted 2009) [#6]
Ideally, sorting should work by some kind of over-ridable call-back so that we can replace it. Sometimes you have data you want to sort that doesn't necessarily "naturally" sort by built in code using simple less than / greater than logic, dates being an obvious one.

I was thinking the API might be more along the lines of getting a GadgetItem back for each row (with heading row being e.g. row=0), and have each cell as a GadgetItem within the parent GadgetItem. Then you can use normal SetGadgetText, etc on these directly. But maybe I'm future-proofing for a more advances cell based one. Is it worth having a similar API for both and trying to futureproof?


SebHoll(Posted 2009) [#7]
SetGadgetColumnText(gadget:TGadget, index:Int, newtext:String)
RemoveGadgetColumn(gadget:TGadget, index:Int) (this would also remove all cells associated with this column)

My original API idea was flexible like this in that columns were effectively added/removed/modified much like items are. This, I assume, is the type of future-proofing advanced behaviour Mark T is referring to. The problem lies with the fact that this naturally implies that columns and data are intrinsically connected, and each 'cell' in the table must have its own specific data associated with it. This would provide the necessary support to implement an effecient column moving/deleteing/reordering commandset.

Despite this being really quite neat for table gadgets, for multi-column listboxes, it would require quite a big overhead of code on each platform to implement this behaviour, and not to mention, it would effectively mean having two APIs for handling items in a listbox: one that is column aware and based on the cell paradigm; and the current implementation based on a linear list of items.

Besides all this, the listbox control doesn't see the data as cells - it sees it as rows (which may or may not have columns in them). Columns are an attribute of the listbox, not the data - they are in effect, mutually exclusive. Deleting a column from a listbox, should only affect the display of the data in the listbox - not the data themselves. Put another way, the listbox columns aren't intrinsically linked in any way to the pseudo columns in the row text.

So in essence, if we were to implement it using the more flexible API, it would no longer be a multi-column list box we were implementing - it would be a table gadget.

However for your run of the mill, OS standard, multi-column text listboxes I feel the API I have proposed above is exactly the tack we should take. Nothing more than we need (to avoid complication), and nothing less (to make it practical to implement).


Ked(Posted 2009) [#8]
You're right. I remember reading a while back on multi-column listboxes and how items where added and removed. I had forgotten that they were added as full rows and not "put this item under this column, etc".

So scratch those two functions. I suspect it would just be easier to call SetGadgetColumns again to remove/add/change title/change width of columns?

:) Everything I mention always seems to be pointing to a table gadget, which is really not what I mean... or is it? :P (Joking)


SebHoll(Posted 2009) [#9]
I suspect it would just be easier to call SetGadgetColumns again to remove/add/change title/change width of columns?

Precisely, or use the SetGadgetColumn( gadget:TGadget, text$, width, flags ) function to set it on a column by column bases without having to redefine the others.


Ked(Posted 2009) [#10]
Precisely, or use the SetGadgetColumn( gadget:TGadget, text$, width, flags ) function to set it on a column by column bases without having to redefine the others.

Nice. That makes it a lot easier. :)

But, with that function wouldn't it be just like SetGadgetColumnText()? How will you know what column is being changed?


SebHoll(Posted 2009) [#11]
How will you know what column is being changed?

I'm not sure that I fully understand your question. The 'column by column' indexing is on a gadget basis, instead of being related to the data. The gadget is aware of how many columns have been set simply from the length of the string array passed to SetGadgetColumns(). The columns will then be labelled with indices, (with column 0 being the column with the name set to the zeroth element in the string list etc.) and so can be accessed using the indices after an initial SetGadgetColumns() call.


Ked(Posted 2009) [#12]
No, I mean: What's the purpose of SetGadgetColumn()? I understand what SetGadgetColumns() does. :) Sorry, I really didn't make that clear.

It seems like SetGadgetColumn() is a combination of SetGadgetColumnText() and SetGadgetColumnWidth() but it doesn't have an index parameter. So how will you know which column is being updated?


Mark Tiffany(Posted 2009) [#13]
Sensible argument there. Presumably each row will be a gadget item. So you use AddGadgetItem and get the row's gadgetitem back, then can use ModifyGadgetItem to set everything for the row including icon, text, etc, and RemoveGadgetItem to remove.

If the above is true, maybe you could still use the 0 (or -1?) index as the column headers, and hence to set the column headers up, using e.g. ModifyGadgetItem "1|2|3". I don't think it quite works, as I can't see how you set widths / flags, etc on each column.

Also, I'd suggest considering use of | as the separator as (from memory) that's used elsewhere in maxgui...tooltips for toolbars I think?


SebHoll(Posted 2009) [#14]
@ Ked:

Ah... I see - SetGadgetColumn() is indeed missing an index parameter. My mistake, when typing out the post.

Hope that clears things up. :-)


Ked(Posted 2009) [#15]
Yeah, much better! :) Thanks.


Space_guy(Posted 2009) [#16]
So any news on this? I would love to use this as I switched to develop more on mac and so far I used the win32 hacks to make it work.


Difference(Posted 2009) [#17]
Me too


SebHoll(Posted 2009) [#18]
Alas, the API has been locked down for the time-being until we decide what we're going to do, going forward (see MaxGUI Roadmap thread).


Ked(Posted 2009) [#19]
I know you guys are busy but that thread hasn't been updated either in three weeks. :)