If it’s possible to remove them from the constructor, I wouldn’t mind at least considering this. There will always be a way of setting a specific UID via a setter, and the ability to retrieve them via screen.getElementById(), however… would anyone be terribly upset about updating the standard constructors to not require these?
Anyways, before anything is updated, I’d like to hear everyone’s take on the pros/cons!
I use uids to get a reference to the elements due to my centralized listeners approach.
I have absolutely no problem with setting my uids via a setter instead of the constructor.
Well… there is the alternative of 3 extra constructors… /shrug Honestly, when all is said and done, this would be the easiest to implement and would provide the ability to handle things however the user sees fit.
I think I’ll try a bit of local experimenting and see how this works out.
@madjack I missed this… is it the request about disabled controls?
Yeah… I think this is a good thing. Right now, buttons use the pressed state, correct? Which seems a little confusing to me even if you have a pressed state defined for the button. I’ll get on adding isEnabled to all controls and some way of defining a specific visual/font variation for enabled state specifically.
EDIT: or more specifically, see if I can figure out a way to do what you suggested and make it part of the primitive element class.
EDIT 2: I may have some questions along the way… like this one (for instance) what would a disabled combobox look like? /blink… /blink… grey out the text? or? And… a disabled combobox… can you still see the dropdown? or? I hope there are too many instances where I will need to know what to do with this… but the select list, combo box, select box etc have me a little confused. Actually… add Slider, spinner, dial… ugh… I really don’t know what a disabled anything looks like… aside from buttons =(
There isn’t any standard as to how some controls should act like when disabled. I have seen many different iterations.
Except for the obvious can’t select or propagate anything:
ComboBox/SelectBox - Clicking on this sometimes opens the list, in certain GUIs, in others not at all. You do what you want. Go for the easy and fast solution.
Slider - Shouldn’t respond to any mouse hover, click or whatever.
No need to say that it should be obvious visually when a control is disabled. As far as tooltips, it depends on the GUI implementer.
Hmmm… apparently I missed tonights build with the update that resolves the UID issue. Sooooo… options are… grab the latest from the repo, or wait til tomorrow night =(
Seen the update.
My advice would be to deprecate the UID-using constructors. Six constructors per class is FAR too much. It would be okay if the constructors were the same everywhere, but they aren’t - some classes have additional booleans, so you’re back to choosing the right among six constructors every time you create a control
Instead, I’d use a minimal constructor and use DSL style. Caller code would look like this: new Menu(screen).at(x, y).size(w, h).scrollable(true).resizeBorders(1, 1, 1, 1)
That way, you never need to look up anything because resizeBorders() is always the same feature.
(I can outline the generics trickery for the DSL setup if there’s interest.)
BTW @madjack please open your own thread, this is about UIDs, not about enable/disable. Let’s keep the threads focused.
@kwando said:
That builder pattern DSL that @toolforger suggested looks sweet =)
The downside is that it’s super painful to maintain across subclasses since you end up having to duplicate all of the methods to call “super” and return “this”. Super nice for the callers though. Really super-duper nice in languages like Groovy with dynamic typing… there you don’t have to duplicate the methods for each subclass.
@pspeed Good point!, I spend a great deal of my days inside ruby and did no think about the implications of the maintenance burden of this pattern in java.
No need to duplicate methods across subclasses, @pspeed. Here’s the pattern (replacing angle brackets with parentheses because nested angle brackets are still getting eaten):
[java]class Element(MY_TYPE extends Element(MY_TYPE)) { // incantation might be slightly wrong, but that’s the general idea @SuppressWarning(“uncheckedOrWhateverItIsHere”)
protected MY_TYPE me() {
return (MY_TYPE) this;
}
MY_TYPE at(float x, y) {
this.x = x; this.y = y; // Or whatever is needed here
return me();
}
}
class Button extends Element(Button) {
// no need to override at() here, it’s already returning a MY_TYPE === Button
}
[/java]
If client code uses Element, you’d want to rename Element to ElementBase(MY_TYPE extends ElementBase(MY_TYPE)) for subclassing and provide Element extends ElementBase(Element) for clients. (With “client” I mean “any non-inheriting use of the class” in this context, don’t know what JME’s standard terminology for that is.)
I have a few issues with the builder pattern approach (though I use them in my game).
Still, I’m not sure how much more minimalistic a constructor can get:
Button b = new Button(screen, new Vector2f(50,50));
At this point were talking about 1 parameter??
And in the case of Sliders, etc… orientation is required in the constructor so it would have to be there unless you added a build() method that was appended to the list of method calls. And then the user would HAVE to know that the orientation method was required prior to calling build()… which becomes problematic in very obvious ways.
Honestly, the builder approach always ends up requiring more typing for the end user, can potentially minimize your available options (like in the case of 4 floats as apposed to just using a Vector4f. Yes, I understand this could allow for a Vector… but the the 4 floats were your preference and problematic).
Anyways, I’m not apposed to considering it… but I see this as a potential for deterring people from using the library… not inviting them.
EDIT: I’m a little tired… but how do abstract methods work with builders? I have never tried this. Does it end up looking like:
[java]
new Button(screen) { @Override
public void someAbstractMethod) { }
}.nextMethod().anotherMethod().someOtherFancyMethod().build();
[/java]
?
EDIT: On the other hand, wrappers would be awesome. This would allow people the option without requiring them to use this format.
@pspeed
Something I would like to do, but have never done this before is provide some type of groovy scripting or something similar. Can you point me in the right direction for decent example of implementing this sort of thing? Suggestions of any kind that would be helpful to know before hand?
@t0neg0d said:
@pspeed
Something I would like to do, but have never done this before is provide some type of groovy scripting or something similar. Can you point me in the right direction for decent example of implementing this sort of thing? Suggestions of any kind that would be helpful to know before hand?
It’s not very hard, actually.
[java]ScriptEngineManager factory = new ScriptEngineManager();
engine = factory.getEngineByName(“groovy”);
engine.eval( “Some script string” );
engine.eval( new FileReader(“somescript file”));
[/java]
Notes about the above:
All it requires is that the groovy-all jar be in the classpath.
If you don’t already know groovy then there will be a learning curve. Steeper than just a regular groovy user because to write a nice API you would/should need to learn about how the closures system works, the delegate reference, etc…