[Nifty] Issues with ”ChatArea Example”

Hello all,



Im having a few issues with the “ChatArea Example” seen here. I attempted to modify it and use with NiftyGUI 1.2 since it is the current stable release compatible with JMonkey, but I believe the example is written for Nifty 1.3.


  1. The ScrollPanel doesnt seem to have any relation to the TextArea. When I add more lines to the TextArea, it doesnt automatically scroll and clicking the ScrollBar does nothing. I can print out the contents of the TextArea to System.out and they are growing correctly.


  2. Entering any text with whitespace such as spacebar ’ ’ completely breaks the GUI and hangs my application. It isnt getting past screen.layoutLayers(); in ChatAreaController.java.



    Any thoughts? If there is good documentation somewhere that would help me out with this I havent found it :slight_smile:



    Thanks!

What do you mean? The ChatController is the second code sample in there.



But I’ve been talking to Void and I’ll be porting the chat area control to Nifty 1.3. At the same time I’ll be making it universal, so all the code specific to my project willbe moved to a listener.



This means the code as you see it here will most likely not be updated with any fixes, but I will be availlable for questions.

ChatTest.xml:



[java]<?xml version="1.0" encoding="UTF-8"?>

<nifty>



<!-- +++++++++++++++++++++++++++++++++++++++ -->

<!-- load default styles and controls -->

<!-- +++++++++++++++++++++++++++++++++++++++ -->

<useStyles filename="nifty-default-styles.xml" />

<useControls filename="nifty-default-controls.xml" />



<!-- Control definition of chat area -->

<controlDefinition name="chatArea" controller="niftyguitest.ChatAreaController">

<panel childLayout="center" width="$width" heigh="$height">

<control name="scrollPanel" id="scroll_panel" width="100%" height="100%" horizontal="$horizontal" vertical="$vertical" autoScroll="$autoScroll">

<label text="$text" id="text_area" width="100%" height="100%"

wrap="true" textHAlign="left" textVAlign="top" align="left" />

</control>

</panel>

</controlDefinition>



<!-- +++++++++++++++++++++++++++++++++++++++ -->

<!-- start screen -->

<!-- +++++++++++++++++++++++++++++++++++++++ -->

<screen id="start"

controller="niftyguitest.ChatController">

<layer id="layer" childLayout="center">

<panel id="dialog" style="nifty-panel" childLayout="center"

width="70%" height="90%" align="center" valign="center"

visibleToMouse="true">

<panel childLayout="vertical" align="center" valign="center">

<!-- Chat area = label surrounded by scroll panel -->

<control name="chatArea" id="chat_area" width="90%" height="30%" horizontal="false" autoScroll="bottom" text="tesct" />

<panel height="30px" />

<!-- Text input -->

<panel childLayout="horizontal">

<control name="textfield" id="text_input" width="70%" />

<control name="button" label="Send">

<interact onClick="sendMessage()" />

</control>

</panel>

</panel>

</panel>

</layer>

</screen>

</nifty>[/java]



ChatController.java:



[java]



package niftyguitest;





import de.lessvoid.nifty.Nifty;

import de.lessvoid.nifty.controls.textfield.controller.TextFieldControl;

import de.lessvoid.nifty.elements.Element;

import de.lessvoid.nifty.input.NiftyInputEvent;

import de.lessvoid.nifty.screen.KeyInputHandler;

import de.lessvoid.nifty.screen.Screen;

import de.lessvoid.nifty.screen.ScreenController;



public class ChatController implements ScreenController {

private Element textInput;

private ChatAreaController chatArea;



@Override

public void bind(Nifty nifty, Screen screen) {

textInput = screen.findElementByName("text_input");

chatArea = screen.findControl("chat_area", ChatAreaController.class);

}



@Override

public void onStartScreen() {

textInput.addInputHandler(new KeyInputHandler() {

@Override

public boolean keyEvent(NiftyInputEvent inputEvent) {

if(inputEvent == null) return false;

switch(inputEvent) {

case SubmitText:

sendMessage();

return true;

}

return false;

}

});

textInput.setFocus();

}



@Override

public void onEndScreen() {

// TODO Auto-generated method stub



}



/**

  • Sends a message to the chat area

    */

    public void sendMessage() {

    if(chatArea.getText().isEmpty()) {

    chatArea.append(textInput.getControl(TextFieldControl.class).getText());

    }

    else {

    chatArea.append("ny"+textInput.getControl(TextFieldControl.class).getText());

    }

    textInput.getControl(TextFieldControl.class).setText("");

    textInput.setFocus();

    }

    }[/java]



    ChatAreaController.java:



    [java]package niftyguitest;

    import java.util.Properties;



    import de.lessvoid.nifty.Nifty;

    import de.lessvoid.nifty.controls.Controller;

    import de.lessvoid.nifty.controls.scrollpanel.ScrollPanel;

    //import de.lessvoid.nifty.controls.scrollpanel.ScrollPanel.AutoScroll;

    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.Screen;

    import de.lessvoid.xml.xpp3.Attributes;



    public class ChatAreaController implements Controller {

    private ScrollPanel scrollPanel;

    private Element textArea;

    private Screen screen;



    @Override

    public void bind(Nifty nifty,

    Screen screen,

    Element element,

    Properties parameter,

    ControllerEventListener listener,

    Attributes controlDefinitionAttributes) {

    this.screen = screen;

    scrollPanel = element.findControl("scroll_panel", ScrollPanel.class);

    textArea = element.findElementByName("text_area");

    }



    @Override

    public void onStartScreen() {

    }



    @Override

    public void onFocus(boolean getFocus) {

    }



    @Override

    public boolean inputEvent(NiftyInputEvent inputEvent) {

    return false;

    }



    /public void setAutoScroll(AutoScroll auto) {

    scrollPanel.setAutoScroll(auto);

    }



    public AutoScroll getAutoScroll() {

    return scrollPanel.getAutoScroll();

    }
    /



    public void append(String text) {

    setText(getText()+text);

    }



    public void setText(String text) {

    textArea.getRenderer(TextRenderer.class).setText(text);

    screen.layoutLayers();

    //textArea.setHeight(textArea.getRenderer(TextRenderer.class).getTextHeight());

    }



    public String getText() {

    return textArea.getRenderer(TextRenderer.class).getOriginalText();

    }

    }

    [/java]



    ChatTest.java:



    [java]package niftyguitest;



    import org.lwjgl.input.Mouse;



    import com.jme3.app.SimpleApplication;

    import com.jme3.niftygui.NiftyJmeDisplay;

    import de.lessvoid.nifty.Nifty;





    /**
  • A chat test with Nifty and JME2
  • @author Joakim Lindskog

    *

    */

    public class ChatTest extends SimpleApplication {

    private Nifty nifty;



    public static void main(final String[] args) throws Exception {

    ChatTest app = new ChatTest();

    app.start();

    }



    @Override

    public void simpleInitApp() {



    // Allow mouse to leave the game window (very useful on debugging :slight_smile:

    Mouse.setGrabbed(false);



    NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager,

    inputManager, audioRenderer, guiViewPort);

    nifty = niftyDisplay.getNifty();

    nifty.fromXml("niftyguitest/chatTest.xml", "start");



    // attach the nifty display to the gui view port as a processor

    guiViewPort.addProcessor(niftyDisplay);



    }

    }

    [/java]

With regards to 1:

Yes this has been changed after release 1.2. If you use the current SVN version for nifty, you’ll see the problem no longer exists.



With regards to 2:

Personally, I don’t have this problem. But I’m using a slightly different chat setup, which may be the reason why. I don’t have access to my sources atm. since I’m at work, but if you want I would be happy to send you my chat control once I get home. It is setup as a nifty xcml file with the chat control and a java class with the controller. You should be able to incorporate these without too much trouble.



Mark

Thanks for the response Mark.



When you say the current SVN version of Nifty, are you referring to getting the latest version of 1.2 using Maven as described here? Or some recent version of 1.3?



Letting me view your chat sources would be greatly appreciated! Thanks in advance.

yeah, that’s the nifty version I mean. current version from svn.



And here, as promised, my chat control:

[java]

<?xml version=“1.0” encoding=“UTF-8”?>

<nifty-controls xmlns=“http://nifty-gui.sourceforge.net/nifty.xsd

xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance

xsi:schemaLocation=“http://nifty-gui.sourceforge.net/nifty.xsd http://nifty-gui.sourceforge.net/nifty-controls.xsd”>



<controlDefinition name=“chat-control” style=“nifty-panel”

controller=“com.ractoc.opengamefinder.client.screens.controllers.chat.ChatController”>

<panel childLayout=“vertical” style=“nifty-panel” width=“95%”

height=“100%” align=“center”>

<panel childLayout=“horizontal” width=“100%” height="">

<control name=“scrollPanel” width=“100%” height=“100%”

horizontal=“false” vertical=“true” autoScroll=“bottom”>

<panel id=“chat-panel” childLayout=“vertical” width=“100%”>

<control name=“chat-line-control” text=“test text” />

</panel>

</control>

</panel>

<panel childLayout=“horizontal” align=“left” width=“100%”

id=“chat-text-line”>

<control id=“chat-text-input” name=“textfield” width=“85%”

height=“25px” />

<control id=“chat-text-button” name=“button” label=“send”

width=“15%” height=“25px”>

<interact onClick=“sendText()” />

</control>

</panel>

</panel>

</controlDefinition>



<controlDefinition name=“chat-line-control”

controller=“com.ractoc.opengamefinder.client.screens.controllers.chat.ChatLineController”>

<panel childLayout=“horizontal” width=“95%” align=“center”>

<image id=“chat-line-icon” width=“25px” height=“25px” />

<label id=“chat-line-text” align=“left” textHAlign=“left”

height=“25px” width="
" text="$text" wrap=“true” />

</panel>

</controlDefinition>



</nifty-controls>

[/java]



and the controller that goes with it:

[java]

package com.ractoc.opengamefinder.client.screens.controllers.chat;



import java.util.Properties;



import org.apache.commons.lang.StringUtils;

import org.apache.log4j.Logger;



import com.ractoc.opengamefinder.api.plugins.messages.ChatLineMessage;

import com.ractoc.opengamefinder.client.plugins.results.DisplayScreenMessageResult;

import com.ractoc.pffj.core.PluginController;

import com.ractoc.pffj.core.PluginException;



import de.lessvoid.nifty.Nifty;

import de.lessvoid.nifty.controls.Controller;

import de.lessvoid.nifty.controls.dynamic.CustomControlCreator;

import de.lessvoid.nifty.controls.textfield.controller.TextFieldControl;

import de.lessvoid.nifty.elements.ControllerEventListener;

import de.lessvoid.nifty.elements.Element;

import de.lessvoid.nifty.elements.render.ImageRenderer;

import de.lessvoid.nifty.elements.render.TextRenderer;

import de.lessvoid.nifty.input.NiftyInputEvent;

import de.lessvoid.nifty.layout.manager.VerticalLayout;

import de.lessvoid.nifty.render.NiftyImage;

import de.lessvoid.nifty.screen.KeyInputHandler;

import de.lessvoid.nifty.screen.Screen;

import de.lessvoid.xml.xpp3.Attributes;



public class ChatController implements Controller, KeyInputHandler {



private static Logger logger = Logger.getLogger(ChatController.class.getName());



private Nifty nifty;

private Screen screen;

private Element element;



private TextFieldControl textControl;

private int chatLineCounter;



@Override

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;

textControl = this.element.findElementByName(“chat-text-input”).getControl(TextFieldControl.class);

this.element.findElementByName(“chat-text-input”).addInputHandler(this);

}



@Override

public boolean inputEvent(final NiftyInputEvent inputEvent) {

return false;

}



@Override

public void onFocus(boolean arg0) {

// TODO Auto-generated method stub



}



@Override

public void onStartScreen() {

// TODO Auto-generated method stub



}



public void receivedText(String text, NiftyImage icon) {

chatLineCounter++;

logger.debug(“adding message " + chatLineCounter + " to screen”);

CustomControlCreator createChatLine = new CustomControlCreator(“chat-line-” + chatLineCounter,

“chat-line-control”);

createChatLine.create(nifty, screen, element.findElementByName(“chat-panel”));

Element el = element.findElementByName(“chat-line-” + chatLineCounter);

el.findElementByName(“chat-line-text”).getRenderer(TextRenderer.class).setText(text);

el.findElementByName(“chat-line-icon”).getRenderer(ImageRenderer.class).setImage(icon);



// el.findElementByName(“chat-line-text”).getRenderer(TextRenderer.class).setWidthConstraint(

// el.findElementByName(“chat-line-text”),

// new SizeValue(el.getWidth() - el.findElementByName(“chat-line-icon”).getWidth() + “px”), el.getWidth(),

// nifty.getRenderEngine());



element.getParent().setLayoutManager(new VerticalLayout());

element.getParent().layoutElements();

}



public void sendText() {

String text = textControl.getText();

if (!StringUtils.isEmpty(text)) {

System.out.println(text);

textControl.setText("");

ChatLineMessage clMsg = new ChatLineMessage();

clMsg.setOutBound(true);

clMsg.setLine(text);

try {

DisplayScreenMessageResult result = (DisplayScreenMessageResult) PluginController.getCurrentPluginController().processMessage(“chatPlugin”, clMsg);

logger.debug("message result = " + result.getErrorCode());

} catch (PluginException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

// receivedText(text, null);

}

}



public boolean keyEvent(NiftyInputEvent inputEvent) {

if (inputEvent == NiftyInputEvent.SubmitText) {

sendText();

return true;

}

return false;

}

}

[/java]



The method sendText is used to actually send the message to the server. When a message is received from the server, the method receivedTest is used.



Every chat line consists of two parts, and icon and the text itself. The icon can be used as an avatar.



Some parts of the control are specific for my application, these parts are located entirely in the sendText method though, so should be easily replaced. To make the controller fully universal, the sendText method should use a listener to forward the text to an application specific class. This is something I might be looking into later.

1 Like

Thanks! Ill take a look asap

Before dissecting your code example, I updated to latest Nifty version 1.2 found here to test my ChatArea example:



Index of /nifty-maven-repo/lessvoid/nifty/1.2 nifty-1.2.jar



This still gave me the same issue as before, where the scroll bar seems to do nothing. Am I using the wrong jar? Is this path not the latest 1.2 version?



Thanks!

Also is there a reason you left out ChatController?

Ack, my fault. I meant ChatLineController, but it may not be necessary.



Thanks for the help, Its still not working for me but Im probably just going to look at a solution other than scrolling chat area for now until 1.3 Nifty is supported.



Cheers

No, you’re right, that one should have been in there as well, sorry about that.



Well, here it is then:

[java]

package com.ractoc.opengamefinder.client.screens.controllers.chat;



import java.util.Properties;



import de.lessvoid.nifty.Nifty;

import de.lessvoid.nifty.controls.Controller;

import de.lessvoid.nifty.elements.ControllerEventListener;

import de.lessvoid.nifty.elements.Element;

import de.lessvoid.nifty.input.NiftyInputEvent;

import de.lessvoid.nifty.render.NiftyImage;

import de.lessvoid.nifty.screen.Screen;

import de.lessvoid.xml.xpp3.Attributes;



public class ChatLineController implements Controller {



// private Nifty nifty;

// private Screen screen;

// private Element element;



private String text;

private String name;

private NiftyImage icon;



@Override

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;

}



@Override

public boolean inputEvent(NiftyInputEvent arg0) {

// TODO Auto-generated method stub

return false;

}



@Override

public void onFocus(boolean arg0) {

// TODO Auto-generated method stub



}



@Override

public void onStartScreen() {

// TODO Auto-generated method stub



}



public final String getText() {

return text;

}



public final void setText(String text) {

this.text = text;

}



public final String getName() {

return name;

}



public final void setName(String name) {

this.name = name;

}



public final NiftyImage getIcon() {

return icon;

}



public final void setIcon(NiftyImage icon) {

this.icon = icon;

}

}



[/java]



That should be it.



Mark

Im still getting issue #2 from my original post. I have pretty much the same code as above except I added two debug output statements in ChatAreaController:



[java]public void setText(String text) {

textArea.getRenderer(TextRenderer.class).setText(text);

System.out.println(“Debug line 1”);

screen.layoutLayers();

System.out.println(“Debug line 2”);

//textArea.setHeight(textArea.getRenderer(TextRenderer.class).getTextHeight());

}[/java]



If I enter in “Hello”, it updates fine.



If i enter in “Hello there” (note the space) and hit enter, the screen completely freezes with no exception being thrown.



In the above code, “Debug line 1” is being printed, but not “Debug line 2”, so its freezing sometime in screen.layoutLayers();. Ive tried this from building from source the latest 1.2 and 1.3 versions.



I feel like this has to be a bug but Im not getting any exception or output to work with. Any thoughts or similar experiences from anyone?

Well, there is a difference in that I’m using a label to display the text and you’re using a textarea. So this might be a problem with textarea for some reason. Since I haven’t used textare yet I can’t tell for sure.



What happens if you put a text intot the chat area from the xml?

Thats interesting. Changing this section of the code doesnt break it immediately like i would expect, “hello there” appears and it doesnt crash:



[java]<control name=“scrollPanel” id=“scroll_panel” width=“100%” height=“100%” horizontal="$horizontal" vertical="$vertical" autoScroll="$autoScroll">

<label text=“hello there” id=“text_area” width=“100%” height=“100%”

wrap=“true” textHAlign=“left” textVAlign=“top” align=“left” />

</control>[/java]