Lemur Listbox, area of clickbehaviour and layout question

I have a question about the behaviour of clicks in listboxes.

The clickcommand that is later activating the selector color in a listbox comes from

In the end it is a Button with the value as string. Unfortunately this leads to areas in a list box, that have no click effect. If the size of a listbox is “bigger” then the actual text of that line. I show you a picture of the filebrowser that I did a few weeks ago. If you have only a short/small text (like the 3 dots there) it could be problematic to hit them.

I tried to use this behaviour to “make” the Button the right size.

If I run this code I actual see the right size of the grid cell (e.g. 78, grid with 3 columns = 235). I even see that “cell” is identical with “locatedcell” means the cell that is (containing) the button has the right size before registering the click behaviour and the additional code is not needed at all.


 Panel cell = cellRenderer.getView(value, false, existing);

Panel locatedcell = grid.getCell(row-grid.getRow(), col-grid.getColumn());
 if (locatedcell !=null) {
      Vector3f size = locatedcell.getSize().clone();
      cell.setPreferredSize(locatedcell.getSize().clone());
       //     cell.setPreferredSize(size);
       //     cell.setSize(size);
       //   Vector3f  size2 = grid.getSize();          
        }

If I change the size manually the listbox gains “space” but the click behaviour is only triggered if you click the text.

What can I do, so that the

            CursorEventControl.addListenersToSpatial(cell, clickListener);

is registering to all the cell and not only to the text of that cell?

And a second question (but it might be a new topic):

How can I change the layout of the grid of a listbox?
I am about to change the listbox class so it can contain more then 1 column but the gridpanel has a protected layout, that is forced.even. I would like to change that to none but could not find a way to do this.

As usual if you try to find a solution for a while… or as my teacher just said once. If the question is longer then the answer dont ask it.

I added an invisible background to that cell

 Panel cell = cellRenderer.getView(value, false, existing);
// added this
     cell.setBackground(new QuadBackgroundComponent(new ColorRGBA(ColorRGBA.BlackNoAlpha)));

and now the click behaviour is working correct.

is there a better solution for that?

Use a CellRenderer. For example:

public class LocalPlayerCellRenderer<T> implements CellRenderer<T>, Cloneable {

    @Override
    public Panel getView(T value, boolean selected, Panel existing) {
        return createLocalPlayerContainer((LocalPlayer)value);
    }

    private Container createLocalPlayerContainer(LocalPlayer localPlayer) {

        Container container = new Container("null");

        QuadBackgroundComponent quadBackgroundComponent = new QuadBackgroundComponent(ColorRGBA.BlackNoAlpha);
        container.setBackground(quadBackgroundComponent);

        Label playerNameLabel = container.addChild(new Label(localPlayer.getPlayerName()));
        playerNameLabel.setFontSize(22);

        //Label idLabel = container.addChild(new Label("Id: " + localPlayer.getId()));
        //idLabel.setFontSize(15);

        return container;
    }

}

...
myListBox.setCellRenderer(new MyCellRenderer());

The background component means the whole cell will be clickable.

This should be the behavior by default (ie: there should be an invisible background that is full size). Did you override the cell renderer for the list box?

Edit: I thought the default behavior was to create borderless buttons but I don’t have time to check the code. Either way, I’m 99% sure that the Lemur demos have a listbox with short items and they are clickable anywhere.

I think a CellRenderer is used.

The background component means the whole cell will be clickable.

This is what it should be.

Did you override the cell renderer for the list box?

No, I did not touch it.
Lemur\extensions\LemurProto\src\main\java\com\simsilica\lemur\list\DefaultCellRenderer.java
is used.

I thought the default behavior was to create borderless buttons but I don’t have time to check the code.

I have done a small check:
A button with ElementId = list.item and style = null is created

“background” and “setborder” are called with a value of null. (line 458) I have only seen color with a value.

I have opened the lemur demos listbox (in untouched, original code). The behaviour there is the same. If you click the visible text the selector is set/appears. If you click in the empty area next to the text nothing is happening.

This is at least my finding. But I think by adding the line mentioned above, I found a workaround for me. Maybe it would be even possible to set the border in style.

Edit:
Earlier I had my code changed to

 if (cell.getBackground() == null) {
        cell.setBackground(new QuadBackgroundComponent(new ColorRGBA(ColorRGBA.BlackNoAlpha)))
      }

cause I had realized, that the initial cell/button on the listbox has no background. Once created it has, but not initialy.

If I run the demos in Lemur/examples/demos then I do not get this issue. The list elements are clickable no matter where I click them.

If the issue only happens when overriding the styling to no longer have any backgrounds well then that’s an issue with the styling. It’s important to remember that some users might want that behavior on purpose since leaving out all background quads typically means you want the clicks to fall through the background to something else.

I’ve commented on the pull request and closed it. There may be an underlying issue but I don’t think forcing cells to have backgrounds is the right answer when there is already a listener added to the whole ListBox… and it appears at quick glance that the click listener is setup to work if added to the ListBox, too… it just isn’t. (That would still require the list itself to have a background.)

I get the same issue: running DemoLauncher and then enabling the List Box checkbox shows a panel with a listbox. Wherever I click except for the text of the items, there’s no effect. When my mouse ray hits one of the polygons of the BitmapText, only then does the related list item gets selected.

I did not modify anything except for commenting the BaseStyles.loadGlassStyle(); line because I have not linked Groovy to the project. So Lemur UIs come unstyled. And yes, I think that’s what causes that issue: there’s no background now. I think it’s the same situation that @Aufricer got into.

So, the fix is for the application to add a background… either through styling (super easy, doesn’t need groovy even) or by registering a custom cell renderer.

By forcing all cell renderers to have a background it prevents the use case where this is desirable behavior. ListBox can be used to contain lots of different things. If the user creates one without any backgrounds at all then I need to respect that choice.

You mean you unlinked groovy from the project. The demos already link groovy.

Or have you simply imported the code into your own project?

Either way, your test was diagnostically relevant… so thanks for that.

I simply copied the source folder into my project :} so no dependencies come. Using this setup until the new version is released, then switching back to normal dependency.

And when adding Lemur as a dependency, I have to exclude Groovy since otherwise it leads to problems for Android build. I have been researching this problem and unfortunately there is no guaranteed and well-working way to have Groovy on Android. There is a hack with some cut-down version of Groovy but it brings another set of problems and there was something I don’t quite recall now that made me to turn it down. That’s sad, because Groovy is quite a nice language.

The problem is that Groovy does runtime bytecode generation for scripts. Android relies on all Java bytecode being transpiled to Dalvik bytecode ahead of time. This works fine if you pre-compile Groovy and run it through the standard Dalvik conversion process, but it knocks out loading Groovy scripts on Android at runtime. The stripped down versions of Groovy for Android are probably missing the script engine at the very least. (There is a way to load JVM bytecodes on Android at runtime, but it’s inefficient and probably fairly error-prone.)

This isn’t a Groovy-specific issue, either. Any JVM language will need to ultimately be turned into Dalvik code to run on Android, and this presents a lot of trouble for scripting languages that load code at runtime.

I had the same issue myself, and just wrote the style out in code instead. I suspect it’s probably not a good contribution to the Lemur project because it requires maintenance of duplication.

https://gist.github.com/jayfella/5b40333c545b341a242df0d9e4f4d206

1 Like

Yeah, that’s why I haven’t done it. I have imagined writing a code generator, though… to take any style definition and output the Java code that would have created it.

Theoretically possible but slightly trickier than one might initially think.

Well, JSON or XML are always options, though cumbersone ones to a known extent, and with their own deps and quirks when on Android… Currently for my project I have already done the same thing as @jayfella but in Kotlin (since the project is in Kotlin), but ultimately, when I get to prettifying the GUI, I’ll just use Lua for making the styles since it is already in for all the scripting.

As an alternative, maybe before investing into a code generator, you could consider an option of moving to Lua instead of Groovy since LuaJ has full interop with Java and is 100% compatible with Android and has no bytecode generation, and the dependency is a single jar of 345KB available from Maven.

Yeah, I remember all those issues from using Clojure-Android. It was relying on some special Java compiler, I don’t recall its name now, but I made it to work in an Android Java app runtime on my devices. Too bad the stuff was unofficial and the maintainers abandoned it some time ago. If Clojure would make it to Android, I’d be very happy. However promising were its beginnings, so as dismaying is the course that the company behind it is taking, effectively burying it with its attitude. But I digress…

Someone else can write and maintain that, I guess. I have no interesting in Lua here. I got Groovy almost for free with almost no effort. (Edit: moreover, the DSL is super clean and already very CSS-like.)

For android, a better option is probably just to provide support for precompiling the styles groovy. I could probably even do it as part of the regular build, I guess.

Yeah, Groovy rocks actually. I would be using it if I could, too.

Yes thats right. I never thought about setting the background in styling - will try that once im back to my project.
I had changed listbox directly, not cell renderer.