1 /*
2  * Copyright (C) 2022 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.state.helpers;
17 
18 import static androidx.constraintlayout.core.widgets.ConstraintWidget.HORIZONTAL;
19 import static androidx.constraintlayout.core.widgets.ConstraintWidget.UNKNOWN;
20 import static androidx.constraintlayout.core.widgets.ConstraintWidget.VERTICAL;
21 import static androidx.constraintlayout.core.widgets.Flow.HORIZONTAL_ALIGN_CENTER;
22 import static androidx.constraintlayout.core.widgets.Flow.VERTICAL_ALIGN_CENTER;
23 import static androidx.constraintlayout.core.widgets.Flow.WRAP_NONE;
24 
25 import androidx.constraintlayout.core.state.HelperReference;
26 import androidx.constraintlayout.core.state.State;
27 import androidx.constraintlayout.core.widgets.Flow;
28 import androidx.constraintlayout.core.widgets.HelperWidget;
29 
30 import java.util.HashMap;
31 
32 /**
33  * The FlowReference class can be used to store the relevant properties of a Flow Helper
34  * when parsing the Flow Helper information in a JSON representation.
35  *
36  */
37 public class FlowReference extends HelperReference {
38     protected Flow mFlow;
39 
40     protected HashMap<String, Float> mMapWeights;
41     protected HashMap<String, Float> mMapPreMargin;
42     protected HashMap<String, Float> mMapPostMargin;
43 
44     protected int mWrapMode = WRAP_NONE;
45 
46     protected int mVerticalStyle = UNKNOWN;
47     protected int mFirstVerticalStyle = UNKNOWN;
48     protected int mLastVerticalStyle = UNKNOWN;
49     protected int mHorizontalStyle = UNKNOWN;
50     protected int mFirstHorizontalStyle = UNKNOWN;
51     protected int mLastHorizontalStyle = UNKNOWN;
52 
53     protected int mVerticalAlign = HORIZONTAL_ALIGN_CENTER;
54     protected int mHorizontalAlign = VERTICAL_ALIGN_CENTER;
55 
56     protected int mVerticalGap = 0;
57     protected int mHorizontalGap = 0;
58 
59     protected int mPaddingLeft = 0;
60     protected int mPaddingRight = 0;
61     protected int mPaddingTop = 0;
62     protected int mPaddingBottom = 0;
63 
64     protected int mMaxElementsWrap = UNKNOWN;
65 
66     protected int mOrientation = HORIZONTAL;
67 
68     protected float mFirstVerticalBias = 0.5f;
69     protected float mLastVerticalBias = 0.5f;
70     protected float mFirstHorizontalBias = 0.5f;
71     protected float mLastHorizontalBias = 0.5f;
72 
FlowReference(State state, State.Helper type)73     public FlowReference(State state, State.Helper type) {
74         super(state, type);
75         if (type == State.Helper.VERTICAL_FLOW) {
76             mOrientation = VERTICAL;
77         }
78     }
79 
80     /**
81      * Relate widgets to the FlowReference
82      *
83      * @param id id of a widget
84      * @param weight weight of a widget
85      * @param preMargin preMargin of a widget
86      * @param postMargin postMargin of a widget
87      */
addFlowElement(String id, float weight, float preMargin, float postMargin)88     public void addFlowElement(String id, float weight, float preMargin, float postMargin) {
89         super.add(id);
90         if (!Float.isNaN(weight)) {
91             if (mMapWeights == null) {
92                 mMapWeights = new HashMap<>();
93             }
94             mMapWeights.put(id, weight);
95         }
96         if (!Float.isNaN(preMargin)) {
97             if (mMapPreMargin == null) {
98                 mMapPreMargin = new HashMap<>();
99             }
100             mMapPreMargin.put(id, preMargin);
101         }
102         if (!Float.isNaN(postMargin)) {
103             if (mMapPostMargin == null) {
104                 mMapPostMargin = new HashMap<>();
105             }
106             mMapPostMargin.put(id, postMargin);
107         }
108     }
109 
110     /**
111      * Get the weight of a widget
112      *
113      * @param id id of a widget
114      * @return the weight of a widget
115      */
getWeight(String id)116     protected float getWeight(String id) {
117         if (mMapWeights == null) {
118             return UNKNOWN;
119         }
120         if (mMapWeights.containsKey(id)) {
121             return mMapWeights.get(id);
122         }
123         return UNKNOWN;
124     }
125 
126     /**
127      * Get the post margin of a widget
128      *
129      * @param id id id of a widget
130      * @return the post margin of a widget
131      */
getPostMargin(String id)132     protected float getPostMargin(String id) {
133         if (mMapPreMargin != null  && mMapPreMargin.containsKey(id)) {
134             return mMapPreMargin.get(id);
135         }
136         return 0;
137     }
138 
139     /**
140      * Get the pre margin of a widget
141      *
142      * @param id id id of a widget
143      * @return the pre margin of a widget
144      */
getPreMargin(String id)145     protected float getPreMargin(String id) {
146         if (mMapPostMargin != null  && mMapPostMargin.containsKey(id)) {
147             return mMapPostMargin.get(id);
148         }
149         return 0;
150     }
151 
152     /**
153      * Get wrap mode
154      *
155      * @return wrap mode
156      */
getWrapMode()157     public int getWrapMode() {
158         return mWrapMode;
159     }
160 
161     /**
162      * Set wrap Mode
163      *
164      * @param wrap wrap Mode
165      */
setWrapMode(int wrap)166     public void setWrapMode(int wrap) {
167         this.mWrapMode = wrap;
168     }
169 
170     /**
171      * Get paddingLeft
172      *
173      * @return paddingLeft value
174      */
getPaddingLeft()175     public int getPaddingLeft() {
176         return mPaddingLeft;
177     }
178 
179     /**
180      * Set paddingLeft
181      *
182      * @param padding paddingLeft value
183      */
setPaddingLeft(int padding)184     public void setPaddingLeft(int padding) {
185         this.mPaddingLeft = padding;
186     }
187 
188     /**
189      * Get paddingTop
190      *
191      * @return paddingTop value
192      */
getPaddingTop()193     public int getPaddingTop() {
194         return mPaddingTop;
195     }
196 
197     /**
198      * Set paddingTop
199      *
200      * @param padding paddingTop value
201      */
setPaddingTop(int padding)202     public void setPaddingTop(int padding) {
203         this.mPaddingTop = padding;
204     }
205 
206     /**
207      * Get paddingRight
208      *
209      * @return paddingRight value
210      */
getPaddingRight()211     public int getPaddingRight() {
212         return mPaddingRight;
213     }
214 
215     /**
216      * Set paddingRight
217      *
218      * @param padding paddingRight value
219      */
setPaddingRight(int padding)220     public void setPaddingRight(int padding) {
221         this.mPaddingRight = padding;
222     }
223 
224     /**
225      * Get paddingBottom
226      *
227      * @return paddingBottom value
228      */
getPaddingBottom()229     public int getPaddingBottom() {
230         return mPaddingBottom;
231     }
232 
233     /**
234      * Set padding
235      *
236      * @param padding paddingBottom value
237      */
setPaddingBottom(int padding)238     public void setPaddingBottom(int padding) {
239         this.mPaddingBottom = padding;
240     }
241 
242     /**
243      * Get vertical style
244      *
245      * @return vertical style
246      */
getVerticalStyle()247     public int getVerticalStyle() {
248         return mVerticalStyle;
249     }
250 
251     /**
252      * set vertical style
253      *
254      * @param verticalStyle Flow vertical style
255      */
setVerticalStyle(int verticalStyle)256     public void setVerticalStyle(int verticalStyle) {
257         this.mVerticalStyle = verticalStyle;
258     }
259 
260     /**
261      * Get first vertical style
262      *
263      * @return first vertical style
264      */
getFirstVerticalStyle()265     public int getFirstVerticalStyle() {
266         return mFirstVerticalStyle;
267     }
268 
269     /**
270      * Set first vertical style
271      *
272      * @param firstVerticalStyle Flow first vertical style
273      */
setFirstVerticalStyle(int firstVerticalStyle)274     public void setFirstVerticalStyle(int firstVerticalStyle) {
275         this.mFirstVerticalStyle = firstVerticalStyle;
276     }
277 
278     /**
279      * Get last vertical style
280      *
281      * @return last vertical style
282      */
getLastVerticalStyle()283     public int getLastVerticalStyle() {
284         return mLastVerticalStyle;
285     }
286 
287     /**
288      * Set last vertical style
289      *
290      * @param lastVerticalStyle Flow last vertical style
291      */
setLastVerticalStyle(int lastVerticalStyle)292     public void setLastVerticalStyle(int lastVerticalStyle) {
293         this.mLastVerticalStyle = lastVerticalStyle;
294     }
295 
296     /**
297      * Get horizontal style
298      *
299      * @return horizontal style
300      */
getHorizontalStyle()301     public int getHorizontalStyle() {
302         return mHorizontalStyle;
303     }
304 
305     /**
306      * Set horizontal style
307      *
308      * @param horizontalStyle Flow horizontal style
309      */
setHorizontalStyle(int horizontalStyle)310     public void setHorizontalStyle(int horizontalStyle) {
311         this.mHorizontalStyle = horizontalStyle;
312     }
313 
314     /**
315      * Get first horizontal style
316      *
317      * @return first horizontal style
318      */
getFirstHorizontalStyle()319     public int getFirstHorizontalStyle() {
320         return mFirstHorizontalStyle;
321     }
322 
323     /**
324      * Set first horizontal style
325      *
326      * @param firstHorizontalStyle Flow first horizontal style
327      */
setFirstHorizontalStyle(int firstHorizontalStyle)328     public void setFirstHorizontalStyle(int firstHorizontalStyle) {
329         this.mFirstHorizontalStyle = firstHorizontalStyle;
330     }
331 
332     /**
333      * Get last horizontal style
334      *
335      * @return last horizontal style
336      */
getLastHorizontalStyle()337     public int getLastHorizontalStyle() {
338         return mLastHorizontalStyle;
339     }
340 
341     /**
342      * Set last horizontal style
343      *
344      * @param lastHorizontalStyle Flow last horizontal style
345      */
setLastHorizontalStyle(int lastHorizontalStyle)346     public void setLastHorizontalStyle(int lastHorizontalStyle) {
347         this.mLastHorizontalStyle = lastHorizontalStyle;
348     }
349 
350     /**
351      * Get vertical align
352      * @return vertical align value
353      */
getVerticalAlign()354     public int getVerticalAlign() {
355         return mVerticalAlign;
356     }
357 
358     /**
359      * Set vertical align
360      *
361      * @param verticalAlign vertical align value
362      */
setVerticalAlign(int verticalAlign)363     public void setVerticalAlign(int verticalAlign) {
364         this.mVerticalAlign = verticalAlign;
365     }
366 
367     /**
368      * Get horizontal align
369      *
370      * @return horizontal align value
371      */
getHorizontalAlign()372     public int getHorizontalAlign() {
373         return mHorizontalAlign;
374     }
375 
376     /**
377      * Set horizontal align
378      *
379      * @param horizontalAlign horizontal align value
380      */
setHorizontalAlign(int horizontalAlign)381     public void setHorizontalAlign(int horizontalAlign) {
382         this.mHorizontalAlign = horizontalAlign;
383     }
384 
385     /**
386      * Get vertical gap
387      *
388      * @return vertical gap value
389      */
getVerticalGap()390     public int getVerticalGap() {
391         return mVerticalGap;
392     }
393 
394     /**
395      * Set vertical gap
396      *
397      * @param verticalGap vertical gap value
398      */
setVerticalGap(int verticalGap)399     public void setVerticalGap(int verticalGap) {
400         this.mVerticalGap = verticalGap;
401     }
402 
403     /**
404      * Get horizontal gap
405      *
406      * @return horizontal gap value
407      */
getHorizontalGap()408     public int getHorizontalGap() {
409         return mHorizontalGap;
410     }
411 
412     /**
413      * Set horizontal gap
414      *
415      * @param horizontalGap horizontal gap value
416      */
setHorizontalGap(int horizontalGap)417     public void setHorizontalGap(int horizontalGap) {
418         mHorizontalGap = horizontalGap;
419     }
420 
421     /**
422      * Get max element wrap
423      *
424      * @return max element wrap value
425      */
getMaxElementsWrap()426     public int getMaxElementsWrap() {
427         return mMaxElementsWrap;
428     }
429 
430     /**
431      * Set max element wrap
432      *
433      * @param maxElementsWrap max element wrap value
434      */
setMaxElementsWrap(int maxElementsWrap)435     public void setMaxElementsWrap(int maxElementsWrap) {
436         this.mMaxElementsWrap = maxElementsWrap;
437     }
438 
439     /**
440      * Get the orientation of a Flow
441      *
442      * @return orientation value
443      */
getOrientation()444     public int getOrientation() {
445         return mOrientation;
446     }
447 
448     /**
449      * Set the orientation of a Flow
450      *
451      * @param mOrientation orientation value
452      */
setOrientation(int mOrientation)453     public void setOrientation(int mOrientation) {
454         this.mOrientation = mOrientation;
455     }
456 
457     /**
458      * Get vertical bias
459      *
460      * @return vertical bias value
461      */
getVerticalBias()462     public float getVerticalBias() {
463         return mVerticalBias;
464     }
465 
466 
467     /**
468      * Get first vertical bias
469      *
470      * @return first vertical bias value
471      */
getFirstVerticalBias()472     public float getFirstVerticalBias() {
473         return mFirstVerticalBias;
474     }
475 
476     /**
477      * Set first vertical bias
478      *
479      * @param firstVerticalBias first vertical bias value
480      */
setFirstVerticalBias(float firstVerticalBias)481     public void setFirstVerticalBias(float firstVerticalBias) {
482         this.mFirstVerticalBias = firstVerticalBias;
483     }
484 
485     /**
486      * Get last vertical bias
487      *
488      * @return last vertical bias
489      */
getLastVerticalBias()490     public float getLastVerticalBias() {
491         return mLastVerticalBias;
492     }
493 
494     /**
495      * Set last vertical bias
496      *
497      * @param lastVerticalBias last vertical bias value
498      */
setLastVerticalBias(float lastVerticalBias)499     public void setLastVerticalBias(float lastVerticalBias) {
500         this.mLastVerticalBias = lastVerticalBias;
501     }
502 
503     /**
504      * Get horizontal bias
505      * @return horizontal bias value
506      */
getHorizontalBias()507     public float getHorizontalBias() {
508         return mHorizontalBias;
509     }
510 
511     /**
512      * Get first horizontal bias
513      *
514      * @return first horizontal bias
515      */
getFirstHorizontalBias()516     public float getFirstHorizontalBias() {
517         return mFirstHorizontalBias;
518     }
519 
520     /**
521      * Set first horizontal bias
522      *
523      * @param firstHorizontalBias first horizontal bias value
524      */
setFirstHorizontalBias(float firstHorizontalBias)525     public void setFirstHorizontalBias(float firstHorizontalBias) {
526         this.mFirstHorizontalBias = firstHorizontalBias;
527     }
528 
529     /**
530      * Get last horizontal bias
531      *
532      * @return last horizontal bias value
533      */
getLastHorizontalBias()534     public float getLastHorizontalBias() {
535         return mLastHorizontalBias;
536     }
537 
538     /**
539      * Set last horizontal bias
540      *
541      * @param lastHorizontalBias last horizontal bias value
542      */
setLastHorizontalBias(float lastHorizontalBias)543     public void setLastHorizontalBias(float lastHorizontalBias) {
544         this.mLastHorizontalBias = lastHorizontalBias;
545     }
546 
547     @Override
getHelperWidget()548     public HelperWidget getHelperWidget() {
549         if (mFlow == null) {
550             mFlow = new Flow();
551         }
552         return mFlow;
553     }
554 
555     @Override
setHelperWidget(HelperWidget widget)556     public void setHelperWidget(HelperWidget widget) {
557         if (widget instanceof Flow) {
558             mFlow = (Flow) widget;
559         } else {
560             mFlow = null;
561         }
562     }
563 
564     @Override
apply()565     public void apply() {
566         getHelperWidget();
567         this.setConstraintWidget(mFlow);
568         mFlow.setOrientation(mOrientation);
569         mFlow.setWrapMode(mWrapMode);
570 
571         if (mMaxElementsWrap != UNKNOWN) {
572             mFlow.setMaxElementsWrap(mMaxElementsWrap);
573         }
574 
575         // Padding
576         if (mPaddingLeft != 0) {
577             mFlow.setPaddingLeft(mPaddingLeft);
578         }
579         if (mPaddingTop != 0) {
580             mFlow.setPaddingTop(mPaddingTop);
581         }
582         if (mPaddingRight != 0) {
583             mFlow.setPaddingRight(mPaddingRight);
584         }
585         if (mPaddingBottom != 0) {
586             mFlow.setPaddingBottom(mPaddingBottom);
587         }
588 
589         // Gap
590         if (mHorizontalGap != 0) {
591             mFlow.setHorizontalGap(mHorizontalGap);
592         }
593         if (mVerticalGap != 0) {
594             mFlow.setVerticalGap(mVerticalGap);
595         }
596 
597         // Bias
598         if (mHorizontalBias != 0.5f) {
599             mFlow.setHorizontalBias(mHorizontalBias);
600         }
601         if (mFirstHorizontalBias != 0.5f) {
602             mFlow.setFirstHorizontalBias(mFirstHorizontalBias);
603         }
604         if (mLastHorizontalBias != 0.5f) {
605             mFlow.setLastHorizontalBias(mLastHorizontalBias);
606         }
607         if (mVerticalBias != 0.5f) {
608             mFlow.setVerticalBias(mVerticalBias);
609         }
610         if (mFirstVerticalBias != 0.5f) {
611             mFlow.setFirstVerticalBias(mFirstVerticalBias);
612         }
613         if (mLastVerticalBias != 0.5f) {
614             mFlow.setLastVerticalBias(mLastVerticalBias);
615         }
616 
617         // Align
618         if (mHorizontalAlign != HORIZONTAL_ALIGN_CENTER) {
619             mFlow.setHorizontalAlign(mHorizontalAlign);
620         }
621         if (mVerticalAlign != VERTICAL_ALIGN_CENTER) {
622             mFlow.setVerticalAlign(mVerticalAlign);
623         }
624 
625         // Style
626         if (mVerticalStyle != UNKNOWN) {
627             mFlow.setVerticalStyle(mVerticalStyle);
628         }
629         if (mFirstVerticalStyle != UNKNOWN) {
630             mFlow.setFirstVerticalStyle(mFirstVerticalStyle);
631         }
632         if (mLastVerticalStyle != UNKNOWN) {
633             mFlow.setLastVerticalStyle(mLastVerticalStyle);
634         }
635         if (mHorizontalStyle != UNKNOWN) {
636             mFlow.setHorizontalStyle(mHorizontalStyle);
637         }
638         if (mFirstHorizontalStyle != UNKNOWN) {
639             mFlow.setFirstHorizontalStyle(mFirstHorizontalStyle);
640         }
641         if (mLastHorizontalStyle!= UNKNOWN) {
642             mFlow.setLastHorizontalStyle(mLastHorizontalStyle);
643         }
644 
645         // General attributes of a widget
646         applyBase();
647     }
648 }
649