package com.github.czyzby.lml.parser.impl.action;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Dialog;
import com.badlogic.gdx.scenes.scene2d.utils.Layout;
import com.github.czyzby.lml.parser.action.StageAttacher;
/** Default implementation of {@link StageAttacher}. Allows to specify initial position according to stage's size.
*
* @author MJ */
public class DefaultStageAttacher implements StageAttacher {
/** Centers the widget on the stage. */
public static final StageAttacher CENTERING_STAGE_ATTACHER = new StageAttacher() {
// Since DefaultStageAttacher is mutable, this kind of call delegating makes it safe to use and impossible to
// mutate without reflection.
private final StageAttacher protectedAttacher = new DefaultStageAttacher();
@Override
public void attachToStage(final Actor actor, final Stage stage) {
protectedAttacher.attachToStage(actor, stage);
}
};
private float x, y;
private PositionConverter xConverter, yConverter;
/** Creates a new stage attacher that will center the widget on the stage. */
public DefaultStageAttacher() {
this(0f, 0f, StandardPositionConverter.CENTER, StandardPositionConverter.CENTER);
}
public DefaultStageAttacher(final float x, final float y, final PositionConverter xConverter,
final PositionConverter yConverter) {
this.x = x;
this.y = y;
this.xConverter = xConverter;
this.yConverter = yConverter;
}
@Override
public void attachToStage(final Actor actor, final Stage stage) {
if (actor instanceof Dialog) {
((Dialog) actor).show(stage);
}
if (actor instanceof Layout) {
((Layout) actor).pack();
}
actor.setPosition(xConverter.convertX(x, stage, actor), yConverter.convertY(y, stage, actor));
}
/** @param x initial X value to parse. */
public void setX(final float x) {
this.x = x;
}
/** @param y initial Y value to parse. */
public void setY(final float y) {
this.y = y;
}
/** @param xConverter converts X position. */
public void setXConverter(final PositionConverter xConverter) {
this.xConverter = xConverter;
}
/** @param yConverter converts Y position. */
public void setYConverter(final PositionConverter yConverter) {
this.yConverter = yConverter;
}
/** Allows to converts float values to a position on stage.
*
* @author MJ */
public static interface PositionConverter {
/** @param x value to convert.
* @param stage has the actor.
* @param actor needs an initial position.
* @return converted X position. */
public abstract float convertX(float x, Stage stage, Actor actor);
/** @param y value to convert.
* @param stage has the actor.
* @param actor needs an initial position.
* @return converted Y position. */
public abstract float convertY(float y, Stage stage, Actor actor);
}
/** Allows to converts float values to a position on stage.
*
* @author MJ */
public static enum StandardPositionConverter implements PositionConverter {
/** Ignores float value and centers the actor on the stage according to their sizes. */
CENTER {
@Override
public float convertX(final float x, final Stage stage, final Actor actor) {
return (int) (stage.getWidth() / 2f - actor.getWidth() / 2f);
}
@Override
public float convertY(final float y, final Stage stage, final Actor actor) {
return (int) (stage.getHeight() / 2f - actor.getHeight() / 2f);
}
},
/** Returns the passed float values, effectively using absolute position values. */
ABSOLUTE {
@Override
public float convertX(final float x, final Stage stage, final Actor actor) {
return x;
}
@Override
public float convertY(final float y, final Stage stage, final Actor actor) {
return y;
}
},
/** Treats the passed values as percents of stage size. */
PERCENT {
@Override
public float convertX(final float x, final Stage stage, final Actor actor) {
return (int) (stage.getWidth() * x);
}
@Override
public float convertY(final float y, final Stage stage, final Actor actor) {
return (int) (stage.getHeight() * y);
}
};
}
}