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 
17 package androidx.constraintlayout.core.dsl;
18 
19 import java.util.HashMap;
20 import java.util.Map;
21 
22 /**
23  * Provides the API for creating a Constraint Object for use in the Core
24  * ConstraintLayout & MotionLayout system
25  */
26 public class Constraint {
27 
28     private final String mId;
29     public static final Constraint PARENT = new Constraint("parent");
30 
Constraint(String id)31     public Constraint(String id) {
32         mId = id;
33     }
34 
35     public class VAnchor extends Anchor {
VAnchor(VSide side)36         VAnchor(VSide side) {
37             super(Side.valueOf(side.name()));
38         }
39     }
40 
41     public class HAnchor extends Anchor {
HAnchor(HSide side)42         HAnchor(HSide side) {
43             super(Side.valueOf(side.name()));
44         }
45     }
46 
47     public class Anchor {
48         final Side mSide;
49         Anchor mConnection = null;
50         int mMargin;
51         int mGoneMargin = Integer.MIN_VALUE;
52 
Anchor(Side side)53         Anchor(Side side) {
54             mSide = side;
55         }
56 
getId()57         public String getId() {
58             return mId;
59         }
60 
getParent()61         Constraint getParent() {
62             return Constraint.this;
63         }
64 
build(StringBuilder builder)65         public void build(StringBuilder builder) {
66             if (mConnection != null) {
67                 builder.append(mSide.toString().toLowerCase())
68                         .append(":").append(this).append(",\n");
69             }
70         }
71 
72         @Override
toString()73         public String toString() {
74             StringBuilder ret = new StringBuilder("[");
75 
76             if (mConnection != null) {
77                 ret.append("'").append(mConnection.getId()).append("',")
78                         .append("'").append(mConnection.mSide.toString().toLowerCase()).append("'");
79             }
80 
81             if (mMargin != 0) {
82                 ret.append(",").append(mMargin);
83             }
84 
85             if (mGoneMargin != Integer.MIN_VALUE) {
86                 if ( mMargin == 0) {
87                     ret.append(",0,").append(mGoneMargin);
88                 } else {
89                     ret.append(",").append(mGoneMargin);
90                 }
91             }
92 
93             ret.append("]");
94             return ret.toString();
95         }
96     }
97 
98     public enum Behaviour {
99         SPREAD,
100         WRAP,
101         PERCENT,
102         RATIO,
103         RESOLVED,
104     }
105 
106     public enum ChainMode {
107         SPREAD,
108         SPREAD_INSIDE,
109         PACKED,
110     }
111 
112     public enum VSide {
113         TOP,
114         BOTTOM,
115         BASELINE
116     }
117 
118     public enum HSide {
119         LEFT,
120         RIGHT,
121         START,
122         END
123     }
124 
125     public enum Side {
126         LEFT,
127         RIGHT,
128         TOP,
129         BOTTOM,
130         START,
131         END,
132         BASELINE
133     }
134 
135     static int UNSET = Integer.MIN_VALUE;
136     static Map<ChainMode, String> chainModeMap = new HashMap<>();
137     static {
chainModeMap.put(ChainMode.SPREAD, "spread")138         chainModeMap.put(ChainMode.SPREAD, "spread");
chainModeMap.put(ChainMode.SPREAD_INSIDE, "spread_inside")139         chainModeMap.put(ChainMode.SPREAD_INSIDE, "spread_inside");
chainModeMap.put(ChainMode.PACKED, "packed")140         chainModeMap.put(ChainMode.PACKED, "packed");
141     }
142 
143     String helperType = null;
144     String helperJason = null;
145 
146     private HAnchor mLeft = new HAnchor(HSide.LEFT);
147     private HAnchor mRight = new HAnchor(HSide.RIGHT);
148     private VAnchor mTop = new VAnchor(VSide.TOP);
149     private VAnchor mBottom = new VAnchor(VSide.BOTTOM);
150     private HAnchor mStart = new HAnchor(HSide.START);
151     private HAnchor mEnd = new HAnchor(HSide.END);
152     private VAnchor mBaseline = new VAnchor(VSide.BASELINE);
153     private int mWidth = UNSET;
154     private int mHeight = UNSET;
155     private float mHorizontalBias = Float.NaN;
156     private float mVerticalBias = Float.NaN;
157     private String mDimensionRatio = null;
158     private String mCircleConstraint = null;
159     private int mCircleRadius = Integer.MIN_VALUE;
160     private float mCircleAngle = Float.NaN;
161     private int mEditorAbsoluteX = Integer.MIN_VALUE;
162     private int mEditorAbsoluteY = Integer.MIN_VALUE;
163     private float mVerticalWeight = Float.NaN;
164     private float mHorizontalWeight = Float.NaN;
165     private ChainMode mHorizontalChainStyle = null;
166     private ChainMode mVerticalChainStyle = null;
167     private Behaviour mWidthDefault = null;
168     private Behaviour mHeightDefault = null;
169     private int mWidthMax = UNSET;
170     private int mHeightMax = UNSET;
171     private int mWidthMin = UNSET;
172     private int mHeightMin = UNSET;
173     private float mWidthPercent = Float.NaN;
174     private float mHeightPercent = Float.NaN;
175     private String[] mReferenceIds = null;
176     private boolean mConstrainedWidth = false;
177     private boolean mConstrainedHeight = false;
178 
179     /**
180      * get left anchor
181      *
182      * @return left anchor
183      */
getLeft()184     public HAnchor getLeft() {
185         return mLeft;
186     }
187 
188     /**
189      * get right anchor
190      *
191      * @return right anchor
192      */
getRight()193     public HAnchor getRight() {
194         return mRight;
195     }
196 
197     /**
198      * get top anchor
199      *
200      * @return top anchor
201      */
getTop()202     public VAnchor getTop() {
203         return mTop;
204     }
205 
206     /**
207      * get bottom anchor
208      *
209      * @return bottom anchor
210      */
getBottom()211     public VAnchor getBottom() {
212         return mBottom;
213     }
214 
215     /**
216      * get start anchor
217      *
218      * @return start anchor
219      */
getStart()220     public HAnchor getStart() {
221         return mStart;
222     }
223 
224     /**
225      * get end anchor
226      *
227      * @return end anchor
228      */
getEnd()229     public HAnchor getEnd() {
230         return mEnd;
231     }
232 
233     /**
234      * get baseline anchor
235      *
236      * @return baseline anchor
237      */
getBaseline()238     public VAnchor getBaseline() {
239         return mBaseline;
240     }
241 
242     /**
243      * get horizontalBias
244      *
245      * @return horizontalBias
246      */
getHorizontalBias()247     public float getHorizontalBias() {
248         return mHorizontalBias;
249     }
250 
251     /**
252      * set horizontalBias
253      *
254      * @param horizontalBias
255      */
setHorizontalBias(float horizontalBias)256     public void setHorizontalBias(float horizontalBias) {
257         this.mHorizontalBias = horizontalBias;
258     }
259 
260     /**
261      * get verticalBias
262      *
263      * @return verticalBias
264      */
getVerticalBias()265     public float getVerticalBias() {
266         return mVerticalBias;
267     }
268 
269     /**
270      * set verticalBias
271      *
272      * @param verticalBias
273      */
setVerticalBias(float verticalBias)274     public void setVerticalBias(float verticalBias) {
275         this.mVerticalBias = verticalBias;
276     }
277 
278     /**
279      * get dimensionRatio
280      *
281      * @return dimensionRatio
282      */
getDimensionRatio()283     public String getDimensionRatio() {
284         return mDimensionRatio;
285     }
286 
287     /**
288      * set dimensionRatio
289      *
290      * @param dimensionRatio
291      */
setDimensionRatio(String dimensionRatio)292     public void setDimensionRatio(String dimensionRatio) {
293         this.mDimensionRatio = dimensionRatio;
294     }
295 
296     /**
297      * get circleConstraint
298      *
299      * @return circleConstraint
300      */
getCircleConstraint()301     public String getCircleConstraint() {
302         return mCircleConstraint;
303     }
304 
305     /**
306      * set circleConstraint
307      *
308      * @param circleConstraint
309      */
setCircleConstraint(String circleConstraint)310     public void setCircleConstraint(String circleConstraint) {
311         this.mCircleConstraint = circleConstraint;
312     }
313 
314     /**
315      * get circleRadius
316      *
317      * @return circleRadius
318      */
getCircleRadius()319     public int getCircleRadius() {
320         return mCircleRadius;
321     }
322 
323     /**
324      * set circleRadius
325      *
326      * @param circleRadius
327      */
setCircleRadius(int circleRadius)328     public void setCircleRadius(int circleRadius) {
329         this.mCircleRadius = circleRadius;
330     }
331 
332     /**
333      * get circleAngle
334      *
335      * @return circleAngle
336      */
getCircleAngle()337     public float getCircleAngle() {
338         return mCircleAngle;
339     }
340 
341     /**
342      * set circleAngle
343      *
344      * @param circleAngle
345      */
setCircleAngle(float circleAngle)346     public void setCircleAngle(float circleAngle) {
347         this.mCircleAngle = circleAngle;
348     }
349 
350     /**
351      * get editorAbsoluteX
352      * @return editorAbsoluteX
353      */
getEditorAbsoluteX()354     public int getEditorAbsoluteX() {
355         return mEditorAbsoluteX;
356     }
357 
358     /**
359      * set editorAbsoluteX
360      * @param editorAbsoluteX
361      */
setEditorAbsoluteX(int editorAbsoluteX)362     public void setEditorAbsoluteX(int editorAbsoluteX) {
363         mEditorAbsoluteX = editorAbsoluteX;
364     }
365 
366     /**
367      * get editorAbsoluteY
368      * @return editorAbsoluteY
369      */
getEditorAbsoluteY()370     public int getEditorAbsoluteY() {
371         return mEditorAbsoluteY;
372     }
373 
374     /**
375      * set editorAbsoluteY
376      * @param editorAbsoluteY
377      */
setEditorAbsoluteY(int editorAbsoluteY)378     public void setEditorAbsoluteY(int editorAbsoluteY) {
379         mEditorAbsoluteY = editorAbsoluteY;
380     }
381 
382     /**
383      * get verticalWeight
384      *
385      * @return verticalWeight
386      */
getVerticalWeight()387     public float getVerticalWeight() {
388         return mVerticalWeight;
389     }
390 
391     /**
392      * set verticalWeight
393      *
394      * @param verticalWeight
395      */
setVerticalWeight(float verticalWeight)396     public void setVerticalWeight(float verticalWeight) {
397         this.mVerticalWeight = verticalWeight;
398     }
399 
400     /**
401      * get horizontalWeight
402      *
403      * @return horizontalWeight
404      */
getHorizontalWeight()405     public float getHorizontalWeight() {
406         return mHorizontalWeight;
407     }
408 
409     /**
410      * set horizontalWeight
411      *
412      * @param horizontalWeight
413      */
setHorizontalWeight(float horizontalWeight)414     public void setHorizontalWeight(float horizontalWeight) {
415         this.mHorizontalWeight = horizontalWeight;
416     }
417 
418     /**
419      * get horizontalChainStyle
420      *
421      * @return horizontalChainStyle
422      */
getHorizontalChainStyle()423     public ChainMode getHorizontalChainStyle() {
424         return mHorizontalChainStyle;
425     }
426 
427     /**
428      * set horizontalChainStyle
429      *
430      * @param horizontalChainStyle
431      */
setHorizontalChainStyle( ChainMode horizontalChainStyle)432     public void setHorizontalChainStyle(
433             ChainMode horizontalChainStyle) {
434         this.mHorizontalChainStyle = horizontalChainStyle;
435     }
436 
437     /**
438      * get verticalChainStyle
439      *
440      * @return verticalChainStyle
441      */
442     @SuppressWarnings("HiddenTypeParameter")
getVerticalChainStyle()443     public ChainMode getVerticalChainStyle() {
444         return mVerticalChainStyle;
445     }
446 
447     /**
448      * set verticalChainStyle
449      *
450      * @param verticalChainStyle
451      */
setVerticalChainStyle( @uppressWarnings"HiddenTypeParameter") ChainMode verticalChainStyle)452     public void setVerticalChainStyle(
453             @SuppressWarnings("HiddenTypeParameter") ChainMode verticalChainStyle) {
454         this.mVerticalChainStyle = verticalChainStyle;
455     }
456 
457     /**
458      * get widthDefault
459      *
460      * @return widthDefault
461      */
462     @SuppressWarnings("HiddenTypeParameter")
getWidthDefault()463     public Behaviour getWidthDefault() {
464         return mWidthDefault;
465     }
466 
467     /**
468      * set widthDefault
469      *
470      * @param widthDefault
471      */
setWidthDefault(@uppressWarnings"HiddenTypeParameter") Behaviour widthDefault)472     public void setWidthDefault(@SuppressWarnings("HiddenTypeParameter")
473             Behaviour widthDefault) {
474         this.mWidthDefault = widthDefault;
475     }
476 
477     /**
478      * get heightDefault
479      *
480      * @return heightDefault
481      */
482     @SuppressWarnings("HiddenTypeParameter")
getHeightDefault()483     public Behaviour getHeightDefault() {
484         return mHeightDefault;
485     }
486 
487     /**
488      * set heightDefault
489      *
490      * @param heightDefault
491      */
setHeightDefault(@uppressWarnings"HiddenTypeParameter") Behaviour heightDefault)492     public void setHeightDefault(@SuppressWarnings("HiddenTypeParameter")
493             Behaviour heightDefault) {
494         this.mHeightDefault = heightDefault;
495     }
496 
497     /**
498      * get widthMax
499      *
500      * @return widthMax
501      */
getWidthMax()502     public int getWidthMax() {
503         return mWidthMax;
504     }
505 
506     /**
507      * set widthMax
508      *
509      * @param widthMax
510      */
setWidthMax(int widthMax)511     public void setWidthMax(int widthMax) {
512         this.mWidthMax = widthMax;
513     }
514 
515     /**
516      * get heightMax
517      *
518      * @return heightMax
519      */
getHeightMax()520     public int getHeightMax() {
521         return mHeightMax;
522     }
523 
524     /**
525      * set heightMax
526      *
527      * @param heightMax
528      */
setHeightMax(int heightMax)529     public void setHeightMax(int heightMax) {
530         this.mHeightMax = heightMax;
531     }
532 
533     /**
534      * get widthMin
535      *
536      * @return widthMin
537      */
getWidthMin()538     public int getWidthMin() {
539         return mWidthMin;
540     }
541 
542     /**
543      * set widthMin
544      *
545      * @param widthMin
546      */
setWidthMin(int widthMin)547     public void setWidthMin(int widthMin) {
548         this.mWidthMin = widthMin;
549     }
550 
551     /**
552      * get heightMin
553      *
554      * @return heightMin
555      */
getHeightMin()556     public int getHeightMin() {
557         return mHeightMin;
558     }
559 
560     /**
561      * set heightMin
562      *
563      * @param heightMin
564      */
setHeightMin(int heightMin)565     public void setHeightMin(int heightMin) {
566         this.mHeightMin = heightMin;
567     }
568 
569     /**
570      * get widthPercent
571      *
572      * @return
573      */
getWidthPercent()574     public float getWidthPercent() {
575         return mWidthPercent;
576     }
577 
578     /**
579      * set widthPercent
580      *
581      * @param widthPercent
582      */
setWidthPercent(float widthPercent)583     public void setWidthPercent(float widthPercent) {
584         this.mWidthPercent = widthPercent;
585     }
586 
587     /**
588      * get heightPercent
589      *
590      * @return heightPercent
591      */
getHeightPercent()592     public float getHeightPercent() {
593         return mHeightPercent;
594     }
595 
596     /**
597      * set heightPercent
598      *
599      * @param heightPercent
600      */
setHeightPercent(float heightPercent)601     public void setHeightPercent(float heightPercent) {
602         this.mHeightPercent = heightPercent;
603     }
604 
605     /**
606      * get referenceIds
607      *
608      * @return referenceIds
609      */
getReferenceIds()610     public String[] getReferenceIds() {
611         return mReferenceIds;
612     }
613 
614     /**
615      * set referenceIds
616      *
617      * @param referenceIds
618      */
setReferenceIds(String[] referenceIds)619     public void setReferenceIds(String[] referenceIds) {
620         mReferenceIds = referenceIds;
621     }
622 
623     /**
624      * is constrainedWidth
625      *
626      * @return true if width constrained
627      */
isConstrainedWidth()628     public boolean isConstrainedWidth() {
629         return mConstrainedWidth;
630     }
631 
632     /**
633      * set constrainedWidth
634      *
635      * @param constrainedWidth
636      */
setConstrainedWidth(boolean constrainedWidth)637     public void setConstrainedWidth(boolean constrainedWidth) {
638         this.mConstrainedWidth = constrainedWidth;
639     }
640 
641     /**
642      * is constrainedHeight
643      *
644      * @return true if height constrained
645      */
isConstrainedHeight()646     public boolean isConstrainedHeight() {
647         return mConstrainedHeight;
648     }
649 
650     /**
651      * set constrainedHeight
652      *
653      * @param constrainedHeight
654      */
setConstrainedHeight(boolean constrainedHeight)655     public void setConstrainedHeight(boolean constrainedHeight) {
656         this.mConstrainedHeight = constrainedHeight;
657     }
658 
659     /**
660      * get width
661      * @return width
662      */
getWidth()663     public int getWidth() {
664         return mWidth;
665     }
666 
667     /**
668      * set width
669      *
670      * @param width
671      */
setWidth(int width)672     public void setWidth(int width) {
673         mWidth = width;
674     }
675 
676     /**
677      * get height
678      * @return height
679      */
getHeight()680     public int getHeight() {
681         return mHeight;
682     }
683 
684     /**
685      * set height
686      *
687      * @param height
688      */
setHeight(int height)689     public void setHeight(int height) {
690         mHeight = height;
691     }
692 
693     /**
694      * Connect anchor to Top
695      *
696      * @param anchor anchor to be connected
697      */
linkToTop(VAnchor anchor)698     public void linkToTop(VAnchor anchor) {
699         linkToTop(anchor, 0);
700     }
701 
702     /**
703      * Connect anchor to Left
704      *
705      * @param anchor anchor to be connected
706      */
linkToLeft(HAnchor anchor)707     public void linkToLeft(HAnchor anchor) {
708         linkToLeft(anchor, 0);
709     }
710 
711     /**
712      * Connect anchor to Right
713      *
714      * @param anchor anchor to be connected
715      */
linkToRight(HAnchor anchor)716     public void linkToRight(HAnchor anchor) {
717         linkToRight(anchor, 0);
718     }
719 
720     /**
721      * Connect anchor to Start
722      *
723      * @param anchor anchor to be connected
724      */
linkToStart(HAnchor anchor)725     public void linkToStart(HAnchor anchor) {
726         linkToStart(anchor, 0);
727     }
728 
729     /**
730      * Connect anchor to End
731      *
732      * @param anchor anchor to be connected
733      */
linkToEnd(HAnchor anchor)734     public void linkToEnd(HAnchor anchor) {
735         linkToEnd(anchor, 0);
736     }
737 
738     /**
739      * Connect anchor to Bottom
740      *
741      * @param anchor anchor to be connected
742      */
linkToBottom(VAnchor anchor)743     public void linkToBottom(VAnchor anchor) {
744         linkToBottom(anchor, 0);
745     }
746 
747     /**
748      * Connect anchor to Baseline
749      *
750      * @param anchor anchor to be connected
751      */
linkToBaseline(VAnchor anchor)752     public void linkToBaseline(VAnchor anchor) {
753         linkToBaseline(anchor, 0);
754     }
755 
756     /**
757      * Connect anchor to Top
758      *
759      * @param anchor anchor to be connected
760      * @param margin value of the margin
761      */
linkToTop(VAnchor anchor, int margin)762     public void linkToTop(VAnchor anchor, int margin) {
763         linkToTop(anchor, margin, Integer.MIN_VALUE);
764     }
765 
766     /**
767      * Connect anchor to Left
768      *
769      * @param anchor anchor to be connected
770      * @param margin value of the margin
771      */
linkToLeft(HAnchor anchor, int margin)772     public void linkToLeft(HAnchor anchor, int margin) {
773         linkToLeft(anchor, margin, Integer.MIN_VALUE);
774     }
775 
776     /**
777      * Connect anchor to Right
778      *
779      * @param anchor anchor to be connected
780      * @param margin value of the margin
781      */
linkToRight(HAnchor anchor, int margin)782     public void linkToRight(HAnchor anchor, int margin) {
783         linkToRight(anchor, margin, Integer.MIN_VALUE);
784     }
785 
786     /**
787      * Connect anchor to Start
788      *
789      * @param anchor anchor to be connected
790      * @param margin value of the margin
791      */
linkToStart(HAnchor anchor, int margin)792     public void linkToStart(HAnchor anchor, int margin) {
793         linkToStart(anchor, margin, Integer.MIN_VALUE);
794     }
795 
796     /**
797      * Connect anchor to End
798      *
799      * @param anchor anchor to be connected
800      * @param margin value of the margin
801      */
linkToEnd(HAnchor anchor, int margin)802     public void linkToEnd(HAnchor anchor, int margin) {
803         linkToEnd(anchor, margin, Integer.MIN_VALUE);
804     }
805 
806     /**
807      * Connect anchor to Bottom
808      *
809      * @param anchor anchor to be connected
810      * @param margin value of the margin
811      */
linkToBottom(VAnchor anchor, int margin)812     public void linkToBottom(VAnchor anchor, int margin) {
813         linkToBottom(anchor, margin, Integer.MIN_VALUE);
814     }
815 
816     /**
817      * Connect anchor to Baseline
818      *
819      * @param anchor anchor to be connected
820      * @param margin value of the margin
821      */
linkToBaseline(VAnchor anchor, int margin)822     public void linkToBaseline(VAnchor anchor, int margin) {
823         linkToBaseline(anchor, margin, Integer.MIN_VALUE);
824     }
825 
826     /**
827      * Connect anchor to Top
828      *
829      * @param anchor anchor to be connected
830      * @param margin value of the margin
831      * @param goneMargin value of the goneMargin
832      */
linkToTop(VAnchor anchor, int margin, int goneMargin)833     public void linkToTop(VAnchor anchor, int margin, int goneMargin) {
834         mTop.mConnection = anchor;
835         mTop.mMargin = margin;
836         mTop.mGoneMargin = goneMargin;
837     }
838 
839     /**
840      * Connect anchor to Left
841      *
842      * @param anchor anchor to be connected
843      * @param margin value of the margin
844      * @param goneMargin value of the goneMargin
845      */
linkToLeft(HAnchor anchor, int margin, int goneMargin)846     public void linkToLeft(HAnchor anchor, int margin, int goneMargin) {
847         mLeft.mConnection = anchor;
848         mLeft.mMargin = margin;
849         mLeft.mGoneMargin = goneMargin;
850     }
851 
852     /**
853      * Connect anchor to Right
854      *
855      * @param anchor anchor to be connected
856      * @param margin value of the margin
857      * @param goneMargin value of the goneMargin
858      */
linkToRight(HAnchor anchor, int margin, int goneMargin)859     public void linkToRight(HAnchor anchor, int margin, int goneMargin) {
860         mRight.mConnection = anchor;
861         mRight.mMargin = margin;
862         mRight.mGoneMargin = goneMargin;
863     }
864 
865     /**
866      * Connect anchor to Start
867      *
868      * @param anchor anchor to be connected
869      * @param margin value of the margin
870      * @param goneMargin value of the goneMargin
871      */
linkToStart(HAnchor anchor, int margin, int goneMargin)872     public void linkToStart(HAnchor anchor, int margin, int goneMargin) {
873         mStart.mConnection = anchor;
874         mStart.mMargin = margin;
875         mStart.mGoneMargin = goneMargin;
876     }
877 
878     /**
879      * Connect anchor to End
880      *
881      * @param anchor anchor to be connected
882      * @param margin value of the margin
883      * @param goneMargin value of the goneMargin
884      */
linkToEnd(HAnchor anchor, int margin, int goneMargin)885     public void linkToEnd(HAnchor anchor, int margin, int goneMargin) {
886         mEnd.mConnection = anchor;
887         mEnd.mMargin = margin;
888         mEnd.mGoneMargin = goneMargin;
889     }
890 
891     /**
892      * Connect anchor to Bottom
893      *
894      * @param anchor anchor to be connected
895      * @param margin value of the margin
896      * @param goneMargin value of the goneMargin
897      */
linkToBottom(VAnchor anchor, int margin, int goneMargin)898     public void linkToBottom(VAnchor anchor, int margin, int goneMargin) {
899         mBottom.mConnection = anchor;
900         mBottom.mMargin = margin;
901         mBottom.mGoneMargin = goneMargin;
902     }
903 
904     /**
905      * Connect anchor to Baseline
906      *
907      * @param anchor anchor to be connected
908      * @param margin value of the margin
909      * @param goneMargin value of the goneMargin
910      */
linkToBaseline(VAnchor anchor, int margin, int goneMargin)911     public void linkToBaseline(VAnchor anchor, int margin, int goneMargin) {
912         mBaseline.mConnection = anchor;
913         mBaseline.mMargin = margin;
914         mBaseline.mGoneMargin = goneMargin;
915     }
916 
917     /**
918      * convert a String array into a String representation
919      *
920      * @param str String array to be converted
921      * @return a String representation of the input array.
922      */
convertStringArrayToString(String[] str)923     public String convertStringArrayToString(String[] str) {
924         StringBuilder ret = new StringBuilder("[");
925         for (int i = 0; i < str.length; i++) {
926 
927             ret.append((i == 0) ? "'" : ",'");
928 
929             ret.append(str[i]);
930             ret.append("'");
931 
932         }
933         ret.append("]");
934         return ret.toString();
935     }
936 
append(StringBuilder builder, String name, float value)937     protected void append(StringBuilder builder, String name, float value) {
938         if (Float.isNaN(value)) {
939             return;
940         }
941         builder.append(name);
942         builder.append(":").append(value).append(",\n");
943 
944     }
945 
946     @Override
toString()947     public String toString() {
948         StringBuilder ret = new StringBuilder(mId + ":{\n");
949         mLeft.build(ret);
950         mRight.build(ret);
951         mTop.build(ret);
952         mBottom.build(ret);
953         mStart.build(ret);
954         mEnd.build(ret);
955         mBaseline.build(ret);
956 
957         if (mWidth != UNSET) {
958             ret.append("width:").append(mWidth).append(",\n");
959         }
960         if (mHeight != UNSET) {
961             ret.append("height:").append(mHeight).append(",\n");
962         }
963         append(ret, "horizontalBias", mHorizontalBias);
964         append(ret, "verticalBias", mVerticalBias);
965         if (mDimensionRatio != null) {
966             ret.append("dimensionRatio:'").append(mDimensionRatio).append("',\n");
967         }
968         if (mCircleConstraint != null) {
969             if (!Float.isNaN(mCircleAngle) || mCircleRadius != Integer.MIN_VALUE) {
970                 ret.append("circular:['").append(mCircleConstraint).append("'");
971                 if (!Float.isNaN(mCircleAngle)) {
972                     ret.append(",").append(mCircleAngle);
973                 }
974                 if (mCircleRadius != Integer.MIN_VALUE) {
975                     if (Float.isNaN(mCircleAngle)) {
976                         ret.append(",0,").append(mCircleRadius);
977                     } else {
978                         ret.append(",").append(mCircleRadius);
979                     }
980                 }
981                 ret.append("],\n");
982             }
983         }
984         append(ret, "verticalWeight", mVerticalWeight);
985         append(ret, "horizontalWeight", mHorizontalWeight);
986         if (mHorizontalChainStyle != null) {
987             ret.append("horizontalChainStyle:'").append(chainModeMap.get(mHorizontalChainStyle))
988                     .append("',\n");
989         }
990         if (mVerticalChainStyle != null) {
991             ret.append("verticalChainStyle:'").append(chainModeMap.get(mVerticalChainStyle))
992                     .append("',\n");
993         }
994         if (mWidthDefault != null) {
995             if (mWidthMax == UNSET && mWidthMin == UNSET) {
996                 ret.append("width:'").append(mWidthDefault.toString().toLowerCase())
997                         .append("',\n");
998             } else {
999                 ret.append("width:{value:'").append(mWidthDefault.toString().toLowerCase())
1000                         .append("'");
1001                 if (mWidthMax != UNSET) {
1002                     ret.append(",max:").append(mWidthMax);
1003                 }
1004                 if (mWidthMin != UNSET) {
1005                     ret.append(",min:").append(mWidthMin);
1006                 }
1007                 ret.append("},\n");
1008             }
1009         }
1010         if (mHeightDefault != null) {
1011             if (mHeightMax == UNSET && mHeightMin == UNSET) {
1012                 ret.append("height:'").append(mHeightDefault.toString().toLowerCase())
1013                         .append("',\n");
1014             } else {
1015                 ret.append("height:{value:'").append(mHeightDefault.toString().toLowerCase())
1016                         .append("'");
1017                 if (mHeightMax != UNSET) {
1018                     ret.append(",max:").append(mHeightMax);
1019                 }
1020                 if (mHeightMin != UNSET) {
1021                     ret.append(",min:").append(mHeightMin);
1022                 }
1023                 ret.append("},\n");
1024             }
1025         }
1026         if (!Double.isNaN(mWidthPercent)) {
1027             ret.append("width:'").append((int) mWidthPercent).append("%',\n");
1028         }
1029         if (!Double.isNaN(mHeightPercent)) {
1030             ret.append("height:'").append((int) mHeightPercent).append("%',\n");
1031         }
1032         if (mReferenceIds != null) {
1033             ret.append("referenceIds:")
1034                     .append(convertStringArrayToString(mReferenceIds))
1035                     .append(",\n");
1036         }
1037         if (mConstrainedWidth) {
1038             ret.append("constrainedWidth:").append(mConstrainedWidth).append(",\n");
1039         }
1040         if (mConstrainedHeight) {
1041             ret.append("constrainedHeight:").append(mConstrainedHeight).append(",\n");
1042         }
1043 
1044         ret.append("},\n");
1045         return ret.toString();
1046     }
1047 }
1048