Many Little Lemur Questions

Ok, let’s roll up our sleeves and get to this! :slight_smile:

It’s often rare to want to do this as the layouts take care of a lot of the stuff. For root level windows it’s quite common, though. Best approach, ask the window what it’s preferred size is, Math.min() whatever values you want against your minimum preferred size, then set it back.

Either in styling (the easy way) or directly with code by setting your own cell renderer.

You can see how the ListBox is setup in the glass style. You’d set a fontSize in the list.item styling:

In it’s current configuration, it inherits the default from the root glass style.

It is on my to-do list. I think a few others have cobbled some things together.

Only recently has this become particularly easy since there is now a built in way to handle popups. So now it’s just a matter of combining a Label or TextField with a button and a pop-up list box.

GuiGlobals.getInstance().requestFocus(null); …if you have no better place to go.

http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/GuiGlobals.html#requestFocus(com.jme3.scene.Spatial)

Either set them directly:
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/Panel.html#setBackground(com.simsilica.lemur.core.GuiComponent)
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/Panel.html#setBorder(com.simsilica.lemur.core.GuiComponent)

Or in styling:

addClickCommands() is a convenience function that essentially calls:
addCommands(ButtonAction.Click…)
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/Button.html#addCommands(com.simsilica.lemur.Button.ButtonAction,%20com.simsilica.lemur.Command...)

The available hooks are here:
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/Button.ButtonAction.html

Hide but still participate in layout… JME’s regular cull hint.

Hide from even the layout… I think only removing the child.

But if you just mean like to show/hide a root window, then that’s regular JME stuff. Just remember that all Lemur GUI elements are just spatials.

Or did you mean something else?

You can set the margin on the background component and it will achieve the same effect… assuming the background component supports a margin (in this case it does).

But either way, you can add whatever you want to the component stack for a GUI element. Insets are applied before background only because that’s the order they are in the stack.

Still, 99% of the time (like in the glass style) you will have a QuadBackgroundComponent or a TbtBackgroundComponent… and both of those support setting a margin (they pretty much have to).

Hope that helped a little.

Edit: P.S.: I wish that discourse would show better links for the wiki links above… that last link jumps right into the component stack documentation but you’d never know it from that view.

3 Likes

What are those spatial hooks I’m talking abiut, @pspeed - the ones that provide collision results. It’s bugging me. They are useful.

1 Like

CursorEvents… they work even on regular JME Spatials.

http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/event/CursorEventControl.html

Works just like MouseEventControl except the events contain the collision information, too. Example of MouseEventControl:

3 Likes

I use these in my new advanced crafting system! They are very useful.

2 Likes

Yeah, totally.

I use CursorEvents almost exclusively now because even when I don’t need the information for normal processing, it can be nice to have for debugging.

1 Like

Have a look at this:

Actually, more a “dropdown menu” than a real “combobox”.

I’m not currently updating it, but PR are welcome. :wink:

1 Like
  1. Paul mentioned using layouts to achieve this. I’d be happy to do that but haven’t found great documentation on using the layouts frankly. I got a SpringGridLayout to actually create a grid which required a few forums posts to figure out but that’s about it so far.

As per other people’s suggestions I tried the using setPreferredSize() /getPreferredSize() for setting width of the buttons and it seems to work.

2,5,8) I tried to add a custom .groovy file as described in the recent work in progress thread:

Eek… the easiest and best long-term way is to cut-paste the style files into your own style and just change the textures, fonts, whatever, there. Most of them inherit the background image from the same one or two definitions.

Then just load that style and set it as the default instead of the build in glass style.

GuiGlobals.initialize(this);
BaseStyles.loadStyleResources("custom-styles.groovy");
GuiGlobals.getInstance().getStyles().setDefaultStyle("glass");

But not seeing style changes appear when run so don’t know what to make of that. Either it’s not reading the file properly cause I have the wrong path or I can’t use glass name or something.

  1. The suggestions for this worked perfectly.

Also Paul I would like to achieve this effect that you did in your math game with the panel title bar. How was this achieved?

1 Like

Yes, groovy is just a convenience wrapper over the Java support. There is nothing it’s doing that isn’t ultimately calling Java. So you can at least be confident in that.

The above code is setting things in the “root” style the is inherited by all other styles… but if that style (such as “glass”) overrides that then you won’t see it.

Probably you want to modify the glass style itself.
Attributes attrs = styles.getSelector(“container”, “glass”);

setDefaultStyle(“glass”) does not affect the selectors only the actual retrieval of values. A null style passed to the selectors means you are editing the root style… which is bit different than the “default” style.

I edited my post heavily due to the whinging nature of it and further discoveries. Can you take another look over?

Did you cut-paste the whole glass style? By naming yours something different, you will not be loading the normal glass style… just your custom one.

Lemur is setup to load every one of the loadStyleResources(“foo”) it finds on the classpath. Which is why I get away with having a glass style defined in Lemur core and another add-on one defined in lemur-proto.

I did it in other things, too… I’m surprised it isn’t part of the default styling.

…let me check…

Ah, I believe it is part of the regular style:

…just need to use “title” in your element ID.

You can see it also used in the IsoSurfaceDemo:

Below is a near copy of the glass style written programatically. I do intend to contribute it to lemur at some point. It saves a lot of pain when you can’t use groovy or don’t want to.


package com.jayfella.motorunner.lemur;

import com.jme3.asset.AssetManager;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.Insets3f;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.TbtQuadBackgroundComponent;
import com.simsilica.lemur.geom.TbtQuad;
import com.simsilica.lemur.style.Attributes;
import com.simsilica.lemur.style.Styles;

/**
 * Created by James on 16/01/2018.
 */

public class LemurGuiStyle {

    public LemurGuiStyle(AssetManager assetManager) {

        float guiScale = 10.0f;
        float guiScaleHalf = guiScale * .5f;

        Styles styles = GuiGlobals.getInstance().getStyles();

        Attributes attrs;

        /*
        QuadBackgroundComponent bg = new QuadBackgroundComponent(new ColorRGBA(0.207f, 0.518f, 0.89f, 0.85f));

        TbtQuadBackgroundComponent gradient = TbtQuadBackgroundComponent.create(
                "Textures/Gui/white-rounded.png",
                1, 1, 1, 126, 126,
                1f,false);
        */

        QuadBackgroundComponent bg = new QuadBackgroundComponent(new ColorRGBA(0.207f, 0.207f, 0.207f, 0.85f));

        TbtQuadBackgroundComponent gradient = TbtQuadBackgroundComponent.create(
                "/com/simsilica/lemur/icons/bordered-gradient.png",
                // "Textures/Gui/radial-gradient.png",
                1, 1, 1, 126, 126,
                1f,false);

        TbtQuadBackgroundComponent double_gradient = TbtQuadBackgroundComponent.create(
                "/com/simsilica/lemur/icons/double-gradient-128.png",
                // "Textures/Gui/radial-gradient.png",
                1, 1, 1, 126, 126,
                1f,false);
        double_gradient.setColor(new ColorRGBA(0.5f, 0.75f, 0.85f, 0.5f));

        attrs = styles.getSelector("glass");
        attrs.set("fontSize", 4 * guiScale);

        // label
        attrs = styles.getSelector("label", "glass");
        attrs.set("insets", new Insets3f(2 * guiScaleHalf, 2 * guiScaleHalf, 2 * guiScaleHalf, 2 * guiScaleHalf));
        attrs.set("color", new ColorRGBA(0.5f, 0.75f, 0.75f, 0.85f));

        // title
        attrs = styles.getSelector("title", "glass");
        attrs.set("color", new ColorRGBA(0.8f, 0.9f, 1.0f, 0.85f));
        attrs.set("highlightColor", new ColorRGBA(1.0f, 0.8f, 1.0f, 0.85f));
        attrs.set("shadowColor", new ColorRGBA(0.0f, 0.0f, 0.0f, 0.75f));
        attrs.set("shadowOffset", new Vector3f(2, -2, -1));
        attrs.set("background", double_gradient.clone());
        attrs.set("insets", new Insets3f(2 * guiScale,2 * guiScale,2 * guiScale,2 * guiScale));

        // button
        attrs = styles.getSelector("button", "glass");
        attrs.set("color", new ColorRGBA(0.8f, 0.9f, 1.0f, 0.85f));
        attrs.set("background", gradient.clone());
        ((TbtQuadBackgroundComponent)attrs.get("background")).setColor(new ColorRGBA(0.0f, 0.75f, 0.75f, 0.5f));
        attrs.set("insets", new Insets3f(2 * guiScale,2 * guiScale,2 * guiScale,2 * guiScale));

        // container
        attrs = styles.getSelector("container", "glass");
        attrs.set("background", gradient.clone());
        ((TbtQuadBackgroundComponent)attrs.get("background")).setColor(new ColorRGBA(0.25f, 0.5f, 0.5f, 0.5f));

        // slider
        attrs = styles.getSelector("slider", "glass");
        attrs.set("insets", new Insets3f(2,2,2,2));
        attrs.set("background", bg.clone());
        ((QuadBackgroundComponent)attrs.get("background")).setColor(new ColorRGBA(0.25f, 0.5f, 0.5f, 0.5f));

        attrs = styles.getSelector("slider", "button", "glass");
        attrs.set("background", bg.clone());
        ((QuadBackgroundComponent)attrs.get("background")).setColor(new ColorRGBA(0.5f, 0.75f, 0.75f, 0.5f));
        attrs.set("insets", new Insets3f(0,0,0,0));

        attrs = styles.getSelector("slider", "slider.thumb.button", "glass");
        attrs.set("text", "[]");
        attrs.set("color", new ColorRGBA(0.6f, 0.8f, 0.8f, 0.85f));

        attrs = styles.getSelector("slider", "slider.left.button", "glass");
        attrs.set("text", "-");
        attrs.set("background", bg.clone());
        ((QuadBackgroundComponent)attrs.get("background")).setColor(new ColorRGBA(0.5f, 0.75f, 0.75f, 0.5f));
        ((QuadBackgroundComponent)attrs.get("background")).setMargin(5, 0);
        attrs.set("color", new ColorRGBA(0.6f, 0.8f, 0.8f, 0.85f));

        attrs = styles.getSelector("slider", "slider.right.button", "glass");
        attrs.set("text", "+");
        attrs.set("background", bg.clone());
        ((QuadBackgroundComponent)attrs.get("background")).setColor(new ColorRGBA(0.5f, 0.75f, 0.75f, 0.5f));
        ((QuadBackgroundComponent)attrs.get("background")).setMargin(4, 0);
        attrs.set("color", new ColorRGBA(0.6f, 0.8f, 0.8f, 0.85f));

        // Tabbed Panel
        attrs = styles.getSelector("tabbedPanel", "glass");
        attrs.set("activationColor", new ColorRGBA(0.8f, 0.9f, 1.0f, 0.85f));

        attrs = styles.getSelector("tabbedPanel.container", "glass");
        attrs.set("background", null);

        attrs = styles.getSelector("tab.button", "glass");
        attrs.set("background", gradient.clone());
        ((TbtQuadBackgroundComponent)attrs.get("background")).setColor(new ColorRGBA(0.25f, 0.5f, 0.5f, 0.5f));
        ((TbtQuadBackgroundComponent)attrs.get("background")).setMargin(12, 6);
        attrs.set("color", new ColorRGBA(0.4f, 0.45f, 0.5f, 0.85f));
        attrs.set("insets", new Insets3f(12,6,0,6));

    }

}


2 Likes

Can I just say you guys are freaking amazing. I got it working. Yes i did cut and paste the whole glass style and proto glass style trying to combine them in the way you described in the other thread because I use some proto elements as well.

I put my custom .groovy file in the assets folder.

Here is my custom .groovy file:

Here is my custom loading code:

BaseStyles.loadStyleResources("custom-styles.groovy");
GuiGlobals.getInstance().getStyles().setDefaultStyle("custom");

Are there any resources to see all of the available settings you can set for a selector in the .groovy files?

1 Like

It’s up to the classes as they can define what the want. You can search for the StyleAttribute annotations, though.

For example:

Otherwise, it’s using reflection so any class can define whatever styleable attributes it likes.

Knowing about that StyleAttribute annotation helped a lot . So I’m having success changing existing stylings of components globally. I’m still struggling with changing certain styles on components at a non-global level.

You mentioned before:

You can set the margin on the background component and it will achieve the same effect… assuming the background component supports a margin (in this case it does).

I am just not seeing how…how would you set margins on an individual Container?

Container panel = new Container();

I mean, usually you’d make it part of the style you use for that container. But if you want to set it directly, you will either need to set the background component directly… or know/hope that it is one that supports a margin.

QuadBackgroundComponent qbc = new QuadBackgroundComponent(ColorRGBA.Red, 10, 10);
panel.setBackground(qbc);

Or if you already know/hope what kind of component it is:
((QuadBackgroundComponent)panel.getBackground()).setMargin(10, 10);

That worked like a charm but I don’t feel like I can apply that to other stylings for individual components going forward but at least it’s a pathway.

If you usually wouldn’t do that and would make it part of the style you use for that container can you give an example of that without changing the style for all Containers? I didn’t see anything like setStyle().

As a separate question if you wanted to have 2 global classes of stylings for Containers, lets call them A and B, so that you can apply A to some containers and B to others in your app how would you approach that?

selector(“mySpecial.container”) {
background = whatever you want
}

Container panel = new Container(new ElementId(“mySpecial.container”));

…should pick up your styling and any of container’s other styling that you haven’t specifically overridden.

See this part of the wiki for more details on how precedence is resolved:

That is the key I was missing thanks. Worked perfectly now I’m cookin with grease.

1 Like

This is probably more of a general JME question but with this menu how can I consume mouse clicks so that they don’t reach other click handlers? The buttons consume the event but other elements in the menu don’t. I tried to investigate how the Button/ColorChooser do it but couldn’t figure it out.

I think all handlers get the event, but the event also brings an isConsumed Boolean to check (or similar name).