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 
17 package androidx.constraintlayout.core.state;
18 
19 import static androidx.constraintlayout.core.widgets.ConstraintWidget.MATCH_CONSTRAINT_PERCENT;
20 import static androidx.constraintlayout.core.widgets.ConstraintWidget.MATCH_CONSTRAINT_SPREAD;
21 import static androidx.constraintlayout.core.widgets.ConstraintWidget.MATCH_CONSTRAINT_WRAP;
22 
23 import androidx.constraintlayout.core.widgets.ConstraintWidget;
24 
25 /**
26  * Represents a dimension (width or height) of a constrained widget
27  */
28 public class Dimension {
29 
30     public static final Object FIXED_DIMENSION = new String("FIXED_DIMENSION");
31     public static final Object WRAP_DIMENSION = new String("WRAP_DIMENSION");
32     public static final Object SPREAD_DIMENSION = new String("SPREAD_DIMENSION");
33     public static final Object PARENT_DIMENSION = new String("PARENT_DIMENSION");
34     public static final Object PERCENT_DIMENSION = new String("PERCENT_DIMENSION");
35     public static final Object RATIO_DIMENSION = new String("RATIO_DIMENSION");
36 
37     private final int mWrapContent = -2;
38 
39     int mMin = 0;
40     int mMax = Integer.MAX_VALUE;
41     float mPercent = 1f;
42     int mValue = 0;
43     String mRatioString = null;
44     Object mInitialValue = WRAP_DIMENSION;
45     boolean mIsSuggested = false;
46 
47     /**
48      * Returns true if the dimension is a fixed dimension of
49      * the same given value
50      */
equalsFixedValue(int value)51     public boolean equalsFixedValue(int value) {
52         if (mInitialValue == null
53                 && mValue == value) {
54             return true;
55         }
56         return false;
57     }
58 
59     public enum Type {
60         FIXED,
61         WRAP,
62         MATCH_PARENT,
63         MATCH_CONSTRAINT
64     }
65 
Dimension()66     private Dimension() {
67     }
68 
Dimension(Object type)69     private Dimension(Object type) {
70         mInitialValue = type;
71     }
72 
73     /**
74      * @deprecated Use {@link #createSuggested(int)} instead
75      */
76     @Deprecated
Suggested(int value)77     public static Dimension Suggested(int value) {
78         return createSuggested(value);
79     }
80 
81     // @TODO: add description
createSuggested(int value)82     public static Dimension createSuggested(int value) {
83         Dimension dimension = new Dimension();
84         dimension.suggested(value);
85         return dimension;
86     }
87 
88     /**
89      * @deprecated Use {@link #createSuggested(Object)} instead
90      */
91     @Deprecated
Suggested(Object startValue)92     public static Dimension Suggested(Object startValue) {
93         return createSuggested(startValue);
94     }
95 
96     // @TODO: add description
createSuggested(Object startValue)97     public static Dimension createSuggested(Object startValue) {
98         Dimension dimension = new Dimension();
99         dimension.suggested(startValue);
100         return dimension;
101     }
102 
103     /**
104      * @deprecated Use {@link #createFixed(int)} instead
105      */
106     @Deprecated
Fixed(int value)107     public static Dimension Fixed(int value) {
108         return createFixed(value);
109     }
110 
111     // @TODO: add description
createFixed(int value)112     public static Dimension createFixed(int value) {
113         Dimension dimension = new Dimension(FIXED_DIMENSION);
114         dimension.fixed(value);
115         return dimension;
116     }
117 
118     /**
119      * @deprecated Use {@link #createFixed(Object)} instead
120      */
121     @Deprecated
Fixed(Object value)122     public static Dimension Fixed(Object value) {
123         Dimension dimension = new Dimension(FIXED_DIMENSION);
124         dimension.fixed(value);
125         return dimension;
126     }
127 
128     // @TODO: add description
createFixed(Object value)129     public static Dimension createFixed(Object value) {
130         Dimension dimension = new Dimension(FIXED_DIMENSION);
131         dimension.fixed(value);
132         return dimension;
133     }
134 
135     /**
136      * @deprecated Use {@link #createPercent(Object, float)} instead
137      */
138     @Deprecated
Percent(Object key, float value)139     public static Dimension Percent(Object key, float value) {
140         return createPercent(key, value);
141     }
142 
143     // @TODO: add description
createPercent(Object key, float value)144     public static Dimension createPercent(Object key, float value) {
145         Dimension dimension = new Dimension(PERCENT_DIMENSION);
146         dimension.percent(key, value);
147         return dimension;
148     }
149 
150     /**
151      * @deprecated Use {@link #createParent(int)} instead
152      */
153     @Deprecated
Parent()154     public static Dimension Parent() {
155         return createParent();
156     }
157 
158     // @TODO: add description
createParent()159     public static Dimension createParent() {
160         return new Dimension(PARENT_DIMENSION);
161     }
162 
163     /**
164      * @deprecated Use {@link #createWrap()} instead
165      */
166     @Deprecated
Wrap()167     public static Dimension Wrap() {
168         return createWrap();
169     }
170 
171     // @TODO: add description
createWrap()172     public static Dimension createWrap() {
173         return new Dimension(WRAP_DIMENSION);
174     }
175 
176     /**
177      * @deprecated Use {@link #createSpread()} instead
178      */
179     @Deprecated
Spread()180     public static Dimension Spread() {
181         return createSpread();
182     }
183 
184     // @TODO: add description
createSpread()185     public static Dimension createSpread() {
186         return new Dimension(SPREAD_DIMENSION);
187     }
188 
189     /**
190      * @deprecated Use {@link #createRatio(String)} instead
191      */
192     @Deprecated
Ratio(String ratio)193     public static Dimension Ratio(String ratio) {
194         return createRatio(ratio);
195     }
196 
197     // @TODO: add description
createRatio(String ratio)198     public static Dimension createRatio(String ratio) {
199         Dimension dimension = new Dimension(RATIO_DIMENSION);
200         dimension.ratio(ratio);
201         return dimension;
202     }
203 
204     // @TODO: add description
percent(Object key, float value)205     public Dimension percent(Object key, float value) {
206         mPercent = value;
207         return this;
208     }
209 
210     // @TODO: add description
min(int value)211     public Dimension min(int value) {
212         if (value >= 0) {
213             mMin = value;
214         }
215         return this;
216     }
217 
218     // @TODO: add description
min(Object value)219     public Dimension min(Object value) {
220         if (value == WRAP_DIMENSION) {
221             mMin = mWrapContent;
222         }
223         return this;
224     }
225 
226     // @TODO: add description
max(int value)227     public Dimension max(int value) {
228         if (mMax >= 0) {
229             mMax = value;
230         }
231         return this;
232     }
233 
234     // @TODO: add description
max(Object value)235     public Dimension max(Object value) {
236         if (value == WRAP_DIMENSION && mIsSuggested) {
237             mInitialValue = WRAP_DIMENSION;
238             mMax = Integer.MAX_VALUE;
239         }
240         return this;
241     }
242 
243     // @TODO: add description
suggested(int value)244     public Dimension suggested(int value) {
245         mIsSuggested = true;
246         if (value >= 0) {
247             mMax = value;
248         }
249         return this;
250     }
251 
252     // @TODO: add description
suggested(Object value)253     public Dimension suggested(Object value) {
254         mInitialValue = value;
255         mIsSuggested = true;
256         return this;
257     }
258 
259     // @TODO: add description
fixed(Object value)260     public Dimension fixed(Object value) {
261         mInitialValue = value;
262         if (value instanceof Integer) {
263             mValue = (Integer) value;
264             mInitialValue = null;
265         }
266         return this;
267     }
268 
269     // @TODO: add description
fixed(int value)270     public Dimension fixed(int value) {
271         mInitialValue = null;
272         mValue = value;
273         return this;
274     }
275 
276     // @TODO: add description
ratio(String ratio)277     public Dimension ratio(String ratio) { // WxH ratio
278         mRatioString = ratio;
279         return this;
280     }
281 
setValue(int value)282     void setValue(int value) {
283         mIsSuggested = false; // fixed value
284         mInitialValue = null;
285         mValue = value;
286     }
287 
getValue()288     int getValue() {
289         return mValue;
290     }
291 
292     /**
293      * Apply the dimension to the given constraint widget
294      */
apply(State state, ConstraintWidget constraintWidget, int orientation)295     public void apply(State state, ConstraintWidget constraintWidget, int orientation) {
296         if (mRatioString != null) {
297             constraintWidget.setDimensionRatio(mRatioString);
298         }
299         if (orientation == ConstraintWidget.HORIZONTAL) {
300             if (mIsSuggested) {
301                 constraintWidget.setHorizontalDimensionBehaviour(
302                         ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT);
303                 int type = MATCH_CONSTRAINT_SPREAD;
304                 if (mInitialValue == WRAP_DIMENSION) {
305                     type = MATCH_CONSTRAINT_WRAP;
306                 } else if (mInitialValue == PERCENT_DIMENSION) {
307                     type = MATCH_CONSTRAINT_PERCENT;
308                 }
309                 constraintWidget.setHorizontalMatchStyle(type, mMin, mMax, mPercent);
310             } else { // fixed
311                 if (mMin > 0) {
312                     constraintWidget.setMinWidth(mMin);
313                 }
314                 if (mMax < Integer.MAX_VALUE) {
315                     constraintWidget.setMaxWidth(mMax);
316                 }
317                 if (mInitialValue == WRAP_DIMENSION) {
318                     constraintWidget.setHorizontalDimensionBehaviour(
319                             ConstraintWidget.DimensionBehaviour.WRAP_CONTENT);
320                 } else if (mInitialValue == PARENT_DIMENSION) {
321                     constraintWidget.setHorizontalDimensionBehaviour(
322                             ConstraintWidget.DimensionBehaviour.MATCH_PARENT);
323                 } else if (mInitialValue == null) {
324                     constraintWidget.setHorizontalDimensionBehaviour(
325                             ConstraintWidget.DimensionBehaviour.FIXED);
326                     constraintWidget.setWidth(mValue);
327                 }
328             }
329         } else {
330             if (mIsSuggested) {
331                 constraintWidget.setVerticalDimensionBehaviour(
332                         ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT);
333                 int type = MATCH_CONSTRAINT_SPREAD;
334                 if (mInitialValue == WRAP_DIMENSION) {
335                     type = MATCH_CONSTRAINT_WRAP;
336                 } else if (mInitialValue == PERCENT_DIMENSION) {
337                     type = MATCH_CONSTRAINT_PERCENT;
338                 }
339                 constraintWidget.setVerticalMatchStyle(type, mMin, mMax, mPercent);
340             } else { // fixed
341                 if (mMin > 0) {
342                     constraintWidget.setMinHeight(mMin);
343                 }
344                 if (mMax < Integer.MAX_VALUE) {
345                     constraintWidget.setMaxHeight(mMax);
346                 }
347                 if (mInitialValue == WRAP_DIMENSION) {
348                     constraintWidget.setVerticalDimensionBehaviour(
349                             ConstraintWidget.DimensionBehaviour.WRAP_CONTENT);
350                 } else if (mInitialValue == PARENT_DIMENSION) {
351                     constraintWidget.setVerticalDimensionBehaviour(
352                             ConstraintWidget.DimensionBehaviour.MATCH_PARENT);
353                 } else if (mInitialValue == null) {
354                     constraintWidget.setVerticalDimensionBehaviour(
355                             ConstraintWidget.DimensionBehaviour.FIXED);
356                     constraintWidget.setHeight(mValue);
357                 }
358             }
359         }
360     }
361 
362 }
363