Lemur: developer commands console

There is a repository on github for it: CommandsConsoleGUI.

Can be customized without changing it directly. Just use the test class as quickstart.

Hit F10 (on the test) to toggle console (initially closed).

Features:
Main
= Command (and params) auto complete “startWith”, key TAB, case insensitive
= Command (and params) auto complete “contains” , key Ctrl+TAB, case insensitive
= Command history, key up/down. Saved and loaded from file, see /statsShowAll.
= Command params can be enclosed into double quotes.
= Command hint (Listbox) while it is being typed.
= If a clicked dump entry is a valid command, it will replace the input field text (that will be dumped).
= Batch execute initialization console commands. Configurable at file, see /statsShowAll.
= Console style can be changed on the fly.
= Line wrapping works for all styles.
Nagivation
= Navigate dump area, key pgup/pgdown or mouse scroll. Dump is saved to a file, see /statsShowAll.
= Auto scroll after command.
Commands
= Several commands available already, see command /help
= Comment detection, line starting with such token will be ignored
= Omit the “command being run” info entry by ending a line with ‘#’, good at init file, mainly for /echo commands.
Editing
= Multi-line copy: Ctrl+b (or Shift+click) marks CopyFrom “begin”, Ctrl+c marks CopyTo “end”.
= Single line wrap detection when copying.
= Ctrl+del clear the input command line
= ctrl+home sroll top, ctrl+end scroll bottom
= Big lines are wrapped, each part ends with ‘’
= Ctrl+/ comment toggle on the input line.
= Any changes to the input text will reset the command history cursor, hit Down to access your last non issued command.

Above the input field is the log area, below is the command hints/auto completion.
(This screenshot may not be updated)

my init file currently has this:

# console commands here will be executed at startup

/consoleStyle console

# enable hacks
/HKtoggle true
/fixCursor

/consoleHeight 0.8

# just some echo test
/echo 123#

Snapshots at googledrive.

Original Post:

Just got lemur libs (n00b here).
I am trying to create that developer console where we have a text area to dump any text we want (like the output of the typed commands), and a single line text input field.
Is there such implementation somewhere?

EDIT: I am having some problems:

  1. I am not being able to limit the TextField height, it is getting stretched.
  2. I see no text input blinking cursor.
  3. I can’t select text, copy/paste
    EDIT: I can navigate left/right/home/end

Any tips?

PS.: my start point was GuiDemo.java here

1 Like

There is no built in component for this yet, unfortunately.

Off the top of my head, your best bet might be to have a single line TextField for the entry and then a ListPanel for the text (broken up before adding)… ListPanels will have a fixed display height.

Your TextField should have a cursor if it has focus. It will not be blinking, though.

1 Like

I could not find ListPanel.java, I created a ListBox<String> with a TextField as dump area, but it is overflowing below the limits of the console, and it is still editable.

I am also trying to figure out how to place an event to the Enter key at the input TextField that dumps the typed command and allows running it.

The cursor is not visible here for some reason, I am on linux btw.

I created a gist of what I am trying to do:

Obs.: I am new on gist too, I dont know if/how other ppl can edit/directlyContribute to it. May be only I can update it?

It is an app state, make sure you properly initialize it:

@Override
public void simpleInitApp() {
    stateConsDev = new ConsoleGuiState();
    stateConsDev.setEnabled(true);
    getStateManager().attach(stateConsDev);
}    

Suggestions and code drops are welcome!
I will drop updates there as soon I can get them working.

PS.: The license I used is basically the same of JME. I am new on this too, if someone contributes, I must add the credit at “authors” comment, or also at copyright? just point it out so I can update it.

Oopp… yeah, I got the name wrong, sorry.

Not sure what you mean by ‘dump area’.

Maybe the cursor is invisible because of the current style?

You can hook into many of the text editors key events with the action map:
http://jmonkeyengine-contributions.github.io/Lemur/javadoc/Lemur/com/simsilica/lemur/TextField.html#getActionMap()

(Sorry no real documentation there.)

But something like:
textfield.getActionMap().put(new KeyAction(KeyInput.KEY_RETURN), yourListener);

2 Likes

the dump area (ListBox above) is the place where the user typed command will output their resulting messages like (the input field is below):

#player jumped
/jump

The event worked thx! everytime I press enter, the typed text is dumped.

I am using BaseStyles.GLASS, still looking for other styles to test. I got the full git for lemur so I can look for examples there.

How to add rows to the ListBox?
I changed the code to use Label inside ListBox.
I found that ListBox has GridPanel.
I tried to set the GridPanel to ListModel (1 column, many rows) with:

new ListModel<String>(new VersionedList<String>(),lstbx.getCellRenderer());

but I think I am still missing something as when I try to set a row, the cell is null at

 lstbx.getGridPanel().getCell(iDumpCount,0)

You shouldn’t be doing that directly setting the grid if you use a list box. Just add things to the list model. If you want the latest item on the bottom then just pad the list with some extra values I guess.

Else you can just use a grid panel directly and manage the scrolling yourself.

1 Like

yes, I just “learned” how it all works right now…

Anyway, It is almost working. as I updated at gist.
I am simply adding entries to the ListModel → VersionedList list.
The entries are properly showing now!

How to scroll the slider to the bottom?
I still cant find a way to make the slider scroll to the bottom every time a new entry is added.
The problem is, whenever I add an entry, the slider draggable button moves up, and the currently shown row just remains there.

There isn’t an automatic way to do this… at least not yet. You’ll have to grab the range model for the bar and set its value. As I recall, it might be upside down so it’s possible that setting it to zero works.

listBox.getSlider().getModel()…

1 Like

Perfect! I was a bit lost on where to look for that!

but I still had to use a trick for every new entry added:

lstbx.getSlider().getModel().setMinimum(-1);
lstbx.getSlider().getModel().setValue(-1); //scroll to bottom

Basically, if I try to use value 0, it will not show the last line, it will only at most the last-1 line.
And the minimum gets fixed to 0, so it must be set again every time.
On gist.

That’s probably a bug.

Mostly ListBox works great… but every now and then I’m reminded why it’s still in proto and not in core yet. :slight_smile:

1 Like

It is fast also, I put 10000 entries on it and the scroll was still very fast!

Btw, I made the initial number of visible rows adaptative based on the listboxHeight/fontHeight. It would be cool to have a method like lstbx.getGridPanel().setVisibleAdaptative(true); :slight_smile:

Now, I am hiding the console by detaching from the guiNode, but I cannot find a way to lose focus from the input TextField, like in, with it hidden, everything I type gets sent to it. I bound f10 as console toggle key at the test class.
Is there some way to disable a LemurGUI and reenable it without reinitializing it?

If you just want to change focus then request focus for null.

Other than that, as long as you enable/disable the mouse then I think Lemur will disable/enable itself… actually there may already be a method on GuiGlobals to do that for you.

1 Like

Perfect!
GuiGlobals.getInstance().setCursorEventsEnabled()
I think the console basic usability is functional now, thx!
on gist.

But, I am still puzzled about the TextField cursor visibility.

On debug, I checked it has material applied and has cullhint inherit (never), but the material applied to it differs from the one on the test below (when using same style of course). About: TextField.text(TextEntryComponent).cursor.material

if I test this code, the cursor will show up properly for this panel!

    Styles styles = GuiGlobals.getInstance().getStyles();
    BitmapFont font = styles.getAttributes("textField", null).get("font", BitmapFont.class);
		TextEntryComponent tec = new TextEntryComponent(new DocumentModel("Testing123"), font);
		pnlTest = new Panel();
    pnlTest.getControl(GuiControl.class).setLayerOrder("text");
		pnlTest.getControl(GuiControl.class).setComponent("text", tec);
		ctnrConsole.addChild( pnlTest );
	}
    GuiGlobals.getInstance().requestFocus(pnlTest);

But for the input TextField, no matter what I do, if I initialize it with null (defaults glass) or

	tfInput = new TextField(strCommandPrefixChar,Styles.ROOT_STYLE);
//or
	tfInput = new TextField(strCommandPrefixChar,BaseStyles.GLASS);

I am still trying to understand what happens on the TextField that is different from that test above, and makes text cursor invisible here.

from gist, type the command /test to see it.

EDIT: I know what is happening, if I add this code to the test tec.setAlpha(-1); the cursor will vanish the same way TextField one is invisible (by having alpha -1). Does it mean to blend alpha by inverting the colors? Could it be a limitation of my GPU? or may be some configuration I am missing?
Anyway, if I could access TextField.text(TextEntryComponent), I would be able to fix the alpha here :slight_smile:
EDIT: confirmed, with reflection, I set its alpha to 1 and it showed up properly!

I’ve never had a problem with the cursor showing up… so not sure why it’s happening that way for you.

I will say that:
Styles.ROOT_STYLE);
…won’t do anything unless you have a root style defined.

,BaseStyles.GLASS);
…won’t do anything unless you’ve loaded the glass style.

I don’t see the code where you initialize any of that so it’s hard to say.

It is working now, but I had to use reflection to set TextField.text.setAlpha(1)

Yes I initialize it properly

	BaseStyles.loadGlassStyle();
	GuiGlobals.getInstance().getStyles().setDefaultStyle(BaseStyles.GLASS);

In debug, I saw that alpha being set to -1, I still dont understand why tho.

If it is to invert colors, may be my machine has some limitation, my GPU is an old GeForce GTS 250. Or may be I have something miss-configured here…

The full code is on the gist

What code is setting it to -1. It’s not really a valid alpha value so I don’t know what of my code would do that.

[jump to my next post]

oh!

well, the TextField.text.bitmapText.getAlpha() is returning -1 on this stack:

TextEntryComponent.resetCursorColor() line: 290	
TextEntryComponent.setColor(ColorRGBA) line: 307	
TextField.setColor(ColorRGBA) line: 162	
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
Method.invoke(Object, Object...) line: 497	
Styles.applyStyles(Object, ElementId, String) line: 471	
Styles.applyStyles(Object, String, String) line: 425	
TextField.<init>(DocumentModel, boolean, ElementId, String) line: 106	
TextField.<init>(String) line: 70	

at TextField constructor, the bitmap font is initialized with:

BitmapFont font = styles.getAttributes(elementId.getId(), style).get("font", BitmapFont.class);
this.text = new TextEntryComponent(model, font);
//where elementId.id="textField", style=null

//for this stack:
/*
TextField.<init>(DocumentModel, boolean, ElementId, String) line: 100	
TextField.<init>(String) line: 70	
*/

// even if I instantiate it like this (but style="glass" now): 
tfInput = new TextField(strCommandPrefixChar,BaseStyles.GLASS);

so at TextEntryComponent() constructor, I can already detect the alpha as -1 after

this.bitmapText = new BitmapText(font);

if you think I can give another clue, point it out!

[jump to my next post]

I found it!

//BitmapText
public float getAlpha() {
    return letters.getBaseAlpha();
}

//stack
Letters.<init>(BitmapFont, StringBlock, boolean) line: 58	
BitmapText.<init>(BitmapFont, boolean, boolean) line: 73	
BitmapText.<init>(BitmapFont) line: 56	
TextEntryComponent.<init>(DocumentModel, BitmapFont) line: 131	
TextField.<init>(DocumentModel, boolean, ElementId, String) line: 100	
TextField.<init>(String) line: 70	

com.jme3.font.BitmapFont.Align.Letters.baseAlpha initializes as -1!

Yeah, I believe that indicates ‘use no overriding alpha’… ie: it will only use the alpha of the color.

That really has nothing to do with why the cursor won’t show up.

Note: the cursor is only designed to show up when the TextField has the focus. Let’s get that out of the way just in case.

The cursor isn’t even bitmap text so the only way the text could affect it is if you squashed the z thickness of your GUI elements somehow and then everything is getting slammed together and not rendered properly.

Can you put together a simple single class test case the illustrates the issue?