I find myself in a position of wanting to overcome this bit of design deficit from the really early days of Lemur.
Text entry components are notoriously difficult to get right and something like TextField would have normally incubated in lemur-proto for a while before becoming core. The problem is that a GUI library without a text field is pretty useless… so I had to do what I could at the time. Most things are or have been fixable over time. Perhaps a testament to luck or existing experience with writing UI libraries.
Anyway, at the time, I made DocumentModel a concrete class because I was in a hurry and couldn’t think of any reason to make it an interface + an implementing class. Every instinct I had told me this was wrong and now I find myself regretting that. I’d like to fix it.
So I’m wondering how many people instantiate DocumentModel directly versus just using the one that TextField returns from its getModel() method?
I’m also curious how many of you actually refer to the DocumentModel at all… because I’d also like to move it to a different package, too. That part is more optional, though.
Either of these things is a potentially breaking change even if it’s a simple one for you to fix. I’ve tried super super hard to avoid this in Lemur to some success. Sometimes it is inevitable I guess.
Given how little other feedback I’ve gotten, I went ahead with the most drastic approach hoping that most folks have left this an implementation detail until now.
I’ve just committed changes to Lemur master that move the DocumentModel class into the new com.simsilica.lemur.text package… and I’ve made DocumentModel an interface. There is now a new DefaultDocumentModel class that implements it and has the previous behavior (along with proper clone() support).
This will go into the unreleased Lemur 1.10.1.
Worst case for most people that this hits is just to redo imports. I suspect not a lot of folks are referring to this directly.
Why am I doing this? Well, I want to support proper password fields and other sort of input constraints in the future and being able to wrap DocumentModels is the easiest/best way to do that. The only proper way to do that was to have a separate interface and implementation that I can then provide wrapper classes for down the line.
Yeah, based on further work today the benefits of this change are quite extensive.
I’ve already pretty trivially implemented text fields that only accept alpha or numeric or can filter their output as upper case or *** password style.
This will make creating a proper PasswordField a snap.
Well… I’m curious too now xD. The full extent code is:
public class CustomDocumentModel extends DocumentModel {
@Override
public void insert( char c ) {
if((Character.isLetterOrDigit(c) || Character.isSpaceChar(c)) && c != 'º' && c != 'ª') {
super.insert(c);
}
}
}
And it is in a piece of code made by another member of my team so… . It seams to be for a kind search/filter text field.
Ahah! You will now be able to do this without extending document model. You can use a DocumentModelFilter and pass it a custom input transform that filters out characters you don’t want.
You can see some examples of alpha-only and digit-only in the new demo.
Lemur is just using JME’s BitmapText… so beyond the support it provides there is nothing. (So you might be able to transform color information but that’s it.)
Supporting formatting in a document would require a new kind of GUI element and lots of work, I guess.
My personal use case is very limited for at least my current project. Less text means cheaper for international support. So your not breaking anything at my end.
But if i did need a lot of text outside options menus and “you died” messages. Say for project No 3 or 4. I would need pretty close to a solid subset of html and full Latin + Russian support. In fact i would be tempted to look at some text to texture thing for that.
Most won’t need to access it… and those that did need to access it probably would have been disappointed anyway.
For a TextField it’s the model object underneath that keeps track of the text and carat position… which for a single line field is no big deal but for a multiline field is a bit complicated.