public override SpecificLayout GetBestLayout(LayoutQuery query) { // The score of a Specific_ScrollLayout is defined in returnLayout: // If the child layout has negative score, the Specific_ScrollLayout refuses to do a layout // If the child layout has nonnegative score, the Specific_ScrollLayout's score equals // (this.resultingScore * (what fraction of the child layout is visible)) if (query.MinScore.CompareTo(this.resultingScore) > 0) { // Demands too high of a score: no solution return(null); } if (query.MaxHeight <= 0) { return(null); } // what fraction of the score of the sublayout will appear onscreen at once double scoreFraction = Math.Max(query.MinScore.DividedBy(this.resultingScore), 0); // what fraction of the child's height we need to include in the size of the ScrollView double requiredHeightFraction = scoreFraction; // the child's height divided by the ScrollView's height double requiredHeightMultiplier; if (requiredHeightFraction != 0) { requiredHeightMultiplier = 1 / requiredHeightFraction; } else { requiredHeightMultiplier = double.PositiveInfinity; } // the maximum child height double maxChildHeight = query.MaxHeight * requiredHeightMultiplier; if (query.MinimizesWidth()) { // For a min-width query, first shrink the width as much as possible before continuing SpecificLayout minWidth_childLayout = this.subLayout.GetBestLayout(query.New_MinWidth_LayoutQuery(query.MaxWidth, maxChildHeight, this.requiredChildScore)); if (minWidth_childLayout == null) { return(null); } query = query.WithDimensions(minWidth_childLayout.Width, minWidth_childLayout.Height); } SpecificLayout childLayout = this.subLayout.GetBestLayout(query.New_MinHeight_LayoutQuery(query.MaxWidth, maxChildHeight, this.requiredChildScore)); if (childLayout == null) { return(null); } if (!query.MinimizesHeight()) { // For a max-score (or min-width) query, use as much height as was allowed Size size = new Size(childLayout.Width, Math.Min(query.MaxHeight, childLayout.Height)); SpecificLayout result = this.makeLayout(size, childLayout); if (query.Accepts(result)) { return(this.prepareLayoutForQuery(result, query)); } return(null); } else { // For a min-height query, use only as much size as is needed double requiredScrollviewHeight = childLayout.Height * requiredHeightFraction; Size size = new Size(childLayout.Width, requiredScrollviewHeight); SpecificLayout result = this.makeLayout(size, childLayout); if (!query.Accepts(result)) { // Check for possible rounding error SpecificLayout larger = this.makeLayout(new Size(size.Width, size.Height + this.pixelSize), childLayout); if (query.Accepts(larger)) { return(this.prepareLayoutForQuery(larger, query)); } return(null); } return(this.prepareLayoutForQuery(result, query)); } }