} // LayoutHorizontally private void LayoutVertical(LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) { LayoutLength childTop = new LayoutLength(Padding.Top); LayoutLength childLeft = new LayoutLength(Padding.Start); // Where end of child should go LayoutLength width = new LayoutLength(right - left); // Space available for child LayoutLength childSpace = new LayoutLength(width - Padding.Start - Padding.End); List <LayoutItem> LinearChildren = IterateLayoutChildren().ToList(); int count = LinearChildren.Count; switch (LinearAlignment) { case Alignment.Bottom: // totalLength contains the padding already childTop = new LayoutLength(Padding.Top + bottom.AsDecimal() - top.AsDecimal() - _totalLength); break; case Alignment.CenterVertical: // FALL THROUGH case Alignment.Center: // totalLength contains the padding already childTop = new LayoutLength(Padding.Top + (bottom.AsDecimal() - top.AsDecimal() - _totalLength) / 2.0f); break; case Alignment.Top: // FALL THROUGH (default) default: // totalLength contains the padding already childTop = new LayoutLength(Padding.Top); break; } for (int i = 0; i < count; i++) { LayoutItem childLayout = LinearChildren[i]; LayoutLength childWidth = childLayout.MeasuredWidth.Size; LayoutLength childHeight = childLayout.MeasuredHeight.Size; Extents childMargin = childLayout.Margin; childTop += childMargin.Top; switch (LinearAlignment) { case Alignment.Begin: default: { childLeft = new LayoutLength(Padding.Start + childMargin.Start); break; } case Alignment.End: { childLeft = new LayoutLength(width - Padding.End - childWidth - childMargin.End); break; } case Alignment.CenterHorizontal: case Alignment.Center: // FALL THROUGH { childLeft = new LayoutLength(Padding.Start + ((childSpace - childWidth).AsDecimal() / 2.0f) + childMargin.Start - childMargin.End); break; } } childLayout.Layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); childTop += childHeight + childMargin.Bottom + ((i < count - 1) ? CellPadding.Height : 0); } } // LayoutVertical
} // MeasureHorizontal private void MeasureVertical(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) { var widthMode = widthMeasureSpec.Mode; var heightMode = heightMeasureSpec.Mode; bool isExactly = (heightMode == MeasureSpecification.ModeType.Exactly); bool matchWidth = false; bool allFillParent = true; float maxWidth = 0.0f; float alternativeMaxWidth = 0.0f; float weightedMaxWidth = 0.0f; float totalWeight = 0.0f; int childrenCount = IterateLayoutChildren().Count(); // Reset total length _totalLength = 0.0f; float usedExcessSpace = 0.0f; HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK, MeasuredSize.StateType.MeasuredSizeOK); // measure children, and determine if further resolution is required // 1st phase: // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs // to accumulate total used space in _totalLength. // Weighted children are not measured in this phase. // Available space for weighted children will be calculated in the phase 2 based on _totalLength value. foreach (LayoutItem childLayout in IterateLayoutChildren()) { childrenCount++; int childDesiredWidth = childLayout.Owner.WidthSpecification; float childWeight = childLayout.Owner.Weight; Extents childMargin = childLayout.Margin; totalWeight += childWeight; bool useExcessSpace = (childLayout.Owner.HeightSpecification == 0) && (childWeight > 0); if (isExactly && useExcessSpace) { _totalLength = Math.Max(_totalLength, (_totalLength + childMargin.Top + childMargin.Bottom)); } else { if (useExcessSpace) { // The heightMode is either Unspecified or AtMost, and // this child is only laid out using excess space. Measure // using WrapContent so that we can find out the view's // optimal height. // We'll restore the original height of 0 after measurement. MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification( new MeasureSpecification( new LayoutLength(widthMeasureSpec.Size - (childLayout.Margin.Start + childLayout.Margin.End)), widthMeasureSpec.Mode), new LayoutLength(Padding.Start + Padding.End), new LayoutLength(childDesiredWidth)); MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification( new MeasureSpecification( new LayoutLength(heightMeasureSpec.Size - (childLayout.Margin.Top + childLayout.Margin.Bottom)), heightMeasureSpec.Mode), new LayoutLength(Padding.Top + Padding.Bottom), new LayoutLength(LayoutParamPolicies.WrapContent)); childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec); usedExcessSpace += childLayout.MeasuredHeight.Size.AsDecimal(); } else { MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0)); } LayoutLength childHeight = childLayout.MeasuredHeight.Size; LayoutLength length = childHeight + childMargin.Top + childMargin.Bottom; _totalLength = Math.Max(_totalLength, _totalLength + length.AsDecimal()); } bool matchWidthLocally = false; if (widthMode != MeasureSpecification.ModeType.Exactly && childDesiredWidth == LayoutParamPolicies.MatchParent) { // Will have to re-measure at least this child when we know exact height. matchWidth = true; matchWidthLocally = true; } float marginWidth = childLayout.Margin.Start + childLayout.Margin.End; float childWidth = childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth; if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; } if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; } maxWidth = Math.Max(maxWidth, childWidth); allFillParent = (allFillParent && childDesiredWidth == LayoutParamPolicies.MatchParent); if (childWeight > 0) { // Widths of weighted Views are bogus if we end up remeasuring, so keep them separate. weightedMaxWidth = Math.Max(weightedMaxWidth, matchWidthLocally ? marginWidth : childWidth); } else { alternativeMaxWidth = Math.Max(alternativeMaxWidth, matchWidthLocally ? marginWidth : childWidth); } } // foreach _totalLength = Math.Max(_totalLength, _totalLength + CellPadding.Height * (childrenCount - 1)); float heightSize = _totalLength; heightSize = Math.Max(heightSize, SuggestedMinimumHeight.AsDecimal()); MeasuredSize heightSizeAndState = ResolveSizeAndState(new LayoutLength(heightSize + Padding.Top + Padding.Bottom), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); heightSize = heightSizeAndState.Size.AsDecimal(); // 2nd phase: // We cycle through weighted children now (children with weight > 0). // The children are measured with exact size equal to their share of the available space based on their weights. // _totalLength is updated to include weighted children measured sizes. float remainingExcess = heightSize - _totalLength + usedExcessSpace - (Padding.Top + Padding.Bottom); if (remainingExcess != 0 && totalWeight > 0.0f) { float remainingWeight = totalWeight; maxWidth = 0; _totalLength = 0; foreach (LayoutItem childLayout in IterateLayoutChildren()) { float desiredChildWidth = childLayout.Owner.WidthSpecification; float childWeight = childLayout.Owner.Weight; Extents childMargin = childLayout.Margin; if (childWeight > 0) { MeasureWeightedChild(childLayout, remainingExcess, remainingWeight, childWeight, widthMeasureSpec, heightMeasureSpec, childState, Orientation.Vertical); } float length = childLayout.MeasuredHeight.Size.AsDecimal() + childMargin.Top + childMargin.Bottom; _totalLength += length; bool matchWidthLocally = (widthMode != MeasureSpecification.ModeType.Exactly) && (desiredChildWidth == LayoutParamPolicies.MatchParent); float marginWidth = childMargin.Start + childMargin.End; float childWidth = childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth; maxWidth = Math.Max(maxWidth, childWidth); alternativeMaxWidth = Math.Max(alternativeMaxWidth, matchWidthLocally ? marginWidth : childWidth); allFillParent = (allFillParent && desiredChildWidth == LayoutParamPolicies.MatchParent); } // for loop _totalLength = Math.Max(_totalLength, _totalLength + CellPadding.Height * (childrenCount - 1)); } else { alternativeMaxWidth = Math.Max(alternativeMaxWidth, weightedMaxWidth); } if (!allFillParent && widthMode != MeasureSpecification.ModeType.Exactly) { maxWidth = alternativeMaxWidth; } maxWidth += (Owner.WidthSpecification == LayoutParamPolicies.WrapContent) ? (Padding.Start + Padding.End) : 0; maxWidth = Math.Max(maxWidth, SuggestedMinimumWidth.AsRoundedValue()); heightSizeAndState.State = childState.heightState; SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(maxWidth), widthMeasureSpec, childState.widthState), heightSizeAndState); if (matchWidth) { ForceUniformWidth(heightMeasureSpec); } } // MeasureVertical
} // MeasureVertical private void LayoutHorizontal(LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) { bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL; LayoutLength childTop = new LayoutLength(Padding.Top); LayoutLength childLeft = new LayoutLength(Padding.Start); // Where bottom of child should go LayoutLength height = new LayoutLength(bottom - top); // Space available for child LayoutLength childSpace = new LayoutLength(height - Padding.Top - Padding.Bottom); List <LayoutItem> LinearChildren = IterateLayoutChildren().ToList(); int count = LinearChildren.Count; switch (LinearAlignment) { case Alignment.End: // totalLength contains the padding already // In case of RTL map END alignment to the left edge if (isLayoutRtl) { childLeft = new LayoutLength(Padding.Start); } else { childLeft = new LayoutLength(Padding.Start + right.AsDecimal() - left.AsDecimal() - _totalLength); } break; case Alignment.CenterHorizontal: // FALL THROUGH case Alignment.Center: // totalLength contains the padding already childLeft = new LayoutLength(Padding.Start + (right.AsDecimal() - left.AsDecimal() - _totalLength) / 2.0f); break; case Alignment.Begin: // FALL THROUGH (default) default: // totalLength contains the padding already // In case of RTL map BEGIN alignment to the right edge if (isLayoutRtl) { childLeft = new LayoutLength(Padding.Start + right.AsDecimal() - left.AsDecimal() - _totalLength); } else { childLeft = new LayoutLength(Padding.Start); } break; } int start = 0; int dir = 1; // In case of RTL, start drawing from the last child. if (isLayoutRtl) { start = count - 1; dir = -1; } for (int i = 0; i < count; i++) { int childIndex = start + dir * i; // Get a reference to the childLayout at the given index LayoutItem childLayout = LinearChildren[childIndex]; LayoutLength childWidth = childLayout.MeasuredWidth.Size; LayoutLength childHeight = childLayout.MeasuredHeight.Size; Extents childMargin = childLayout.Margin; switch (LinearAlignment) { case Alignment.Bottom: childTop = new LayoutLength(height - Padding.Bottom - childHeight - childMargin.Bottom); break; case Alignment.CenterVertical: case Alignment.Center: // FALLTHROUGH childTop = new LayoutLength(Padding.Top + ((childSpace - childHeight).AsDecimal() / 2.0f) + childMargin.Top - childMargin.Bottom); break; case Alignment.Top: // FALLTHROUGH default default: childTop = new LayoutLength(Padding.Top + childMargin.Top); break; } childLeft += childMargin.Start; childLayout.Layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); childLeft += childWidth + childMargin.End + ((i < count - 1) ? CellPadding.Width : 0); } } // LayoutHorizontally
} // MeasureHorizontal private void MeasureVertical(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) { var widthMode = widthMeasureSpec.Mode; var heightMode = heightMeasureSpec.Mode; bool isWidthExactly = (widthMode == MeasureSpecification.ModeType.Exactly); bool isHeightExactly = (heightMode == MeasureSpecification.ModeType.Exactly); float maxWidth = 0.0f; float totalWeight = 0.0f; int childrenCount = IterateLayoutChildren().Count(); // Child layout, which wants to match its height to its parent's remaining height, is either following 1 or 2. // 1. Child layout whose Owner.HeightSpecification is LayoutParamPolicies.MatchParent. // 2. Child layout whose Owner.HeightSpecification is 0 and Owner.Weight is greater than 0. // The number of child layout which wants to match its height to its parent's remaining height. int childrenMatchParentCount = 0; // Reset measure variable totalLength = 0.0f; HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK, MeasuredSize.StateType.MeasuredSizeOK); // 1ST PHASE: // // We measure all children whose height specification policy is WrapContent without weight. // After 1st phase, remaining height of parent is accumulated to calculate height of children // whose height specification policy is MatchParent. foreach (var childLayout in LayoutChildren) { if (!childLayout.SetPositionByLayout) { continue; } int childDesiredWidth = childLayout.Owner.WidthSpecification; int childDesiredHeight = childLayout.Owner.HeightSpecification; float childWeight = childLayout.Owner.Weight; Extents childMargin = childLayout.Margin; float childMarginWidth = childMargin.Start + childMargin.End; float childMarginHeight = childMargin.Top + childMargin.Bottom; bool useRemainingHeight = (childDesiredHeight == 0) && (childWeight > 0); if ((childDesiredHeight == LayoutParamPolicies.MatchParent) || (useRemainingHeight)) { totalWeight += childWeight; childrenMatchParentCount++; } // MatchParent child layout's margin is not added to totalLength. // Consequently, MatchParent child layout's margin is added to remaining size, // so the margin is not shared with other MatchParent child layouts. // e.g. // LinearLayout has size 100. // Child layout1 is MatchParent and its margin is 20. (This margin is not ad // Child layout2 is MatchParent and its margin is 0. // Then, child layout1's size is 30 and child layout2's size is 50. if ((childDesiredHeight == LayoutParamPolicies.WrapContent) || ((childDesiredHeight > 0) && (!useRemainingHeight))) { MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0)); float childMeasuredHeight = childLayout.MeasuredHeight.Size.AsDecimal(); if (childMeasuredHeight < 0) { totalLength = Math.Max(totalLength, totalLength + childMarginHeight); } else { totalLength = Math.Max(totalLength, totalLength + childMeasuredHeight + childMarginHeight); } } if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; } if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; } float childMeasuredWidth = childLayout.MeasuredWidth.Size.AsDecimal(); if (childMeasuredWidth < 0) { maxWidth = Math.Max(maxWidth, childMarginWidth); } else { maxWidth = Math.Max(maxWidth, childMeasuredWidth + childMarginWidth); } } // 1ST PHASE foreach totalLength = Math.Max(totalLength, totalLength + CellPadding.Height * (childrenCount - 1) + Padding.Top + Padding.Bottom); float heightSize = Math.Max(totalLength, SuggestedMinimumHeight.AsDecimal()); MeasuredSize heightSizeAndState = ResolveSizeAndState(new LayoutLength(heightSize), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); heightSize = heightSizeAndState.Size.AsDecimal(); float remainingHeight = heightSize - totalLength; float totalWeightLength = 0.0f; // Up to now, only WrapContent children's sizes are added to the totalLength. // Since the totalLength is used in OnLayout as the sum of all children's sizes, // the layout size is assigned to the totalLength if MatchParent child exists. if (childrenMatchParentCount > 0) { totalLength = heightSize; } // 2ND PHASE: // // We measure all children whose height specification policy is MatchParent without weight. // After 2nd phase, all children's heights are calculated without considering weight. // And the heights of all weighted children are accumulated to calculate weighted height. foreach (var childLayout in LayoutChildren) { if (!childLayout.SetPositionByLayout) { continue; } int childDesiredWidth = childLayout.Owner.WidthSpecification; int childDesiredHeight = childLayout.Owner.HeightSpecification; float childWeight = childLayout.Owner.Weight; Extents childMargin = childLayout.Margin; float childMarginWidth = childMargin.Start + childMargin.End; bool useRemainingHeight = (childDesiredHeight == 0) && (childWeight > 0); bool needToMeasure = false; if ((childDesiredWidth == LayoutParamPolicies.MatchParent) || (useRemainingHeight)) { if (isWidthExactly) { needToMeasure = true; } // RelativeLayout's MatchParent children should not fill to the RelativeLayout. // Because the children's sizes and positions are calculated by RelativeLayout's APIs. // Therefore, not to fill the RelativeLayout, the mode is changed from Exactly to AtMost. // // Not to print the recursive reference error message for this case, Specification is checked if it is WrapContent. else if (Owner.WidthSpecification == LayoutParamPolicies.WrapContent) { if (childDesiredWidth == LayoutParamPolicies.MatchParent) { Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s WidthSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s WidthSpecification is MatchParent!"); } else { Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s WidthSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s WidthSpecification is 0 with positive weight!"); } } } if (remainingHeight > 0) { if ((childDesiredHeight == LayoutParamPolicies.MatchParent) || (useRemainingHeight)) { if (isHeightExactly) { // In MeasureChildWithMargins(), it is assumed that heightMeasureSpec includes Padding.Top and Padding.Bottom. // Therefore, Padding.Top and Padding.Bottom are added to heightMeasureSpec.Size before it is passed to MeasureChildWithMargins(). heightMeasureSpec.SetSize(new LayoutLength((int)(remainingHeight / childrenMatchParentCount) + Padding.Top + Padding.Bottom)); needToMeasure = true; } // RelativeLayout's MatchParent children should not fill to the RelativeLayout. // Because the children's sizes and positions are calculated by RelativeLayout's APIs. // Therefore, not to fill the RelativeLayout, the mode is changed from Exactly to AtMost. // // Not to print the recursive reference error message for this case, Specification is checked if it is WrapContent. else if (Owner.HeightSpecification == LayoutParamPolicies.WrapContent) { if (childDesiredHeight == LayoutParamPolicies.MatchParent) { Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s HeightSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s HeightSpecification is MatchParent!"); } else { Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s HeightSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s HeightSpecification is 0 with positive weight!"); } } } } if (needToMeasure == true) { MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0)); float childMeasuredWidth = childLayout.MeasuredWidth.Size.AsDecimal(); if (childMeasuredWidth < 0) { maxWidth = Math.Max(maxWidth, childMarginWidth); } else { maxWidth = Math.Max(maxWidth, childMeasuredWidth + childMarginWidth); } } if ((childWeight > 0) && ((childDesiredHeight == LayoutParamPolicies.MatchParent) || (childDesiredHeight == 0))) { float childMeasuredHeight = childLayout.MeasuredHeight.Size.AsDecimal(); if (childMeasuredHeight < 0) { totalWeightLength = Math.Max(totalWeightLength, totalWeightLength + childMargin.Top + childMargin.Bottom); } else { totalWeightLength = Math.Max(totalWeightLength, totalWeightLength + childMeasuredHeight + childMargin.Top + childMargin.Bottom); } } } // 2ND PHASE foreach // 3RD PHASE: // // We measure all weighted children whose owner has weight greater than 0. // After 3rd phase, all weighted children has height which is proportional to their weights // in remaining height of parent. if (totalWeight > 0) { foreach (var childLayout in LayoutChildren) { if (!childLayout.SetPositionByLayout) { continue; } int childDesiredHeight = childLayout.Owner.HeightSpecification; float childWeight = childLayout.Owner.Weight; if ((childWeight > 0) && ((childDesiredHeight == LayoutParamPolicies.MatchParent) || (childDesiredHeight == 0))) { if (isHeightExactly) { MeasureWeightedChild(childLayout, totalWeightLength, totalWeight, childWeight, widthMeasureSpec, heightMeasureSpec, childState, Orientation.Vertical); } // RelativeLayout's MatchParent children should not fill to the RelativeLayout. // Because the children's sizes and positions are calculated by RelativeLayout's APIs. // Therefore, not to fill the RelativeLayout, the mode is changed from Exactly to AtMost. // // Not to print the recursive reference error message for this case, Specification is checked if it is WrapContent. else if (Owner.HeightSpecification == LayoutParamPolicies.WrapContent) { if (childDesiredHeight == LayoutParamPolicies.MatchParent) { Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s HeightSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s HeightSpecification is MatchParent!"); } else { Tizen.Log.Error("NUI", "There is a recursive reference! Parent layout(Owner: " + Owner + ")'s HeightSpecification is WrapContent and child layout(Owner: " + childLayout.Owner + ")'s HeightSpecification is 0 with positive weight!"); } } } } // 3RD PHASE foreach } maxWidth = Math.Max(maxWidth, maxWidth + (Padding.Start + Padding.End)); maxWidth = Math.Max(maxWidth, SuggestedMinimumWidth.AsRoundedValue()); heightSizeAndState.State = childState.heightState; SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(maxWidth), widthMeasureSpec, childState.widthState), heightSizeAndState); } // MeasureVertical
private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) { var widthMode = widthMeasureSpec.Mode; var heightMode = heightMeasureSpec.Mode; bool isExactly = (widthMode == MeasureSpecification.ModeType.Exactly); bool matchHeight = false; bool allFillParent = true; float maxHeight = 0.0f; float alternativeMaxHeight = 0.0f; float weightedMaxHeight = 0.0f; float totalWeight = 0.0f; int childrenCount = IterateLayoutChildren().Count(); // Reset measure variables _totalLength = 0.0f; float usedExcessSpace = 0.0f; HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK, MeasuredSize.StateType.MeasuredSizeOK); // 1st phase: // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs // to accumulate total used space in totalLength based on measured sizes and margins. // Weighted children are not measured at this phase. // Available space for weighted children will be calculated in the phase 2 based on totalLength value. // Max height of children is stored. foreach (LayoutItem childLayout in IterateLayoutChildren()) { int childDesiredHeight = childLayout.Owner.HeightSpecification; float childWeight = childLayout.Owner.Weight; Extents childMargin = childLayout.Margin; totalWeight += childWeight; bool useExcessSpace = (childLayout.Owner.WidthSpecification == 0) && (childWeight > 0); if (isExactly && useExcessSpace) { // Children to be laid out with excess space can be measured later _totalLength = Math.Max(_totalLength, (_totalLength + childMargin.Start + childMargin.End)); } else { if (useExcessSpace) { // Parent is not defiend!!! // The widthMode is either Unspecified or AtMost, and // this child is only laid out using excess space. Measure // using WrapContent so that we can find out the view's // optimal width. MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification( new MeasureSpecification( new LayoutLength(widthMeasureSpec.Size - (childLayout.Margin.Start + childLayout.Margin.End)), widthMeasureSpec.Mode), new LayoutLength(Padding.Start + Padding.End), new LayoutLength(LayoutParamPolicies.WrapContent)); MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification( new MeasureSpecification( new LayoutLength(heightMeasureSpec.Size - (childLayout.Margin.Top + childLayout.Margin.Bottom)), heightMeasureSpec.Mode), new LayoutLength(Padding.Top + Padding.Bottom), new LayoutLength(childDesiredHeight)); childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec); usedExcessSpace += childLayout.MeasuredWidth.Size.AsDecimal(); } else { MeasureChildWithMargins(childLayout, widthMeasureSpec, new LayoutLength(0), heightMeasureSpec, new LayoutLength(0)); } LayoutLength childWidth = childLayout.MeasuredWidth.Size; LayoutLength length = childWidth + childMargin.Start + childMargin.End; _totalLength = Math.Max(_totalLength, _totalLength + length.AsDecimal()); } bool matchHeightLocally = false; if (heightMode != MeasureSpecification.ModeType.Exactly && childDesiredHeight == LayoutParamPolicies.MatchParent) { // A child has set to MatchParent on it's height. // Will have to re-measure at least this child when we know exact height. matchHeight = true; matchHeightLocally = true; } float marginHeight = childMargin.Top + childMargin.Bottom; float childHeight = childLayout.MeasuredHeight.Size.AsDecimal() + marginHeight; if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; } if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; } maxHeight = Math.Max(maxHeight, childHeight); allFillParent = (allFillParent && childDesiredHeight == LayoutParamPolicies.MatchParent); if (childWeight > 0) { // Heights of weighted Views are invalid if we end up remeasuring, so store them separately. weightedMaxHeight = Math.Max(weightedMaxHeight, matchHeightLocally ? marginHeight : childHeight); } else { alternativeMaxHeight = Math.Max(alternativeMaxHeight, matchHeightLocally ? marginHeight : childHeight); } } // foreach _totalLength = Math.Max(_totalLength, _totalLength + CellPadding.Width * (childrenCount - 1)); float widthSize = _totalLength; widthSize = Math.Max(widthSize, SuggestedMinimumWidth.AsDecimal()); MeasuredSize widthSizeAndState = ResolveSizeAndState(new LayoutLength(widthSize + Padding.Start + Padding.End), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); widthSize = widthSizeAndState.Size.AsDecimal(); // 2nd phase: // Expand children with weight to take up available space // We cycle through weighted children now (children with weight > 0). // The children are measured with exact size equal to their share of the available space based on their weights. // _totalLength is updated to include weighted children measured sizes. float remainingExcess = widthSize - _totalLength + usedExcessSpace - (Padding.Start + Padding.End); if (remainingExcess != 0 && totalWeight > 0) { float remainingWeight = totalWeight; maxHeight = 0; _totalLength = 0; foreach (LayoutItem childLayout in IterateLayoutChildren()) { float desiredChildHeight = childLayout.Owner.HeightSpecification; float childWeight = childLayout.Owner.Weight; Extents childMargin = childLayout.Margin; if (childWeight > 0) { MeasureWeightedChild(childLayout, remainingExcess, remainingWeight, childWeight, widthMeasureSpec, heightMeasureSpec, childState, Orientation.Horizontal); } float length = childLayout.MeasuredWidth.Size.AsDecimal() + childMargin.Start + childMargin.End; _totalLength += length; bool matchHeightLocally = (heightMode != MeasureSpecification.ModeType.Exactly) && (desiredChildHeight == LayoutParamPolicies.MatchParent); float marginHeight = childMargin.Top + childMargin.Bottom; float childHeight = childLayout.MeasuredHeight.Size.AsDecimal() + marginHeight; maxHeight = Math.Max(maxHeight, childHeight); alternativeMaxHeight = Math.Max(alternativeMaxHeight, matchHeightLocally ? marginHeight : childHeight); allFillParent = (allFillParent && desiredChildHeight == LayoutParamPolicies.MatchParent); } // for loop _totalLength = Math.Max(_totalLength, _totalLength + CellPadding.Width * (childrenCount - 1)); } else { // No excess space or no weighted children alternativeMaxHeight = Math.Max(alternativeMaxHeight, weightedMaxHeight); } if (!allFillParent && heightMode != MeasureSpecification.ModeType.Exactly) { maxHeight = alternativeMaxHeight; } // Padding should be concerned when specification is Wrapcontent. maxHeight += (Owner.HeightSpecification == LayoutParamPolicies.WrapContent) ? (Padding.Top + Padding.Bottom) : 0; maxHeight = Math.Max(maxHeight, SuggestedMinimumHeight.AsRoundedValue()); widthSizeAndState.State = childState.widthState; SetMeasuredDimensions(widthSizeAndState, ResolveSizeAndState(new LayoutLength(maxHeight), heightMeasureSpec, childState.heightState)); if (matchHeight) { ForceUniformHeight(widthMeasureSpec); } } // MeasureHorizontal
} // MeasureHorizontally void MeasureVertical(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) { var widthMode = widthMeasureSpec.Mode; var heightMode = heightMeasureSpec.Mode; bool isExactly = (heightMode == MeasureSpecification.ModeType.Exactly); bool matchWidth = false; bool allFillParent = true; float maxWidth = 0.0f; float alternativeMaxWidth = 0.0f; float weightedMaxWidth = 0.0f; float totalWeight = 0.0f; // Reset total length _totalLength = 0.0f; LayoutLength usedExcessSpace = new LayoutLength(0); HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK, MeasuredSize.StateType.MeasuredSizeTooSmall); // measure children, and determine if further resolution is required // 1st phase: // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs // to accumulate total used space in mTotalLength based on measured sizes and margins. // Weighted children are not measured at this phase. // Available space for weighted children will be calculated in the phase 2 based on mTotalLength value. uint index = 0; foreach (LayoutItem childLayout in _children) { LayoutLength childDesiredWidth = new LayoutLength(childLayout.Owner.WidthSpecification); LayoutLength childDesiredHeight = new LayoutLength(childLayout.Owner.HeightSpecification); float childWeight = childLayout.Owner.Weight; Extents childMargin = childLayout.Margin; totalWeight += childWeight; bool useExcessSpace = (childDesiredHeight.AsRoundedValue() == 0) && (childWeight > 0); if (isExactly && useExcessSpace) { LayoutLength totalLength = new LayoutLength(_totalLength); _totalLength = Math.Max(totalLength.AsDecimal(), (totalLength + childMargin.Top + childMargin.Bottom).AsDecimal()); } else { LayoutLength childHeight = new LayoutLength(0); if (useExcessSpace) { // The heightMode is either Unspecified or AtMost, and // this child is only laid out using excess space. Measure // using WrapContent so that we can find out the view's // optimal height. We'll restore the original height of 0 // after measurement. MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(widthMeasureSpec, new LayoutLength(childLayout.Padding.Start + childLayout.Padding.End), childDesiredWidth); MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(heightMeasureSpec, new LayoutLength(childLayout.Padding.Top + childLayout.Padding.Bottom), new LayoutLength(LayoutParamPolicies.WrapContent)); childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec); childHeight = childLayout.MeasuredHeight.Size; usedExcessSpace += childHeight; } else { MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec); childHeight = childLayout.MeasuredHeight.Size; } float length = (childHeight + childMargin.Top + childMargin.Bottom).AsDecimal(); float cellPadding = CellPadding.Height; // No need to add cell padding to the end of last item. if (index >= _children.Count - 1) { cellPadding = 0.0f; } _totalLength = Math.Max(_totalLength, _totalLength + length + cellPadding); } bool matchWidthLocally = false; if (widthMode != MeasureSpecification.ModeType.Exactly && childDesiredWidth == new LayoutLength(LayoutParamPolicies.MatchParent)) { // Will have to re-measure at least this child when we know exact height. matchWidth = true; matchWidthLocally = true; } float marginWidth = (childLayout.Margin.Start) + (childLayout.Margin.End); LayoutLength childWidth = new LayoutLength(childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth); // was combineMeasuredStates() if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; } if (childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; } maxWidth = (Math.Max(maxWidth, childWidth.AsDecimal())); allFillParent = (allFillParent && (childDesiredWidth == new LayoutLength(LayoutParamPolicies.MatchParent))); float widthforWeight = childWidth.AsDecimal(); if (matchWidthLocally) { widthforWeight = marginWidth; } if (childWeight > 0) { /* * Widths of weighted Views are bogus if we end up remeasuring, so keep them separate. */ weightedMaxWidth = Math.Max(weightedMaxWidth, widthforWeight); } else { alternativeMaxWidth = Math.Max(alternativeMaxWidth, widthforWeight); } } // foreach Extents padding = Padding; _totalLength += padding.Top + padding.Bottom; LayoutLength heightSize = new LayoutLength(_totalLength); heightSize = new LayoutLength(Math.Max(heightSize.AsDecimal(), SuggestedMinimumHeight.AsDecimal())); MeasuredSize heightSizeAndState = ResolveSizeAndState(heightSize, heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); heightSize = heightSizeAndState.Size; // Either expand children with weight to take up available space or // shrink them if they extend beyond our current bounds. If we skipped // measurement on any children, we need to measure them now. // 2nd phase: // We cycle through weighted children now (children with weight > 0). // The children are measured with exact size equal to their share of the available space based on their weights. // TotalLength is updated to include weighted children measured sizes. float remainingExcess = heightSize.AsDecimal() - _totalLength + usedExcessSpace.AsDecimal(); if (remainingExcess != 0 && totalWeight > 0.0f) { float remainingWeightSum = totalWeight; _totalLength = 0; foreach (LayoutItem childLayout in _children) { int desiredWidth = childLayout.Owner.WidthSpecification; int desiredHeight = childLayout.Owner.HeightSpecification; float childWeight = childLayout.Owner.Weight; Extents childMargin = childLayout.Margin; float childHeight = 0; if (childWeight > 0) { float share = (childWeight * remainingExcess) / remainingWeightSum; remainingExcess -= share; remainingWeightSum -= childWeight; // Always lay out weighted elements with intrinsic size regardless of the parent spec // for consistency between specs. if (desiredHeight == 0) { // This child needs to be laid out from scratch using // only its share of excess space. childHeight = share; } else { // This child had some intrinsic width to which we // need to add its share of excess space. childHeight = childLayout.MeasuredHeight.Size.AsDecimal() + share; } MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(widthMeasureSpec, new LayoutLength(Padding.Start + Padding.End), new LayoutLength(desiredWidth)); MeasureSpecification childHeightMeasureSpec = new MeasureSpecification(new LayoutLength(childHeight), MeasureSpecification.ModeType.Exactly); childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec); // Child may now not fit in vertical dimension. if (childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; } } bool matchWidthLocally = false; if (widthMode != MeasureSpecification.ModeType.Exactly && desiredWidth == (int)ChildLayoutData.MatchParent) { // Will have to re-measure at least this child when we know exact height. matchWidth = true; matchWidthLocally = true; } float marginWidth = childMargin.Start + childMargin.End; float childWidth = childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth; maxWidth = Math.Max(maxWidth, childWidth); allFillParent = allFillParent && desiredWidth == (int)ChildLayoutData.MatchParent; alternativeMaxWidth = Math.Max(alternativeMaxWidth, matchWidthLocally ? marginWidth : childWidth); childHeight = childLayout.MeasuredHeight.Size.AsDecimal(); float length = childHeight + childMargin.Top + childMargin.Bottom; float cellPadding = CellPadding.Height; // No need to add cell padding to the end of last item. if (index >= _children.Count - 1) { cellPadding = 0.0f; } _totalLength = Math.Max(_totalLength, _totalLength + length + cellPadding); } // foreach // Add in our padding _totalLength += Padding.Top + Padding.Bottom; } else { alternativeMaxWidth = Math.Max(alternativeMaxWidth, weightedMaxWidth); } if (!allFillParent && widthMode != MeasureSpecification.ModeType.Exactly) { maxWidth = alternativeMaxWidth; } maxWidth += padding.Start + padding.End; maxWidth = Math.Max(maxWidth, SuggestedMinimumWidth.AsRoundedValue()); heightSizeAndState.State = childState.heightState; SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(maxWidth), widthMeasureSpec, childState.widthState), heightSizeAndState); if (matchWidth) { ForceUniformWidth(_children.Count, heightMeasureSpec); } } // MeasureVertically
/// <summary> /// Measure the layout and its content to determine the measured width and the measured height.<br /> /// </summary> /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param> /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param> /// <since_tizen> 6 </since_tizen> protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) { var gridWidthMode = widthMeasureSpec.Mode; var gridHeightMode = heightMeasureSpec.Mode; int widthSize = (int)widthMeasureSpec.Size.AsRoundedValue(); int heightSize = (int)heightMeasureSpec.Size.AsRoundedValue(); int availableContentWidth; int availableContentHeight; int desiredChildHeight; int desiredChildWidth; Extents gridLayoutPadding = Padding; var childCount = LayoutChildren.Count; // WIDTH SPECIFICATIONS if (childCount > 0) { foreach (LayoutItem childLayout in LayoutChildren) { if (childLayout != null) { MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec); } } // Use first child's dimensions for layout measurement View childOwner = LayoutChildren[0].Owner; desiredChildHeight = (int)LayoutChildren[0].MeasuredHeight.Size.AsRoundedValue(); desiredChildWidth = (int)LayoutChildren[0].MeasuredWidth.Size.AsRoundedValue(); // If child has a margin then add it to desired size Extents childMargin = LayoutChildren[0].Margin; desiredChildHeight += childMargin.Top + childMargin.Bottom; desiredChildWidth += childMargin.Start + childMargin.End; _totalWidth = desiredChildWidth * _columns; // Include padding for max and min checks _totalWidth += gridLayoutPadding.Start + gridLayoutPadding.End; // Ensure width does not exceed specified at most width or less than mininum width _totalWidth = Math.Max(_totalWidth, (int)SuggestedMinimumWidth.AsRoundedValue()); // widthMode EXACTLY so grid must be the given width if (gridWidthMode == MeasureSpecification.ModeType.Exactly || gridWidthMode == MeasureSpecification.ModeType.AtMost) { // In the case of AT_MOST, widthSize is the max limit. _totalWidth = Math.Min(_totalWidth, widthSize); } availableContentWidth = _totalWidth - gridLayoutPadding.Start - gridLayoutPadding.End; widthSize = _totalWidth; // HEIGHT SPECIFICATIONS // heightMode EXACTLY so grid must be the given height if (gridHeightMode == MeasureSpecification.ModeType.Exactly || gridHeightMode == MeasureSpecification.ModeType.AtMost) { if (childCount > 0) { _totalHeight = gridLayoutPadding.Top + gridLayoutPadding.Bottom; for (int i = 0; i < childCount; i += _columns) { _totalHeight += desiredChildHeight; } // Ensure ourHeight does not exceed specified at most height _totalHeight = Math.Min(_totalHeight, heightSize); _totalHeight = Math.Max(_totalHeight, (int)SuggestedMinimumHeight.AsRoundedValue()); heightSize = _totalHeight; } // Child exists // In the case of AT_MOST, availableContentHeight is the max limit. availableContentHeight = heightSize - gridLayoutPadding.Top - gridLayoutPadding.Bottom; } else { // Grid expands to fit content // If number of columns AUTO_FIT then set to 1 column. _columns = (_columns > 0) ? _columns : 1; // Calculate numbers of rows, round down result as later check for remainder. _rows = childCount / _columns; // If number of cells not cleanly dividable by columns, add another row to house remainder cells. _rows += (childCount % _columns > 0) ? 1 : 0; heightSize = desiredChildHeight * _rows + gridLayoutPadding.Top + gridLayoutPadding.Bottom; availableContentHeight = heightSize - gridLayoutPadding.Top - gridLayoutPadding.Bottom; } // If number of columns not defined DetermineNumberOfColumns(availableContentWidth); // Locations define the start, end,top and bottom of each cell. _locations.CalculateLocations(_columns, availableContentWidth, availableContentHeight, childCount); } // Children exists SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(widthSize + Padding.Start + Padding.End), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK), ResolveSizeAndState(new LayoutLength(heightSize + Padding.Top + Padding.Bottom), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK)); }
/// <summary> /// Creates a Extents value. /// </summary> /// <param name="extentsValue">A Extents value.</param> /// <since_tizen> 4 </since_tizen> public PropertyValue(Extents extentsValue) : this(Interop.PropertyValue.NewPropertyValueExtents(Extents.getCPtr(extentsValue)), true) { if (NDalicPINVOKE.SWIGPendingException.Pending) { throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } }
private int CalculateHorizontalSize(MeasureSpecification.ModeType gridWidthMode, MeasureSpecification.ModeType gridHeightMode, int widthSize, int heightSize) { int availableContentWidth; int availableContentHeight; int desiredChildHeight; int desiredChildWidth; Extents gridLayoutPadding = Padding; var childCount = LayoutChildren.Count; // Use first child's dimensions for layout measurement View childOwner = LayoutChildren[0].Owner; desiredChildHeight = (int)LayoutChildren[0].MeasuredHeight.Size.AsRoundedValue(); desiredChildWidth = (int)LayoutChildren[0].MeasuredWidth.Size.AsRoundedValue(); // If child has a margin then add it to desired size Extents childMargin = LayoutChildren[0].Margin; desiredChildHeight += childMargin.Top + childMargin.Bottom; desiredChildWidth += childMargin.Start + childMargin.End; _totalHeight = desiredChildHeight * _rows; _totalHeight += gridLayoutPadding.Top + gridLayoutPadding.Bottom; _totalHeight = Math.Max(_totalHeight, (int)SuggestedMinimumHeight.AsRoundedValue()); if (gridHeightMode == MeasureSpecification.ModeType.Exactly || gridHeightMode == MeasureSpecification.ModeType.AtMost) { _totalHeight = Math.Min(_totalHeight, heightSize); } availableContentHeight = _totalHeight - gridLayoutPadding.Top - gridLayoutPadding.Bottom; heightSize = _totalHeight; if (gridWidthMode == MeasureSpecification.ModeType.Exactly || gridWidthMode == MeasureSpecification.ModeType.AtMost) { if (childCount > 0) { _totalWidth = gridLayoutPadding.Start + gridLayoutPadding.End; for (int i = 0; i < childCount; i += _rows) { _totalWidth += desiredChildWidth; } _totalWidth = Math.Min(_totalWidth, widthSize); _totalWidth = Math.Max(_totalWidth, (int)SuggestedMinimumWidth.AsRoundedValue()); widthSize = _totalWidth; } // Child exists // In the case of AT_MOST, availableContentHeight is the max limit. availableContentWidth = widthSize - gridLayoutPadding.Start - gridLayoutPadding.End; } else { _rows = (_rows > 0) ? _rows : 1; _columns = childCount / _rows; _columns += (childCount % _rows > 0) ? 1 : 0; widthSize = desiredChildWidth * _columns + gridLayoutPadding.Start + gridLayoutPadding.End; availableContentWidth = widthSize - gridLayoutPadding.Start - gridLayoutPadding.End; } // If number of rows not defined DetermineNumberOfRows(availableContentHeight); _locations.CalculateLocationsRow(_rows, availableContentWidth, availableContentHeight, childCount); return(availableContentWidth); }
void InsertChild( LayoutItem child ) { // Store created node for child Interop.FlexLayout.FlexLayout_AddChildWithMargin(swigCPtr, View.getCPtr(child.Owner), Extents.getCPtr(child.Owner.Margin), measureChildDelegate, LayoutChildren.Count-1); }
private void MeasureWeightedChild(LayoutItem childLayout, float remainingExcess, float remainingWeight, float childWeight, MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec, HeightAndWidthState childState, Orientation orientation) { bool horizontal = false; if (orientation == Orientation.Horizontal) { horizontal = true; } float childsShare = (childWeight * remainingExcess) / remainingWeight; remainingExcess -= childsShare; remainingWeight -= childWeight; float desiredWidth = childLayout.Owner.WidthSpecification; float desiredHeight = childLayout.Owner.HeightSpecification; float childLength = 0; Extents layoutPadding = Padding; // Always lay out weighted elements with intrinsic size regardless of the parent spec. // for consistency between specs. if ((horizontal && (desiredWidth == 0)) || (!horizontal && (desiredHeight == 0))) { // This child needs to be laid out from scratch using // only its share of excess space. childLength = childsShare; } else { // This child had some intrinsic width to which we // need to add its share of excess space. if (horizontal) { childLength = childLayout.MeasuredWidth.Size.AsDecimal() + childsShare; } else { childLength = childLayout.MeasuredHeight.Size.AsDecimal() + childsShare; } } MeasureSpecification childWidthMeasureSpec; MeasureSpecification childHeightMeasureSpec; if (horizontal) { childWidthMeasureSpec = new MeasureSpecification(new LayoutLength(childLength), MeasureSpecification.ModeType.Exactly); childHeightMeasureSpec = GetChildMeasureSpecification(heightMeasureSpec, new LayoutLength(layoutPadding.Top + layoutPadding.Bottom), new LayoutLength(desiredHeight)); } else // vertical { childWidthMeasureSpec = GetChildMeasureSpecification(widthMeasureSpec, new LayoutLength(Padding.Start + Padding.End), new LayoutLength(desiredWidth)); childHeightMeasureSpec = new MeasureSpecification(new LayoutLength(childLength), MeasureSpecification.ModeType.Exactly); } childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec); // Child may now not fit in horizontal dimension. if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; } // Child may now not fit in vertical dimension. if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; } }
private void Initialize() { _layoutPositionData = new LayoutData(this, TransitionCondition.Unspecified, 0, 0, 0, 0); _padding = new Extents(0, 0, 0, 0); _margin = new Extents(0, 0, 0, 0); }
/// <summary> /// Measure the layout and its content to determine the measured width and the measured height.<br /> /// </summary> /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param> /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param> /// <since_tizen> 6 </since_tizen> protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) { bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL; Extents padding = Owner.Padding; Extents margin = Owner.Margin; Interop.FlexLayout.FlexLayout_SetMargin(swigCPtr, Extents.getCPtr(margin)); Interop.FlexLayout.FlexLayout_SetPadding(swigCPtr, Extents.getCPtr(padding)); float width = FlexUndefined; // Behaves as WrapContent (Flex Auto) float height = FlexUndefined; // Behaves as WrapContent (Flex Auto) if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || widthMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost) { width = widthMeasureSpec.Size.AsDecimal(); } if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || heightMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost) { height = heightMeasureSpec.Size.AsDecimal(); } // Save measureSpec to measure children. // In other Layout, we can pass it as parameter to measuring child but in FlexLayout we can't // because measurChild function is called by native callback. parentMeasureSpecificationWidth = widthMeasureSpec; parentMeasureSpecificationHeight = heightMeasureSpec; // Assign child properties for (int i = 0; i < LayoutChildren.Count; i++) { LayoutItem layoutItem = LayoutChildren[i]; View Child = layoutItem?.Owner; HandleRef childHandleRef = (HandleRef)Child.GetValue(FlexItemProperty); if (childHandleRef.Handle == IntPtr.Zero || Child == null) { continue; } AlignmentType flexAlignemnt = GetFlexAlignmentSelf(Child); PositionType flexPosition = GetFlexPositionType(Child); float flexAspectRatio = GetFlexAspectRatio(Child); float flexBasis = GetFlexBasis(Child); float flexShrink = GetFlexShrink(Child); float flexGrow = GetFlexGrow(Child); Interop.FlexLayout.FlexLayout_SetFlexAlignmentSelf(childHandleRef, (int)flexAlignemnt); Interop.FlexLayout.FlexLayout_SetFlexPositionType(childHandleRef, (int)flexPosition); Interop.FlexLayout.FlexLayout_SetFlexAspectRatio(childHandleRef, flexAspectRatio); Interop.FlexLayout.FlexLayout_SetFlexBasis(childHandleRef, flexBasis); Interop.FlexLayout.FlexLayout_SetFlexShrink(childHandleRef, flexShrink); Interop.FlexLayout.FlexLayout_SetFlexGrow(childHandleRef, flexGrow); } Interop.FlexLayout.FlexLayout_CalculateLayout(swigCPtr, width, height, isLayoutRtl); LayoutLength flexLayoutWidth = new LayoutLength(Interop.FlexLayout.FlexLayout_GetWidth(swigCPtr)); LayoutLength flexLayoutHeight = new LayoutLength(Interop.FlexLayout.FlexLayout_GetHeight(swigCPtr)); Debug.WriteLineIf(LayoutDebugFlex, "FlexLayout OnMeasure width:" + flexLayoutWidth.AsRoundedValue() + " height:" + flexLayoutHeight.AsRoundedValue()); SetMeasuredDimensions(GetDefaultSize(flexLayoutWidth, widthMeasureSpec), GetDefaultSize(flexLayoutHeight, heightMeasureSpec)); }
void InsertChild(LayoutItem child) { // Store created node for child IntPtr childPtr = Interop.FlexLayout.FlexLayout_AddChildWithMargin(swigCPtr, View.getCPtr(child.Owner), Extents.getCPtr(child.Owner.Margin), measureChildDelegate, LayoutChildren.Count - 1); HandleRef childHandleRef = new HandleRef(child.Owner, childPtr); SetChildValue(child.Owner, FlexItemProperty, childHandleRef); }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(Extents obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }
public Extents GetPadding() { Extents ret = new Extents(LayoutPINVOKE.LayoutItemWrapperImpl_GetPadding(swigCPtr), true); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; }
internal Extents Assign(Extents copy) { Extents ret = new Extents(Interop.Extents.Extents_Assign__SWIG_0(swigCPtr, Extents.getCPtr(copy)), false); if (NDalicPINVOKE.SWIGPendingException.Pending) { throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) { var widthMode = widthMeasureSpec.Mode; var heightMode = heightMeasureSpec.Mode; bool isExactly = (widthMode == MeasureSpecification.ModeType.Exactly); bool matchHeight = false; bool allFillParent = true; float maxHeight = 0.0f; float alternativeMaxHeight = 0.0f; float weightedMaxHeight = 0.0f; float totalWeight = 0.0f; // Reset total length _totalLength = 0.0f; LayoutLength usedExcessSpace = new LayoutLength(0); HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK, MeasuredSize.StateType.MeasuredSizeOK); // Measure children, and determine if further resolution is required // 1st phase: // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs // to accumulate total used space in totalLength based on measured sizes and margins. // Weighted children are not measured at this phase. // Available space for weighted children will be calculated in the phase 2 based on totalLength value. foreach (LayoutItem childLayout in _children) { LayoutLength childDesiredWidth = new LayoutLength(childLayout.Owner.WidthSpecification); LayoutLength childDesiredHeight = new LayoutLength(childLayout.Owner.HeightSpecification); float childWeight = childLayout.Owner.Weight; Extents childMargin = childLayout.Margin; totalWeight += childWeight; bool useExcessSpace = (childDesiredWidth.AsRoundedValue() == 0) && (childWeight > 0); if (isExactly && useExcessSpace) { _totalLength += childMargin.Start + childMargin.End; } else { if (useExcessSpace) { // The widthMode is either UNSPECIFIED or AT_MOST, and // this child is only laid out using excess space. Measure // using WRAP_CONTENT so that we can find out the view's // optimal width. MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(widthMeasureSpec, new LayoutLength(childLayout.Padding.Start + childLayout.Padding.End), new LayoutLength(LayoutParamPolicies.WrapContent)); MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(heightMeasureSpec, new LayoutLength(childLayout.Padding.Top + childLayout.Padding.Bottom), childDesiredHeight); childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec); usedExcessSpace += childLayout.MeasuredWidth.Size; } else { MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec); } LayoutLength childWidth = childLayout.MeasuredWidth.Size; LayoutLength length = childWidth + childMargin.Start + childMargin.End; if (isExactly) { _totalLength += length.AsDecimal(); } else { _totalLength = Math.Max(_totalLength, _totalLength + length.AsDecimal() + CellPadding.Width); } } bool matchHeightLocally = false; if (heightMode != MeasureSpecification.ModeType.Exactly && (int)childDesiredHeight.AsRoundedValue() == LayoutParamPolicies.MatchParent) { // Will have to re-measure at least this child when we know exact height. matchHeight = true; matchHeightLocally = true; } LayoutLength marginHeight = new LayoutLength(childMargin.Top + childMargin.Bottom); LayoutLength childHeight = childLayout.MeasuredHeight.Size + marginHeight; if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; } if (childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) { childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; } maxHeight = Math.Max(maxHeight, childHeight.AsDecimal()); allFillParent = (allFillParent && childDesiredHeight.AsRoundedValue() == LayoutParamPolicies.MatchParent); if (childWeight > 0) { /* * Heights of weighted Views are bogus if we end up * remeasuring, so keep them separate. */ weightedMaxHeight = Math.Max(weightedMaxHeight, matchHeightLocally ? marginHeight.AsDecimal() : childHeight.AsDecimal()); } else { alternativeMaxHeight = Math.Max(alternativeMaxHeight, matchHeightLocally ? marginHeight.AsDecimal() : childHeight.AsDecimal()); } } // foreach Extents padding = Padding; _totalLength += padding.Start + padding.End; LayoutLength widthSize = new LayoutLength(_totalLength); widthSize = new LayoutLength(Math.Max(widthSize.AsDecimal(), SuggestedMinimumWidth.AsDecimal())); MeasuredSize widthSizeAndState = ResolveSizeAndState(widthSize, widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); widthSize = widthSizeAndState.Size; if (!allFillParent && heightMode != MeasureSpecification.ModeType.Exactly) { maxHeight = alternativeMaxHeight; } maxHeight += padding.Top + padding.Bottom; maxHeight = Math.Max(maxHeight, SuggestedMinimumHeight.AsRoundedValue()); widthSizeAndState.State = childState.widthState; SetMeasuredDimensions(widthSizeAndState, ResolveSizeAndState(new LayoutLength(maxHeight), heightMeasureSpec, childState.heightState)); if (matchHeight) { ForceUniformHeight(_children.Count, widthMeasureSpec); } } // MeasureHorizontally