package com.github.czyzby.lml.parser.impl.annotation.processor; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.utils.GdxRuntimeException; import com.badlogic.gdx.utils.reflect.Field; import com.badlogic.gdx.utils.reflect.ReflectionException; import com.github.czyzby.kiwi.util.gdx.reflection.Reflection; import com.github.czyzby.lml.annotation.processor.OnChangeProcessor; /** Abstract base for on change field processors. Attaches a custom {@link ChangeListener} to an actor in order to * update the field. * * @author MJ */ public abstract class AbstractOnChangeProcessor<Widget> implements OnChangeProcessor { @Override public void process(final Field field, final Object owner, final Object actor) { ((Actor) actor).addListener(new OnChangeListener<Widget>(this, owner, field)); } /** @param actor has a change listener attached. Performs unchecked cast of the actor for extra utility, so * {@link OnChangeProcessor#canProcess(Field, Object)} should be properly implemented to avoid class cast * exceptions. * @return value extracted from the actor. Will be set as the annotated field's value. */ protected abstract Object extractValueFromActor(Widget actor); private static class OnChangeListener<Widget> extends ChangeListener { private final AbstractOnChangeProcessor<Widget> processor; private final Object owner; private final Field field; public OnChangeListener(final AbstractOnChangeProcessor<Widget> processor, final Object owner, final Field field) { this.processor = processor; this.owner = owner; this.field = field; } @Override @SuppressWarnings("unchecked") public void changed(final ChangeEvent event, final Actor actor) { try { Reflection.setFieldValue(field, owner, processor.extractValueFromActor((Widget) actor)); } catch (final ReflectionException exception) { throw new GdxRuntimeException( "Unable to update OnChange-annotated field: " + field + " of object: " + owner, exception); } } } }