[Nifty] Editing effect dynamically --Solved

Hi,



I’m trying to create my own checkbox control. ( So that I can change it’s appeareance dynamically )



For that, I’ve created a class :

[java]

public class CustomCheckboxControl extends CheckboxControl

{

private Nifty customNifty;

private Screen customScreen;

private Element customElem;

private Element imageElt;



public void bind(

final Nifty niftyParam,

final Screen screenParam,

final Element elementParam,

final Properties propertiesParam,

final ControllerEventListener listenerParam,

final Attributes controlDefinitionAttributes) {

super.bind( niftyParam, screenParam, elementParam, propertiesParam, listenerParam, controlDefinitionAttributes);

customNifty = niftyParam;

customScreen = screenParam;

customElem = elementParam;

imageElt = customElem.findElementByName(“select”);

}

[…]

[/java]



I wanted to add a method like :

[java]

public void setSelectionImage( String img )

{

EffectManager effectManager = imageElt.getEffectManager();

/* Doesn’t work like that

Effect effect = effectManager.getEffect( “imageOverlay” );

effect.setFileName( img );

*/

}

[/java]

But I don’t know how to access to the current effects of an element



I tried to do it via the ControlEffectAttributes class, but I can’t retrieve a Effect element ( only a EffectType element )

[java]

ControlEffectAttributes effectParam = new ControlEffectAttributes();

effectParam.setName(“imageOverlay”);

effectParam.setAttribute( “filename”, “checkbox/checkbox.png” );

effectParam.setAttribute( “width”, “20px” );

effectParam.setAttribute( “height”, “20px” );

effectParam.setAttribute( “inset”, “-7” );

//Effect effect = effectParam.create();

[/java]

Or using directly the class imageOverlay

[java]

ImageOverlay overlayEffect = new ImageOverlay();

[/java]



But I’m stuck :frowning:



Can someone give me a tip ? :smiley:



Edit :

Second try !



It seems I’ve understood how to instanciate an effect :

[java]

public void setSelectionImage( String img )

{

EffectManager effectManager = imageElt.getEffectManager();



boolean needToRelaunch = false;

if( effectManager.isActive( EffectEventId.onActive ) )

{

effectManager.stopEffect( EffectEventId.onActive );

needToRelaunch = true;

}

effectManager.resetSingleEffect( EffectEventId.onActive );

//effectManager.removeAllEffects();





// On custom overlay Effect

ImageOverlay overlayEffect = new ImageOverlay();

Properties properties = new Properties();

properties.put( “name” , “imageOverlay” );

properties.put( “filename” , img );

properties.put( “width” , “26px” );

properties.put( “height” , “27px” );

overlayEffect.activate( customNifty, imageElt, new EffectProperties(properties) );

Effect effect = new Effect( customNifty, false, false, false, “”, “”, “”, true, EffectEventId.onActive );

effect.init( imageElt, overlayEffect, new EffectProperties(new Properties()), new TimeProvider(), new LinkedList<Object>() );





effectManager.registerEffect( EffectEventId.onActive, effect );

if( needToRelaunch )

imageElt.startEffect( EffectEventId.onActive );

}

[/java]



But it seems I have not totally understood how it works, the display doesn’t change xD



( What I want to change is the line :

[java]

<onActive name=“imageOverlay” filename=“grey-style/checkbox/grey-checkmark.png” width=“26px” height=“27px” />

[/java]

)

Uhm, now I understand but I don’t think it’s possible to change effects that are already applied to an element :confused: Well, it would be possible but there are two issues:


  • There is no public way to access the effect class. I’ve just checked it and you only have access to the EffectManager but not to the underlying EffectProcessor that holds all the effects.
  • Even if you would have access to the Effect and especially the concrete EffectImpl there is still no way to change the parameters because the EffectImpls do not expose the parameters.



    It shouldn’t be to hard to add this and especially allow access to the effect parameters so that you can modify them but this is not available right now. I’ve added a feature request for this but I’m not sure of this will be a part of Nifty 1.3 :confused:



    There might be a workaround possible if you know the images you want to change before. Actually there are two ways :slight_smile:


  1. You can set the alternateEnable attribute of the effect and trigger to use the effect only when the alternateKey you can set at Screen level matches. Something like that:



    [xml]<onActive name="imageOverlay" filename="grey-style/checkbox/grey-checkmark-1.png" width="26px" height="27px" alternateEnable="showImage1" />

    <onActive name="imageOverlay" filename="grey-style/checkbox/grey-checkmark-2.png" width="26px" height="27px" alternateEnable="showImage2" />[/xml]



    And change the alternateKey for all screens to toggle between the images:



    [java]// show image 1

    nifty.setAlternateKey("showImage1");



    // show image 2

    nifty.setAlternateKey("showImage2")[/java]



    The drawback is, that this is a global parameter for the whole screen and might not suite your needs at all :smiley:


  2. Use a custom effect and switch between the images with a customKey



    [xml]<onCustom customKey=“show1” name=“imageOverlay” filename=“grey-style/checkbox/grey-checkmark-1.png” width=“26px” height=“27px” />

    <onCustom customKey=“show2” name=“imageOverlay” filename=“grey-style/checkbox/grey-checkmark-2.png” width=“26px” height=“27px” />[/xml]



    You’ll need to start the effect from Java and select which one of the effects should start with the customKey:



    [java]// show image 1

    element.startEffect(EffectEventId.onCustom, null, “show1”);



    // show image 2

    element.startEffect(EffectEventId.onCustom, null, “show2”);[/java]



    Stopping the effect works the same. The 1.3 checkbox is actually using this onCustom effect to show/hide the checkmark.
1 Like

I tink I will go to solution 2. :slight_smile:



But something is bugging me :



Half the time, the nifty system cancel my effect saying :


Dec 31, 2010 4:59:16 PM de.lessvoid.nifty.effects.EffectProcessor startEffect
INFO: starting effect [(Fade)] canceled because customKey [iconAxe_show] does not match key set at the effect
Dec 31, 2010 4:59:16 PM de.lessvoid.nifty.effects.EffectProcessor startEffect
INFO: starting effect [(ImageOverlay)] canceled because customKey [iconAxe_show] does not match key set at the effect
Dec 31, 2010 4:59:16 PM de.lessvoid.nifty.effects.EffectProcessor startEffect
INFO: starting effect [(ImageSize)] canceled because customKey [iconAxe_show] does not match key set at the effect
Dec 31, 2010 4:59:16 PM de.lessvoid.nifty.effects.EffectProcessor startEffect
INFO: starting effect [(Fade)] canceled because customKey [iconAxe_show] does not match key set at the effect
Dec 31, 2010 4:59:16 PM de.lessvoid.nifty.effects.EffectProcessor startEffect
INFO: starting effect [(ImageOverlay)] canceled because customKey [iconAxe_show] does not match key set at the effect


I can't understand what that means. We need to define a keyset for each effect?

My xml is like that :
[java]
<style id="ae-checkbox-style#select">
<effect overlay="true">
<onCustom customKey="iconAxe_hide" name="fade" start="#f" end="#0" length="250" neverStopRendering="true" />
<onCustom customKey="iconAxe_hide" name="imageOverlay" filename="iconAxe_hover.png" post="true" imageMode="normal" width="40px" height="40px" neverStopRendering="true"/>
<onCustom customKey="iconAxe_show" name="imageSize" startSize="2.0" endSize="1.0" length="250" />
<onCustom customKey="iconAxe_show" name="fade" start="#0" end="#f" length="250" />
<onCustom customKey="iconAxe_show" name="imageOverlay" filename="iconAxe_hover.png" post="true" imageMode="normal" width="40px" height="40px" neverStopRendering="true"/>


<onCustom customKey="iconBook_hide" name="fade" start="#f" end="#0" length="250" neverStopRendering="true" />
<onCustom customKey="iconBook_hide" name="imageOverlay" filename="iconBook_hover.png" post="true" imageMode="normal" width="40px" height="40px" neverStopRendering="true"/>
<onCustom customKey="iconBook_show" name="imageSize" startSize="2.0" endSize="1.0" length="250" />
<onCustom customKey="iconBook_show" name="fade" start="#0" end="#f" length="250" />
<onCustom customKey="iconBook_show" name="imageOverlay" filename="iconBook_hover.png" post="true" imageMode="normal" width="40px" height="40px" neverStopRendering="true"/>
</effect>
</style>
[/java]

And my calling method is :
[java]
private void updateView( )
{
if( effectName.equals( lastActiveEffectName ) && checked == lastChecked )
return;
lastActiveEffectName = effectName;
lastChecked = checked;

String realEffectName = effectName + "_";
if( checked )
realEffectName += "show";
else
realEffectName += "hide";

if( imageElt.isEffectActive( EffectEventId.onCustom ) )
imageElt.stopEffect( EffectEventId.onCustom );

imageElt.startEffect( EffectEventId.onCustom, null, realEffectName );
}
[/java]

Thanks in advance :D

Edit :

It seems that
[java]
if( imageElt.isEffectActive( EffectEventId.onCustom ) )
imageElt.stopEffect( EffectEventId.onCustom );
[/java]
is not enough.
I've replaed it by
[java]
imageElt.getEffectManager().resetAll();
[/java]
And it works :)

I’ve managed to get a pretty nifty gui :slight_smile:



One last question on that topic :



For now I create my buttons like this :

[java]

<control id=“panel_0” type=“ae-checkbox” >

<interact onClick=“togglePanel(0)” />

</control>

[/java]

And i set which effect I want inside java :

[java]

CustomCheckboxControl control = screen.findControl( “panel_0”, CustomCheckboxControl.class );

control.setEffect( “iconMap”, false );

[/java]

( setEffect is a custom method from my control )



On some of my gui, I wish to have a default effect on the button without having to set it via code.

How can we add custom attribute to a control ?



What is wish is something like that :

[java]

<control id=“panel_0” type=“ae-checkbox” firstEffect=“iconMenu” >

<interact onClick=“togglePanel(0)” />

</control>

[/java]

And inside my controller

[java]

@Override

public void onStartScreen()

{

String firstEffect = elem.get(…);

setEffect( firstEffect );

}

[/java]



Thanks in advance :slight_smile:

uhm, and where is the problem? :slight_smile:



you can have custom attributes on the control. they are available in your control controller bind() method as the “Properties parameter” parameter.



[java]/**

  • Controller.
  • @author void

    */

    public interface Controller {



    /**
  • Bind this Controller to a certain element.
  • @param nifty nifty
  • @param element the Element
  • @param parameter parameters from the xml source to init the controller *** <-- THAT’S THE PARAMETER ***
  • @param listener the ControllerEventListener

    */

    void bind(

    Nifty nifty,

    Screen screen,

    Element element,

    Properties parameter,

    ControllerEventListener listener,

    Attributes controlDefinitionAttributes);



    [/java]

Haha, silly me.



I checked how to access to properties inside the Element instance, but didn’t checked the other parameters…

Well, it was 5 AM so I have an excuse :smiley:



That solves the matter ! Thanks for your answers!