com.badlogic.gdx.scenes.scene2d.ui.Container.java Source code

Java tutorial

Introduction

Here is the source code for com.badlogic.gdx.scenes.scene2d.ui.Container.java

Source

package com.badlogic.gdx.scenes.scene2d.ui;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.ui.Value.Fixed;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.scenes.scene2d.utils.Layout;

/** A group with a single child that sizes and positions the child using constraints. This provides layout similar to a
 * {@link Table} with a single cell but is more lightweight.
 * @author Nathan Sweet */
public class Container<T extends Actor> extends WidgetGroup {
    private T actor;
    private Value minWidth = Value.minWidth, minHeight = Value.minHeight;
    private Value prefWidth = Value.prefWidth, prefHeight = Value.prefHeight;
    private Value maxWidth = Value.zero, maxHeight = Value.zero;
    private Value padTop = Value.zero, padLeft = Value.zero, padBottom = Value.zero, padRight = Value.zero;
    private float fillX, fillY;
    private int align;
    private Drawable background;
    private boolean clip;
    private boolean round = true;

    /** Creates a container with no actor. */
    public Container() {
        setTouchable(Touchable.childrenOnly);
        setTransform(false);
    }

    public Container(T actor) {
        this();
        setActor(actor);
    }

    public void draw(Batch batch, float parentAlpha) {
        validate();
        if (isTransform()) {
            applyTransform(batch, computeTransform());
            drawBackground(batch, parentAlpha, 0, 0);
            if (clip) {
                batch.flush();
                float padLeft = this.padLeft.get(this), padBottom = this.padBottom.get(this);
                boolean draw = background == null ? clipBegin(0, 0, getWidth(), getHeight())
                        : clipBegin(padLeft, padBottom, getWidth() - padLeft - padRight.get(this),
                                getHeight() - padBottom - padTop.get(this));
                if (draw) {
                    drawChildren(batch, parentAlpha);
                    batch.flush();
                    clipEnd();
                }
            } else
                drawChildren(batch, parentAlpha);
            resetTransform(batch);
        } else {
            drawBackground(batch, parentAlpha, getX(), getY());
            super.draw(batch, parentAlpha);
        }
    }

    /** Called to draw the background, before clipping is applied (if enabled). Default implementation draws the background
     * drawable. */
    protected void drawBackground(Batch batch, float parentAlpha, float x, float y) {
        if (background == null)
            return;
        Color color = getColor();
        batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
        background.draw(batch, x, y, getWidth(), getHeight());
    }

    /** Sets the background drawable and adjusts the container's padding to match the background.
     * @see #setBackground(Drawable, boolean) */
    public void setBackground(Drawable background) {
        setBackground(background, true);
    }

    /** Sets the background drawable and, if adjustPadding is true, sets the container's padding to
     * {@link Drawable#getBottomHeight()} , {@link Drawable#getTopHeight()}, {@link Drawable#getLeftWidth()}, and
     * {@link Drawable#getRightWidth()}.
     * @param background If null, the background will be cleared and padding removed. */
    public void setBackground(Drawable background, boolean adjustPadding) {
        if (this.background == background)
            return;
        this.background = background;
        if (adjustPadding) {
            if (background == null)
                pad(Value.zero);
            else
                pad(background.getTopHeight(), background.getLeftWidth(), background.getBottomHeight(),
                        background.getRightWidth());
            invalidate();
        }
    }

    /** @see #setBackground(Drawable) */
    public Container<T> background(Drawable background) {
        setBackground(background);
        return this;
    }

    public Drawable getBackground() {
        return background;
    }

    public void layout() {
        if (actor == null)
            return;

        float padLeft = this.padLeft.get(this), padBottom = this.padBottom.get(this);
        float containerWidth = getWidth() - padLeft - padRight.get(this);
        float containerHeight = getHeight() - padBottom - padTop.get(this);
        float minWidth = this.minWidth.get(actor), minHeight = this.minHeight.get(actor);
        float prefWidth = this.prefWidth.get(actor), prefHeight = this.prefHeight.get(actor);
        float maxWidth = this.maxWidth.get(actor), maxHeight = this.maxHeight.get(actor);

        float width;
        if (fillX > 0)
            width = containerWidth * fillX;
        else
            width = Math.min(prefWidth, containerWidth);
        if (width < minWidth)
            width = minWidth;
        if (maxWidth > 0 && width > maxWidth)
            width = maxWidth;

        float height;
        if (fillY > 0)
            height = containerHeight * fillY;
        else
            height = Math.min(prefHeight, containerHeight);
        if (height < minHeight)
            height = minHeight;
        if (maxHeight > 0 && height > maxHeight)
            height = maxHeight;

        float x = padLeft;
        if ((align & Align.right) != 0)
            x += containerWidth - width;
        else if ((align & Align.left) == 0) // center
            x += (containerWidth - width) / 2;

        float y = padBottom;
        if ((align & Align.top) != 0)
            y += containerHeight - height;
        else if ((align & Align.bottom) == 0) // center
            y += (containerHeight - height) / 2;

        if (round) {
            x = Math.round(x);
            y = Math.round(y);
            width = Math.round(width);
            height = Math.round(height);
        }

        actor.setBounds(x, y, width, height);
        if (actor instanceof Layout)
            ((Layout) actor).validate();
    }

    /** @param actor May be null. */
    public void setActor(T actor) {
        if (actor == this)
            throw new IllegalArgumentException("actor cannot be the Container.");
        if (this.actor != null)
            super.removeActor(this.actor);
        this.actor = actor;
        if (actor != null)
            super.addActor(actor);
    }

    /** @return May be null. */
    public T getActor() {
        return actor;
    }

    /** @deprecated Container may have only a single child.
     * @see #setActor(Actor) */
    public void addActor(Actor actor) {
        throw new UnsupportedOperationException("Use Container#setActor.");
    }

    /** @deprecated Container may have only a single child.
     * @see #setActor(Actor) */
    public void addActorAt(int index, Actor actor) {
        throw new UnsupportedOperationException("Use Container#setActor.");
    }

    /** @deprecated Container may have only a single child.
     * @see #setActor(Actor) */
    public void addActorBefore(Actor actorBefore, Actor actor) {
        throw new UnsupportedOperationException("Use Container#setActor.");
    }

    /** @deprecated Container may have only a single child.
     * @see #setActor(Actor) */
    public void addActorAfter(Actor actorAfter, Actor actor) {
        throw new UnsupportedOperationException("Use Container#setActor.");
    }

    public boolean removeActor(Actor actor) {
        if (actor != this.actor)
            return false;
        setActor(null);
        return true;
    }

    /** Sets the minWidth, prefWidth, maxWidth, minHeight, prefHeight, and maxHeight to the specified value. */
    public Container<T> size(Value size) {
        if (size == null)
            throw new IllegalArgumentException("size cannot be null.");
        minWidth = size;
        minHeight = size;
        prefWidth = size;
        prefHeight = size;
        maxWidth = size;
        maxHeight = size;
        return this;
    }

    /** Sets the minWidth, prefWidth, maxWidth, minHeight, prefHeight, and maxHeight to the specified values. */
    public Container<T> size(Value width, Value height) {
        if (width == null)
            throw new IllegalArgumentException("width cannot be null.");
        if (height == null)
            throw new IllegalArgumentException("height cannot be null.");
        minWidth = width;
        minHeight = height;
        prefWidth = width;
        prefHeight = height;
        maxWidth = width;
        maxHeight = height;
        return this;
    }

    /** Sets the minWidth, prefWidth, maxWidth, minHeight, prefHeight, and maxHeight to the specified value. */
    public Container<T> size(float size) {
        size(new Fixed(size));
        return this;
    }

    /** Sets the minWidth, prefWidth, maxWidth, minHeight, prefHeight, and maxHeight to the specified values. */
    public Container<T> size(float width, float height) {
        size(new Fixed(width), new Fixed(height));
        return this;
    }

    /** Sets the minWidth, prefWidth, and maxWidth to the specified value. */
    public Container<T> width(Value width) {
        if (width == null)
            throw new IllegalArgumentException("width cannot be null.");
        minWidth = width;
        prefWidth = width;
        maxWidth = width;
        return this;
    }

    /** Sets the minWidth, prefWidth, and maxWidth to the specified value. */
    public Container<T> width(float width) {
        width(new Fixed(width));
        return this;
    }

    /** Sets the minHeight, prefHeight, and maxHeight to the specified value. */
    public Container<T> height(Value height) {
        if (height == null)
            throw new IllegalArgumentException("height cannot be null.");
        minHeight = height;
        prefHeight = height;
        maxHeight = height;
        return this;
    }

    /** Sets the minHeight, prefHeight, and maxHeight to the specified value. */
    public Container<T> height(float height) {
        height(new Fixed(height));
        return this;
    }

    /** Sets the minWidth and minHeight to the specified value. */
    public Container<T> minSize(Value size) {
        if (size == null)
            throw new IllegalArgumentException("size cannot be null.");
        minWidth = size;
        minHeight = size;
        return this;
    }

    /** Sets the minWidth and minHeight to the specified values. */
    public Container<T> minSize(Value width, Value height) {
        if (width == null)
            throw new IllegalArgumentException("width cannot be null.");
        if (height == null)
            throw new IllegalArgumentException("height cannot be null.");
        minWidth = width;
        minHeight = height;
        return this;
    }

    public Container<T> minWidth(Value minWidth) {
        if (minWidth == null)
            throw new IllegalArgumentException("minWidth cannot be null.");
        this.minWidth = minWidth;
        return this;
    }

    public Container<T> minHeight(Value minHeight) {
        if (minHeight == null)
            throw new IllegalArgumentException("minHeight cannot be null.");
        this.minHeight = minHeight;
        return this;
    }

    /** Sets the minWidth and minHeight to the specified value. */
    public Container<T> minSize(float size) {
        minSize(new Fixed(size));
        return this;
    }

    /** Sets the minWidth and minHeight to the specified values. */
    public Container<T> minSize(float width, float height) {
        minSize(new Fixed(width), new Fixed(height));
        return this;
    }

    public Container<T> minWidth(float minWidth) {
        this.minWidth = new Fixed(minWidth);
        return this;
    }

    public Container<T> minHeight(float minHeight) {
        this.minHeight = new Fixed(minHeight);
        return this;
    }

    /** Sets the prefWidth and prefHeight to the specified value. */
    public Container<T> prefSize(Value size) {
        if (size == null)
            throw new IllegalArgumentException("size cannot be null.");
        prefWidth = size;
        prefHeight = size;
        return this;
    }

    /** Sets the prefWidth and prefHeight to the specified values. */
    public Container<T> prefSize(Value width, Value height) {
        if (width == null)
            throw new IllegalArgumentException("width cannot be null.");
        if (height == null)
            throw new IllegalArgumentException("height cannot be null.");
        prefWidth = width;
        prefHeight = height;
        return this;
    }

    public Container<T> prefWidth(Value prefWidth) {
        if (prefWidth == null)
            throw new IllegalArgumentException("prefWidth cannot be null.");
        this.prefWidth = prefWidth;
        return this;
    }

    public Container<T> prefHeight(Value prefHeight) {
        if (prefHeight == null)
            throw new IllegalArgumentException("prefHeight cannot be null.");
        this.prefHeight = prefHeight;
        return this;
    }

    /** Sets the prefWidth and prefHeight to the specified value. */
    public Container<T> prefSize(float width, float height) {
        prefSize(new Fixed(width), new Fixed(height));
        return this;
    }

    /** Sets the prefWidth and prefHeight to the specified values. */
    public Container<T> prefSize(float size) {
        prefSize(new Fixed(size));
        return this;
    }

    public Container<T> prefWidth(float prefWidth) {
        this.prefWidth = new Fixed(prefWidth);
        return this;
    }

    public Container<T> prefHeight(float prefHeight) {
        this.prefHeight = new Fixed(prefHeight);
        return this;
    }

    /** Sets the maxWidth and maxHeight to the specified value. */
    public Container<T> maxSize(Value size) {
        if (size == null)
            throw new IllegalArgumentException("size cannot be null.");
        maxWidth = size;
        maxHeight = size;
        return this;
    }

    /** Sets the maxWidth and maxHeight to the specified values. */
    public Container<T> maxSize(Value width, Value height) {
        if (width == null)
            throw new IllegalArgumentException("width cannot be null.");
        if (height == null)
            throw new IllegalArgumentException("height cannot be null.");
        maxWidth = width;
        maxHeight = height;
        return this;
    }

    public Container<T> maxWidth(Value maxWidth) {
        if (maxWidth == null)
            throw new IllegalArgumentException("maxWidth cannot be null.");
        this.maxWidth = maxWidth;
        return this;
    }

    public Container<T> maxHeight(Value maxHeight) {
        if (maxHeight == null)
            throw new IllegalArgumentException("maxHeight cannot be null.");
        this.maxHeight = maxHeight;
        return this;
    }

    /** Sets the maxWidth and maxHeight to the specified value. */
    public Container<T> maxSize(float size) {
        maxSize(new Fixed(size));
        return this;
    }

    /** Sets the maxWidth and maxHeight to the specified values. */
    public Container<T> maxSize(float width, float height) {
        maxSize(new Fixed(width), new Fixed(height));
        return this;
    }

    public Container<T> maxWidth(float maxWidth) {
        this.maxWidth = new Fixed(maxWidth);
        return this;
    }

    public Container<T> maxHeight(float maxHeight) {
        this.maxHeight = new Fixed(maxHeight);
        return this;
    }

    /** Sets the padTop, padLeft, padBottom, and padRight to the specified value. */
    public Container<T> pad(Value pad) {
        if (pad == null)
            throw new IllegalArgumentException("pad cannot be null.");
        padTop = pad;
        padLeft = pad;
        padBottom = pad;
        padRight = pad;
        return this;
    }

    public Container<T> pad(Value top, Value left, Value bottom, Value right) {
        if (top == null)
            throw new IllegalArgumentException("top cannot be null.");
        if (left == null)
            throw new IllegalArgumentException("left cannot be null.");
        if (bottom == null)
            throw new IllegalArgumentException("bottom cannot be null.");
        if (right == null)
            throw new IllegalArgumentException("right cannot be null.");
        padTop = top;
        padLeft = left;
        padBottom = bottom;
        padRight = right;
        return this;
    }

    public Container<T> padTop(Value padTop) {
        if (padTop == null)
            throw new IllegalArgumentException("padTop cannot be null.");
        this.padTop = padTop;
        return this;
    }

    public Container<T> padLeft(Value padLeft) {
        if (padLeft == null)
            throw new IllegalArgumentException("padLeft cannot be null.");
        this.padLeft = padLeft;
        return this;
    }

    public Container<T> padBottom(Value padBottom) {
        if (padBottom == null)
            throw new IllegalArgumentException("padBottom cannot be null.");
        this.padBottom = padBottom;
        return this;
    }

    public Container<T> padRight(Value padRight) {
        if (padRight == null)
            throw new IllegalArgumentException("padRight cannot be null.");
        this.padRight = padRight;
        return this;
    }

    /** Sets the padTop, padLeft, padBottom, and padRight to the specified value. */
    public Container<T> pad(float pad) {
        Value value = new Fixed(pad);
        padTop = value;
        padLeft = value;
        padBottom = value;
        padRight = value;
        return this;
    }

    public Container<T> pad(float top, float left, float bottom, float right) {
        padTop = new Fixed(top);
        padLeft = new Fixed(left);
        padBottom = new Fixed(bottom);
        padRight = new Fixed(right);
        return this;
    }

    public Container<T> padTop(float padTop) {
        this.padTop = new Fixed(padTop);
        return this;
    }

    public Container<T> padLeft(float padLeft) {
        this.padLeft = new Fixed(padLeft);
        return this;
    }

    public Container<T> padBottom(float padBottom) {
        this.padBottom = new Fixed(padBottom);
        return this;
    }

    public Container<T> padRight(float padRight) {
        this.padRight = new Fixed(padRight);
        return this;
    }

    /** Sets fillX and fillY to 1. */
    public Container<T> fill() {
        fillX = 1f;
        fillY = 1f;
        return this;
    }

    /** Sets fillX to 1. */
    public Container<T> fillX() {
        fillX = 1f;
        return this;
    }

    /** Sets fillY to 1. */
    public Container<T> fillY() {
        fillY = 1f;
        return this;
    }

    public Container<T> fill(float x, float y) {
        fillX = x;
        fillY = y;
        return this;
    }

    /** Sets fillX and fillY to 1 if true, 0 if false. */
    public Container<T> fill(boolean x, boolean y) {
        fillX = x ? 1f : 0;
        fillY = y ? 1f : 0;
        return this;
    }

    /** Sets fillX and fillY to 1 if true, 0 if false. */
    public Container<T> fill(boolean fill) {
        fillX = fill ? 1f : 0;
        fillY = fill ? 1f : 0;
        return this;
    }

    /** Sets the alignment of the actor within the container. Set to {@link Align#center}, {@link Align#top}, {@link Align#bottom},
     * {@link Align#left}, {@link Align#right}, or any combination of those. */
    public Container<T> align(int align) {
        this.align = align;
        return this;
    }

    /** Sets the alignment of the actor within the container to {@link Align#center}. This clears any other alignment. */
    public Container<T> center() {
        align = Align.center;
        return this;
    }

    /** Sets {@link Align#top} and clears {@link Align#bottom} for the alignment of the actor within the container. */
    public Container<T> top() {
        align |= Align.top;
        align &= ~Align.bottom;
        return this;
    }

    /** Sets {@link Align#left} and clears {@link Align#right} for the alignment of the actor within the container. */
    public Container<T> left() {
        align |= Align.left;
        align &= ~Align.right;
        return this;
    }

    /** Sets {@link Align#bottom} and clears {@link Align#top} for the alignment of the actor within the container. */
    public Container<T> bottom() {
        align |= Align.bottom;
        align &= ~Align.top;
        return this;
    }

    /** Sets {@link Align#right} and clears {@link Align#left} for the alignment of the actor within the container. */
    public Container<T> right() {
        align |= Align.right;
        align &= ~Align.left;
        return this;
    }

    public float getMinWidth() {
        return minWidth.get(actor) + padLeft.get(this) + padRight.get(this);
    }

    public Value getMinHeightValue() {
        return minHeight;
    }

    public float getMinHeight() {
        return minHeight.get(actor) + padTop.get(this) + padBottom.get(this);
    }

    public Value getPrefWidthValue() {
        return prefWidth;
    }

    public float getPrefWidth() {
        float v = prefWidth.get(actor);
        if (background != null)
            v = Math.max(v, background.getMinWidth());
        return v + padLeft.get(this) + padRight.get(this);
    }

    public Value getPrefHeightValue() {
        return prefHeight;
    }

    public float getPrefHeight() {
        float v = prefHeight.get(actor);
        if (background != null)
            v = Math.max(v, background.getMinHeight());
        return v + padTop.get(this) + padBottom.get(this);
    }

    public Value getMaxWidthValue() {
        return maxWidth;
    }

    public float getMaxWidth() {
        float v = maxWidth.get(actor);
        if (v > 0)
            v += padLeft.get(this) + padRight.get(this);
        return v;
    }

    public Value getMaxHeightValue() {
        return maxHeight;
    }

    public float getMaxHeight() {
        float v = maxHeight.get(actor);
        if (v > 0)
            v += padTop.get(this) + padBottom.get(this);
        return v;
    }

    /** @return May be null if this value is not set. */
    public Value getPadTopValue() {
        return padTop;
    }

    public float getPadTop() {
        return padTop.get(this);
    }

    /** @return May be null if this value is not set. */
    public Value getPadLeftValue() {
        return padLeft;
    }

    public float getPadLeft() {
        return padLeft.get(this);
    }

    /** @return May be null if this value is not set. */
    public Value getPadBottomValue() {
        return padBottom;
    }

    public float getPadBottom() {
        return padBottom.get(this);
    }

    /** @return May be null if this value is not set. */
    public Value getPadRightValue() {
        return padRight;
    }

    public float getPadRight() {
        return padRight.get(this);
    }

    /** Returns {@link #getPadLeft()} plus {@link #getPadRight()}. */
    public float getPadX() {
        return padLeft.get(this) + padRight.get(this);
    }

    /** Returns {@link #getPadTop()} plus {@link #getPadBottom()}. */
    public float getPadY() {
        return padTop.get(this) + padBottom.get(this);
    }

    public float getFillX() {
        return fillX;
    }

    public float getFillY() {
        return fillY;
    }

    public int getAlign() {
        return align;
    }

    /** If true (the default), positions and sizes are rounded to integers. */
    public void setRound(boolean round) {
        this.round = round;
    }

    /** Causes the contents to be clipped if they exceed the container bounds. Enabling clipping will set
     * {@link #setTransform(boolean)} to true. */
    public void setClip(boolean enabled) {
        clip = enabled;
        setTransform(enabled);
        invalidate();
    }

    public boolean getClip() {
        return clip;
    }

    public Actor hit(float x, float y, boolean touchable) {
        if (clip) {
            if (touchable && getTouchable() == Touchable.disabled)
                return null;
            if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight())
                return null;
        }
        return super.hit(x, y, touchable);
    }

    public void drawDebug(ShapeRenderer shapes) {
        validate();
        if (isTransform()) {
            applyTransform(shapes, computeTransform());
            if (clip) {
                shapes.flush();
                float padLeft = this.padLeft.get(this), padBottom = this.padBottom.get(this);
                boolean draw = background == null ? clipBegin(0, 0, getWidth(), getHeight())
                        : clipBegin(padLeft, padBottom, getWidth() - padLeft - padRight.get(this),
                                getHeight() - padBottom - padTop.get(this));
                if (draw) {
                    drawDebugChildren(shapes);
                    clipEnd();
                }
            } else
                drawDebugChildren(shapes);
            resetTransform(shapes);
        } else
            super.drawDebug(shapes);
    }
}