# Lemur library enhanced by Textselect and ScrollModes

Hello,

I want to do a hobby project and may develope a 3D game during the next years. I have started some years ago and work when I find time and mute. I have no IT background but did some reading in the forum here. I have tried nifty a while ago and recently tested and tried lemur.

For what I have in mind I need a textfield, that allows selecting text, copy and paste etc., like a chat window in games, where you can copy and paste text with outside game world.

While studying lemur I could not find that functionality and I believe it is hard to add it from outside the library/jar.

As I am not experienced but lazy enough to start from scretch and I think lemur is quiete mature I just tried my luck, made an github account, downloaded the lemur library and enhanced it.

I added /changed the following (hope I wont forget anything):

• added “textblockers” to the standard scrollmode:
→ its not possible anymore to have visible text outside a textbox
→ added a maxlinecount, that can differ from setPreferredLineCount

→ in the standard example the password field grew once there was an offset and you return the cursor to the left

• added an optional scrollmode “full”
→ offset in X and Y direction is possible. No scrollbars, but you have a getOffset_Y() and getOffset_X() function, in case you want to add them by yourself
→ rewrote the current offset x method, it caused an recursive call/stack overflow in the function resetCursorPosition() once you add to many words at once

→ offset in Y direction, autoadjust in x direction
→ separat usable autoadjust function, that wrap lines once a word or a character would be out of the textbox, the scrollmode comes with autoadjust for words

• added two optional textselect modes (unstatic and static)
→ replacing the current anchor system with an field of anchors
→ you can have as many selected areas in text as you want
→ add, delete and reverse textselect areas (in any position of the text) is possible
→ get the currently selected text is possible
→ the standard textselect mode, onces activated, comes with the functionality of STR+A; STR+C;STR+V; STR+X + selecting and deselecting with shift + lemur standard cursor movements (e.g. up, down, home)
→ standard selectmode is unstatic: selected areas are removed once cursor is moved without shift key

• changed the lemur demos to add and show the new functionallity

In total I have changed the following files:

Lemur\src\main\java\com\simsilica\lemur\component\TextEntryComponent.Java
Lemur\src\main\java\com\simsilica\lemur\text\DefaultDocumentModel.java
Lemur\src\main\java\com\simsilica\lemur\text\DocumentModel.java
Lemur\examples\demos\src\main\java\demo\TextEntryDemoState.java
Lemur\src\main\java\com\simsilica\lemur\text\DocumentModelFilter.java

As pictures and movies say more then 1.000 words, I made an account on vimeo and uploaded something for you.

Why do I write all this? Even if I myself wont need all the changes I made?
After I started adding the functionality I said to myself:
Even if you just need one area in a text to be selected it would be nice to have the ability to add many. And I wanted to make it fully functional. I also thought, that I will take everything I need from the community, so I would like to offer to give something back.

I hope that the changes I made are worth to be considered to be taken into the Lemur library (so I myself can just use the ready jar). For sure it will need some code revision as i am not fit in e.g. naming conventions and I am not completely sure if the changes are interfering somewhere they should not.

If you are interessted I would clean and sort the code, as it currently still contain personal notices and reminders and share it with you.
Just let me know and please also tell me how to share or commit – not in detail, but I had a lot of first times recently: first time github, take code from there, first time making a video, first time uploading a video somewhere. And sharing the code will be another first time.

Cheers from Tunisia

5 Likes

I will have to take a look at it some time. I also had it on my to-do list to add the same functionality so I will have to compare it with those designs and see how closely they intersect.

Looks really neat, though.

Edit: no rush, but is the code available to look at somewhere?

https://github.com/Aufricer/Lemur_Enhancements/tree/master/Export_LemurChanges/src

As mentioned above I have changed the following files

Lemur\src\main\java\com\simsilica\lemur\component\TextEntryComponent.Java
Lemur\src\main\java\com\simsilica\lemur\text\DefaultDocumentModel.java
Lemur\src\main\java\com\simsilica\lemur\text\DocumentModel.java
Lemur\examples\demos\src\main\java\demo\TextEntryDemoState.java
Lemur\src\main\java\com\simsilica\lemur\text\DocumentModelFilter.java
“+” Lemur\src\main\java\com\simsilica\lemur\TextField.java

I forgot the last one…

Anyone that want to have a try just need to replace the files mentioned above in the current standard lemur library. While cleaning the code today I made the examples more clear, so everybody can see what is possible now.

I tried to not change existing things to much and in the end the adjustements are minimal. I also have not developed any new design but copied from what I found in the library.

It just needed some diligent work to add the functionallity.

I have added an optional Multiselect mode to the Lemur Listbox.
The following changes are applied:

• deselection of any select panel (the yellow marker), even in single select mode is possible
• selecting multiple lines is possible
• insert in demo will insert even if there is no selection yet
• remove in demo will remove all selected lines and the select panels

I needed to modifiy the following files

Lemur\extensions\LemurProto\src\main\java\com\simsilica\lemur\ListBox.java
Lemur\extensions\LemurProto\src\main\java\com\simsilica\lemur\list\SelectionModel.java
Lemur\examples\demos\src\main\java\demo\ListBoxDemoState.java

I have uploaded them to the same github repositories

Compared with the changes to the textfield the modifications this times are minimal. If someone want to use it, he or she should only replace the files with the original files.

As the discussion was coming up in the forum from time to time I would like to ask about the consumption of events.

I needed to make the select panels disappear. My first thought was to use the same functionality as is used to add them. But the adding comes from a listener to the grid line. The grid line cant be reached while there is an panel in front of it.
My first idea was to make a Cursorlistener that is passing the click event through. But the event is always consumed automatically.

Would it be possible and would it work to add an method that do “consumed = false” to the

Lemur\src\main\java\com\simsilica\lemur\event\AbstractCursorEvent.java

If you add a listener to an element that is “blocking” an event you could, by calling this method, avoid the consumption. I did not try it, as I find an easy approach in listbox and always try to keep code invasion as small as possible.
Or was there another way to not consume events?

Don’t consume them in the first place.

If something consumes an event then it consumes it. “Unconsuming” it by something else doesn’t make sense. To avoid breaking all kinds of things, you’d have to somehow have a way to notify that other thing that consumed it that it didn’t really consume it anymore. And maybe it says no, I really do want to consume it and you can’t have it. And then they get into a big argument and 30 seconds later they decide it’s ok, the second guy can have it… then a third one that never got the event yet decides it wants to consume it now and they all argue again.

Something in the approach feels wrong to me.

Yes you are probably right. I just thought its a way. Cause it would be similiar to the inbuilt PopupState where you can decide if an click is consumed or passed through (and close sthg. in that specific case).

Anyhow - I think I could make the things working for me and if I need more I modify it for my needs.

Bye the way as Its not explicitly said often: Thank you for your work, advice and help. Its good to know that we can come back with our problems.

1 Like

Hello Paul!
What is the status of Textselect on Lemur 1.15.0 now in 2021?

Same. This feature has not bubbled up to the top of my list yet.

1 Like

Thank you for the answer. A bit unhappy for me.
Wanted to see if I can tinker an XML editor with jme3 on a tree in 3d.

If you urgently need it, you may implement it by yourself.
If I remember correct it was just a field of selected textpositions. Each possition you convert to x and y coordinates and then you add a color block.
Color block was already in and even anchors.

Sry I wish I had time and had realy hoped to spend up to 5 months in 2021 on my small hobby but closed boarders etc. keeping me bound.
As usual stuff is/was not that complicated once you could afford the time invested to be familiar with.

2 Likes

com.simsilica.lemur.component.SelTextEntryComponent.Java
com.simsilica.lemur.text.DefaultSelDocumentModel.java
com.simsilica.lemur.text.SelDocumentModel.java
com.simsilica.lemur.text.SelDocumentModelFilter.java
com.simsilica.lemur.SelTextField.java

taken over as Sel * to avoid collisions with Lemur updates.

Do you have a license notice for it?

Thanks for the preliminary work.

Thank you for these nice improvements to text-field, I’ve just merged the changes with latest Lemur and it looks awesome

1 Like

Bug report: Highlighting works very well on the gui node, but not on the root node, because the text behind the marking is covered by it.

Sounds like you need to enable transparency on the GUI hierarchy in the scene (place them in the transparent bucket).

1 Like

Or the layers aren’t setup right.

No note and not needed (for me).
But:
If you improve or enhance you may share it back.
I still check the forum and took a lot of interessting ideas and concepts from here. There is also plenty of bookmarks waiting for me.
Is that software store still in use ?

JME/Lemur by concept is made to adjust it to your needs. Of course not all (special) use cases are built in.
So I am kind of happy if stuff I adjusted might help others.
Grab and take what you need and make it working for your use case.
Hope to see it in the WIP sooner or later.

1 Like

Thx Aufricer.
I would like to show the result … … but that should take years.

At the moment I still don’t believe that I have the right UI libraries for jme3.

But back to Lemur: Do any of you know why TextField (and the derived SelTextField) have a black background, while the label and button are transparent?

Thank you very much

Because text fields have a black background so that they look different than labels. You can change it, though. Just give it a new background of your choosing.

2 Likes

First:

It helps… Thanks! … sometimes.
Edit: It behaves depending on getWorldScale () … So I don’t have a clear statement now.

I have one more question today, the demo doesn’t show it …

When I use CollisionResult, and
colision.getGeometry().getParent() == textField

I would like to

1. Place the cursor at the click position
2. Selection from begin to end of the click & move mouse action.

How do I set the position of the cursor?
How do I set the positions of the selection?

P.S.:
With:

                int[] xy = new int[2];
xy[0] = (int) contactPoint.getX();
xy[1] = (int) contactPoint.getY();
System.out.println("§§§§§§§§§§§§§§#  " + xy[0] + ", " + xy[1]);
int[] lines = textField.getTextlinesbyCoordinates(xy);
if (lines != null) {
System.out.println("§§§§§§§§§§§§§§§  " + lines[0] + ", " + lines[1]);
}


do I get the right position in the string … And now?

1. Place the cursor at the string position?
2. Selection from begin to end of substring?

I have used lemurs mousebutton event. As I see

int[] lines = textField.getTextlinesbyCoordinates(xy)


in your code I assume you have used my modifications, so I will just give you an answer (no intention to cut word off someone)

Have a look to the whole class:

In my future project I have it separate and call it like that on each textfield I a, going to need it.

selector = new Textfieldselectors();
textField = new TextField(text, elementId.child(TextField_ID), style);