Best practice: How to dynamically change menu contents

Hi,

I’ve started creating a simple Menu using Nifty, but by now it’s grown a bit more complex and I’ve run into some problems.
What I basically want to do is this: When I click a button in the main menu on the left side of the screen (e.g. “settings”), a new dialogue appears on the right side. I’ve laid out the menu in XML, so there is a panel on the left side for the main menu buttons and free space on the right side.

How can I fill this space on the right side, according to the button that was clicked on the left? Right now I help myself by creating a new layer for every submenu and reconstructing the separation of the screen in every layer (which is a horrible practice…), but I didn’t manage to detach and reattach the contents of a panel so far, so… I’d be glad for some hints on this.

What I’ve tried so far
[java]
Element rootNode = …; // parent element of submenu
Element submenu = nifty.getScreen(“menu”).findElementByName(“submenu”); // the container panel for the current submenu

// remove and reattach
submenu.markForRemoval();
rootNode.add(submenu);

// just move somewhere else
submenu.markForMove(storage);
submenu.markForMove(rootNode);
[/java]
Well, none of it worked ^^

The good news is that dynamic modification of nifty is possible and works well, we use it all the time in HeroDex. We found it easier using builders rather than XML though - so we define our main screens in XML but then all the popups etc overlayed on that is done using nifty panels created through builders.

The first thing I would do is do rootNode.findElementByName() rather than going right back to the screen level. That will both reduce the chance of naming collisions and give it less to search.

Note that “markForRemoval” does not remove something immediately - it gets removed on the next update cycle by nifty. So removing then re-adding will have odd effects.

Use a builder to create a new menu object, remove the old one and add the new one.

Use a builder to create a new menu object, remove the old one and add the new one.
Thanks for your response, but I don't understand why this should work and not one of the approaches I've tried using.

I just wouldn’t want to mix xml and the java builder too much, or I can spare me the use of XML in the first place. My Idea was, rather than using the builder, to store anything I might need later on an invisible layer and then just move stuff around as I need it…

Well, I’ll try the builder then I guess, hope that works

edit:
[java]
submenu.markForRemoval();
Element replacement = screen.findElementByName(“replace”);
rootNode.add(replacement);
replacement.setVisible(true);
[/java]
That’s totally working. I guess I just can’t remove an element and then add the removed element again, but when I keep a copy on the invisible layer, it’s working perfectly well. And that means I can avoid the java builder again :smiley:

I added the setVisible-Line, as I move my elements from an invisible layer and the visibility setting is apperently being inherited.

One more question: If the parent element has 3 children, and I remove the second child, is there a way to reattach another element at the second position (rootNode.add(…) obviously does only insert at the last position)?

It’s because markForRemoval doesn’t actually remove things immediately. You would need to listen for the removal completing then doing your addition.

For putting things back in a certain sequence - I’m not sure of the answer off hand, sorry. See if you can find something in the javadoc or manual.

Well, I found this (April 2011) and I’m working on a workaround, but as markForRemoval and markForMove work asynchronously, this is pretty hopeless.

So the best thing to do is wrapping the parts I want to exchange in another named Panel, which can not be considered “best practice”, but it should do the trick.
Note@Developer: If you would find the time to implement an insert(Element e, int index), that would be awesome :slight_smile: