private void AccumulateNegativeDesiredWidth(RPNode node, double x) { double initialX = x; bool isHorizontallyCenteredFromLeft = false; bool isHorizontallyCenteredFromRight = false; MUX_ASSERT(node.IsMeasured()); // If we are going in the negative direction, move the cursor // left by the desired width of the node with which we are // currently working and refresh the minimum negative value. x -= node.GetDesiredWidth(); m_minX = Math.Min(m_minX, x); if (node.IsAlignRightWithPanel()) { if (!m_isMinCapped) { m_minX = x; m_isMinCapped = true; } } else if (node.IsAlignRightWith()) { // If the AlignRightWithNode and AlignLeftWithNode are the // same element, we can skip the former, since we will move // through the latter later. if (node.m_alignRightWithNode != node.m_alignLeftWithNode) { AccumulatePositiveDesiredWidth(node.m_alignRightWithNode, x); } } else if (node.IsAlignHorizontalCenterWith()) { isHorizontallyCenteredFromRight = true; } else if (node.IsLeftOf()) { AccumulateNegativeDesiredWidth(node.m_leftOfNode, x); } if (node.IsAlignLeftWithPanel()) { if (m_isMaxCapped) { m_maxX = Math.Max(m_maxX, initialX); } else { m_maxX = initialX; m_isMaxCapped = true; } } else if (node.IsAlignLeftWith()) { // If this element's left is aligned to some other element's // left, now we will be going in the negative direction to // that other element in order to continue the traversal of // the dependency chain. But first, since we arrived to the // node where we currently are by going in the negative // direction, that means that we have already moved the // cursor left to calculate the minimum negative value, // so we will use the initial value of X. AccumulateNegativeDesiredWidth(node.m_alignLeftWithNode, initialX); } else if (node.IsAlignHorizontalCenterWith()) { isHorizontallyCenteredFromLeft = true; } else if (node.IsRightOf()) { // If this element is to the right of some other element, // now we will be going in the positive direction to that // other element in order to continue the traversal of the // dependency chain. But first, since we arrived to the // node where we currently are by going in the negative // direction, that means that we have already moved the // cursor left to calculate the minimum negative value, so // we will use the initial value of X. AccumulatePositiveDesiredWidth(node.m_rightOfNode, initialX); } if (isHorizontallyCenteredFromLeft && isHorizontallyCenteredFromRight) { double centerX = x + (node.GetDesiredWidth() / 2.0f); double edgeX = centerX + (node.m_alignHorizontalCenterWithNode.GetDesiredWidth() / 2.0f); m_maxX = Math.Max(m_maxX, edgeX); AccumulateNegativeDesiredWidth(node.m_alignHorizontalCenterWithNode, edgeX); } else if (node.IsHorizontalCenterAnchored()) { // If this node is horizontally anchored to the center, then it // means that it is the root of this dependency chain based on // the current definition of precedence for raints: // e.g. AlignLeftWithPanel // > AlignLeftWith // > RightOf // > AlignHorizontalCenterWithPanel // Thus, we can report its width as twice the width of // either the difference from center to left or the difference // from center to right, whichever is the greatest. double centerX = x + (node.GetDesiredWidth() / 2.0f); double upper = m_maxX - centerX; double lower = centerX - m_minX; m_maxX = Math.Max(upper, lower) * 2.0f; m_minX = 0.0f; } }
private void CalculateMeasureRectHorizontally(RPNode node, Size availableSize, out double x, out double width) { bool isHorizontallyCenteredFromLeft = false; bool isHorizontallyCenteredFromRight = false; // The initial values correspond to the entire available space. In // other words, the edges of the element are aligned to the edges // of the panel by default. We will now rain each side of this // space as necessary. x = 0.0f; width = availableSize.Width; // If we have infinite available width, then the Width of the // MeasureRect is also infinite; we do not have to rain it. if (availableSize.Width != double.PositiveInfinity) { // Constrain the left side of the available space, i.e. // a) The child has its left edge aligned with the panel (default), // b) The child has its left edge aligned with the left edge of a sibling, // or c) The child is positioned to the right of a sibling. // // |;; | | // |;; | | // |;; |:::::::::::::::| ;;:::::::::::::;; // |;; |; ;| . ;; ;; // |;; |; ;| .;;............ ;; ;; // |;; |; ;| .;;;;:::::::::::: ;; ;; // |;; |; ;| ':;;:::::::::::: ;; ;; // |;; |; ;| ': ;; ;; // |;; |:::::::::::::::| ::::::::::::::::: // |;; | | // |;; | | // AlignLeftWithPanel AlignLeftWith RightOf // if (!node.IsAlignLeftWithPanel()) { if (node.IsAlignLeftWith()) { RPNode alignLeftWithNeighbor = node.m_alignLeftWithNode; double restrictedHorizontalSpace = alignLeftWithNeighbor.m_arrangeRect.X; x = restrictedHorizontalSpace; width -= restrictedHorizontalSpace; } else if (node.IsAlignHorizontalCenterWith()) { isHorizontallyCenteredFromLeft = true; } else if (node.IsRightOf()) { RPNode rightOfNeighbor = node.m_rightOfNode; double restrictedHorizontalSpace = rightOfNeighbor.m_arrangeRect.X + rightOfNeighbor.m_arrangeRect.Width; x = restrictedHorizontalSpace; width -= restrictedHorizontalSpace; } } // Constrain the right side of the available space, i.e. // a) The child has its right edge aligned with the panel (default), // b) The child has its right edge aligned with the right edge of a sibling, // or c) The child is positioned to the left of a sibling. // // | | ;;| // | | ;;| // ;;:::::::::::::;; |;:::::::::::::;| ;;| // ;; ;; . |; ;| ;;| // ;; ;; ............;;. |; ;| ;;| // ;; ;; ::::::::::::;;;;. |; ;| ;;| // ;; ;; ::::::::::::;;:' |; ;| ;;| // ;; ;; :' |; ;| ;;| // ::::::::::::::::: |:::::::::::::::| ;;| // | | ;;| // | | ;;| // LeftOf AlignRightWith AlignRightWithPanel // if (!node.IsAlignRightWithPanel()) { if (node.IsAlignRightWith()) { RPNode alignRightWithNeighbor = node.m_alignRightWithNode; width -= availableSize.Width - (alignRightWithNeighbor.m_arrangeRect.X + alignRightWithNeighbor.m_arrangeRect.Width); } else if (node.IsAlignHorizontalCenterWith()) { isHorizontallyCenteredFromRight = true; } else if (node.IsLeftOf()) { RPNode leftOfNeighbor = node.m_leftOfNode; width -= availableSize.Width - leftOfNeighbor.m_arrangeRect.X; } } if (isHorizontallyCenteredFromLeft && isHorizontallyCenteredFromRight) { RPNode alignHorizontalCenterWithNeighbor = node.m_alignHorizontalCenterWithNode; double centerOfNeighbor = alignHorizontalCenterWithNeighbor.m_arrangeRect.X + (alignHorizontalCenterWithNeighbor.m_arrangeRect.Width / 2.0f); width = Math.Min(centerOfNeighbor, availableSize.Width - centerOfNeighbor) * 2.0f; x = centerOfNeighbor - (width / 2.0f); } } }