LemurProto - ListBox and GridPanel

I finally got around to extracting some of the semi-experimental UI components out into their own project: LemurProto.

The point of the LemurProto project is to incubate things that will eventually make it into Lemur core once they are hardened. I try very hard not to check in half-baked things into core… well, I try. :slight_smile: LemurProto gives me (and others) a place to put things that may need a little work before being finalized.

Consequently, the GUI elements in LemurProto may change and break from one version to the next… part of the growing pains.

The project source can be found here:
https://code.google.com/p/jmonkeyplatform-contributions/source/browse/#svn%2Ftrunk%2FLemur%2Fextensions%2FLemurProto

And the current release is here:
https://jmonkeyplatform-contributions.googlecode.com/svn/trunk/Lemur/extensions/LemurProto/release/LemurProto.jar

Right now the main GUI element folks would be interested in is the ListBox and I’ve prioritized this motivated by @nehon so you can thank him. :slight_smile:

By default, the list will render its elements as text labels and use a standard String.valueOf() for list model values. This behavior can be changed with cell renderers.

Basic usage is as follows:
[java]
VersionedList myList = new VersionedList(myListOfStrings);
ListBox listBox = new ListBox(myList);
[/java]

If items are added or removed from myList then the list box is automatically updated (thus the VersionedList).

Selection can be watched by grabbing a versioned reference to the selection model.

Custom renderers can be specified be setting the CellRenderer. A cell renderer can either create new cells every time it is accessed or it can reuse existing cells. One cell is created for every visible item in the list and as it is scrolled the renderer is asked for new cells (and can simply just reset the value of the existing one if it likes). This is slightly different than Swing’s model which tends to reuse on JLabel and uses it to paint every item (and then has tons of infrastructure built just to support using a Swing component to paint). Lemur opts to prefer a static set of components based on the visible size of the list. Anyway, you don’t have to worry about that unless you want a custom renderer… and then you can just look at DefaultCellRenderer’s source.

I think it’s pretty straight-forward:
https://code.google.com/p/jmonkeyplatform-contributions/source/browse/trunk/Lemur/extensions/LemurProto/src/main/java/com/simsilica/lemur/list/DefaultCellRenderer.java

There are probably some things yet missing from this implementation of ListBox (and its underlying GridPanel) because I haven’t used it “in anger” yet… but it’s functional and has all of the obvious parts. Please feel free to report issues or missing pieces you might find.

2 Likes

\o/ yay, thanks you Paul!!!

I will have to check this out when I get home tonight.

Note: I just pushed another release that includes ListBox.getSlider() and ListBox.getGridPanel().

The former is necessary if you want access to the model to manually scroll the list. And either are necessary if you want to manually set styling on them.

@pspeed said: Note: I just pushed another release that includes ListBox.getSlider() and ListBox.getGridPanel().

The former is necessary if you want access to the model to manually scroll the list. And either are necessary if you want to manually set styling on them.


Thanks Paul :wink:

I managed to change the slider style throught the style scheme though. But this is gonna make thing easier.

@nehon said: Thanks Paul ;)

I managed to change the slider style throught the style scheme though. But this is gonna make thing easier.

Overall, styles are the better way but for one-off things it’s sometimes easier just to set backgrounds/colors/etc. directly.

…but at least now you can get the slider model to set it as you drag. :slight_smile:

Hi again

Thank you for yet another awesome contribution.

While the ListBox is obviously useful for me I was most interested in the GridPanel and just how many ways that could be used.

I did however find one issue which I believe originates in ArrayGridModel. If you have an array that is not the same width and height you can get “index out of bounds” error.

[java]
public ArrayGridModel( T[][] array ) {
this.array = array;
this.cols = array.length;
if( cols > 0 )
this.rows = array[0].length;
}
[/java]

[java]
@Override
public T getCell( int row, int col, T existing ) {
return array[row][col];
}
[/java]

In the constructor and in rest of the code it is array[column][row] but in “getCell” it is backwards array[row][column]

Ah, good catch. I’ll take a look at it.

What do you think you will use GridPanel for? I abstracted it out because it always felt to me that list boxes and tables are very similar.

Uses for GridPanel.

1.) Action bar. Action sets (rows) which could be rapidly switched in and out by changing the visible row(s) on the grid. Eg. Player on land has standard action set but when entering water the action bar switches to underwater skills. Or pickup item get an action set that allows player to throw, drop or place item that replaces standard set.

2.) Grid based mini games. Eg. Memory games or combination locks.

3.) The obvious table as you already mentioned. Table based on an entity set specifically will be on my list of things to figure out.

4.) Tabed or multi screen elements. Switch visible grid cells on tab switch to swap out containers.

Sounds cool. Some of those technically could have been done with the SpringGridLayout and a regular container but you are right that it might be easier if you have easy access to the grid model’s row/column nature.

A new release is up. Links are still the same.

Release notes (small):
-Fixed a cols/rows swap in ArrayGridModel.
-Removed some stdout debug output from ListBox.
-ListBox now cleans up internal grid item listeners when the
list model is swapped out.

Thanks @kylar for the bug report. I’ve made ArrayGridModel consistently row, column now.

@nehon, regarding your questions about dragging… you were right that the selection listener is foiling your attempts to do it at the list level because it is internally adding a listener to every item. I looked at making this configurable but I think I will wait. I’d almost like to include ‘drag to scroll’ internally but I will wait to see your code. I’d let the developer specify their own item listener but the state transfer is complicated if they swap it out after the list has been around (a case I’d have to cover even if it doesn’t affect you) and externally it’s not trivial to find out which grid index was clicked… though I suppose that could be added to the grid panel class.

For now I add a custom DragHandler to each cell.
I override startDrag to save the Slider value on start, then I override mouseMove (I don’t remember the exact name of the method) where I compute the new Slider value. I use the startDrag position (already accessible in the DragHandler) and the Y value given in the method.
The cell needs to have a background (even transparent)

I still didn’t test how it plays with cell selection though, hopefully there won’t be any conflict.

The ListBox is nice, the scroll scheme is pretty smooth in the end, and it works nicely on a mobile device.

Thanks for the follow-up. Glad it’s working for you.

I ended up working on creating a grid/table using an EntitySet as a data source.

What works so far:

  • Ordering rows by a column’s value as data changes (Screenshot is sorted by 3rd column)
  • Updating rows when entities are added and removed from the EntitySet.
  • Cell contents can be updated by calling update(). (Applies changes to EntitySet before resorting rows and updating visible cells)
  • Columns can be added and removed.

What still needs to be done

  • Column headings and indicating which column the data is sorted by.
  • Scrolling or paging. Currently only show the top X.
  • Column reordering and perhaps the ability to do this with drag and drop.
  • Reversing the sort order.

@pspeed you were right though in that the SpringGrid layout turned out to be exactly what I needed and I was underestimating the power of the humble panel and layout.

If anyone is interested I can clean up the classes and post them.

1 Like

Looks pretty neat.