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.HORIZONTAL; 20 import static androidx.constraintlayout.core.widgets.ConstraintWidget.UNKNOWN; 21 import static androidx.constraintlayout.core.widgets.ConstraintWidget.VERTICAL; 22 23 import androidx.constraintlayout.core.motion.utils.TypedBundle; 24 import androidx.constraintlayout.core.motion.utils.TypedValues; 25 import androidx.constraintlayout.core.state.helpers.Facade; 26 import androidx.constraintlayout.core.widgets.ConstraintAnchor; 27 import androidx.constraintlayout.core.widgets.ConstraintWidget; 28 29 import org.jspecify.annotations.Nullable; 30 31 import java.util.ArrayList; 32 import java.util.HashMap; 33 34 public class ConstraintReference implements Reference { 35 36 private Object mKey; 37 38 @Override setKey(Object key)39 public void setKey(Object key) { 40 this.mKey = key; 41 } 42 43 @Override getKey()44 public Object getKey() { 45 return mKey; 46 } 47 setTag(String tag)48 public void setTag(String tag) { 49 mTag = tag; 50 } 51 getTag()52 public String getTag() { 53 return mTag; 54 } 55 56 public interface ConstraintReferenceFactory { 57 // @TODO: add description create(State state)58 ConstraintReference create(State state); 59 } 60 61 final State mState; 62 63 String mTag = null; 64 65 Facade mFacade = null; 66 67 int mHorizontalChainStyle = ConstraintWidget.CHAIN_SPREAD; 68 int mVerticalChainStyle = ConstraintWidget.CHAIN_SPREAD; 69 70 float mHorizontalChainWeight = UNKNOWN; 71 float mVerticalChainWeight = UNKNOWN; 72 73 protected float mHorizontalBias = 0.5f; 74 protected float mVerticalBias = 0.5f; 75 76 protected int mMarginLeft = 0; 77 protected int mMarginRight = 0; 78 protected int mMarginStart = 0; 79 protected int mMarginEnd = 0; 80 protected int mMarginTop = 0; 81 protected int mMarginBottom = 0; 82 83 protected int mMarginLeftGone = 0; 84 protected int mMarginRightGone = 0; 85 protected int mMarginStartGone = 0; 86 protected int mMarginEndGone = 0; 87 protected int mMarginTopGone = 0; 88 protected int mMarginBottomGone = 0; 89 90 int mMarginBaseline = 0; 91 int mMarginBaselineGone = 0; 92 93 float mPivotX = Float.NaN; 94 float mPivotY = Float.NaN; 95 96 float mRotationX = Float.NaN; 97 float mRotationY = Float.NaN; 98 float mRotationZ = Float.NaN; 99 100 float mTranslationX = Float.NaN; 101 float mTranslationY = Float.NaN; 102 float mTranslationZ = Float.NaN; 103 104 float mAlpha = Float.NaN; 105 106 float mScaleX = Float.NaN; 107 float mScaleY = Float.NaN; 108 109 int mVisibility = ConstraintWidget.VISIBLE; 110 111 protected Object mLeftToLeft = null; 112 protected Object mLeftToRight = null; 113 protected Object mRightToLeft = null; 114 protected Object mRightToRight = null; 115 protected Object mStartToStart = null; 116 protected Object mStartToEnd = null; 117 protected Object mEndToStart = null; 118 protected Object mEndToEnd = null; 119 protected Object mTopToTop = null; 120 protected Object mTopToBottom = null; 121 @Nullable Object mTopToBaseline = null; 122 protected Object mBottomToTop = null; 123 protected Object mBottomToBottom = null; 124 @Nullable Object mBottomToBaseline = null; 125 Object mBaselineToBaseline = null; 126 Object mBaselineToTop = null; 127 Object mBaselineToBottom = null; 128 Object mCircularConstraint = null; 129 private float mCircularAngle; 130 private float mCircularDistance; 131 132 State.Constraint mLast = null; 133 134 Dimension mHorizontalDimension = Dimension.createFixed(Dimension.WRAP_DIMENSION); 135 Dimension mVerticalDimension = Dimension.createFixed(Dimension.WRAP_DIMENSION); 136 137 private Object mView; 138 private ConstraintWidget mConstraintWidget; 139 140 private HashMap<String, Integer> mCustomColors = new HashMap<>(); 141 private HashMap<String, Float> mCustomFloats = new HashMap<>(); 142 143 TypedBundle mMotionProperties = null; 144 145 // @TODO: add description setView(Object view)146 public void setView(Object view) { 147 mView = view; 148 if (mConstraintWidget != null) { 149 mConstraintWidget.setCompanionWidget(mView); 150 } 151 } 152 getView()153 public Object getView() { 154 return mView; 155 } 156 157 // @TODO: add description setFacade(Facade facade)158 public void setFacade(Facade facade) { 159 mFacade = facade; 160 if (facade != null) { 161 setConstraintWidget(facade.getConstraintWidget()); 162 } 163 } 164 165 @Override getFacade()166 public Facade getFacade() { 167 return mFacade; 168 } 169 170 // @TODO: add description 171 @Override setConstraintWidget(ConstraintWidget widget)172 public void setConstraintWidget(ConstraintWidget widget) { 173 if (widget == null) { 174 return; 175 } 176 mConstraintWidget = widget; 177 mConstraintWidget.setCompanionWidget(mView); 178 } 179 180 @Override getConstraintWidget()181 public ConstraintWidget getConstraintWidget() { 182 if (mConstraintWidget == null) { 183 mConstraintWidget = createConstraintWidget(); 184 mConstraintWidget.setCompanionWidget(mView); 185 } 186 return mConstraintWidget; 187 } 188 189 // @TODO: add description createConstraintWidget()190 public ConstraintWidget createConstraintWidget() { 191 return new ConstraintWidget( 192 getWidth().getValue(), 193 getHeight().getValue()); 194 } 195 196 static class IncorrectConstraintException extends Exception { 197 198 private final ArrayList<String> mErrors; 199 IncorrectConstraintException(ArrayList<String> errors)200 IncorrectConstraintException(ArrayList<String> errors) { 201 mErrors = errors; 202 } 203 getErrors()204 public ArrayList<String> getErrors() { 205 return mErrors; 206 } 207 208 @Override getMessage()209 public String getMessage() { return toString(); } 210 211 @Override toString()212 public String toString() { 213 return "IncorrectConstraintException: " + mErrors.toString(); 214 } 215 } 216 217 /** 218 * Validate the constraints 219 */ validate()220 public void validate() throws IncorrectConstraintException { 221 ArrayList<String> errors = new ArrayList<>(); 222 if (mLeftToLeft != null && mLeftToRight != null) { 223 errors.add("LeftToLeft and LeftToRight both defined"); 224 } 225 if (mRightToLeft != null && mRightToRight != null) { 226 errors.add("RightToLeft and RightToRight both defined"); 227 } 228 if (mStartToStart != null && mStartToEnd != null) { 229 errors.add("StartToStart and StartToEnd both defined"); 230 } 231 if (mEndToStart != null && mEndToEnd != null) { 232 errors.add("EndToStart and EndToEnd both defined"); 233 } 234 if ((mLeftToLeft != null || mLeftToRight != null 235 || mRightToLeft != null || mRightToRight != null) 236 && (mStartToStart != null || mStartToEnd != null 237 || mEndToStart != null || mEndToEnd != null)) { 238 errors.add("Both left/right and start/end constraints defined"); 239 } 240 if (errors.size() > 0) { 241 throw new IncorrectConstraintException(errors); 242 } 243 } 244 get(Object reference)245 private Object get(Object reference) { 246 if (reference == null) { 247 return null; 248 } 249 if (!(reference instanceof ConstraintReference)) { 250 return mState.reference(reference); 251 } 252 return reference; 253 } 254 ConstraintReference(State state)255 public ConstraintReference(State state) { 256 mState = state; 257 } 258 setHorizontalChainStyle(int chainStyle)259 public void setHorizontalChainStyle(int chainStyle) { 260 mHorizontalChainStyle = chainStyle; 261 } 262 getHorizontalChainStyle()263 public int getHorizontalChainStyle() { 264 return mHorizontalChainStyle; 265 } 266 setVerticalChainStyle(int chainStyle)267 public void setVerticalChainStyle(int chainStyle) { 268 mVerticalChainStyle = chainStyle; 269 } 270 271 // @TODO: add description getVerticalChainStyle(int chainStyle)272 public int getVerticalChainStyle(int chainStyle) { 273 return mVerticalChainStyle; 274 } 275 getHorizontalChainWeight()276 public float getHorizontalChainWeight() { 277 return mHorizontalChainWeight; 278 } 279 setHorizontalChainWeight(float weight)280 public void setHorizontalChainWeight(float weight) { 281 mHorizontalChainWeight = weight; 282 } 283 getVerticalChainWeight()284 public float getVerticalChainWeight() { 285 return mVerticalChainWeight; 286 } 287 setVerticalChainWeight(float weight)288 public void setVerticalChainWeight(float weight) { 289 mVerticalChainWeight = weight; 290 } 291 292 // @TODO: add description clearVertical()293 public ConstraintReference clearVertical() { 294 top().clear(); 295 baseline().clear(); 296 bottom().clear(); 297 return this; 298 } 299 300 // @TODO: add description clearHorizontal()301 public ConstraintReference clearHorizontal() { 302 start().clear(); 303 end().clear(); 304 left().clear(); 305 right().clear(); 306 return this; 307 } 308 getTranslationX()309 public float getTranslationX() { 310 return mTranslationX; 311 } 312 getTranslationY()313 public float getTranslationY() { 314 return mTranslationY; 315 } 316 getTranslationZ()317 public float getTranslationZ() { 318 return mTranslationZ; 319 } 320 getScaleX()321 public float getScaleX() { 322 return mScaleX; 323 } 324 getScaleY()325 public float getScaleY() { 326 return mScaleY; 327 } 328 getAlpha()329 public float getAlpha() { 330 return mAlpha; 331 } 332 getPivotX()333 public float getPivotX() { 334 return mPivotX; 335 } 336 getPivotY()337 public float getPivotY() { 338 return mPivotY; 339 } 340 getRotationX()341 public float getRotationX() { 342 return mRotationX; 343 } 344 getRotationY()345 public float getRotationY() { 346 return mRotationY; 347 } 348 getRotationZ()349 public float getRotationZ() { 350 return mRotationZ; 351 } 352 353 // @TODO: add description pivotX(float x)354 public ConstraintReference pivotX(float x) { 355 mPivotX = x; 356 return this; 357 } 358 359 // @TODO: add description pivotY(float y)360 public ConstraintReference pivotY(float y) { 361 mPivotY = y; 362 return this; 363 } 364 365 // @TODO: add description rotationX(float x)366 public ConstraintReference rotationX(float x) { 367 mRotationX = x; 368 return this; 369 } 370 371 // @TODO: add description rotationY(float y)372 public ConstraintReference rotationY(float y) { 373 mRotationY = y; 374 return this; 375 } 376 377 // @TODO: add description rotationZ(float z)378 public ConstraintReference rotationZ(float z) { 379 mRotationZ = z; 380 return this; 381 } 382 383 // @TODO: add description translationX(float x)384 public ConstraintReference translationX(float x) { 385 mTranslationX = x; 386 return this; 387 } 388 389 // @TODO: add description translationY(float y)390 public ConstraintReference translationY(float y) { 391 mTranslationY = y; 392 return this; 393 } 394 395 // @TODO: add description translationZ(float z)396 public ConstraintReference translationZ(float z) { 397 mTranslationZ = z; 398 return this; 399 } 400 401 // @TODO: add description scaleX(float x)402 public ConstraintReference scaleX(float x) { 403 mScaleX = x; 404 return this; 405 } 406 407 // @TODO: add description scaleY(float y)408 public ConstraintReference scaleY(float y) { 409 mScaleY = y; 410 return this; 411 } 412 413 // @TODO: add description alpha(float alpha)414 public ConstraintReference alpha(float alpha) { 415 mAlpha = alpha; 416 return this; 417 } 418 419 // @TODO: add description visibility(int visibility)420 public ConstraintReference visibility(int visibility) { 421 mVisibility = visibility; 422 return this; 423 } 424 425 // @TODO: add description left()426 public ConstraintReference left() { 427 if (mLeftToLeft != null) { 428 mLast = State.Constraint.LEFT_TO_LEFT; 429 } else { 430 mLast = State.Constraint.LEFT_TO_RIGHT; 431 } 432 return this; 433 } 434 435 // @TODO: add description right()436 public ConstraintReference right() { 437 if (mRightToLeft != null) { 438 mLast = State.Constraint.RIGHT_TO_LEFT; 439 } else { 440 mLast = State.Constraint.RIGHT_TO_RIGHT; 441 } 442 return this; 443 } 444 445 // @TODO: add description start()446 public ConstraintReference start() { 447 if (mStartToStart != null) { 448 mLast = State.Constraint.START_TO_START; 449 } else { 450 mLast = State.Constraint.START_TO_END; 451 } 452 return this; 453 } 454 455 // @TODO: add description end()456 public ConstraintReference end() { 457 if (mEndToStart != null) { 458 mLast = State.Constraint.END_TO_START; 459 } else { 460 mLast = State.Constraint.END_TO_END; 461 } 462 return this; 463 } 464 465 // @TODO: add description top()466 public ConstraintReference top() { 467 if (mTopToTop != null) { 468 mLast = State.Constraint.TOP_TO_TOP; 469 } else { 470 mLast = State.Constraint.TOP_TO_BOTTOM; 471 } 472 return this; 473 } 474 475 // @TODO: add description bottom()476 public ConstraintReference bottom() { 477 if (mBottomToTop != null) { 478 mLast = State.Constraint.BOTTOM_TO_TOP; 479 } else { 480 mLast = State.Constraint.BOTTOM_TO_BOTTOM; 481 } 482 return this; 483 } 484 485 // @TODO: add description baseline()486 public ConstraintReference baseline() { 487 mLast = State.Constraint.BASELINE_TO_BASELINE; 488 return this; 489 } 490 491 // @TODO: add description addCustomColor(String name, int color)492 public void addCustomColor(String name, int color) { 493 mCustomColors.put(name, color); 494 } 495 496 // @TODO: add description addCustomFloat(String name, float value)497 public void addCustomFloat(String name, float value) { 498 if (mCustomFloats == null) { 499 mCustomFloats = new HashMap<>(); 500 } 501 mCustomFloats.put(name, value); 502 } 503 dereference()504 private void dereference() { 505 mLeftToLeft = get(mLeftToLeft); 506 mLeftToRight = get(mLeftToRight); 507 mRightToLeft = get(mRightToLeft); 508 mRightToRight = get(mRightToRight); 509 mStartToStart = get(mStartToStart); 510 mStartToEnd = get(mStartToEnd); 511 mEndToStart = get(mEndToStart); 512 mEndToEnd = get(mEndToEnd); 513 mTopToTop = get(mTopToTop); 514 mTopToBottom = get(mTopToBottom); 515 mBottomToTop = get(mBottomToTop); 516 mBottomToBottom = get(mBottomToBottom); 517 mBaselineToBaseline = get(mBaselineToBaseline); 518 mBaselineToTop = get(mBaselineToTop); 519 mBaselineToBottom = get(mBaselineToBottom); 520 } 521 522 // @TODO: add description leftToLeft(Object reference)523 public ConstraintReference leftToLeft(Object reference) { 524 mLast = State.Constraint.LEFT_TO_LEFT; 525 mLeftToLeft = reference; 526 return this; 527 } 528 529 // @TODO: add description leftToRight(Object reference)530 public ConstraintReference leftToRight(Object reference) { 531 mLast = State.Constraint.LEFT_TO_RIGHT; 532 mLeftToRight = reference; 533 return this; 534 } 535 536 // @TODO: add description rightToLeft(Object reference)537 public ConstraintReference rightToLeft(Object reference) { 538 mLast = State.Constraint.RIGHT_TO_LEFT; 539 mRightToLeft = reference; 540 return this; 541 } 542 543 // @TODO: add description rightToRight(Object reference)544 public ConstraintReference rightToRight(Object reference) { 545 mLast = State.Constraint.RIGHT_TO_RIGHT; 546 mRightToRight = reference; 547 return this; 548 } 549 550 // @TODO: add description startToStart(Object reference)551 public ConstraintReference startToStart(Object reference) { 552 mLast = State.Constraint.START_TO_START; 553 mStartToStart = reference; 554 return this; 555 } 556 557 // @TODO: add description startToEnd(Object reference)558 public ConstraintReference startToEnd(Object reference) { 559 mLast = State.Constraint.START_TO_END; 560 mStartToEnd = reference; 561 return this; 562 } 563 564 // @TODO: add description endToStart(Object reference)565 public ConstraintReference endToStart(Object reference) { 566 mLast = State.Constraint.END_TO_START; 567 mEndToStart = reference; 568 return this; 569 } 570 571 // @TODO: add description endToEnd(Object reference)572 public ConstraintReference endToEnd(Object reference) { 573 mLast = State.Constraint.END_TO_END; 574 mEndToEnd = reference; 575 return this; 576 } 577 578 // @TODO: add description topToTop(Object reference)579 public ConstraintReference topToTop(Object reference) { 580 mLast = State.Constraint.TOP_TO_TOP; 581 mTopToTop = reference; 582 return this; 583 } 584 585 // @TODO: add description topToBottom(Object reference)586 public ConstraintReference topToBottom(Object reference) { 587 mLast = State.Constraint.TOP_TO_BOTTOM; 588 mTopToBottom = reference; 589 return this; 590 } 591 topToBaseline(Object reference)592 ConstraintReference topToBaseline(Object reference) { 593 mLast = State.Constraint.TOP_TO_BASELINE; 594 mTopToBaseline = reference; 595 return this; 596 } 597 598 // @TODO: add description bottomToTop(Object reference)599 public ConstraintReference bottomToTop(Object reference) { 600 mLast = State.Constraint.BOTTOM_TO_TOP; 601 mBottomToTop = reference; 602 return this; 603 } 604 605 // @TODO: add description bottomToBottom(Object reference)606 public ConstraintReference bottomToBottom(Object reference) { 607 mLast = State.Constraint.BOTTOM_TO_BOTTOM; 608 mBottomToBottom = reference; 609 return this; 610 } 611 bottomToBaseline(Object reference)612 ConstraintReference bottomToBaseline(Object reference) { 613 mLast = State.Constraint.BOTTOM_TO_BASELINE; 614 mBottomToBaseline = reference; 615 return this; 616 } 617 618 // @TODO: add description baselineToBaseline(Object reference)619 public ConstraintReference baselineToBaseline(Object reference) { 620 mLast = State.Constraint.BASELINE_TO_BASELINE; 621 mBaselineToBaseline = reference; 622 return this; 623 } 624 625 // @TODO: add description baselineToTop(Object reference)626 public ConstraintReference baselineToTop(Object reference) { 627 mLast = State.Constraint.BASELINE_TO_TOP; 628 mBaselineToTop = reference; 629 return this; 630 } 631 632 // @TODO: add description baselineToBottom(Object reference)633 public ConstraintReference baselineToBottom(Object reference) { 634 mLast = State.Constraint.BASELINE_TO_BOTTOM; 635 mBaselineToBottom = reference; 636 return this; 637 } 638 639 // @TODO: add description centerHorizontally(Object reference)640 public ConstraintReference centerHorizontally(Object reference) { 641 Object ref = get(reference); 642 mStartToStart = ref; 643 mEndToEnd = ref; 644 mLast = State.Constraint.CENTER_HORIZONTALLY; 645 mHorizontalBias = 0.5f; 646 return this; 647 } 648 649 // @TODO: add description centerVertically(Object reference)650 public ConstraintReference centerVertically(Object reference) { 651 Object ref = get(reference); 652 mTopToTop = ref; 653 mBottomToBottom = ref; 654 mLast = State.Constraint.CENTER_VERTICALLY; 655 mVerticalBias = 0.5f; 656 return this; 657 } 658 659 // @TODO: add description circularConstraint(Object reference, float angle, float distance)660 public ConstraintReference circularConstraint(Object reference, float angle, float distance) { 661 Object ref = get(reference); 662 mCircularConstraint = ref; 663 mCircularAngle = angle; 664 mCircularDistance = distance; 665 mLast = State.Constraint.CIRCULAR_CONSTRAINT; 666 return this; 667 } 668 669 // @TODO: add description width(Dimension dimension)670 public ConstraintReference width(Dimension dimension) { 671 return setWidth(dimension); 672 } 673 674 // @TODO: add description height(Dimension dimension)675 public ConstraintReference height(Dimension dimension) { 676 return setHeight(dimension); 677 } 678 getWidth()679 public Dimension getWidth() { 680 return mHorizontalDimension; 681 } 682 683 // @TODO: add description setWidth(Dimension dimension)684 public ConstraintReference setWidth(Dimension dimension) { 685 mHorizontalDimension = dimension; 686 return this; 687 } 688 getHeight()689 public Dimension getHeight() { 690 return mVerticalDimension; 691 } 692 693 // @TODO: add description setHeight(Dimension dimension)694 public ConstraintReference setHeight(Dimension dimension) { 695 mVerticalDimension = dimension; 696 return this; 697 } 698 699 // @TODO: add description margin(Object marginValue)700 public ConstraintReference margin(Object marginValue) { 701 return margin(mState.convertDimension(marginValue)); 702 } 703 704 // @TODO: add description marginGone(Object marginGoneValue)705 public ConstraintReference marginGone(Object marginGoneValue) { 706 return marginGone(mState.convertDimension(marginGoneValue)); 707 } 708 709 // @TODO: add description margin(int value)710 public ConstraintReference margin(int value) { 711 if (mLast != null) { 712 switch (mLast) { 713 case LEFT_TO_LEFT: 714 case LEFT_TO_RIGHT: { 715 mMarginLeft = value; 716 } 717 break; 718 case RIGHT_TO_LEFT: 719 case RIGHT_TO_RIGHT: { 720 mMarginRight = value; 721 } 722 break; 723 case START_TO_START: 724 case START_TO_END: { 725 mMarginStart = value; 726 } 727 break; 728 case END_TO_START: 729 case END_TO_END: { 730 mMarginEnd = value; 731 } 732 break; 733 case TOP_TO_TOP: 734 case TOP_TO_BOTTOM: 735 case TOP_TO_BASELINE: { 736 mMarginTop = value; 737 } 738 break; 739 case BOTTOM_TO_TOP: 740 case BOTTOM_TO_BOTTOM: 741 case BOTTOM_TO_BASELINE: { 742 mMarginBottom = value; 743 } 744 break; 745 case BASELINE_TO_BOTTOM: 746 case BASELINE_TO_TOP: 747 case BASELINE_TO_BASELINE: { 748 mMarginBaseline = value; 749 } 750 break; 751 case CIRCULAR_CONSTRAINT: { 752 mCircularDistance = value; 753 } 754 break; 755 default: 756 break; 757 } 758 } else { 759 mMarginLeft = value; 760 mMarginRight = value; 761 mMarginStart = value; 762 mMarginEnd = value; 763 mMarginTop = value; 764 mMarginBottom = value; 765 } 766 return this; 767 } 768 769 // @TODO: add description marginGone(int value)770 public ConstraintReference marginGone(int value) { 771 if (mLast != null) { 772 switch (mLast) { 773 case LEFT_TO_LEFT: 774 case LEFT_TO_RIGHT: { 775 mMarginLeftGone = value; 776 } 777 break; 778 case RIGHT_TO_LEFT: 779 case RIGHT_TO_RIGHT: { 780 mMarginRightGone = value; 781 } 782 break; 783 case START_TO_START: 784 case START_TO_END: { 785 mMarginStartGone = value; 786 } 787 break; 788 case END_TO_START: 789 case END_TO_END: { 790 mMarginEndGone = value; 791 } 792 break; 793 case TOP_TO_TOP: 794 case TOP_TO_BOTTOM: 795 case TOP_TO_BASELINE: { 796 mMarginTopGone = value; 797 } 798 break; 799 case BOTTOM_TO_TOP: 800 case BOTTOM_TO_BOTTOM: 801 case BOTTOM_TO_BASELINE: { 802 mMarginBottomGone = value; 803 } 804 break; 805 case BASELINE_TO_TOP: 806 case BASELINE_TO_BOTTOM: 807 case BASELINE_TO_BASELINE: { 808 mMarginBaselineGone = value; 809 } 810 break; 811 default: 812 break; 813 } 814 } else { 815 mMarginLeftGone = value; 816 mMarginRightGone = value; 817 mMarginStartGone = value; 818 mMarginEndGone = value; 819 mMarginTopGone = value; 820 mMarginBottomGone = value; 821 } 822 return this; 823 } 824 825 // @TODO: add description horizontalBias(float value)826 public ConstraintReference horizontalBias(float value) { 827 mHorizontalBias = value; 828 return this; 829 } 830 831 // @TODO: add description verticalBias(float value)832 public ConstraintReference verticalBias(float value) { 833 mVerticalBias = value; 834 return this; 835 } 836 837 // @TODO: add description bias(float value)838 public ConstraintReference bias(float value) { 839 if (mLast == null) { 840 return this; 841 } 842 switch (mLast) { 843 case CENTER_HORIZONTALLY: 844 case LEFT_TO_LEFT: 845 case LEFT_TO_RIGHT: 846 case RIGHT_TO_LEFT: 847 case RIGHT_TO_RIGHT: 848 case START_TO_START: 849 case START_TO_END: 850 case END_TO_START: 851 case END_TO_END: { 852 mHorizontalBias = value; 853 } 854 break; 855 case CENTER_VERTICALLY: 856 case TOP_TO_TOP: 857 case TOP_TO_BOTTOM: 858 case TOP_TO_BASELINE: 859 case BOTTOM_TO_TOP: 860 case BOTTOM_TO_BOTTOM: 861 case BOTTOM_TO_BASELINE: { 862 mVerticalBias = value; 863 } 864 break; 865 default: 866 break; 867 } 868 return this; 869 } 870 871 /** 872 * Clears all constraints. 873 */ clearAll()874 public ConstraintReference clearAll() { 875 mLeftToLeft = null; 876 mLeftToRight = null; 877 mMarginLeft = 0; 878 mRightToLeft = null; 879 mRightToRight = null; 880 mMarginRight = 0; 881 mStartToStart = null; 882 mStartToEnd = null; 883 mMarginStart = 0; 884 mEndToStart = null; 885 mEndToEnd = null; 886 mMarginEnd = 0; 887 mTopToTop = null; 888 mTopToBottom = null; 889 mMarginTop = 0; 890 mBottomToTop = null; 891 mBottomToBottom = null; 892 mMarginBottom = 0; 893 mBaselineToBaseline = null; 894 mCircularConstraint = null; 895 mHorizontalBias = 0.5f; 896 mVerticalBias = 0.5f; 897 mMarginLeftGone = 0; 898 mMarginRightGone = 0; 899 mMarginStartGone = 0; 900 mMarginEndGone = 0; 901 mMarginTopGone = 0; 902 mMarginBottomGone = 0; 903 return this; 904 } 905 906 // @TODO: add description clear()907 public ConstraintReference clear() { 908 if (mLast != null) { 909 switch (mLast) { 910 case LEFT_TO_LEFT: 911 case LEFT_TO_RIGHT: { 912 mLeftToLeft = null; 913 mLeftToRight = null; 914 mMarginLeft = 0; 915 mMarginLeftGone = 0; 916 } 917 break; 918 case RIGHT_TO_LEFT: 919 case RIGHT_TO_RIGHT: { 920 mRightToLeft = null; 921 mRightToRight = null; 922 mMarginRight = 0; 923 mMarginRightGone = 0; 924 } 925 break; 926 case START_TO_START: 927 case START_TO_END: { 928 mStartToStart = null; 929 mStartToEnd = null; 930 mMarginStart = 0; 931 mMarginStartGone = 0; 932 } 933 break; 934 case END_TO_START: 935 case END_TO_END: { 936 mEndToStart = null; 937 mEndToEnd = null; 938 mMarginEnd = 0; 939 mMarginEndGone = 0; 940 } 941 break; 942 case TOP_TO_TOP: 943 case TOP_TO_BOTTOM: 944 case TOP_TO_BASELINE: { 945 mTopToTop = null; 946 mTopToBottom = null; 947 mTopToBaseline = null; 948 mMarginTop = 0; 949 mMarginTopGone = 0; 950 } 951 break; 952 case BOTTOM_TO_TOP: 953 case BOTTOM_TO_BOTTOM: 954 case BOTTOM_TO_BASELINE: { 955 mBottomToTop = null; 956 mBottomToBottom = null; 957 mBottomToBaseline = null; 958 mMarginBottom = 0; 959 mMarginBottomGone = 0; 960 } 961 break; 962 case BASELINE_TO_BASELINE: { 963 mBaselineToBaseline = null; 964 } 965 break; 966 case CIRCULAR_CONSTRAINT: { 967 mCircularConstraint = null; 968 } 969 break; 970 default: 971 break; 972 } 973 } else { 974 clearAll(); 975 } 976 return this; 977 } 978 getTarget(Object target)979 private ConstraintWidget getTarget(Object target) { 980 if (target instanceof Reference) { 981 Reference referenceTarget = (Reference) target; 982 return referenceTarget.getConstraintWidget(); 983 } 984 return null; 985 } 986 applyConnection(ConstraintWidget widget, Object opaqueTarget, State.Constraint type)987 private void applyConnection(ConstraintWidget widget, 988 Object opaqueTarget, 989 State.Constraint type) { 990 ConstraintWidget target = getTarget(opaqueTarget); 991 if (target == null) { 992 return; 993 } 994 switch (type) { 995 // TODO: apply RTL 996 default: 997 break; 998 } 999 switch (type) { 1000 case START_TO_START: { 1001 widget.getAnchor(ConstraintAnchor.Type.LEFT).connect(target.getAnchor( 1002 ConstraintAnchor.Type.LEFT), mMarginStart, mMarginStartGone, false); 1003 } 1004 break; 1005 case START_TO_END: { 1006 widget.getAnchor(ConstraintAnchor.Type.LEFT).connect(target.getAnchor( 1007 ConstraintAnchor.Type.RIGHT), mMarginStart, mMarginStartGone, false); 1008 } 1009 break; 1010 case END_TO_START: { 1011 widget.getAnchor(ConstraintAnchor.Type.RIGHT).connect(target.getAnchor( 1012 ConstraintAnchor.Type.LEFT), mMarginEnd, mMarginEndGone, false); 1013 } 1014 break; 1015 case END_TO_END: { 1016 widget.getAnchor(ConstraintAnchor.Type.RIGHT).connect(target.getAnchor( 1017 ConstraintAnchor.Type.RIGHT), mMarginEnd, mMarginEndGone, false); 1018 } 1019 break; 1020 case LEFT_TO_LEFT: { 1021 widget.getAnchor(ConstraintAnchor.Type.LEFT).connect(target.getAnchor( 1022 ConstraintAnchor.Type.LEFT), mMarginLeft, mMarginLeftGone, false); 1023 } 1024 break; 1025 case LEFT_TO_RIGHT: { 1026 widget.getAnchor(ConstraintAnchor.Type.LEFT).connect(target.getAnchor( 1027 ConstraintAnchor.Type.RIGHT), mMarginLeft, mMarginLeftGone, false); 1028 } 1029 break; 1030 case RIGHT_TO_LEFT: { 1031 widget.getAnchor(ConstraintAnchor.Type.RIGHT).connect(target.getAnchor( 1032 ConstraintAnchor.Type.LEFT), mMarginRight, mMarginRightGone, false); 1033 } 1034 break; 1035 case RIGHT_TO_RIGHT: { 1036 widget.getAnchor(ConstraintAnchor.Type.RIGHT).connect(target.getAnchor( 1037 ConstraintAnchor.Type.RIGHT), mMarginRight, mMarginRightGone, false); 1038 } 1039 break; 1040 case TOP_TO_TOP: { 1041 widget.getAnchor(ConstraintAnchor.Type.TOP).connect(target.getAnchor( 1042 ConstraintAnchor.Type.TOP), mMarginTop, mMarginTopGone, false); 1043 } 1044 break; 1045 case TOP_TO_BOTTOM: { 1046 widget.getAnchor(ConstraintAnchor.Type.TOP).connect(target.getAnchor( 1047 ConstraintAnchor.Type.BOTTOM), mMarginTop, mMarginTopGone, false); 1048 } 1049 break; 1050 case TOP_TO_BASELINE: { 1051 widget.immediateConnect(ConstraintAnchor.Type.TOP, target, 1052 ConstraintAnchor.Type.BASELINE, mMarginTop, mMarginTopGone); 1053 } 1054 break; 1055 case BOTTOM_TO_TOP: { 1056 widget.getAnchor(ConstraintAnchor.Type.BOTTOM).connect(target.getAnchor( 1057 ConstraintAnchor.Type.TOP), mMarginBottom, mMarginBottomGone, false); 1058 } 1059 break; 1060 case BOTTOM_TO_BOTTOM: { 1061 widget.getAnchor(ConstraintAnchor.Type.BOTTOM).connect(target.getAnchor( 1062 ConstraintAnchor.Type.BOTTOM), mMarginBottom, mMarginBottomGone, false); 1063 } 1064 break; 1065 case BOTTOM_TO_BASELINE: { 1066 widget.immediateConnect(ConstraintAnchor.Type.BOTTOM, target, 1067 ConstraintAnchor.Type.BASELINE, mMarginBottom, mMarginBottomGone); 1068 } 1069 break; 1070 case BASELINE_TO_BASELINE: { 1071 widget.immediateConnect(ConstraintAnchor.Type.BASELINE, target, 1072 ConstraintAnchor.Type.BASELINE, mMarginBaseline, mMarginBaselineGone); 1073 } 1074 break; 1075 case BASELINE_TO_TOP: { 1076 widget.immediateConnect(ConstraintAnchor.Type.BASELINE, 1077 target, ConstraintAnchor.Type.TOP, mMarginBaseline, mMarginBaselineGone); 1078 } 1079 break; 1080 case BASELINE_TO_BOTTOM: { 1081 widget.immediateConnect(ConstraintAnchor.Type.BASELINE, target, 1082 ConstraintAnchor.Type.BOTTOM, mMarginBaseline, mMarginBaselineGone); 1083 } 1084 break; 1085 case CIRCULAR_CONSTRAINT: { 1086 widget.connectCircularConstraint(target, mCircularAngle, (int) mCircularDistance); 1087 } 1088 break; 1089 default: 1090 break; 1091 } 1092 } 1093 1094 /** 1095 * apply all the constraints attributes of the mConstraintWidget 1096 */ applyWidgetConstraints()1097 public void applyWidgetConstraints() { 1098 applyConnection(mConstraintWidget, mLeftToLeft, State.Constraint.LEFT_TO_LEFT); 1099 applyConnection(mConstraintWidget, mLeftToRight, State.Constraint.LEFT_TO_RIGHT); 1100 applyConnection(mConstraintWidget, mRightToLeft, State.Constraint.RIGHT_TO_LEFT); 1101 applyConnection(mConstraintWidget, mRightToRight, State.Constraint.RIGHT_TO_RIGHT); 1102 applyConnection(mConstraintWidget, mStartToStart, State.Constraint.START_TO_START); 1103 applyConnection(mConstraintWidget, mStartToEnd, State.Constraint.START_TO_END); 1104 applyConnection(mConstraintWidget, mEndToStart, State.Constraint.END_TO_START); 1105 applyConnection(mConstraintWidget, mEndToEnd, State.Constraint.END_TO_END); 1106 applyConnection(mConstraintWidget, mTopToTop, State.Constraint.TOP_TO_TOP); 1107 applyConnection(mConstraintWidget, mTopToBottom, State.Constraint.TOP_TO_BOTTOM); 1108 applyConnection(mConstraintWidget, mTopToBaseline, State.Constraint.TOP_TO_BASELINE); 1109 applyConnection(mConstraintWidget, mBottomToTop, State.Constraint.BOTTOM_TO_TOP); 1110 applyConnection(mConstraintWidget, mBottomToBottom, State.Constraint.BOTTOM_TO_BOTTOM); 1111 applyConnection(mConstraintWidget, mBottomToBaseline, State.Constraint.BOTTOM_TO_BASELINE); 1112 applyConnection(mConstraintWidget, mBaselineToBaseline, 1113 State.Constraint.BASELINE_TO_BASELINE); 1114 applyConnection(mConstraintWidget, mBaselineToTop, State.Constraint.BASELINE_TO_TOP); 1115 applyConnection(mConstraintWidget, mBaselineToBottom, State.Constraint.BASELINE_TO_BOTTOM); 1116 applyConnection(mConstraintWidget, mCircularConstraint, 1117 State.Constraint.CIRCULAR_CONSTRAINT); 1118 } 1119 1120 // @TODO: add description 1121 @Override apply()1122 public void apply() { 1123 if (mConstraintWidget == null) { 1124 return; 1125 } 1126 if (mFacade != null) { 1127 mFacade.apply(); 1128 } 1129 mHorizontalDimension.apply(mState, mConstraintWidget, HORIZONTAL); 1130 mVerticalDimension.apply(mState, mConstraintWidget, VERTICAL); 1131 dereference(); 1132 1133 applyWidgetConstraints(); 1134 1135 if (mHorizontalChainStyle != ConstraintWidget.CHAIN_SPREAD) { 1136 mConstraintWidget.setHorizontalChainStyle(mHorizontalChainStyle); 1137 } 1138 if (mVerticalChainStyle != ConstraintWidget.CHAIN_SPREAD) { 1139 mConstraintWidget.setVerticalChainStyle(mVerticalChainStyle); 1140 } 1141 if (mHorizontalChainWeight != UNKNOWN) { 1142 mConstraintWidget.setHorizontalWeight(mHorizontalChainWeight); 1143 } 1144 if (mVerticalChainWeight != UNKNOWN) { 1145 mConstraintWidget.setVerticalWeight(mVerticalChainWeight); 1146 } 1147 1148 mConstraintWidget.setHorizontalBiasPercent(mHorizontalBias); 1149 mConstraintWidget.setVerticalBiasPercent(mVerticalBias); 1150 1151 mConstraintWidget.frame.pivotX = mPivotX; 1152 mConstraintWidget.frame.pivotY = mPivotY; 1153 mConstraintWidget.frame.rotationX = mRotationX; 1154 mConstraintWidget.frame.rotationY = mRotationY; 1155 mConstraintWidget.frame.rotationZ = mRotationZ; 1156 mConstraintWidget.frame.translationX = mTranslationX; 1157 mConstraintWidget.frame.translationY = mTranslationY; 1158 mConstraintWidget.frame.translationZ = mTranslationZ; 1159 mConstraintWidget.frame.scaleX = mScaleX; 1160 mConstraintWidget.frame.scaleY = mScaleY; 1161 mConstraintWidget.frame.alpha = mAlpha; 1162 mConstraintWidget.frame.visibility = mVisibility; 1163 mConstraintWidget.setVisibility(mVisibility); 1164 mConstraintWidget.frame.setMotionAttributes(mMotionProperties); 1165 if (mCustomColors != null) { 1166 for (String key : mCustomColors.keySet()) { 1167 Integer color = mCustomColors.get(key); 1168 mConstraintWidget.frame.setCustomAttribute(key, 1169 TypedValues.Custom.TYPE_COLOR, color); 1170 } 1171 } 1172 if (mCustomFloats != null) { 1173 for (String key : mCustomFloats.keySet()) { 1174 float value = mCustomFloats.get(key); 1175 mConstraintWidget.frame.setCustomAttribute(key, 1176 TypedValues.Custom.TYPE_FLOAT, value); 1177 } 1178 } 1179 } 1180 } 1181