void CalculateArrangeRectVertically(RPNode node, out double y, out double height) { Rect measureRect = node.m_measureRect; double desiredHeight = Math.Min(measureRect.Height, node.GetDesiredHeight()); MUX_ASSERT(node.IsMeasured() && (measureRect.Height != double.PositiveInfinity)); // The initial values correspond to the top corner, using the // desired size of element. If no attached properties were set, // this means that the element will default to the top corner of // the panel. y = measureRect.Y; height = desiredHeight; if (node.IsTopAnchored()) { if (node.IsBottomAnchored()) { y = measureRect.Y; height = measureRect.Height; } else { y = measureRect.Y; height = desiredHeight; } } else if (node.IsBottomAnchored()) { y = measureRect.Y + measureRect.Height - desiredHeight; height = desiredHeight; } else if (node.IsVerticalCenterAnchored()) { y = measureRect.Y + (measureRect.Height / 2.0f) - (desiredHeight / 2.0f); height = desiredHeight; } }
void AccumulateNegativeDesiredHeight(RPNode node, double y) { double initialY = y; bool isVerticallyCenteredFromTop = false; bool isVerticallyCenteredFromBottom = false; MUX_ASSERT(node.IsMeasured()); // If we are going in the negative direction, move the cursor // down by the desired height of the node with which we are // currently working and refresh the minimum negative value. y -= node.GetDesiredHeight(); m_minY = Math.Min(m_minY, y); if (node.IsAlignBottomWithPanel()) { if (!m_isMinCapped) { m_minY = y; m_isMinCapped = true; } } else if (node.IsAlignBottomWith()) { // If the AlignBottomWithNode and AlignTopWithNode are the // same element, we can skip the former, since we will move // through the latter later. if (node.m_alignBottomWithNode != node.m_alignTopWithNode) { AccumulatePositiveDesiredHeight(node.m_alignBottomWithNode, y); } } else if (node.IsAlignVerticalCenterWith()) { isVerticallyCenteredFromBottom = true; } else if (node.IsAbove()) { AccumulateNegativeDesiredHeight(node.m_aboveNode, y); } if (node.IsAlignTopWithPanel()) { if (m_isMaxCapped) { m_maxY = Math.Max(m_maxY, initialY); } else { m_maxY = initialY; m_isMaxCapped = true; } } else if (node.IsAlignTopWith()) { // If this element's top is aligned to some other element's // top, 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 down to calculate the minimum negative value, // so we will use the initial value of Y. AccumulateNegativeDesiredHeight(node.m_alignTopWithNode, initialY); } else if (node.IsAlignVerticalCenterWith()) { isVerticallyCenteredFromTop = true; } else if (node.IsBelow()) { // If this element is below some other element, now we'll // 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 down to // calculate the minimum negative value, so we will use // the initial value of Y. AccumulatePositiveDesiredHeight(node.m_belowNode, initialY); } if (isVerticallyCenteredFromTop && isVerticallyCenteredFromBottom) { double centerY = y + (node.GetDesiredHeight() / 2.0f); double edgeY = centerY + (node.m_alignVerticalCenterWithNode.GetDesiredHeight() / 2.0f); m_maxY = Math.Max(m_maxY, edgeY); AccumulateNegativeDesiredHeight(node.m_alignVerticalCenterWithNode, edgeY); } else if (node.IsVerticalCenterAnchored()) { // If this node is vertically 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. AlignTopWithPanel // > AlignTopWith // > Below // > AlignVerticalCenterWithPanel // Thus, we can report its height as twice the height of // either the difference from center to top or the difference // from center to bottom, whichever is the greatest. double centerY = y + (node.GetDesiredHeight() / 2.0f); double upper = m_maxY - centerY; double lower = centerY - m_minY; m_maxY = Math.Max(upper, lower) * 2.0f; m_minY = 0.0f; } }