NiftyGui 2 items on screen simultaneously with alternating focus

Well, I think I understand what you are trying to do. I don’t understand your code tho :slight_smile: and the code refers to some files that you’ve not attached so I wasn’t able to try your example completly.



To help you anyway I’ve played around with the original console example in the nifty-examples project. The original approach was kinda silly tho because the console - being just another layer - will not care about the keyboard focus correctly. You could probably workaround the issues with changing the focus manually but there is a better way :smiley:



Popups will automatically save the current focus element of the screen when the popup layer is created and restored when the popup has been closed. So all I’ve done is to move the console control into a popup and simple toggle the popup with F1!



I’ve updated the console example in the nifty examples project and you can find it in svn or browse it online at:



http://nifty-gui.svn.sourceforge.net/viewvc/nifty-gui/nifty-examples/trunk/src/main/java/de/lessvoid/nifty/examples/console/

http://nifty-gui.svn.sourceforge.net/viewvc/nifty-gui/nifty-examples/trunk/src/main/resources/console/



Maybe you can take a look there - I think this approach works better for your problem too.



It looks like this now:

Wow this looks ace - cheers, ive made most of the changes.



However on pressing f1 it doesnt open the console. I think its because i have a key handler in my chat handler and thats capturing the f1 press instead of the console handler?



The chatpanelhandler is in the first post…

As I've said, I can't compile your code because of missing classes, like



import org.snow.networking.SnowNetwork;

import org.snow.utils.SnowReference;

import org.snow.utils.SnowUtils;



The GUIKeyBoardMapping class is missing too. So it's kinda hard to get it working here.



I don't know what exactly you've changed now too. So I don't know why your key events are not reaching your ConsoleHandler?  :?



Why are you adding an additional KeyboardInputHandler with: "screen.addKeyboardInputHandler(new GUIKeyBoardMapping(), this);" anyway? Controls usually get NiftyInputEvents with the inputEvent() method that is even part of the Controller interface you've implemented? o_O



So can you send a complete example, that I can compile? Maybe remove all of the stuff that's not necessary to reproduce any issue.

GUIKeyboardMapper just is the same as the other handler but allows f1 or end to be == console key.



Other than that I add another listener in ChatPanelHandler cos that means i can get key input events - the control when i type doesnt fire inputEvents…



my xml now looks as follows



package org.snow.GUI.controllers;

import java.util.ArrayList;
import java.util.Arrays;

import de.lessvoid.nifty.EndNotify;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.controls.console.controller.ConsoleCommandHandler;
import de.lessvoid.nifty.controls.console.controller.ConsoleControl;
import de.lessvoid.nifty.effects.EffectEventId;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.input.NiftyInputEvent;
import de.lessvoid.nifty.input.keyboard.KeyboardInputEvent;
import de.lessvoid.nifty.input.mapping.DefaultInputMapping;
import de.lessvoid.nifty.screen.KeyInputHandler;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import org.snow.networking.ClientNetworkHandler;
import org.snow.utils.SnowUtils;

/**
 * ConsoleDemoStartScreen.
 *
 * @author void
 */
public class ConsoleHandler implements ScreenController, KeyInputHandler {
    private Nifty nifty;
     private Screen screen;
     private boolean consoleVisible = false;
     private boolean allowConsoleToggle = true;

   ArrayList<String> commands = new ArrayList<String>(Arrays.asList(

   "testnetwork"));
    public void bind(final Nifty newNifty, final Screen newScreen) {
          nifty = newNifty;
          screen = newScreen;
          screen.addKeyboardInputHandler(new GUIKeyBoardMapping(), this);
        }

        public void onStartScreen() {
        }

        public void onEndScreen() {
        }

        public void back() {
      
        }

        public boolean keyEvent(final NiftyInputEvent inputEvent) {
          if (inputEvent == NiftyInputEvent.ConsoleToggle) {
            toggleConsole();
            return true;
          } else {
            return false;
          }
        }

        private void toggleConsole() {
          if (allowConsoleToggle) {
            allowConsoleToggle = false;
            if (consoleVisible) {
              closeConsole();
            } else {
              openConsole();
            }
          }
        }

        private void openConsole() {
          Element popup = nifty.createPopup("consolePopup");

          final ConsoleControl control = popup.findControl("console", ConsoleControl.class);
          control.output("Nifty Console DemonVersion: 1.0");
          control.addCommandHandler(new ConsoleCommandHandler() {
            public void execute(final String line) {
              // just echo to the console
              control.output("your input was: " + line);
              if ("exit".equals(line.toLowerCase())) {
                back();
              }
            }
          });

          nifty.showPopup(screen, "consolePopup", null);
          consoleVisible = true;
          allowConsoleToggle = true;
        }

        private void closeConsole() {
          nifty.closePopup("consolePopup", new EndNotify() {
            @Override
            public void perform() {
              consoleVisible = false;
              allowConsoleToggle = true;
            }
          });
        }
   

   private void executeCommand(ConsoleControl control, String command) {

      if (command.contains("testnetwork")) {
         // test network connectivity

         control.output("Network is connected:"
               + ClientNetworkHandler.isConnected());
      }

   }

   private boolean checkValidCommand(String commandIn) {
      if (commands.contains(commandIn)) {
         return true;
      }

      return false;
   }

   



   
}



chat panel handler


package org.snow.GUI.controllers;

import java.util.Properties;

import org.snow.networking.SnowNetwork;
import org.snow.utils.SnowReference;
import org.snow.utils.SnowUtils;

import de.lessvoid.nifty.EndNotify;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.controls.Controller;
import de.lessvoid.nifty.controls.console.controller.ConsoleControl;
import de.lessvoid.nifty.controls.textfield.controller.TextFieldControl;
import de.lessvoid.nifty.effects.EffectEventId;
import de.lessvoid.nifty.elements.ControllerEventListener;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.elements.render.TextRenderer;
import de.lessvoid.nifty.input.NiftyInputEvent;
import de.lessvoid.nifty.screen.KeyInputHandler;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.xml.xpp3.Attributes;

/**
 * MultiplayerPanelControl.
 *
 * @author void
 */
public class ChatPanelController implements Controller, KeyInputHandler {
   private Nifty nifty;
   private Screen screen;
   private Element element;
   private TextFieldControl chatsend;
   private SnowNetwork snowClient;
   public static Element chatField;

   public void bind(final Nifty niftyParam, final Screen screenParam,
         final Element newElement, final Properties properties,
         final ControllerEventListener newListener,
         final Attributes controlDefinitionAttributes) {

      nifty = niftyParam;
      screen = screenParam;
      element = newElement;
      snowClient = SnowReference.getSnowNetwork();
      chatField = screen.findElementByName("chatfield");

      SnowReference.setChatField(chatField.getRenderer(TextRenderer.class));
      System.out.println("Setup chat field:" + chatField.getId());
   }

   public void onStartScreen() {

      chatsend = screen.findControl("chatsend", TextFieldControl.class);
      
      screen.addKeyboardInputHandler(new GUIKeyBoardMapping(), this);

   }

   public void onFocus(final boolean getFocus) {
   }

   public void inputEvent(final NiftyInputEvent inputEvent) {
      System.out.println("woah");
   }

   public void removePanel() {
      nifty.removeElement(screen, element);
   }

   @Override
   public boolean keyEvent(NiftyInputEvent arg0) {
      
      if (arg0 == NiftyInputEvent.Activate) {
         String message = chatsend.getText();
         if (message.length() >= 1000) {
            return false;
         }
         if (snowClient != null)
            snowClient.sendTextMessage(message);
         chatsend.setText("");
         return true;
      }
      System.out.println("keykey");
      return false;

   }

}



and console handler


package org.snow.GUI.controllers;

import java.util.ArrayList;
import java.util.Arrays;

import de.lessvoid.nifty.EndNotify;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.controls.console.controller.ConsoleCommandHandler;
import de.lessvoid.nifty.controls.console.controller.ConsoleControl;
import de.lessvoid.nifty.effects.EffectEventId;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.input.NiftyInputEvent;
import de.lessvoid.nifty.input.keyboard.KeyboardInputEvent;
import de.lessvoid.nifty.input.mapping.DefaultInputMapping;
import de.lessvoid.nifty.screen.KeyInputHandler;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import org.snow.networking.ClientNetworkHandler;
import org.snow.utils.SnowUtils;

/**
 * ConsoleDemoStartScreen.
 *
 * @author void
 */
public class ConsoleHandler implements ScreenController, KeyInputHandler {
    private Nifty nifty;
     private Screen screen;
     private boolean consoleVisible = false;
     private boolean allowConsoleToggle = true;

   ArrayList<String> commands = new ArrayList<String>(Arrays.asList(

   "testnetwork"));
    public void bind(final Nifty newNifty, final Screen newScreen) {
          nifty = newNifty;
          screen = newScreen;
          screen.addKeyboardInputHandler(new GUIKeyBoardMapping(), this);
        }

        public void onStartScreen() {
        }

        public void onEndScreen() {
        }

        public void back() {
      
        }

        public boolean keyEvent(final NiftyInputEvent inputEvent) {
          if (inputEvent == NiftyInputEvent.ConsoleToggle) {
            toggleConsole();
            return true;
          } else {
            return false;
          }
        }

        private void toggleConsole() {
          if (allowConsoleToggle) {
            allowConsoleToggle = false;
            if (consoleVisible) {
              closeConsole();
            } else {
              openConsole();
            }
          }
        }

        private void openConsole() {
          Element popup = nifty.createPopup("consolePopup");

          final ConsoleControl control = popup.findControl("console", ConsoleControl.class);
          control.output("Nifty Console DemonVersion: 1.0");
          control.addCommandHandler(new ConsoleCommandHandler() {
            public void execute(final String line) {
              // just echo to the console
              control.output("your input was: " + line);
              if ("exit".equals(line.toLowerCase())) {
                back();
              }
            }
          });

          nifty.showPopup(screen, "consolePopup", null);
          consoleVisible = true;
          allowConsoleToggle = true;
        }

        private void closeConsole() {
          nifty.closePopup("consolePopup", new EndNotify() {
            @Override
            public void perform() {
              consoleVisible = false;
              allowConsoleToggle = true;
            }
          });
        }
   

   private void executeCommand(ConsoleControl control, String command) {

      if (command.contains("testnetwork")) {
         // test network connectivity

         control.output("Network is connected:"
               + ClientNetworkHandler.isConnected());
      }

   }

   private boolean checkValidCommand(String commandIn) {
      if (commands.contains(commandIn)) {
         return true;
      }

      return false;
   }

   



   
}




You dont really need the other classes - you can remove anything which doesnt resolve because the GUI is the only problem area - pressing f1 doesnt work - the keyevent is not registering within consolehandler.

Ok, let's see. You've not posted your latest xml so I can only guess what's the problem.



Could it be that you're still using that in your xml:


<screen id="start" controller="de.lessvoid.nifty.examples.multiplayer.StartScreenController">



when you really want this:

<screen id="start" controller="de.lessvoid.nifty.examples.test.ConsoleHandler">

?

In that case the events actual will be sent to StartScreenController instead of the ConsoleHandler. Can you check this please?

Besides this you really should be able to remove the addKeyboardInputHandler() from the ChatPanelController! No matter what control is active all events will be sent to registered KeyboardInputhandler of the screen. It works in my ConsoleDemo in nifty-examples it really should work with your code too!

:-o Of course! I thought that was your initial problem and that's why I've suggested the popup in the first place!!! :lol:



Ok, let's sort this out then too!


  1. The Popup mechanism in Nifty will just add another layer on top of all the layers that are present on your screen. When the popup is open it blocks all events from reaching the "lower" layers. That's the whole point of the popup mechanism!


  2. You could create the console dynamically from java when you need to open it and remove the console again from the screen when you close it.



    This is how it should work:


// Create "nifty-console" dynamically from java:
CustomControlCreator createConsole = new CustomControlCreator("console", "nifty-console");
createConsole.set("lines", "20");
createConsole.set("align", "center");
createConsole.set("valign", "center");
final Element consoleElement = createConsole.create(nifty, screen, screen.findElementByName("consoleParent"));



This will add the console to the screen. Btw this will work with any controls or elements.

// Give the newly created console control the keyboard focus
consoleElement.setFocus();



If you are clever then you'll save the current focus element in a variable to restore it later when we close the console again:

// save current focus element for restore later
oldFocusElement = screen.getFocusHandler().getKeyboardFocusElement();



To remove the console later again you can execute:

// remove the console
Element console = consoleLayer.findElementByName("console");
console.markForRemoval(new EndNotify() {
  public void perform() {
    // reset the focus when we have a valid oldFocusElement
    if (oldFocusElement != null) {
      oldFocusElement.setFocus();
    }
  });



Some things to note are:

1. You'll need the current Nifty from svn because the markForRemoval is pretty new.
2. You'll need the current Nifty from svn because there was an infinite loop bug when you'd dynamically create controls that create other controls dynamically themself. The console control is one of these controls. This has been fixed now in svn tho.

I've commited another fully working example to the nifty-examples project and you can find it in svn:

http://nifty-gui.svn.sourceforge.net/viewvc/nifty-gui/nifty-examples/trunk/src/main/resources/console/console-samescreen.xml?revision=884&view=markup
http://nifty-gui.svn.sourceforge.net/viewvc/nifty-gui/nifty-examples/trunk/src/main/java/de/lessvoid/nifty/examples/console/ConsoleSameScreenStartScreen.java?revision=884&view=markup

I hope that this is finally what you need ;)


Hahah ok - so the version of jme im using has the infinite loop bug!



Does anybody know if we can update the jme3 build with the latest nifty build - or does that happen automatically?



Thanks void - thats perfect!

Hi there again,



I’ve just commited another update to the console example in svn. Instead of creating the console dynamically we can simple hide the layer XD The only thing we need to take care of is that Nifty currently does not remove hidden elements from the chain of focusable elements. So we kinda need to work around this with some additional code to do that manual. The example in svn will do that now.



You can find it in svn as well as browse it online here:



http://nifty-gui.svn.sourceforge.net/viewvc/nifty-gui/nifty-examples/trunk/src/main/resources/console/console-samescreen.xml?revision=885&view=markup



http://nifty-gui.svn.sourceforge.net/viewvc/nifty-gui/nifty-examples/trunk/src/main/java/de/lessvoid/nifty/examples/console/ConsoleSameScreenStartScreen.java?revision=886&view=markup

now THAT has done the trick!



Sweet.



Thanks so much!