Or do I? What’s the relation between specifying a controller in the xml, like so
[java]<screen id=“start” controller=“de.lessvoid.nifty.examples.helloworld.HelloWorldStartScreen”>[/java]
and specifying a controller in the fromXml method (fromXml(String fileId, InputStream input, String startScreen, ScreenController… controllers))?
If you specify the controller only in the XML then it will be instantiated for you when the XML is loaded.
When you specify it on the fromXml method then it will use your instance provided but needs to know which screen to associate it with… and uses the class name defined in the XML for that.
Normally you lay out a base UI using XML, then using code you update / add the data, move stuff around etc. This way even somebody who has no idea about the code can go about and improve the UI w/o you having to change anything in the code, same is true for yourself off ^^.
So it does not actually do much else than try to map the name to the name of the class provided in fromXml? Hmm… It would be great if I did not have to “define” the class in the xml (to be loaded), because I’m using Clojure. In Clojure, creating static .class files is kind of a chore. On the other hand, there is a “macro” for just this situation with Listeners/Controllers: proxy. With it one can create instances of “anonymous” classes to pass to Java code. But they get strange names:
[java]
(def dynamic-class (proxy [Object] []
(toString []
“hello”)))
(.toString dynamic-class) => “hello”
(.getName (class dynamic-class)) => “user.proxy$java.lang.Object$0”
[/java]
It would be great if I could provide the an instance of a controller in the code, and not have to care much about the xml part. Would it work if I wrote “user.proxy$java.lang.Object$0” in the xml?
But an XML file could have 50 different screens in it that use a variety of different controllers. The class is used to match them up.
You can construct the whole UI via code if you want. However you will not be able to use the coming visual editors or be in any way compatible to external software.
I don’t mean that I don’t want to use xml for the UI layout, that’s perfectly fine. What I’m wondering (and what I want) is if there is a way to do the basic layout in XML, then do a controller in the code, and not have to give the name of it in xml, because the controller is an anonymous class.
But from what I have understood, I need to enter the name of the controller class in the XML. But what I would like then is to instead enter the name of the screen in the java/clojure code, or something to that effect. So it’s just the other way around.
This to me seems better. Is there anything I am missing here?
This might be a Nifty thing, so maybe I should go there to beg for the feature.
a) it’s definitely a nifty thing.
b) you might be able to fake it just by creating your own class that you always use (since presumably you will never pass more than one controller or want more than one)… this class could wrap your anonymous classes… and I suppose even delegate to different ones based on the screen name. However, you would then have to specify this wrapper/delegator class in your XML. At least it would always be the same.
Maybe there is a nifty trick I don’t know of… in which case I’d like to know also because leaving the controller out of the XML would be my preference as well and just tie them together at runtime by screen name.
Hhmmzz…
If I understand it correctly, you want to load the screen from XML based on the screen id and not based on the controller class.
This is definately possible, in fact, you can do it straight from the following method:
[java]
nifty.fromXml(configurateionXmlFile, screenId);
[/java]
Here I supply the full location of the xml file, this can be either on the classpath or on the filesystem I think. I only use classpath atm, so you would have to experiment a bit which works best for you. The second parameter is the screen id as you set it up in your XML:
[xml]
<screen id="loginScreen" controller="com.ractoc.opengamefinder.client.screens.controllers.LoginScreenController">
[/xml]
The screenId in you java method should be the same as the screen in the xml you want to load and display.
I hope this helps a bit.
As far as I know the only real use for providing the fromXml method with a controller class is if you need to pass stuff into the controller class which are not availlable at the time the xml file is parsed.
Would it work if I wrote “user.proxy$java.lang.Object$0″ in the xml?
YES! That would work! :) Currently the class name is used to match ScreenControllers between XML and Java (the others have explained that very well already). Anonymous inner classes can be used as well - when you get used to the odd class names.
I do understand the problem tho. In some cases you already have an existing class in Java and just want to have that specific instance as the ScreenController. As paul suggested the best way would probably be when you're able to bind an existing ScreenController instance to a Screen. Which shouldn't be that hard because Nifty keeps the instance at the Screen class internally. So when a screen is materialized from the XML it should be allowed to attached a ScreenController to that screen. The only thing that's a bit tricky would be that you need to attach the ScreenController to the Screen BEFORE this Screen is started. Besides that this should work out quite well. I'll add a feature request for this for 1.4 on the sf.net tracker ;)
@tufflax: Cross posting here and at the sf.net Nifty forum is not a great idea I think. It just makes tracking posts hard. Here is the sf.net post for reference but I've closed it there https://sourceforge.net/projects/nifty-gui/forums/forum/807893/topic/4623594/index/page/1 :)
OK, but the thing is that in Clojure, the name of a “proxy class” depends only on the class and Interfaces I am extending. So if I make 2 controllers that extend the same class, that would not work (they get the same name). Plus, the name is kind of an implementation detail, and shouldn’t really be relied on.
I guess I have to do go the other way, AOT compiling classes like one would with Java. I long for Nifty 1.4 though.
Thank you everyone!