content: /*
   * Copyright (C) 2019 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package androidx.constraintlayout.core.widgets.analyzer;
  
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour.FIXED;
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT;
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.DimensionBehaviour.MATCH_PARENT;
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.HORIZONTAL;
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.MATCH_CONSTRAINT_PERCENT;
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.MATCH_CONSTRAINT_RATIO;
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.MATCH_CONSTRAINT_SPREAD;
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.MATCH_CONSTRAINT_WRAP;
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.UNKNOWN;
  import static androidx.constraintlayout.core.widgets.ConstraintWidget.VERTICAL;
  import static androidx.constraintlayout.core.widgets.analyzer.WidgetRun.RunType.CENTER;
  
  import androidx.constraintlayout.core.widgets.ConstraintAnchor;
  import androidx.constraintlayout.core.widgets.ConstraintWidget;
  import androidx.constraintlayout.core.widgets.Helper;
  
  public class HorizontalWidgetRun extends WidgetRun {
  
      private static int[] sTempDimensions = new int[2];
  
      public HorizontalWidgetRun(ConstraintWidget widget) {
          super(widget);
          start.mType = DependencyNode.Type.LEFT;
          end.mType = DependencyNode.Type.RIGHT;
          this.orientation = HORIZONTAL;
      }
  
      @Override
      public String toString() {
          return "HorizontalRun " + mWidget.getDebugName();
      }
  
      @Override
      void clear() {
          mRunGroup = null;
          start.clear();
          end.clear();
          mDimension.clear();
          mResolved = false;
      }
  
      @Override
      void reset() {
          mResolved = false;
          start.clear();
          start.resolved = false;
          end.clear();
          end.resolved = false;
          mDimension.resolved = false;
      }
  
      @Override
      boolean supportsWrapComputation() {
          if (super.mDimensionBehavior == ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT) {
              if (super.mWidget.mMatchConstraintDefaultWidth == MATCH_CONSTRAINT_SPREAD) {
                  return true;
              }
              return false;
          }
          return true;
      }
  
      @Override
      void apply() {
          if (mWidget.measured) {
              mDimension.resolve(mWidget.getWidth());
          }
          if (!mDimension.resolved) {
              super.mDimensionBehavior = mWidget.getHorizontalDimensionBehaviour();
              if (super.mDimensionBehavior != ConstraintWidget.DimensionBehaviour.MATCH_CONSTRAINT) {
                  if (mDimensionBehavior == MATCH_PARENT) {
                      ConstraintWidget parent = mWidget.getParent();
                      if (parent != null
                              && (parent.getHorizontalDimensionBehaviour() == FIXED
                              || parent.getHorizontalDimensionBehaviour() == MATCH_PARENT)) {
                          int resolvedDimension = parent.getWidth()
                                  - mWidget.mLeft.getMargin() - mWidget.mRight.getMargin();
                          addTarget(start, parent.mHorizontalRun.start, mWidget.mLeft.getMargin());
                          addTarget(end, parent.mHorizontalRun.end, -mWidget.mRight.getMargin());
                          mDimension.resolve(resolvedDimension);
                          return;
                      }
                  }
                  if (mDimensionBehavior == FIXED) {
                      mDimension.resolve(mWidget.getWidth());
                  }
              }
          } else {
              if (mDimensionBehavior == MATCH_PARENT) {
                  ConstraintWidget parent = mWidget.getParent();
                  if (parent != null
                          && (parent.getHorizontalDimensionBehaviour() == FIXED
                          || parent.getHorizontalDimensionBehaviour() == MATCH_PARENT)) {
                      addTarget(start, parent.mHorizontalRun.start, mWidget.mLeft.getMargin());
                      addTarget(end, parent.mHorizontalRun.end, -mWidget.mRight.getMargin());
                      return;
                  }
              }
          }
  
          // three basic possibilities:
          // <-s-e->
          // <-s-e
          //   s-e->
          // and a variation if the dimension is not yet known:
          // <-s-d-e->
          // <-s<-d<-e
          //   s->d->e->
  
          if (mDimension.resolved && mWidget.measured) {
              if (mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT].mTarget != null
                      && mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT].mTarget
                      != null) { // <-s-e->
                  if (mWidget.isInHorizontalChain()) {
                      start.mMargin = mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT].getMargin();
                      end.mMargin = -mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT].getMargin();
                  } else {
                      DependencyNode startTarget =
                              getTarget(mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT]);
                      if (startTarget != null) {
                          addTarget(start, startTarget,
                                  mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT].getMargin());
                      }
                      DependencyNode endTarget =
                              getTarget(mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT]);
                      if (endTarget != null) {
                          addTarget(end, endTarget,
                                  -mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT].getMargin());
                      }
                      start.delegateToWidgetRun = true;
                      end.delegateToWidgetRun = true;
                  }
              } else if (mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT].mTarget
                      != null) { // <-s-e
                  DependencyNode target =
                          getTarget(mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT]);
                  if (target != null) {
                      addTarget(start, target,
                              mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT].getMargin());
                      addTarget(end, start, mDimension.value);
                  }
              } else if (mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT].mTarget
                      != null) {   //   s-e->
                  DependencyNode target =
                          getTarget(mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT]);
                  if (target != null) {
                      addTarget(end, target,
                              -mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT].getMargin());
                      addTarget(start, end, -mDimension.value);
                  }
              } else {
                  // no connections, nothing to do.
                  if (!(mWidget instanceof Helper) && mWidget.getParent() != null
                          && mWidget.getAnchor(ConstraintAnchor.Type.CENTER).mTarget == null) {
                      DependencyNode left = mWidget.getParent().mHorizontalRun.start;
                      addTarget(start, left, mWidget.getX());
                      addTarget(end, start, mDimension.value);
                  }
              }
          } else {
              if (mDimensionBehavior == MATCH_CONSTRAINT) {
                  switch (mWidget.mMatchConstraintDefaultWidth) {
                      case MATCH_CONSTRAINT_RATIO: {
                          if (mWidget.mMatchConstraintDefaultHeight == MATCH_CONSTRAINT_RATIO
                          ) {
                              // need to look into both side
                              start.updateDelegate = this;
                              end.updateDelegate = this;
                              mWidget.mVerticalRun.start.updateDelegate = this;
                              mWidget.mVerticalRun.end.updateDelegate = this;
                              mDimension.updateDelegate = this;
  
                              if (mWidget.isInVerticalChain()) {
                                  mDimension.mTargets.add(mWidget.mVerticalRun.mDimension);
                                  mWidget.mVerticalRun.mDimension.mDependencies.add(mDimension);
                                  mWidget.mVerticalRun.mDimension.updateDelegate = this;
                                  mDimension.mTargets.add(mWidget.mVerticalRun.start);
                                  mDimension.mTargets.add(mWidget.mVerticalRun.end);
                                  mWidget.mVerticalRun.start.mDependencies.add(mDimension);
                                  mWidget.mVerticalRun.end.mDependencies.add(mDimension);
                              } else if (mWidget.isInHorizontalChain()) {
                                  mWidget.mVerticalRun.mDimension.mTargets.add(mDimension);
                                  mDimension.mDependencies.add(mWidget.mVerticalRun.mDimension);
                              } else {
                                  mWidget.mVerticalRun.mDimension.mTargets.add(mDimension);
                              }
                              break;
                          }
                          // we have a ratio, but we depend on the other side computation
                          DependencyNode targetDimension = mWidget.mVerticalRun.mDimension;
                          mDimension.mTargets.add(targetDimension);
                          targetDimension.mDependencies.add(mDimension);
                          mWidget.mVerticalRun.start.mDependencies.add(mDimension);
                          mWidget.mVerticalRun.end.mDependencies.add(mDimension);
                          mDimension.delegateToWidgetRun = true;
                          mDimension.mDependencies.add(start);
                          mDimension.mDependencies.add(end);
                          start.mTargets.add(mDimension);
                          end.mTargets.add(mDimension);
                      }
                      break;
                      case MATCH_CONSTRAINT_PERCENT: {
                          // we need to look up the parent dimension
                          ConstraintWidget parent = mWidget.getParent();
                          if (parent == null) {
                              break;
                          }
                          DependencyNode targetDimension = parent.mVerticalRun.mDimension;
                          mDimension.mTargets.add(targetDimension);
                          targetDimension.mDependencies.add(mDimension);
                          mDimension.delegateToWidgetRun = true;
                          mDimension.mDependencies.add(start);
                          mDimension.mDependencies.add(end);
                      }
                      break;
                      case MATCH_CONSTRAINT_SPREAD: {
                          // the work is done in the update()
                      }
                      break;
                      default:
                          break;
                  }
              }
              if (mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT].mTarget != null
                      && mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT].mTarget
                      != null) { // <-s-d-e->
  
                  if (mWidget.isInHorizontalChain()) {
                      start.mMargin = mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT].getMargin();
                      end.mMargin = -mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT].getMargin();
                  } else {
                      DependencyNode startTarget =
                              getTarget(mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT]);
                      DependencyNode endTarget =
                              getTarget(mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT]);
                      if (false) {
                          if (startTarget != null) {
                              addTarget(start, startTarget,
                                      mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT].getMargin());
                          }
                          if (endTarget != null) {
                              addTarget(end, endTarget,
                                      -mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT]
                                              .getMargin());
                          }
                      } else {
                          if (startTarget != null) {
                              startTarget.addDependency(this);
                          }
                          if (endTarget != null) {
                              endTarget.addDependency(this);
                          }
                      }
                      mRunType = CENTER;
                  }
              } else if (mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT].mTarget
                      != null) { // <-s<-d<-e
                  DependencyNode target =
                          getTarget(mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT]);
                  if (target != null) {
                      addTarget(start, target,
                              mWidget.mListAnchors[ConstraintWidget.ANCHOR_LEFT].getMargin());
                      addTarget(end, start, 1, mDimension);
                  }
              } else if (mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT].mTarget
                      != null) {   //   s->d->e->
                  DependencyNode target =
                          getTarget(mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT]);
                  if (target != null) {
                      addTarget(end, target,
                              -mWidget.mListAnchors[ConstraintWidget.ANCHOR_RIGHT].getMargin());
                      addTarget(start, end, -1, mDimension);
                  }
              } else {
                  // no connections, nothing to do.
                  if (!(mWidget instanceof Helper) && mWidget.getParent() != null) {
                      DependencyNode left = mWidget.getParent().mHorizontalRun.start;
                      addTarget(start, left, mWidget.getX());
                      addTarget(end, start, 1, mDimension);
                  }
              }
          }
      }
  
      private void computeInsetRatio(int[] dimensions,
              int x1,
              int x2,
              int y1,
              int y2,
              float ratio,
              int side) {
          int dx = x2 - x1;
          int dy = y2 - y1;
          switch (side) {
              case UNKNOWN: {
                  int candidateX1 = (int) (0.5f + dy * ratio);
                  int candidateY1 = dy;
                  int candidateX2 = dx;
                  int candidateY2 = (int) (0.5f + dx / ratio);
                  if (candidateX1 <= dx && candidateY1 <= dy) {
                      dimensions[HORIZONTAL] = candidateX1;
                      dimensions[VERTICAL] = candidateY1;
                  } else if (candidateX2 <= dx && candidateY2 <= dy) {
                      dimensions[HORIZONTAL] = candidateX2;
                      dimensions[VERTICAL] = candidateY2;
                  }
              }
              break;
              case HORIZONTAL: {
                  int horizontalSide = (int) (0.5f + dy * ratio);
                  dimensions[HORIZONTAL] = horizontalSide;
                  dimensions[VERTICAL] = dy;
              }
              break;
              case VERTICAL: {
                  int verticalSide = (int) (0.5f + dx * ratio);
                  dimensions[HORIZONTAL] = dx;
                  dimensions[VERTICAL] = verticalSide;
              }
              break;
              default:
                  break;
          }
      }
  
      @Override
      public void update(Dependency dependency) {
          switch (mRunType) {
              case START: {
                  updateRunStart(dependency);
              }
              break;
              case END: {
                  updateRunEnd(dependency);
              }
              break;
              case CENTER: {
                  updateRunCenter(dependency, mWidget.mLeft, mWidget.mRight, HORIZONTAL);
                  return;
              }
              default:
                  break;
          }
  
          if (!mDimension.resolved) {
              if (mDimensionBehavior == MATCH_CONSTRAINT) {
                  switch (mWidget.mMatchConstraintDefaultWidth) {
                      case MATCH_CONSTRAINT_RATIO: {
                          if (mWidget.mMatchConstraintDefaultHeight == MATCH_CONSTRAINT_SPREAD
                                  || mWidget.mMatchConstraintDefaultHeight
                                  == MATCH_CONSTRAINT_RATIO) {
                              DependencyNode secondStart = mWidget.mVerticalRun.start;
                              DependencyNode secondEnd = mWidget.mVerticalRun.end;
                              boolean s1 = mWidget.mLeft.mTarget != null;
                              boolean s2 = mWidget.mTop.mTarget != null;
                              boolean e1 = mWidget.mRight.mTarget != null;
                              boolean e2 = mWidget.mBottom.mTarget != null;
  
                              int definedSide = mWidget.getDimensionRatioSide();
  
                              if (s1 && s2 && e1 && e2) {
                                  float ratio = mWidget.getDimensionRatio();
                                  if (secondStart.resolved && secondEnd.resolved) {
                                      if (!(start.readyToSolve && end.readyToSolve)) {
                                          return;
                                      }
                                      int x1 = start.mTargets.get(0).value + start.mMargin;
                                      int x2 = end.mTargets.get(0).value - end.mMargin;
                                      int y1 = secondStart.value + secondStart.mMargin;
                                      int y2 = secondEnd.value - secondEnd.mMargin;
                                      computeInsetRatio(sTempDimensions,
                                              x1, x2, y1, y2, ratio, definedSide);
                                      mDimension.resolve(sTempDimensions[HORIZONTAL]);
                                      mWidget.mVerticalRun.mDimension
                                              .resolve(sTempDimensions[VERTICAL]);
                                      return;
                                  }
                                  if (start.resolved && end.resolved) {
                                      if (!(secondStart.readyToSolve && secondEnd.readyToSolve)) {
                                          return;
                                      }
                                      int x1 = start.value + start.mMargin;
                                      int x2 = end.value - end.mMargin;
                                      int y1 = secondStart.mTargets.get(0).value
                                              + secondStart.mMargin;
                                      int y2 = secondEnd.mTargets.get(0).value - secondEnd.mMargin;
                                      computeInsetRatio(sTempDimensions,
                                              x1, x2, y1, y2, ratio, definedSide);
                                      mDimension.resolve(sTempDimensions[HORIZONTAL]);
                                      mWidget.mVerticalRun.mDimension
                                              .resolve(sTempDimensions[VERTICAL]);
                                  }
                                  if (!(start.readyToSolve && end.readyToSolve
                                          && secondStart.readyToSolve
                                          && secondEnd.readyToSolve)) {
                                      return;
                                  }
                                  int x1 = start.mTargets.get(0).value + start.mMargin;
                                  int x2 = end.mTargets.get(0).value - end.mMargin;
                                  int y1 = secondStart.mTargets.get(0).value + secondStart.mMargin;
                                  int y2 = secondEnd.mTargets.get(0).value - secondEnd.mMargin;
                                  computeInsetRatio(sTempDimensions,
                                          x1, x2, y1, y2, ratio, definedSide);
                                  mDimension.resolve(sTempDimensions[HORIZONTAL]);
                                  mWidget.mVerticalRun.mDimension.resolve(sTempDimensions[VERTICAL]);
                              } else if (s1 && e1) {
                                  if (!(start.readyToSolve && end.readyToSolve)) {
                                      return;
                                  }
                                  float ratio = mWidget.getDimensionRatio();
                                  int x1 = start.mTargets.get(0).value + start.mMargin;
                                  int x2 = end.mTargets.get(0).value - end.mMargin;
  
                                  switch (definedSide) {
                                      case UNKNOWN:
                                      case HORIZONTAL: {
                                          int dx = x2 - x1;
                                          int ldx = getLimitedDimension(dx, HORIZONTAL);
                                          int dy = (int) (0.5f + ldx * ratio);
                                          int ldy = getLimitedDimension(dy, VERTICAL);
                                          if (dy != ldy) {
                                              ldx = (int) (0.5f + ldy / ratio);
                                          }
                                          mDimension.resolve(ldx);
                                          mWidget.mVerticalRun.mDimension.resolve(ldy);
                                      }
                                      break;
                                      case VERTICAL: {
                                          int dx = x2 - x1;
                                          int ldx = getLimitedDimension(dx, HORIZONTAL);
                                          int dy = (int) (0.5f + ldx / ratio);
                                          int ldy = getLimitedDimension(dy, VERTICAL);
                                          if (dy != ldy) {
                                              ldx = (int) (0.5f + ldy * ratio);
                                          }
                                          mDimension.resolve(ldx);
                                          mWidget.mVerticalRun.mDimension.resolve(ldy);
                                      }
                                      break;
                                      default:
                                          break;
                                  }
                              } else if (s2 && e2) {
                                  if (!(secondStart.readyToSolve && secondEnd.readyToSolve)) {
                                      return;
                                  }
                                  float ratio = mWidget.getDimensionRatio();
                                  int y1 = secondStart.mTargets.get(0).value + secondStart.mMargin;
                                  int y2 = secondEnd.mTargets.get(0).value - secondEnd.mMargin;
  
                                  switch (definedSide) {
                                      case UNKNOWN:
                                      case VERTICAL: {
                                          int dy = y2 - y1;
                                          int ldy = getLimitedDimension(dy, VERTICAL);
                                          int dx = (int) (0.5f + ldy / ratio);
                                          int ldx = getLimitedDimension(dx, HORIZONTAL);
                                          if (dx != ldx) {
                                              ldy = (int) (0.5f + ldx * ratio);
                                          }
                                          mDimension.resolve(ldx);
                                          mWidget.mVerticalRun.mDimension.resolve(ldy);
                                      }
                                      break;
                                      case HORIZONTAL: {
                                          int dy = y2 - y1;
                                          int ldy = getLimitedDimension(dy, VERTICAL);
                                          int dx = (int) (0.5f + ldy * ratio);
                                          int ldx = getLimitedDimension(dx, HORIZONTAL);
                                          if (dx != ldx) {
                                              ldy = (int) (0.5f + ldx / ratio);
                                          }
                                          mDimension.resolve(ldx);
                                          mWidget.mVerticalRun.mDimension.resolve(ldy);
                                      }
                                      break;
                                      default:
                                          break;
                                  }
                              }
                          } else {
                              int size = 0;
                              int ratioSide = mWidget.getDimensionRatioSide();
                              switch (ratioSide) {
                                  case HORIZONTAL: {
                                      size = (int) (0.5f + mWidget.mVerticalRun.mDimension.value
                                              / mWidget.getDimensionRatio());
                                  }
                                  break;
                                  case ConstraintWidget.VERTICAL: {
                                      size = (int) (0.5f + mWidget.mVerticalRun.mDimension.value
                                              * mWidget.getDimensionRatio());
                                  }
                                  break;
                                  case ConstraintWidget.UNKNOWN: {
                                      size = (int) (0.5f + mWidget.mVerticalRun.mDimension.value
                                              * mWidget.getDimensionRatio());
                                  }
                                  break;
                                  default:
                                      break;
                              }
                              mDimension.resolve(size);
                          }
                      }
                      break;
                      case MATCH_CONSTRAINT_PERCENT: {
                          ConstraintWidget parent = mWidget.getParent();
                          if (parent != null) {
                              if (parent.mHorizontalRun.mDimension.resolved) {
                                  float percent = mWidget.mMatchConstraintPercentWidth;
                                  int targetDimensionValue = parent.mHorizontalRun.mDimension.value;
                                  int size = (int) (0.5f + targetDimensionValue * percent);
                                  mDimension.resolve(size);
                              }
                          }
                      }
                      break;
                      default:
                          break;
                  }
              }
          }
  
          if (!(start.readyToSolve && end.readyToSolve)) {
              return;
          }
  
          if (start.resolved && end.resolved && mDimension.resolved) {
              return;
          }
  
          if (!mDimension.resolved
                  && mDimensionBehavior == MATCH_CONSTRAINT
                  && mWidget.mMatchConstraintDefaultWidth == MATCH_CONSTRAINT_SPREAD
                  && !mWidget.isInHorizontalChain()) {
  
              DependencyNode startTarget = start.mTargets.get(0);
              DependencyNode endTarget = end.mTargets.get(0);
              int startPos = startTarget.value + start.mMargin;
              int endPos = endTarget.value + end.mMargin;
  
              int distance = endPos - startPos;
              start.resolve(startPos);
              end.resolve(endPos);
              mDimension.resolve(distance);
              return;
          }
  
          if (!mDimension.resolved
                  && mDimensionBehavior == MATCH_CONSTRAINT
                  && matchConstraintsType == MATCH_CONSTRAINT_WRAP) {
              if (start.mTargets.size() > 0 && end.mTargets.size() > 0) {
                  DependencyNode startTarget = start.mTargets.get(0);
                  DependencyNode endTarget = end.mTargets.get(0);
                  int startPos = startTarget.value + start.mMargin;
                  int endPos = endTarget.value + end.mMargin;
                  int availableSpace = endPos - startPos;
                  int value = Math.min(availableSpace, mDimension.wrapValue);
                  int max = mWidget.mMatchConstraintMaxWidth;
                  int min = mWidget.mMatchConstraintMinWidth;
                  value = Math.max(min, value);
                  if (max > 0) {
                      value = Math.min(max, value);
                  }
                  mDimension.resolve(value);
              }
          }
  
          if (!mDimension.resolved) {
              return;
          }
          // ready to solve, centering.
          DependencyNode startTarget = start.mTargets.get(0);
          DependencyNode endTarget = end.mTargets.get(0);
          int startPos = startTarget.value + start.mMargin;
          int endPos = endTarget.value + end.mMargin;
          float bias = mWidget.getHorizontalBiasPercent();
          if (startTarget == endTarget) {
              startPos = startTarget.value;
              endPos = endTarget.value;
              // TODO: this might be a nice feature to support, but I guess for now let's stay
              // compatible with 1.1
              bias = 0.5f;
          }
          int distance = (endPos - startPos - mDimension.value);
          start.resolve((int) (0.5f + startPos + distance * bias));
          end.resolve(start.value + mDimension.value);
      }
  
      // @TODO: add description
      @Override
      public void applyToWidget() {
          if (start.resolved) {
              mWidget.setX(start.value);
          }
      }
  
  }
  