public LayoutQuery WithDimensions(double width, double height, LayoutScore score) { LayoutQuery result = this.Clone(); result.setMaxWidth(width); result.setMaxHeight(height); result.setMinScore(score); return(result); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { long allocated = GC.GetTotalMemory(false); // format a number like 1234567 into a string like 1,234,567 string formatted = String.Format("{0:#,0}", allocated); this.textBlockLayout.setText("Memory usage: " + formatted + " bytes"); return(base.GetBestLayout(query)); }
// Given a SpecificLayout, sets any necessary properties to make it suitable to return to the caller of GetBestLayout(LayoutQuery) protected SpecificLayout prepareLayoutForQuery(SpecificLayout layout, LayoutQuery query) { if (layout != null) { if (layout.Width < 0 || layout.Height < 0) { ErrorReporter.ReportParadox("Illegal layout size: " + layout.Size); this.GetBestLayout(query); } } int numMatches; //if (query.Debug) { if (query.ProposedSolution_ForDebugging != null) { if (!query.Accepts(query.ProposedSolution_ForDebugging)) { ErrorReporter.ReportParadox("Error: the proposed solution was not valid"); } } if (layout != null && !query.Accepts(layout)) { ErrorReporter.ReportParadox("Error: the returned layout was not valid"); LayoutQuery query2 = query.DebugClone(); this.GetBestLayout(query2); } } if (layout != null) { //layout.Set_SourceParent(this); numMatches = 0; /*foreach (LayoutChoice_Set ancestor in layout.GetAncestors()) * { * if (ancestor == this) * numMatches++; * } * if (numMatches == 0) * ErrorReporter.ReportParadox("Error: the returned layout did not come from this layout"); * if (numMatches > 1) * ErrorReporter.ReportParadox("Error: the returned layout contained multiple ancestors matching this one"); */ layout.SourceQuery = query; } if (this.parents.Count < 1 && !(this is ViewManager)) { throw new InvalidOperationException("No parents assigned to " + this); } query.OnAnswered(this); return(layout); }
private SpecificLayout MakeLayout(double width, double height, LayoutQuery layoutQuery) { SpecificLayout layout = this.prepareLayoutForQuery(new Specific_LeafLayout(this.view, new LayoutDimensions(width, height, this.ComputeScore(width, height))), layoutQuery); if (!layoutQuery.Accepts(layout)) { ErrorReporter.ReportParadox("Error; ImageLayout attempted to return an invalid layout result"); } return(layout); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { SpecificLayout best_specificLayout = null; SpecificLayout debugResult = query.ProposedSolution_ForDebugging; if (debugResult != null) { debugResult = debugResult.Clone(); } List <LayoutChoice_Set> good_sourceLayouts = new List <LayoutChoice_Set>(); LayoutQuery originalQuery = query; foreach (LayoutChoice_Set layoutSet in this.layoutOptions) { if (best_specificLayout != null) { // make the query more strict, so we will only ever get dimensions that are at least as good as this // TODO: figure out why it's not better to use OptimizedPastExample query = query.OptimizedUsingExample(best_specificLayout); } SpecificLayout currentLayout; if (query.Debug) { // if the proposed layout is an option, then be sure to consider it if (debugResult != null && debugResult.GetAncestors().Contains(layoutSet)) { query.ProposedSolution_ForDebugging = debugResult; currentLayout = layoutSet.GetBestLayout(query); query.ProposedSolution_ForDebugging = debugResult; return(this.prepareLayoutForQuery(currentLayout, query)); } } currentLayout = layoutSet.GetBestLayout(query); if (currentLayout != null && query.PreferredLayout(currentLayout, best_specificLayout) == currentLayout) { // keep track of this query (which must be the best so far) best_specificLayout = currentLayout; good_sourceLayouts.Add(layoutSet); if (query.Debug && query.ProposedSolution_ForDebugging != null) { if (query.PreferredLayout(query.ProposedSolution_ForDebugging, best_specificLayout) != query.ProposedSolution_ForDebugging) { ErrorReporter.ReportParadox("Error; query " + query + " prefers " + best_specificLayout + " over proposed debug solution " + query.ProposedSolution_ForDebugging); LayoutQuery debugQuery = query.DebugClone(); layoutSet.GetBestLayout(debugQuery); } } } } originalQuery.ProposedSolution_ForDebugging = debugResult; return(this.prepareLayoutForQuery(best_specificLayout, originalQuery)); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { query = query.WithDefaults(this.defaultsOverride.LayoutDefaults); SpecificLayout result = this.SubLayout.GetBestLayout(query); if (result != null) { result = new OverrideLayoutDefaults_SpecificLayout(result, this.defaultsOverride.ViewDefaults); } return(this.prepareLayoutForQuery(result, query)); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { if (query.MaxWidth <= 0 || query.MaxHeight <= 0) { double width = 0; double height = 0; if (this.ComputeScore(width, height).CompareTo(query.MinScore) < 0) { return(null); } return(this.MakeLayout(width, height, query)); } LayoutScore score = this.ComputeScore(query.MaxWidth, query.MaxHeight); if (score.CompareTo(query.MinScore) < 0) { return(null); } double ratio = query.MinScore.DividedBy(score); if (query.MinimizesWidth()) { double width = Math.Ceiling(query.MaxWidth * ratio / this.pixelSize) * this.pixelSize; if (this.ComputeScore(width, query.MaxHeight).CompareTo(query.MinScore) < 0) { // the score has some additional components that the division didn't catch, so we have to add another pixel width += this.pixelSize; } if (width > query.MaxWidth) { // We had to round up past the max height, so there is no solution return(null); } return(this.MakeLayout(width, query.MaxHeight, query)); } if (query.MinimizesHeight()) { double height = Math.Ceiling(query.MaxHeight * ratio / this.pixelSize) * this.pixelSize; if (this.ComputeScore(query.MaxWidth, height).CompareTo(query.MinScore) < 0) { // the score has some additional components that the division didn't catch, so we have to add another pixel height += this.pixelSize; } if (height > query.MaxHeight) { // We had to round up past the max height, so there is no solution return(null); } return(this.MakeLayout(query.MaxWidth, height, query)); } return(MakeLayout(query.MaxWidth, query.MaxHeight, query)); }
protected LayoutQuery CopyFrom(LayoutQuery original) { this.setMaxWidth(original.maxWidth); this.setMaxHeight(original.maxHeight); this.setMinScore(original.minScore); if (original.Debug) { this.Debug = true; } this.Cost = original.Cost; this.ProposedSolution_ForDebugging = original.ProposedSolution_ForDebugging; return(this); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { if (this.font != query.LayoutDefaults.TextBox_Defaults.Font) { // invalidate size cache if the font name or font scale is changing this.font = query.LayoutDefaults.TextBox_Defaults.Font; this.layoutsByWidth = new Dictionary <double, FormattedParagraph>(); } // don't bother doing the layout if the required score is too high if (query.MinScore.CompareTo(this.BestPossibleScore) > 0) { return(null); } TextLayout.NumMeasures++; if (TextLayout.NumMeasures % 80 == 0) { System.Diagnostics.Debug.WriteLine("num text measurements = " + TextLayout.NumMeasures); } DateTime startTime = DateTime.Now; this.TextItem_Text = this.TextItem_Configurer.ModelledText; //ErrorReporter.ReportParadox("avg num computations per query = " + (double)numComputations / (double)numQueries); numQueries++; SpecificLayout result; if (query.MinimizesWidth()) { result = this.Get_MinWidth_Layout(query); } else { if (query.MinimizesHeight()) { result = this.Get_MinHeight_Layout(query); } else { result = this.Get_MaxScoring_Layout(query); } } DateTime endTime = DateTime.Now; TextLayout.TextTime += endTime.Subtract(startTime); return(result); }
// computes the size of the highest-scoring layout satisfying the given criteria private SpecificLayout Get_MaxScoring_Layout(LayoutQuery query) { if (query.MaxWidth < 0 || query.MaxHeight < 0) { return(null); } Specific_TextLayout specificLayout = this.ComputeDimensions(new Size(query.MaxWidth, query.MaxHeight), query.Debug); if (query.Accepts(specificLayout)) { return(this.prepareLayoutForQuery(specificLayout, query)); } return(null); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { if (this.SubLayout == null) { this.SubLayout = this.build(); } for (int i = 0; i < this.buttonNameProviders.Count; i++) { MenuItem menuItem = this.buttonNameProviders[i].Get(); this.buttons[i].Text = menuItem.Name; this.subtitles[i].setText(menuItem.Subtitle); } return(base.GetBestLayout(query)); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { LayoutQuery parentQuery = query.WithScore(query.MinScore.Minus(this.BonusScore)); SpecificLayout parentResult = base.GetBestLayout(parentQuery); if (parentResult == null) { return(null); } SpecificLayout result = this.makeSpecificLayout(this.View, parentResult.Size, this.BonusScore, parentResult, new Thickness()); this.prepareLayoutForQuery(result, query); return(result); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { if (query.MaxWidth < this.Width) { return(null); } if (query.MaxHeight < this.Height) { return(null); } if (!this.isScoreAtLeast(query)) { return(null); } return(this); }
public bool SameType(LayoutQuery other) { if (this.MinimizesWidth() != other.MinimizesWidth()) { return(false); } if (this.MinimizesHeight() != other.MinimizesHeight()) { return(false); } if (this.MaximizesScore() != other.MaximizesScore()) { return(false); } return(true); }
public override SpecificLayout GetBestLayout(LayoutQuery layoutQuery) { IEnumerable <LayoutDimensions> options = this.getLayoutOptions(layoutQuery); LayoutDimensions dimensions = null; foreach (LayoutDimensions candidate in options) { dimensions = layoutQuery.PreferredLayout(candidate, dimensions); } Specific_LeafLayout result = null; if (dimensions != null) { result = new Specific_LeafLayout(this.view, dimensions); } return(result); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { // don't bother doing the layout if the required score is too high if (query.MinScore.CompareTo(this.BestPossibleScore) > 0) { return(null); } TextLayout.NumMeasures++; if (TextLayout.NumMeasures % 80 == 0) { System.Diagnostics.Debug.WriteLine("num text measurements = " + TextLayout.NumMeasures); } DateTime startTime = DateTime.Now; this.TextItem_Text = this.TextItem_Configurer.ModelledText; //ErrorReporter.ReportParadox("avg num computations per query = " + (double)numComputations / (double)numQueries); numQueries++; SpecificLayout result; if (query.MinimizesWidth()) { result = this.Get_MinWidth_Layout(query); } else { if (query.MinimizesHeight()) { result = this.Get_MinHeight_Layout(query); } else { result = this.Get_MaxScoring_Layout(query); } } DateTime endTime = DateTime.Now; TextLayout.TextTime += endTime.Subtract(startTime); return(result); }
// computes the size of the layout with smallest height satisfying the given criteria private SpecificLayout Get_MinHeight_Layout(LayoutQuery query) { if (query.MaxWidth < 0 || query.MaxHeight < 0) { return(null); } // first check whether this query will accept a cropped layout Specific_TextLayout specificLayout = this.ComputeDimensions(new Size(0, 0), query.Debug); if (query.Accepts(specificLayout)) { return(this.prepareLayoutForQuery(specificLayout, query)); } specificLayout = this.ComputeDimensions(new Size(query.MaxWidth, query.MaxHeight), query.Debug); if (query.Accepts(specificLayout)) { return(this.prepareLayoutForQuery(specificLayout.GetBestLayout(query), query)); } return(null); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { Specific_ContainerLayout result; SpecificLayout sublayoutResult; if (this.SubLayout != null) { // We have a sublayout and haven't been asked to wrap it in another view, so we can just forward the query on to it sublayoutResult = this.SubLayout.GetBestLayout(query); if (this.view == null) { // If we haven't been asked to wrap the sublayout's result, we can just directly use it return(sublayoutResult); } else { if (sublayoutResult == null) { return(null); } result = this.makeSpecificLayout(this.view, sublayoutResult.Size, LayoutScore.Zero, sublayoutResult, new Thickness()); this.prepareLayoutForQuery(result, query); return(result); } } // if there is no subLayout, for now we just return an empty size Specific_ContainerLayout empty = this.makeSpecificLayout(this.view, new Size(), LayoutScore.Zero, null, new Thickness()); if (query.Accepts(empty)) { result = empty; } else { result = null; } this.prepareLayoutForQuery(result, query); return(result); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { Specific_ContainerLayout result; // Determine whether there's room for the border double borderWidth = this.BorderThickness.Left + this.BorderThickness.Right; double borderHeight = this.BorderThickness.Top + this.BorderThickness.Bottom; LayoutQuery subQuery = query.WithDimensions(query.MaxWidth - borderWidth, query.MaxHeight - borderHeight); if (subQuery.MaxWidth < 0 || subQuery.MaxHeight < 0) { return(null); } // Query sublayout if it exists if (this.SubLayout != null) { SpecificLayout best_subLayout = this.SubLayout.GetBestLayout(subQuery); if (best_subLayout != null) { result = this.makeSpecificLayout(this.view, new Size(best_subLayout.Width + borderWidth, best_subLayout.Height + borderHeight), LayoutScore.Zero, best_subLayout, this.BorderThickness); result.ChildFillsAvailableSpace = this.ChildFillsAvailableSpace; this.prepareLayoutForQuery(result, query); return(result); } return(null); } // if there is no subLayout, for now we just return an empty size Specific_ContainerLayout empty = this.makeSpecificLayout(this.view, new Size(), LayoutScore.Zero, null, new Thickness()); if (query.Accepts(empty)) { result = empty; } else { result = null; } this.prepareLayoutForQuery(result, query); return(result); }
// computes the size of the layout with smallest width satisfying the given criteria private SpecificLayout Get_MinWidth_Layout(LayoutQuery query) { if (query.MaxWidth < 0 || query.MaxHeight < 0) { return(null); } // first check whether this query will accept a cropped layout Specific_TextLayout specificLayout = this.ComputeDimensions(new Size(0, 0), query.Debug); if (query.Accepts(specificLayout)) { return(this.prepareLayoutForQuery(specificLayout, query)); } // not satisfied with cropping so we need to try harder to do a nice-looking layout Specific_TextLayout nonCropping_layout = this.Get_NonCropping_MinWidthLayout(query); if (nonCropping_layout != null) { return(this.prepareLayoutForQuery(nonCropping_layout, query)); } return(null); }
public override SpecificLayout GetBestLayout(LayoutQuery query) { return(null); // not relevant }
// computes the layout dimensions of the layout of minimum width such that there is no cropping private Specific_TextLayout Get_NonCropping_MinWidthLayout(LayoutQuery query) { Specific_TextLayout bestAllowedDimensions = this.ComputeDimensions(new Size(double.PositiveInfinity, double.PositiveInfinity), query.Debug); double pixelSize = 1; double maxRejectedWidth = 0; int numIterations = 0; bool firstIteration = true; double maxWidth = query.MaxWidth; while (maxRejectedWidth < bestAllowedDimensions.Width - pixelSize / 2) { numIterations++; // given the current width, compute the required height Specific_TextLayout newDimensions = this.ComputeDimensions(new Size(maxWidth, double.PositiveInfinity), query.Debug); if (newDimensions.Height <= query.MaxHeight && query.MinScore.CompareTo(newDimensions.Score) <= 0) { // this layout fits in the required dimensions if (newDimensions.Width <= bestAllowedDimensions.Width && newDimensions.Width <= query.MaxWidth) { // this layout is at least as good as the best layout we found so far bestAllowedDimensions = newDimensions; maxWidth = newDimensions.Width; } else { // we've found a layout having sufficiently small width and height, but it isn't any better than what we'd previously found // So, we're not making progress with this process and should quit break; } } else { // this layout does not fit in the required dimensions if (maxWidth > maxRejectedWidth) { maxRejectedWidth = maxWidth; } // if the first layout we found was too tall, then there will need to be some cropping if (double.IsPositiveInfinity(bestAllowedDimensions.Width)) { return(null); } } // calculate a new size, by guessing based on required area double desiredArea = newDimensions.Height * Math.Max(maxWidth, newDimensions.Width); maxWidth = desiredArea / query.MaxHeight; // Make sure that the next value we check is inside the range that we haven't checked yet, to make sure we're making progress // If our area-based is outside the unexplored range, then from now on just split the remaining range in half on each iteration if (maxWidth < (maxRejectedWidth + pixelSize / 2)) { if (firstIteration) { // The first time that we find we have enough area to make the width very tiny, we calculate the true minimum amount of width required Size desiredSize = this.formatText(maxWidth, query.Debug, this.FontSize).Size; if (desiredSize.Width > maxWidth) { maxRejectedWidth = desiredSize.Width - pixelSize / 2; } maxWidth = desiredSize.Width; } else { // The second time we find that we have enough area to make the width very tiny, we don't recalculate the true min width required because we already did // Instead we just do a binary search maxWidth = (maxRejectedWidth + bestAllowedDimensions.Width) / 2; } } else { if (maxWidth > (bestAllowedDimensions.Width - pixelSize / 2)) { maxWidth = (maxRejectedWidth + bestAllowedDimensions.Width) / 2; } } firstIteration = false; } if (this.LoggingEnabled) { System.Diagnostics.Debug.WriteLine("Spent " + numIterations + " iterations in Get_NonCropping_MinWidthLayout with query = " + query + " and text length = " + this.TextLength); } if (!query.Accepts(bestAllowedDimensions)) { return(null); } return(bestAllowedDimensions); }
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(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(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)); } }
public LayoutQuery_And_Response(LayoutQuery query, SpecificLayout response) { this.Query = query; this.Response = response; }
private IEnumerable <LayoutDimensions> getLayoutOptions(LayoutQuery query) { return(this.dimensionOptions); }
/* * private static LayoutChoice_Set NewRow(string text) * { * Horizontal_GridLayout_Builder builder = new Horizontal_GridLayout_Builder(); * * builder.AddLayout(New_TextBoxLayout(text)); * * builder.AddLayout(new ImageLayout(null, LayoutScore.Get_UsedSpace_LayoutScore(GetNextScoreWeight()))); * return builder.Build(); * * } */ public override SpecificLayout GetBestLayout(LayoutQuery query) { return(base.GetBestLayout(query)); }
// asks for the best dimensions that this set allows public abstract SpecificLayout GetBestLayout(LayoutQuery query);