Guideline.java
/*
* Copyright (C) 2015 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.widgets;
import androidx.constraintlayout.core.LinearSystem;
import androidx.constraintlayout.core.SolverVariable;
import java.util.HashMap;
import static androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour.WRAP_CONTENT;
/**
* Guideline
*/
public class Guideline extends ConstraintWidget {
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
public static final int RELATIVE_PERCENT = 0;
public static final int RELATIVE_BEGIN = 1;
public static final int RELATIVE_END = 2;
public static final int RELATIVE_UNKNOWN = -1;
protected float mRelativePercent = -1;
protected int mRelativeBegin = -1;
protected int mRelativeEnd = -1;
private ConstraintAnchor mAnchor = mTop;
private int mOrientation = HORIZONTAL;
private int mMinimumPosition = 0;
private boolean resolved;
public Guideline() {
mAnchors.clear();
mAnchors.add(mAnchor);
final int count = mListAnchors.length;
for (int i = 0; i < count; i++) {
mListAnchors[i] = mAnchor;
}
}
@Override
public void copy(ConstraintWidget src, HashMap<ConstraintWidget,ConstraintWidget> map) {
super.copy(src, map);
Guideline srcGuideline = (Guideline) src;
mRelativePercent = srcGuideline.mRelativePercent;
mRelativeBegin = srcGuideline.mRelativeBegin;
mRelativeEnd = srcGuideline.mRelativeEnd;
setOrientation(srcGuideline.mOrientation);
}
@Override
public boolean allowedInBarrier() {
return true;
}
public int getRelativeBehaviour() {
if (mRelativePercent != -1) {
return RELATIVE_PERCENT;
}
if (mRelativeBegin != -1) {
return RELATIVE_BEGIN;
}
if (mRelativeEnd != -1) {
return RELATIVE_END;
}
return RELATIVE_UNKNOWN;
}
public void setOrientation(int orientation) {
if (mOrientation == orientation) {
return;
}
mOrientation = orientation;
mAnchors.clear();
if (mOrientation == VERTICAL) {
mAnchor = mLeft;
} else {
mAnchor = mTop;
}
mAnchors.add(mAnchor);
final int count = mListAnchors.length;
for (int i = 0; i < count; i++) {
mListAnchors[i] = mAnchor;
}
}
public ConstraintAnchor getAnchor() {
return mAnchor;
}
/**
* Specify the xml type for the container
*
* @return
*/
@Override
public String getType() {
return "Guideline";
}
public int getOrientation() {
return mOrientation;
}
public void setMinimumPosition(int minimum) {
mMinimumPosition = minimum;
}
@Override
public ConstraintAnchor getAnchor(ConstraintAnchor.Type anchorType) {
switch (anchorType) {
case LEFT:
case RIGHT: {
if (mOrientation == VERTICAL) {
return mAnchor;
}
}
break;
case TOP:
case BOTTOM: {
if (mOrientation == HORIZONTAL) {
return mAnchor;
}
}
break;
case BASELINE:
case CENTER:
case CENTER_X:
case CENTER_Y:
case NONE:
return null;
}
throw new AssertionError(anchorType.name());
}
public void setGuidePercent(int value) {
setGuidePercent(value / 100f);
}
public void setGuidePercent(float value) {
if (value > -1) {
mRelativePercent = value;
mRelativeBegin = -1;
mRelativeEnd = -1;
}
}
public void setGuideBegin(int value) {
if (value > -1) {
mRelativePercent = -1;
mRelativeBegin = value;
mRelativeEnd = -1;
}
}
public void setGuideEnd(int value) {
if (value > -1) {
mRelativePercent = -1;
mRelativeBegin = -1;
mRelativeEnd = value;
}
}
public float getRelativePercent() {
return mRelativePercent;
}
public int getRelativeBegin() {
return mRelativeBegin;
}
public int getRelativeEnd() {
return mRelativeEnd;
}
public void setFinalValue(int position) {
if (LinearSystem.FULL_DEBUG) {
System.out.println("*** SET FINAL GUIDELINE VALUE " + position + " FOR " + getDebugName());
}
mAnchor.setFinalValue(position);
resolved = true;
}
public boolean isResolvedHorizontally() {
return resolved;
}
public boolean isResolvedVertically() {
return resolved;
}
@Override
public void addToSolver(LinearSystem system, boolean optimize) {
if (LinearSystem.FULL_DEBUG) {
System.out.println("\n----------------------------------------------");
System.out.println("-- adding " + getDebugName() + " to the solver");
System.out.println("----------------------------------------------\n");
}
ConstraintWidgetContainer parent = (ConstraintWidgetContainer) getParent();
if (parent == null) {
return;
}
ConstraintAnchor begin = parent.getAnchor(ConstraintAnchor.Type.LEFT);
ConstraintAnchor end = parent.getAnchor(ConstraintAnchor.Type.RIGHT);
boolean parentWrapContent = mParent != null ? mParent.mListDimensionBehaviors[DIMENSION_HORIZONTAL] == WRAP_CONTENT : false;
if (mOrientation == HORIZONTAL) {
begin = parent.getAnchor(ConstraintAnchor.Type.TOP);
end = parent.getAnchor(ConstraintAnchor.Type.BOTTOM);
parentWrapContent = mParent != null ? mParent.mListDimensionBehaviors[DIMENSION_VERTICAL] == WRAP_CONTENT : false;
}
if (resolved && mAnchor.hasFinalValue()) {
SolverVariable guide = system.createObjectVariable(mAnchor);
if (LinearSystem.FULL_DEBUG) {
System.out.println("*** SET FINAL POSITION FOR GUIDELINE " + getDebugName() + " TO " + mAnchor.getFinalValue());
}
system.addEquality(guide, mAnchor.getFinalValue());
if (mRelativeBegin != -1) {
if (parentWrapContent) {
system.addGreaterThan(system.createObjectVariable(end), guide, 0, SolverVariable.STRENGTH_EQUALITY);
}
} else if (mRelativeEnd != -1) {
if (parentWrapContent) {
SolverVariable parentRight = system.createObjectVariable(end);
system.addGreaterThan(guide, system.createObjectVariable(begin), 0, SolverVariable.STRENGTH_EQUALITY);
system.addGreaterThan(parentRight, guide, 0, SolverVariable.STRENGTH_EQUALITY);
}
}
resolved = false;
return;
}
if (mRelativeBegin != -1) {
SolverVariable guide = system.createObjectVariable(mAnchor);
SolverVariable parentLeft = system.createObjectVariable(begin);
system.addEquality(guide, parentLeft, mRelativeBegin, SolverVariable.STRENGTH_FIXED);
if (parentWrapContent) {
system.addGreaterThan(system.createObjectVariable(end), guide, 0, SolverVariable.STRENGTH_EQUALITY);
}
} else if (mRelativeEnd != -1) {
SolverVariable guide = system.createObjectVariable(mAnchor);
SolverVariable parentRight = system.createObjectVariable(end);
system.addEquality(guide, parentRight, -mRelativeEnd, SolverVariable.STRENGTH_FIXED);
if (parentWrapContent) {
system.addGreaterThan(guide, system.createObjectVariable(begin), 0, SolverVariable.STRENGTH_EQUALITY);
system.addGreaterThan(parentRight, guide, 0, SolverVariable.STRENGTH_EQUALITY);
}
} else if (mRelativePercent != -1) {
SolverVariable guide = system.createObjectVariable(mAnchor);
SolverVariable parentRight = system.createObjectVariable(end);
system.addConstraint(LinearSystem
.createRowDimensionPercent(system, guide, parentRight,
mRelativePercent));
}
}
@Override
public void updateFromSolver(LinearSystem system, boolean optimize) {
if (getParent() == null) {
return;
}
int value = system.getObjectVariableValue(mAnchor);
if (mOrientation == VERTICAL) {
setX(value);
setY(0);
setHeight(getParent().getHeight());
setWidth(0);
} else {
setX(0);
setY(value);
setWidth(getParent().getWidth());
setHeight(0);
}
}
void inferRelativePercentPosition() {
float percent = (getX() / (float) getParent().getWidth());
if (mOrientation == HORIZONTAL) {
percent = (getY() / (float) getParent().getHeight());
}
setGuidePercent(percent);
}
void inferRelativeBeginPosition() {
int position = getX();
if (mOrientation == HORIZONTAL) {
position = getY();
}
setGuideBegin(position);
}
void inferRelativeEndPosition() {
int position = getParent().getWidth() - getX();
if (mOrientation == HORIZONTAL) {
position = getParent().getHeight() - getY();
}
setGuideEnd(position);
}
public void cyclePosition() {
if (mRelativeBegin != -1) {
// cycle to percent-based position
inferRelativePercentPosition();
} else if (mRelativePercent != -1) {
// cycle to end-based position
inferRelativeEndPosition();
} else if (mRelativeEnd != -1) {
// cycle to begin-based position
inferRelativeBeginPosition();
}
}
public boolean isPercent() {
return mRelativePercent != -1 && mRelativeBegin == -1 && mRelativeEnd == -1;
}
}