Lemur resize border

I am trying to create resize borders to my dialogs (yes, rectangular boxes with text on it as usual :)).
I am using buttons for that, the center element in the border layout will go everything else.
The problem is north and south buttons that will not shrink to like 3 dots in height, east and west will be 1 dot width if I put no text on it.

So, before trying to set the preferred size, I get that value to use as minimum constraints (x,y,z).

Force scaling the button is not an option, I tested.

Is there some better way to do that also?

Try setting the font size really small. I guess since you are using buttons that the text has some height constraints when determining preferred size.

I think there probably are better ways to do this though your approach is pretty clever.

Another approach would be to build a ResizablePanel type class that forces a particular background component that is your resize borders. The GUI content could then be a child panel. You could then just add a mouse or cursor listener to yourself to detect when dragging on the borders is happening.

The RollupPanel might be a good example of a GUI element that manages a child.

I recommend using a CursorListener for mouse clicking because it will give you the actual collision information… which can be useful for verifying that your own background was what was clicked and where it was clicked.

Else your current approach is probably the easiest if you can get your sizing stuff worked out.

1 Like

cool, fontSize 0.1f worked thx! I wasnt able to visualize the ResizablePanel yet :slight_smile:

I was re-reading the way we set the background color for the style ex.:

attrs = styles.getSelector(Button.ELEMENT_ID, STYLE_CONSOLE);
clBg = new ColorRGBA(0,0.25f,0,0.75f);
attrs.set(Button.LAYER_BACKGROUND, new QuadBackgroundComponent(clBg));

but to reach specific buttons I ended using this:

GuiComponent gcBkg = pnl.getBackground();
QuadBackgroundComponent qbc = (QuadBackgroundComponent)
	gcBkg.getGuiControl().getComponent("background");
qbc.setColor(colorBkp);

Is it possible to configure the identification of specific elements so we could set that on the style? or the above direct color setup is the expected, being the style really the generic and not the specific?

PS.: before modifying the button bkg color I backup it with setUserData() on the very spatial (quite cool this thing btw), so I can restore it later (in case of mouse hovering bkg highlight).

If I understand the question correctly, this is what ElementId objects are for. They identify the “class” of object to the styling system. (For example, by default Button has an ElementId(“button”))

You can read more details about styling here:

By the way, I believe this code is being redundant:

You’ve asked for the background component then asked for the gui control that contains it… then asked for that control’s background component. Which should be the gcBkg you already grabbed.

This should have been all you needed:

QuadBackgroundComponent qbc = (QuadBackgroundComponent)pnl.getBackground();
qbc.setColor(colorBkp);

Or if you wanted to be more general:

ColoredComponent cc = (ColoredComponent)pnl.getBackground();
cc.setColor(colorBkp);

…which would then work with any of the various GuiComponents that implement ColoredComponent.

1 Like

ColoredComponent and new ElementId()! yes, sometimes I miss the obvious, thx!

I am using this to let me freely modify the dialog size without crashes:

pnl.setPreferredSize(newsize);
if(pnl is attached to GuiNode){
	try{
		pnl.getControl(GuiControl.class).update(1f/30f); //use real fps?
//			pnl.updateLogicalState(1f/30f);
	}catch(IllegalArgumentException ex){
		pnl.setPreferredSize(backup); //restore the backup
	}
}

So basically, if the user tries any invalid size, it will be restored to a safe one.

If I didnt check for the GuiNode it would have bad side effects like some style initializations would fail and listeners would get deaf.

Basically, I would like to let lemur try the new size and throw any problems it finds so I can restore in case of failure. I wonder if it may cause me trouble later or if this trick is robust enough? because I understand the update is not happenning when it should.

It should be fine. Where are you putting this code?

1 Like

cool, it happens during the drag border event, here

MiscLemurHelpersStateI.setGrantedSize(Panel, Vector3f, boolean) line: 868	
ConsoleVarsDialogStateI<T>(LemurDialogGUIStateAbs<T,R>).drag(Spatial, Vector3f) line: 383	
DialogMouseCursorListenerI.drag(ArrayList<MouseCursorButtonData>, CursorMotionEvent, Spatial, Spatial) line: 161	
DialogMouseCursorListenerI(MouseCursorListenerAbs).cursorMoved(CursorMotionEvent, Spatial, Spatial) line: 178	
CursorEventControl.cursorMoved(CursorMotionEvent, Spatial, Spatial) line: 141	
PickEventSession.cursorMoved(int, int) line: 442	
MouseAppState.dispatchMotion() line: 93	
MouseAppState(BasePickState).update(float) line: 169	
AppStateManager.update(float) line: 287	
ConsoleTestI<T>(SimpleApplication).update() line: 236

PS.: I think I will have to queue it in case changes happen while it is no at the GuiNode (or another jme viewport)

I was mostly curious because of this:

Mostly, the Lemur GUI elements are already pretty aware of if they are attached or not. Thought there might have been an easy way to answer that question.

Curious, in what case will you be getting drag events when it’s not in a situation where a drag could/should be handled?

1 Like

I actually configure everything before attaching them to the GuiNode, including the initialization preferred size, so it may happen while it is not attached yet.

And, another thing I do is, to hide the dialog (top Spatial directly attached to GuiNode) I just detach it from the GuiNode, and some configurations may happen while it is not attached too.

May be I should queue and check before apply changes to everything… may solve some problems I face from time to time, I think I work better with lazy initializations and validated/postponed apply of configurations :).

I would like to add that this was not enough:

try{pnl.getControl(GuiControl.class).update(1f/30f); ...

I think it is because of some delayed visual effects I am using…

but this made things get stable (not crash), despite the dialog looks bad and incomplete whenever an impossible layout happens (like 1x1 lol) it is not really a problem now:

@Override
public void updateLogicalState(float tpf) {
	try{
		super.updateLogicalState(tpf);
	}catch(Exception e){
		// log exception...
	}
}

I think I will even override all dialog contents with a simple label “impossible layout”, will make things clear to users so they can grow it back (happened only when shrinking) :slight_smile:

from this tip:

thx!

created the ResizablePanel, but…

Lemur/ResizablePanel.java at master · AquariusPower/Lemur · GitHub (not updated as often as…)
https://github.com/AquariusPower/DevConsLeJME/blob/master/GenericDialog/src/main/java/com/github/devconslejme/ResizablePanel.java (…this one)

basically, the resizable background border (BkgResBor), after the contents panel are set above it, even if I set the contents preferred size to -= border*2 (in X and Y, where border=3), the contents will expand and hide the BkgResBor, any idea what to do?

should I set some kind of invisible borders (?) so that BkgResBor is raycast hittable?

but then, wouldnt the very borders be enough instead of that BkgResBor? or it still would have any advantage?

I havent coded the dragging yet :slight_smile:

You are saying that the outer panel does not have any “space” around the contents that it contains?

You either need to give your outer panel a border that has a margin or you need to give your inner panel insets. The right idea is probably to give the outer panel a border component that has its margins set properly to be whatever the border wants to display.

2 Likes

wow… DragAndDropControl seems to have so many ready things I could use instead of CursorListener, I will try it first see what happens.

btw my reference is this post Lemur resize border - #2 by pspeed

EDIT: the border worked great!

If you haven’t already seen it, there is a demo of the drag and drop stuff here:

…among other things.

1 Like

cool!

btw, it is almost working, I can already drag to resize, but only corners right and bottom work partially.

also, if I drag too fast in a direction outside the panel it will stop dragging, but I think there is some methods there to deal with that, I will try it later :slight_smile:

it is minimalistically working! as we still have to move the mouse slowly or it will lose the dragging hook when moving towards outside the ResizablePanel…

Also, I believe you may consider the code a bit messy: missing constructors I didnt use on the test, not your coding style, may be a few more issues…

would you be interested in absorbing this class?
or I just put it into my other project?
later on, you can grab it anytime you want anyway,
despite I believe you may even implement the “complex” (to me) part, in a completely different way :slight_smile:

If you consume the down event then you should continue to get mouse move events even after leaving the original component.

That’s probably for the best. I have no time right now to properly beat on it and this way others can look/use/comment in the mean time.

1 Like

mmm… I cant seem to find a way to reach DragEvent.cursorEvent.setConsumed() (not inherited, is composite), am I missing something?

EDIT: I found no mouseDown, and only DragEvent

Personally, I would not use drag and drop stuff for a resize border. I’d just add a listener, set consumed on the event, if the mouse goes outside of the border then increase the size in that direction.

DragAndDropControl is meant for something completely different.

1 Like