Nifty custom spinner control

Hi I needed a spinner control and unfortunately nifty doesn’t have one so I started coding my own but I’ve run into an issue I’m having trouble resolving
My custom control is the following <controlDefinition name=“spinnerselector” controller=“Utils.NiftySpinnerSelector”>
<panel childLayout=“horizontal” backgroundColor="#8001" width=“171” height=“52”>
<control id=“spinnerField” name=“textfield” style=“nifty-textfield” height=“23px” text="${CALL.getInitialValue()}" width=“50px”/>
<panel childLayout=“vertical” width=“165” paddingTop=“6px” paddingBottom=“6px”>
<control childLayout=“horizontal” id=“spinnerUpButton” backgroundImage=“Interface/slider-arrow-up.png” width=“20px” height=“25px” paddingLeft=“2px” name=“button”>
<interact onClick=“SpinnerButtonUp()”/>
</control>
<control childLayout=“horizontal” id=“spinnerDownButton” backgroundImage=“Interface/slider-arrow-down.png” width=“20px” height=“25px” paddingLeft=“2px” name=“button”>
<interact onClick=“SpinnerButtonDown()”/>
</control>
</panel>
</panel>
</controlDefinition>

I am using this like so
<panel childLayout=“horizontal” width=“100%”>
<control name=“spinnerselector” id=“strength” maximum=“9” minimum=“2” value=“6”/>
</panel>

My custom java code is

package Utils;

import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.controls.Button;
import de.lessvoid.nifty.controls.Controller;
import de.lessvoid.nifty.controls.TextField;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.input.NiftyInputEvent;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.xml.xpp3.Attributes;
import java.util.Properties;

public class NiftySpinnerSelector implements Controller
{
int value = 0;
int minimum = 0;
int maximum = 0;
Button buttonUp = null;
Button buttonDown = null;
TextField field = null;

public void onStartScreen() {
}

public void onFocus(final boolean getFocus) {
}

public boolean inputEvent(final NiftyInputEvent inputEvent) {
System.out.println(“Spinner input event”);
return false;
}
public void init(Properties parameter, Attributes controlDefinitionAttributes) {
//throw new UnsupportedOperationException(“Not supported yet.”);
// System.out.println(“testing max value=”+controlDefinitionAttributes.get(“maxvalue”));
}
public void bind(Nifty nifty, Screen screen, Element element, Properties parameter, Attributes controlDefinitionAttributes) {
buttonUp = screen.findNiftyControl(“spinnerUpButton”, Button.class);
buttonDown = screen.findNiftyControl(“spinnerDownButton”, Button.class);
field = screen.findNiftyControl(“spinnerField”, TextField.class);
value = Integer.parseInt(parameter.get(“value”).toString());
minimum = Integer.parseInt(parameter.get(“minimum”).toString());
maximum = Integer.parseInt(parameter.get(“maximum”).toString());

}    
public void SpinnerButtonUp()
{        
    //String username = loginElement.getControl(TextFieldControl.class).getText();
    SetValue(value + 1);
    field.setText(GetStrValue());
}
public void SpinnerButtonDown()
{
    SetValue(value - 1);
    field.setText(GetStrValue());
}
public void SetValue(int nvalue)
{
    if(nvalue &gt;= minimum &amp;&amp; nvalue &lt;= maximum) 
    {
        value = nvalue;
    }
}
public int GetValue()
{
    return value;
}    
public String GetStrValue()
{
    return Integer.toString(value);
}
public String getInitialValue()
{
    return GetStrValue();
}

}

When I have the code being used it gets through the bind step successfully. It finds all the controls it seems happy and I get an exception divide by zero error

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.ArithmeticException: / by zero
at de.lessvoid.nifty.render.image.areaprovider.SpriteAreaProvider.getSourceArea(SpriteAreaProvider.java:49)
at de.lessvoid.nifty.render.image.areaprovider.CachedAreaProvider.getSourceArea(CachedAreaProvider.java:28)
at de.lessvoid.nifty.render.image.CompoundImageMode.render(CompoundImageMode.java:28)
at de.lessvoid.nifty.render.NiftyImage.render(NiftyImage.java:53)
at de.lessvoid.nifty.render.NiftyRenderEngineImpl.renderImage(NiftyRenderEngineImpl.java:244)
at de.lessvoid.nifty.elements.render.ImageRenderer.render(ImageRenderer.java:30)
at de.lessvoid.nifty.elements.Element.renderElement(Element.java:627)
at de.lessvoid.nifty.elements.Element.render(Element.java:612)
at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)
at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)
at de.lessvoid.nifty.elements.Element.render(Element.java:606)
at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)
at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)
at de.lessvoid.nifty.elements.Element.render(Element.java:606)
at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)
at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)
at de.lessvoid.nifty.elements.Element.render(Element.java:606)
at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)
at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)
at de.lessvoid.nifty.elements.Element.render(Element.java:606)
at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)
at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)
at de.lessvoid.nifty.elements.Element.render(Element.java:606)
at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)
at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)
at de.lessvoid.nifty.elements.Element.render(Element.java:606)
at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)
at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)
at de.lessvoid.nifty.elements.Element.render(Element.java:606)
at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)
at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)
at de.lessvoid.nifty.elements.Element.render(Element.java:606)
at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)
at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)
at de.lessvoid.nifty.elements.Element.render(Element.java:615)
at de.lessvoid.nifty.screen.Screen.renderLayers(Screen.java:313)
at de.lessvoid.nifty.Nifty.render(Nifty.java:280)
at com.jme3.niftygui.NiftyJmeDisplay.postQueue(NiftyJmeDisplay.java:176)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:981)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1037)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:251)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:722)

Thanks for any help :slight_smile:

Your second panel is missing a height, I guess that would initialize it to 0 pixels high, which might explain the divide by zero inside an “area provider”.

<panel childLayout=“vertical” width=“165” paddingTop=“6px” paddingBottom=“6px”>

I doubt nifty will be able to use a “vertical” childLayout without knowing having a height for the element.

Hi Nihal,

Thanks for responding
I have tried your fix but I’m still getting the same error if I try to see the component in the nifty renderer in jMonkey it has 2 errors a null pointer exception and a divide by 0 exception

I thought that for a vertical component you had to define a width but since its laying components vertically the size is the conglomerate of all its child components

Anyway I did set all the fields and no luck unfortunately

<controlDefinition name=“spinnerselector” controller=“Utils.NiftySpinnerSelector”>
<panel childLayout=“horizontal” backgroundColor="#8001" width=“70px” height=“32px” paddingTop=“6px” paddingBottom=“6px”>
<control id=“spinnerField” name=“textfield” style=“nifty-textfield” width=“50px” height=“23px” text="${CALL.getInitialValue()}"/>
<panel childLayout=“vertical” width=“21px” height=“30px”>
<control childLayout=“horizontal” id=“spinnerUpButton” backgroundImage=“Interface/slider-arrow-up.png” width=“15px” height=“15px” paddingLeft=“2px” name=“button”>
<interact onClick=“SpinnerButtonUp()”/>
</control>
<control childLayout=“horizontal” id=“spinnerDownButton” backgroundImage=“Interface/slider-arrow-down.png” width=“15px” height=“15px” paddingLeft=“2px” name=“button”>
<interact onClick=“SpinnerButtonDown()”/>
</control>
</panel>
</panel>
</controlDefinition>

Any other issues you can see? thanks

Ok I haven’t fixed this but I have found the issue for some reason it dislikes my images and is crashing in this weird way instead of giving an image exception
When i change the images to a different one in the same directory it loads fine when i don’t use a background image it loads fine

Also the majority of the width or heights arent needed

Im currently working with this example
<controlDefinition name=“spinnerselector” controller=“Utils.NiftySpinnerSelector”>
<panel childLayout=“horizontal” backgroundColor="#8001" height=“32px” paddingTop=“6px” paddingBottom=“6px”>
<control id=“spinnerField” name=“textfield” style=“nifty-textfield” width=“50px” height=“26px” paddingRight=“3px”/>
<panel childLayout=“vertical”>
<control id=“spinnerUpButton” width=“20px” height=“13px” name=“button”>
<image filename=“Interface/slider-arrow-up.png” />
<interact onClick=“SpinnerButtonUp()”/>
</control>
<control id=“spinnerDownButton” width=“20px” height=“13px” name=“button”>
<image filename=“Interface/slider-arrow-down.png” />
<interact onClick=“SpinnerButtonDown()”/>
</control>
</panel>
</panel>
</controlDefinition>

The image tags arent working but it doesnt crash either.

The control is loading properly and does work I’ll post the final code here when its working perhaps someone can benefit from working sliders :slight_smile:

Cheers Nihal :slight_smile: