Dimension.java

/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.constraintlayout.core.state;

import static androidx.constraintlayout.core.widgets.ConstraintWidget.MATCH_CONSTRAINT_PERCENT;
import static androidx.constraintlayout.core.widgets.ConstraintWidget.MATCH_CONSTRAINT_SPREAD;
import static androidx.constraintlayout.core.widgets.ConstraintWidget.MATCH_CONSTRAINT_WRAP;

import androidx.constraintlayout.core.widgets.ConstraintWidget;

/**
 * Represents a dimension (width or height) of a constrained widget
 */
public class Dimension {

    public static final Object FIXED_DIMENSION = new String("FIXED_DIMENSION");
    public static final Object WRAP_DIMENSION = new String("WRAP_DIMENSION");
    public static final Object SPREAD_DIMENSION = new String("SPREAD_DIMENSION");
    public static final Object PARENT_DIMENSION = new String("PARENT_DIMENSION");
    public static final Object PERCENT_DIMENSION = new String("PERCENT_DIMENSION");
    public static final Object RATIO_DIMENSION = new String("RATIO_DIMENSION");

    private final int mWrapContent = -2;

    int mMin = 0;
    int mMax = Integer.MAX_VALUE;
    float mPercent = 1f;
    int mValue = 0;
    String mRatioString = null;
    Object mInitialValue = WRAP_DIMENSION;
    boolean mIsSuggested = false;

    /**
     * Returns true if the dimension is a fixed dimension of
     * the same given value
     */
    public boolean equalsFixedValue(int value) {
        if (mInitialValue == null
                && mValue == value) {
            return true;
        }
        return false;
    }

    public enum Type {
        FIXED,
        WRAP,
        MATCH_PARENT,
        MATCH_CONSTRAINT
    }

    private Dimension() {
    }

    private Dimension(Object type) {
        mInitialValue = type;
    }

    // @TODO: add description
    public static Dimension createSuggested(int value) {
        Dimension dimension = new Dimension();
        dimension.suggested(value);
        return dimension;
    }

    // @TODO: add description
    public static Dimension createSuggested(Object startValue) {
        Dimension dimension = new Dimension();
        dimension.suggested(startValue);
        return dimension;
    }

    // @TODO: add description
    public static Dimension createFixed(int value) {
        Dimension dimension = new Dimension(FIXED_DIMENSION);
        dimension.fixed(value);
        return dimension;
    }

    // @TODO: add description
    public static Dimension createFixed(Object value) {
        Dimension dimension = new Dimension(FIXED_DIMENSION);
        dimension.fixed(value);
        return dimension;
    }

    // @TODO: add description
    public static Dimension createPercent(Object key, float value) {
        Dimension dimension = new Dimension(PERCENT_DIMENSION);
        dimension.percent(key, value);
        return dimension;
    }

    // @TODO: add description
    public static Dimension createParent() {
        return new Dimension(PARENT_DIMENSION);
    }

    // @TODO: add description
    public static Dimension createWrap() {
        return new Dimension(WRAP_DIMENSION);
    }

    // @TODO: add description
    public static Dimension createSpread() {
        return new Dimension(SPREAD_DIMENSION);
    }

    // @TODO: add description
    public static Dimension createRatio(String ratio) {
        Dimension dimension = new Dimension(RATIO_DIMENSION);
        dimension.ratio(ratio);
        return dimension;
    }

    // @TODO: add description
    public Dimension percent(Object key, float value) {
        mPercent = value;
        return this;
    }

    // @TODO: add description
    public Dimension min(int value) {
        if (value >= 0) {
            mMin = value;
        }
        return this;
    }

    // @TODO: add description
    public Dimension min(Object value) {
        if (value == WRAP_DIMENSION) {
            mMin = mWrapContent;
        }
        return this;
    }

    // @TODO: add description
    public Dimension max(int value) {
        if (mMax >= 0) {
            mMax = value;
        }
        return this;
    }

    // @TODO: add description
    public Dimension max(Object value) {
        if (value == WRAP_DIMENSION && mIsSuggested) {
            mInitialValue = WRAP_DIMENSION;
            mMax = Integer.MAX_VALUE;
        }
        return this;
    }

    // @TODO: add description
    public Dimension suggested(int value) {
        mIsSuggested = true;
        if (value >= 0) {
            mMax = value;
        }
        return this;
    }

    // @TODO: add description
    public Dimension suggested(Object value) {
        mInitialValue = value;
        mIsSuggested = true;
        return this;
    }

    // @TODO: add description
    public Dimension fixed(Object value) {
        mInitialValue = value;
        if (value instanceof Integer) {
            mValue = (Integer) value;
            mInitialValue = null;
        }
        return this;
    }

    // @TODO: add description
    public Dimension fixed(int value) {
        mInitialValue = null;
        mValue = value;
        return this;
    }

    // @TODO: add description
    public Dimension ratio(String ratio) { // WxH ratio
        mRatioString = ratio;
        return this;
    }

    void setValue(int value) {
        mIsSuggested = false; // fixed value
        mInitialValue = null;
        mValue = value;
    }

    int getValue() {
        return mValue;
    }

    /**
     * Apply the dimension to the given constraint widget
     */
    public void apply(State state, ConstraintWidget constraintWidget, int orientation) {
        if (mRatioString != null) {
            constraintWidget.setDimensionRatio(mRatioString);
        }
        if (orientation == ConstraintWidget.HORIZONTAL) {
            if (mIsSuggested) {
                constraintWidget.setHorizontalDimensionBehaviour(
                        ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT);
                int type = MATCH_CONSTRAINT_SPREAD;
                if (mInitialValue == WRAP_DIMENSION) {
                    type = MATCH_CONSTRAINT_WRAP;
                } else if (mInitialValue == PERCENT_DIMENSION) {
                    type = MATCH_CONSTRAINT_PERCENT;
                }
                constraintWidget.setHorizontalMatchStyle(type, mMin, mMax, mPercent);
            } else { // fixed
                if (mMin > 0) {
                    constraintWidget.setMinWidth(mMin);
                }
                if (mMax < Integer.MAX_VALUE) {
                    constraintWidget.setMaxWidth(mMax);
                }
                if (mInitialValue == WRAP_DIMENSION) {
                    constraintWidget.setHorizontalDimensionBehaviour(
                            ConstraintWidget.DimensionBehaviour.WRAP_CONTENT);
                } else if (mInitialValue == PARENT_DIMENSION) {
                    constraintWidget.setHorizontalDimensionBehaviour(
                            ConstraintWidget.DimensionBehaviour.MATCH_PARENT);
                } else if (mInitialValue == null) {
                    constraintWidget.setHorizontalDimensionBehaviour(
                            ConstraintWidget.DimensionBehaviour.FIXED);
                    constraintWidget.setWidth(mValue);
                }
            }
        } else {
            if (mIsSuggested) {
                constraintWidget.setVerticalDimensionBehaviour(
                        ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT);
                int type = MATCH_CONSTRAINT_SPREAD;
                if (mInitialValue == WRAP_DIMENSION) {
                    type = MATCH_CONSTRAINT_WRAP;
                } else if (mInitialValue == PERCENT_DIMENSION) {
                    type = MATCH_CONSTRAINT_PERCENT;
                }
                constraintWidget.setVerticalMatchStyle(type, mMin, mMax, mPercent);
            } else { // fixed
                if (mMin > 0) {
                    constraintWidget.setMinHeight(mMin);
                }
                if (mMax < Integer.MAX_VALUE) {
                    constraintWidget.setMaxHeight(mMax);
                }
                if (mInitialValue == WRAP_DIMENSION) {
                    constraintWidget.setVerticalDimensionBehaviour(
                            ConstraintWidget.DimensionBehaviour.WRAP_CONTENT);
                } else if (mInitialValue == PARENT_DIMENSION) {
                    constraintWidget.setVerticalDimensionBehaviour(
                            ConstraintWidget.DimensionBehaviour.MATCH_PARENT);
                } else if (mInitialValue == null) {
                    constraintWidget.setVerticalDimensionBehaviour(
                            ConstraintWidget.DimensionBehaviour.FIXED);
                    constraintWidget.setHeight(mValue);
                }
            }
        }
    }

}