1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package androidx.constraintlayout.core.widgets; 17 18 import androidx.constraintlayout.core.widgets.analyzer.BasicMeasure; 19 20 import java.util.HashSet; 21 22 /** 23 * Base class for Virtual layouts 24 */ 25 public class VirtualLayout extends HelperWidget { 26 27 private int mPaddingTop = 0; 28 private int mPaddingBottom = 0; 29 @SuppressWarnings("unused") private int mPaddingLeft = 0; 30 @SuppressWarnings("unused") private int mPaddingRight = 0; 31 @SuppressWarnings("unused") private int mPaddingStart = 0; 32 private int mPaddingEnd = 0; 33 private int mResolvedPaddingLeft = 0; 34 private int mResolvedPaddingRight = 0; 35 36 private boolean mNeedsCallFromSolver = false; 37 private int mMeasuredWidth = 0; 38 private int mMeasuredHeight = 0; 39 40 protected BasicMeasure.Measure mMeasure = new BasicMeasure.Measure(); 41 42 ///////////////////////////////////////////////////////////////////////////////////////////// 43 // Accessors 44 ///////////////////////////////////////////////////////////////////////////////////////////// 45 46 // @TODO: add description setPadding(int value)47 public void setPadding(int value) { 48 mPaddingLeft = value; 49 mPaddingTop = value; 50 mPaddingRight = value; 51 mPaddingBottom = value; 52 mPaddingStart = value; 53 mPaddingEnd = value; 54 } 55 56 // @TODO: add description setPaddingStart(int value)57 public void setPaddingStart(int value) { 58 mPaddingStart = value; 59 mResolvedPaddingLeft = value; 60 mResolvedPaddingRight = value; 61 } 62 setPaddingEnd(int value)63 public void setPaddingEnd(int value) { 64 mPaddingEnd = value; 65 } 66 67 // @TODO: add description setPaddingLeft(int value)68 public void setPaddingLeft(int value) { 69 mPaddingLeft = value; 70 mResolvedPaddingLeft = value; 71 } 72 73 // @TODO: add description applyRtl(boolean isRtl)74 public void applyRtl(boolean isRtl) { 75 if (mPaddingStart > 0 || mPaddingEnd > 0) { 76 if (isRtl) { 77 mResolvedPaddingLeft = mPaddingEnd; 78 mResolvedPaddingRight = mPaddingStart; 79 } else { 80 mResolvedPaddingLeft = mPaddingStart; 81 mResolvedPaddingRight = mPaddingEnd; 82 } 83 } 84 } 85 setPaddingTop(int value)86 public void setPaddingTop(int value) { 87 mPaddingTop = value; 88 } 89 90 // @TODO: add description setPaddingRight(int value)91 public void setPaddingRight(int value) { 92 mPaddingRight = value; 93 mResolvedPaddingRight = value; 94 } 95 setPaddingBottom(int value)96 public void setPaddingBottom(int value) { 97 mPaddingBottom = value; 98 } 99 getPaddingTop()100 public int getPaddingTop() { 101 return mPaddingTop; 102 } 103 getPaddingBottom()104 public int getPaddingBottom() { 105 return mPaddingBottom; 106 } 107 getPaddingLeft()108 public int getPaddingLeft() { 109 return mResolvedPaddingLeft; 110 } 111 getPaddingRight()112 public int getPaddingRight() { 113 return mResolvedPaddingRight; 114 } 115 116 ///////////////////////////////////////////////////////////////////////////////////////////// 117 // Solver callback 118 ///////////////////////////////////////////////////////////////////////////////////////////// 119 needsCallbackFromSolver(boolean value)120 protected void needsCallbackFromSolver(boolean value) { 121 mNeedsCallFromSolver = value; 122 } 123 124 // @TODO: add description needSolverPass()125 public boolean needSolverPass() { 126 return mNeedsCallFromSolver; 127 } 128 129 ///////////////////////////////////////////////////////////////////////////////////////////// 130 // Measure 131 ///////////////////////////////////////////////////////////////////////////////////////////// 132 133 // @TODO: add description measure(int widthMode, int widthSize, int heightMode, int heightSize)134 public void measure(int widthMode, int widthSize, int heightMode, int heightSize) { 135 // nothing 136 } 137 138 @Override updateConstraints(ConstraintWidgetContainer container)139 public void updateConstraints(ConstraintWidgetContainer container) { 140 captureWidgets(); 141 } 142 143 // @TODO: add description captureWidgets()144 public void captureWidgets() { 145 for (int i = 0; i < mWidgetsCount; i++) { 146 ConstraintWidget widget = mWidgets[i]; 147 if (widget != null) { 148 widget.setInVirtualLayout(true); 149 } 150 } 151 } 152 getMeasuredWidth()153 public int getMeasuredWidth() { 154 return mMeasuredWidth; 155 } 156 getMeasuredHeight()157 public int getMeasuredHeight() { 158 return mMeasuredHeight; 159 } 160 161 // @TODO: add description setMeasure(int width, int height)162 public void setMeasure(int width, int height) { 163 mMeasuredWidth = width; 164 mMeasuredHeight = height; 165 } 166 measureChildren()167 protected boolean measureChildren() { 168 BasicMeasure.Measurer measurer = null; 169 if (mParent != null) { 170 measurer = ((ConstraintWidgetContainer) mParent).getMeasurer(); 171 } 172 if (measurer == null) { 173 return false; 174 } 175 176 for (int i = 0; i < mWidgetsCount; i++) { 177 ConstraintWidget widget = mWidgets[i]; 178 if (widget == null) { 179 continue; 180 } 181 182 if (widget instanceof Guideline) { 183 continue; 184 } 185 186 DimensionBehaviour widthBehavior = widget.getDimensionBehaviour(HORIZONTAL); 187 DimensionBehaviour heightBehavior = widget.getDimensionBehaviour(VERTICAL); 188 189 boolean skip = widthBehavior == DimensionBehaviour.MATCH_CONSTRAINT 190 && widget.mMatchConstraintDefaultWidth != MATCH_CONSTRAINT_WRAP 191 && heightBehavior == DimensionBehaviour.MATCH_CONSTRAINT 192 && widget.mMatchConstraintDefaultHeight != MATCH_CONSTRAINT_WRAP; 193 194 if (skip) { 195 // we don't need to measure here as the dimension of the widget 196 // will be completely computed by the solver. 197 continue; 198 } 199 200 if (widthBehavior == DimensionBehaviour.MATCH_CONSTRAINT) { 201 widthBehavior = DimensionBehaviour.WRAP_CONTENT; 202 } 203 if (heightBehavior == DimensionBehaviour.MATCH_CONSTRAINT) { 204 heightBehavior = DimensionBehaviour.WRAP_CONTENT; 205 } 206 mMeasure.horizontalBehavior = widthBehavior; 207 mMeasure.verticalBehavior = heightBehavior; 208 mMeasure.horizontalDimension = widget.getWidth(); 209 mMeasure.verticalDimension = widget.getHeight(); 210 measurer.measure(widget, mMeasure); 211 widget.setWidth(mMeasure.measuredWidth); 212 widget.setHeight(mMeasure.measuredHeight); 213 widget.setBaselineDistance(mMeasure.measuredBaseline); 214 } 215 return true; 216 } 217 218 BasicMeasure.Measurer mMeasurer = null; 219 measure(ConstraintWidget widget, ConstraintWidget.DimensionBehaviour horizontalBehavior, int horizontalDimension, ConstraintWidget.DimensionBehaviour verticalBehavior, int verticalDimension)220 protected void measure(ConstraintWidget widget, 221 ConstraintWidget.DimensionBehaviour horizontalBehavior, 222 int horizontalDimension, 223 ConstraintWidget.DimensionBehaviour verticalBehavior, 224 int verticalDimension) { 225 while (mMeasurer == null && getParent() != null) { 226 ConstraintWidgetContainer parent = (ConstraintWidgetContainer) getParent(); 227 mMeasurer = parent.getMeasurer(); 228 } 229 mMeasure.horizontalBehavior = horizontalBehavior; 230 mMeasure.verticalBehavior = verticalBehavior; 231 mMeasure.horizontalDimension = horizontalDimension; 232 mMeasure.verticalDimension = verticalDimension; 233 mMeasurer.measure(widget, mMeasure); 234 widget.setWidth(mMeasure.measuredWidth); 235 widget.setHeight(mMeasure.measuredHeight); 236 widget.setHasBaseline(mMeasure.measuredHasBaseline); 237 widget.setBaselineDistance(mMeasure.measuredBaseline); 238 } 239 240 // @TODO: add description contains(HashSet<ConstraintWidget> widgets)241 public boolean contains(HashSet<ConstraintWidget> widgets) { 242 for (int i = 0; i < mWidgetsCount; i++) { 243 ConstraintWidget widget = mWidgets[i]; 244 if (widgets.contains(widget)) { 245 return true; 246 } 247 } 248 return false; 249 } 250 } 251