예제 #1
0
        public override SpecificLayout GetBestLayout(LayoutQuery query)
        {
            double width = query.MaxWidth;

            if (this.pixelWidth > 0)
            {
                width = Math.Floor(query.MaxWidth / this.pixelWidth) * this.pixelWidth;
            }
            double height = query.MaxHeight;

            if (this.pixelHeight > 0)
            {
                height = Math.Floor(query.MaxHeight / this.pixelHeight) * this.pixelHeight;
            }
            if (width != query.MaxWidth || height != query.MaxHeight)
            {
                query = query.WithDimensions(width, height);
            }
            SpecificLayout internalLayout = this.layoutToManage.GetBestLayout(query);

            if (internalLayout != null)
            {
                Size size = new Size(Math.Ceiling(internalLayout.Width / this.pixelWidth) * this.pixelWidth, Math.Ceiling(internalLayout.Height / this.pixelHeight) * this.pixelHeight);
                Specific_ContainerLayout result = new Specific_ContainerLayout(null, size, new LayoutScore(), internalLayout, new Thickness(0));
                return(this.prepareLayoutForQuery(result, query));
            }
            return(null);
        }
예제 #2
0
        private SpecificLayout getMinHeightChildLayout(double width)
        {
            LayoutQuery    childQuery  = new MinHeight_LayoutQuery(width, double.PositiveInfinity, this.requiredChildScore);
            SpecificLayout childLayout = this.subLayout.GetBestLayout(childQuery);

            return(childLayout);
        }
예제 #3
0
        private SpecificLayout Query_SubLayout(LayoutQuery query)
        {
            numComputations++;

            /*if (this.true_queryResults.Count == 4)
             * {
             *  System.Diagnostics.Debug.WriteLine("Lots of queries being sent to " + this.layoutToManage);
             * }*/
            if (!query.Debug)
            {
                if (this.true_queryResults.ContainsKey(query))
                {
                    ErrorReporter.ReportParadox("Error, layoutCache repeated a query that was already present");
                }
            }
            SpecificLayout result = this.layoutToManage.GetBestLayout(query);

            if (!query.Debug)
            {
                if (this.true_queryResults.ContainsKey(query))
                {
                    ErrorReporter.ReportParadox("Error, layoutCache query results were saved before it completed?");
                }
                query.OnAnswered(this.layoutToManage);
                this.true_queryResults[query] = result;
            }
            return(result);
        }
예제 #4
0
 public Specific_ScrollLayout(ScrollView view, Size size, LayoutScore score, SpecificLayout sublayout)
     : base(view, size, score, sublayout, new Thickness())
 {
     this.View = view;
     if (double.IsInfinity(this.SubLayout.Height))
     {
         ErrorReporter.ReportParadox("Infinite Specific_ScrollLayout height: " + this);
     }
 }
예제 #5
0
        // 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);
        }
예제 #6
0
        private SpecificLayout inferredLayout(LayoutQuery query, SpecificLayout response)
        {
            this.inferred_queryResults[query] = response;
            LayoutQuery_And_Response pair = new LayoutQuery_And_Response(query, response);

            this.orderedResponses.Add(pair);
            //this.debugCheck(pair);
            return(response);
        }
예제 #7
0
        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);
        }
예제 #8
0
        // returns a Dictionary that maps each view in the tree to its closest containing ancestor layout
        private Dictionary <View, SpecificLayout> findAncestors(SpecificLayout layout)
        {
            Dictionary <View, SpecificLayout> parents = new Dictionary <View, SpecificLayout>();

            if (layout != null)
            {
                this.addAllParents(layout.GetParticipatingChildren(), layout, parents);
            }
            return(parents);
        }
예제 #9
0
        public override LayoutQuery OptimizedUsingExample(SpecificLayout example)
        {
            MinWidth_LayoutQuery result = this;

            if (this.MaxWidth > example.Width)
            {
                result = this.Clone((MinWidth_LayoutQuery)null);
                result.setMaxWidth(example.Width);
            }
            return(result);
        }
예제 #10
0
        public override LayoutQuery OptimizedUsingExample(SpecificLayout example)
        {
            MinHeight_LayoutQuery result = this;

            if (this.MaxHeight > example.Height)
            {
                result = this.Clone((MinHeight_LayoutQuery)null);
                result.setMaxHeight(example.Height);
            }
            return(result);
        }
예제 #11
0
        public override LayoutQuery OptimizedUsingExample(SpecificLayout example)
        {
            MaxScore_LayoutQuery result = this;

            if (this.MinScore.CompareTo(example.Score) < 0)
            {
                result = this.Clone((MaxScore_LayoutQuery)null);
                result.setMinScore(example.Score);
            }
            return(result);
        }
예제 #12
0
        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));
        }
예제 #13
0
        public override SpecificLayout GetBestLayout(LayoutQuery query)
        {
            if (this.true_queryResults == null)
            {
                this.Initialize();
            }
            numQueries++;
            if (numQueries % 10000 == 0)
            {
                double rate = (double)numComputations / (double)numQueries;
                System.Diagnostics.Debug.WriteLine("Overall LayoutCache miss rate: " + numComputations + " of " + numQueries + " = " + rate);
                if (rate < 0.02)
                {
                    System.Diagnostics.Debug.WriteLine("Surprisingly high layoutcache hit rate");
                }
            }

            SpecificLayout fastResult = this.GetBestLayout_Quickly(query);

            if (query.Debug)
            {
                SpecificLayout correctResult = this.Query_SubLayout(query);
                if (correctResult != null && !query.Accepts(correctResult))
                {
                    ErrorReporter.ReportParadox("Error: LayoutCache was given an incorrect response by its sublayout");
                }
                bool correct = true;
                if (query.PreferredLayout(correctResult, fastResult) != correctResult)
                {
                    ErrorReporter.ReportParadox("Error: layout cache returned incorrect (superior) result");
                    query.ProposedSolution_ForDebugging = fastResult;
                    correct = false;
                }
                if (query.PreferredLayout(fastResult, correctResult) != fastResult)
                {
                    ErrorReporter.ReportParadox("Error: layout cache returned incorrect (inferior) result");
                    query.ProposedSolution_ForDebugging = correctResult;
                    correct = false;
                }
                if (!correct)
                {
                    this.GetBestLayout_Quickly(query);
                    this.Query_SubLayout(query);
                }
                this.debugCheck(new LayoutQuery_And_Response(query, fastResult));
                return(this.prepareLayoutForQuery(correctResult, query));
            }
            //this.debugCheck(new LayoutQuery_And_Response(query, fastResult));
            if (fastResult != null)
            {
                fastResult = fastResult.Clone();
            }
            return(this.prepareLayoutForQuery(fastResult, query));
        }
예제 #14
0
        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));
        }
예제 #15
0
 public bool Accepts(SpecificLayout layout)
 {
     if (layout == null)
     {
         return(false);
     }
     if (layout.GetBestLayout(this) != null)
     {
         return(true);
     }
     return(false);
 }
예제 #16
0
        private void debugCheck(LayoutQuery_And_Response queryAndResponse)
        {
            // make sure that each query likes its response at least as much as all others
            SpecificLayout result = queryAndResponse.Response;
            LayoutQuery    query  = queryAndResponse.Query;

            for (int i = 0; i < this.orderedResponses.Count; i++)
            {
                LayoutQuery_And_Response other = this.orderedResponses[i];
                if (other.Query.PreferredLayout(other.Response, result) != other.Response)
                {
                    ErrorReporter.ReportParadox("New response is a better solution to previous query than preexisting response.\n" +
                                                "Layout      : " + this.layoutToManage + "\n" +
                                                "Old query   : " + other.Query + "\n" +
                                                "Old response: " + other.Response + "\n" +
                                                "New query   : " + query + "\n" +
                                                "New response: " + result);
                    LayoutQuery query2 = other.Query.Clone();
                    query2.Debug = true;
                    query2.ProposedSolution_ForDebugging = result;
                    SpecificLayout oldQueryNewDebugResult = this.GetBestLayout(query2.Clone());
                    LayoutQuery    query1 = query.Clone();
                    query1.Debug = true;
                    SpecificLayout newQueryDebugResult = this.GetBestLayout(query1.Clone());
                    System.Diagnostics.Debug.WriteLine("Results from LayoutCache discrepancy: Old query new result = " + oldQueryNewDebugResult + ", New query new result = " + newQueryDebugResult);
                    this.layoutToManage.GetBestLayout(query2.Clone());
                    this.layoutToManage.GetBestLayout(query1.Clone());
                }
                if (query.PreferredLayout(result, other.Response) != result)
                {
                    ErrorReporter.ReportParadox("New response is a worse solution to new query than previous response.\n" +
                                                "Layout      : " + this.layoutToManage + "\n" +
                                                "Old query   : " + other.Query + "\n" +
                                                "Old response: " + other.Response + "\n" +
                                                "New query   : " + query + "\n" +
                                                "New response: " + result);

                    LayoutQuery query1 = query.Clone();
                    query1.Debug = true;
                    query1.ProposedSolution_ForDebugging = other.Response;
                    SpecificLayout newQueryDebugResult = this.GetBestLayout(query1);
                    LayoutQuery    query2 = other.Query.Clone();
                    query2.Debug = true;
                    SpecificLayout oldQueryNewDebugResult = this.GetBestLayout(query2);
                    System.Diagnostics.Debug.WriteLine("Results from LayoutCache discrepancy: Old query new result = " + oldQueryNewDebugResult + ", New query new result = " + newQueryDebugResult);
                    this.GetBestLayout(query1.Clone());
                    this.GetBestLayout(query2.Clone());
                }
            }
        }
예제 #17
0
        private SpecificLayout makeLayout(Size size, SpecificLayout childLayout)
        {
            double childHeight = childLayout.Height;

            if (childHeight == 0)
            {
                childHeight = 1;
            }
            LayoutScore    score           = this.resultingScore.Times(size.Height / childHeight);
            LayoutScore    scoreDifference = score.Minus(childLayout.Score);
            SpecificLayout result          = new Specific_ScrollLayout(this.view, size, scoreDifference, childLayout);

            return(result);
        }
예제 #18
0
        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);
        }
예제 #19
0
 private void addAllParents(IEnumerable <SpecificLayout> candidates, SpecificLayout parentView_layout, Dictionary <View, SpecificLayout> accumulator)
 {
     foreach (SpecificLayout childLayout in candidates)
     {
         if (childLayout.View != null)
         {
             accumulator[childLayout.View] = parentView_layout;
             this.addAllParents(childLayout.GetParticipatingChildren(), childLayout, accumulator);
         }
         else
         {
             this.addAllParents(childLayout.GetParticipatingChildren(), parentView_layout, accumulator);
         }
     }
 }
예제 #20
0
        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);
        }
예제 #21
0
        // returns whichever layout it likes better
        public SpecificLayout PreferredLayout(SpecificLayout tieWinner, SpecificLayout tieLoser)
        {
            if (!this.Accepts(tieWinner))
            {
                if (this.Accepts(tieLoser))
                {
                    return(tieLoser);
                }
                else
                {
                    return(null);
                }
            }
            if (!this.Accepts(tieLoser))
            {
                return(tieWinner);
            }
            LayoutDimensions dimensions1 = new LayoutDimensions();

            dimensions1.Width  = tieWinner.Width;
            dimensions1.Height = tieWinner.Height;
            dimensions1.Score  = tieWinner.Score;
            LayoutDimensions dimensions2 = new LayoutDimensions();

            dimensions2.Width  = tieLoser.Width;
            dimensions2.Height = tieLoser.Height;
            dimensions2.Score  = tieLoser.Score;
            // TODO: when asking a MaxScore_LayoutQuery which layout it likes better, consider calling isScoreAtLeast instead of computing all the scores
            if (this.PreferredLayout(dimensions1, dimensions2) == dimensions1)
            {
                return(tieWinner);
            }
            else
            {
                return(tieLoser);
            }
        }
예제 #22
0
 // returns a stricter query that won't even be satisfied by this example
 public LayoutQuery OptimizedPastExample(SpecificLayout example)
 {
     return(this.OptimizedPastDimensions(example.Dimensions));
 }
예제 #23
0
        // Attempts to find a strictly larger query so we can get an upper bound on the required size (and if possible, we want a query whose response is accepted by the original)
        private LayoutQuery_And_Response Find_LargerQuery(LayoutQuery query)
        {
            LayoutQuery_And_Response bestResult = null;

            // check each previous query and response to see if we can use one of them
            // TODO do something faster and more complicated that doesn't entail checking every query, using something like an R-tree
            foreach (LayoutQuery_And_Response queryAndResponse in this.orderedResponses)
            {
                LayoutQuery    otherQuery  = queryAndResponse.Query;
                SpecificLayout otherResult = queryAndResponse.Response;

                // check whether the answer to the previous query must also be the answer to the current query
                bool otherEncompassesInputs  = true;
                bool otherEncompassesOutputs = true;
                bool inputAccepted           = true;
                bool thisEncompassesInputs   = true;
                // If we're looking for the min width or min height, then tightening the score means we can't necessarily use the other result as the best result
                if (query.MaximizesScore())
                {
                    if (otherQuery.MaxWidth < query.MaxWidth)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MaxWidth > query.MaxWidth)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherQuery.MaxHeight < query.MaxHeight)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MaxHeight > query.MaxHeight)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherQuery.MinScore.CompareTo(query.MinScore) > 0)
                    {
                        otherEncompassesOutputs = false;
                    }

                    if (otherResult == null || otherResult.Width > query.MaxWidth)
                    {
                        inputAccepted = false;
                    }
                    if (otherResult == null || otherResult.Height > query.MaxHeight)
                    {
                        inputAccepted = false;
                    }
                }
                if (query.MinimizesWidth())
                {
                    if (otherQuery.MaxWidth < query.MaxWidth)
                    {
                        otherEncompassesOutputs = false;
                    }

                    if (otherQuery.MaxHeight < query.MaxHeight)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MaxHeight > query.MaxHeight)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherQuery.MinScore.CompareTo(query.MinScore) > 0)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MinScore.CompareTo(query.MinScore) < 0)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherResult == null || otherResult.Score.CompareTo(query.MinScore) < 0)
                    {
                        inputAccepted = false;
                    }
                    if (otherResult == null || otherResult.Height > query.MaxHeight)
                    {
                        inputAccepted = false;
                    }
                }
                if (query.MinimizesHeight())
                {
                    if (otherQuery.MaxWidth < query.MaxWidth)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MaxWidth > query.MaxWidth)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherQuery.MaxHeight < query.MaxHeight)
                    {
                        otherEncompassesOutputs = false;
                    }

                    if (otherQuery.MinScore.CompareTo(query.MinScore) > 0)
                    {
                        otherEncompassesInputs = false;
                    }
                    if (otherQuery.MinScore.CompareTo(query.MinScore) < 0)
                    {
                        thisEncompassesInputs = false;
                    }

                    if (otherResult == null || otherResult.Width > query.MaxWidth)
                    {
                        inputAccepted = false;
                    }
                    if (otherResult == null || otherResult.Score.CompareTo(query.MinScore) < 0)
                    {
                        inputAccepted = false;
                    }
                }
                if (otherEncompassesInputs)
                {
                    if (query.SameType(otherQuery) && query.Accepts(otherResult))
                    {
                        // The previous query had looser inputs but its result was still in our range, so we know its result will be right for us too
                        return(queryAndResponse);
                    }
                    if (query.SameType(otherQuery) && inputAccepted && otherEncompassesOutputs)
                    {
                        if (!query.Accepts(otherResult))
                        {
                            // The previous query had looser inputs, and demonstrated that the best output is worse than our threshold
                            // So, our current query has no solution
                            return(new LayoutQuery_And_Response(otherQuery, null));
                        }
                    }
                    if (otherEncompassesOutputs && otherResult == null)
                    {
                        // The previous query had looser inputs and looser outputs but no solution, so the current query will also have no solution
                        return(queryAndResponse);
                    }
                    if (query.SameType(otherQuery) && thisEncompassesInputs)
                    {
                        if (otherResult != null)
                        {
                            // If we already asked the same question then we already know what the best answer is
                            // We just have to double-check whether the best answer is good enough
                            if (query.Accepts(otherResult))
                            {
                                return(queryAndResponse);
                            }
                            else
                            {
                                return(new LayoutQuery_And_Response(otherQuery, null));
                            }
                        }
                    }
                }
            }

            if (query.Debug)
            {
                if (bestResult != null && bestResult.Response != null && !bestResult.Query.Accepts(bestResult.Response))
                {
                    ErrorReporter.ReportParadox("Query does not accept its recorded answer");
                }
            }
            // return the most useful query+response that we found
            return(bestResult);
        }
예제 #24
0
 public OverrideLayoutDefaults_SpecificLayout(SpecificLayout sublayout, ViewDefaults defaultsOverride)
     : base(null, sublayout.Size, LayoutScore.Zero, sublayout, new Thickness(0))
 {
     this.defaultsOverride = defaultsOverride;
 }
예제 #25
0
 public Specific_ContainerLayout(View view, Size size, LayoutScore bonusScore, SpecificLayout subLayout, Thickness borderThickness)
 {
     this.Initialize();
     this.view            = view;
     this.Size            = size;
     this.bonusScore      = bonusScore;
     this.BorderThickness = borderThickness;
     this.subLayout       = subLayout;
 }
예제 #26
0
        // redoes the layout
        private void DoLayout()
        {
            this.needsRelayout = false;

            // determine which views are currently focused so we can re-focus them after redoing the layout
            List <View> focusedViews = new List <View>();

            if (this.specificLayout != null)
            {
                foreach (SpecificLayout layout in this.specificLayout.GetDescendents())
                {
                    if (layout.View != null && layout.View.IsFocused && layout.GetParticipatingChildren().Count() < 1)
                    {
                        focusedViews.Add(layout.View);
                    }
                }
            }

            // check some data in preparation for computing stats
            int      num_grid_preComputations = GridLayout.NumComputations;
            DateTime startTime = DateTime.Now;

            // record the parent of each view before the relayout, to help us know which parents to disconnect
            Dictionary <View, SpecificLayout> preParents = this.findAncestors(this.specificLayout);

            // recompute the new desired layout
            // generally we expect the overall score to be positive, so we start by hypothesizing
            // that there exists a layout with positive score, and only checking negative-scoring layouts if no positive-scoring layout is found
            LayoutQuery query = new MaxScore_LayoutQuery(this.displaySize.Width, this.displaySize.Height, LayoutScore.Zero, this.visualDefaults.LayoutDefaults);
            DateTime    getBestLayout_startDate = DateTime.Now;

            this.specificLayout = this.GetSublayout().GetBestLayout(query);
            if (this.specificLayout == null)
            {
                query = query.WithScore(LayoutScore.Minimum);
                this.specificLayout = this.GetSublayout().GetBestLayout(query);
            }

            DateTime getBestLayout_endDate = DateTime.Now;

            // find the parent of each view after the relayout, to help us know which parents to disconnect
            Dictionary <View, SpecificLayout> postParents = this.findAncestors(this.specificLayout);

            // disconnect any parents that are no longer the same
            foreach (View view in preParents.Keys)
            {
                SpecificLayout preLayout = preParents[view];
                if (preLayout != null)
                {
                    SpecificLayout postLayout = this.DictionaryGet(postParents, view);
                    if (postLayout == null || preLayout.View != postLayout.View)
                    {
                        // The parent of <view> has changed.
                        // Disconnect it from the previous parent.
                        preLayout.Remove_VisualDescendent(view);
                    }
                }
            }

            // record that our layout is up-to-date (so any future updates will trigger a relayout)
            this.Reset_ChangeAnnouncement();

            // update our actual view
            this.mainView.Content = this.specificLayout.DoLayout(displaySize, this.visualDefaults.ViewDefaults);

            // Inform each layout whose view was reattached, in case they need to restore any state that can only be restored after being reattached (most likely because the view system would overwrite it)
            foreach (SpecificLayout layout in postParents.Values)
            {
                layout.AfterLayoutAttached();
            }

            // display stats
            DateTime endTime  = DateTime.Now;
            TimeSpan duration = endTime.Subtract(startTime);

            System.Diagnostics.Debug.WriteLine("ViewManager DoLayout finished in " + duration + " (" + query.Cost + ") queries");
            System.Diagnostics.Debug.WriteLine("Text formatting time = " + TextLayout.TextTime + " for " + TextLayout.NumMeasures + " measures");
            int num_grid_postComputations = GridLayout.NumComputations;

            System.Diagnostics.Debug.WriteLine("Num grid computations = " + (num_grid_postComputations - num_grid_preComputations));
            TextLayout.NumMeasures = 0;
            TextLayout.TextTime    = new TimeSpan();

            // refocus the previously focused views
            foreach (View view in focusedViews)
            {
                if (postParents.ContainsKey(view))
                {
                    view.Focus();
                }
            }

            System.Diagnostics.Debug.WriteLine("ViewManager completed layout at " + DateTime.Now);

            if (this.LayoutCompleted != null)
            {
                ViewManager_LayoutStats stats = new ViewManager_LayoutStats();
                stats.ViewManager_LayoutDuration         = duration;
                stats.ViewManager_getBestLayout_Duration = getBestLayout_endDate.Subtract(getBestLayout_startDate);
                this.LayoutCompleted.Invoke(stats);
            }
        }
예제 #27
0
 public void CopyFrom(SpecificLayout original)
 {
     base.CopyFrom(original);
     this.SourceQuery = original.SourceQuery;
     //this.ancestors = new List<LayoutChoice_Set>(original.ancestors);
 }
예제 #28
0
 protected Specific_ContainerLayout makeSpecificLayout(View view, Size size, LayoutScore bonusScore, SpecificLayout subLayout, Thickness border)
 {
     return(new Specific_ContainerLayout(view, size, bonusScore, subLayout, border));
 }
예제 #29
0
        private SpecificLayout GetBestLayout_Quickly(LayoutQuery query)
        {
            SpecificLayout result = null;

            // A layout of size 0 in one dimension doesn't get any points for being nonzero in the other dimension
            if ((query.MaxHeight == 0) != (query.MaxWidth == 0))
            {
                result = this.GetBestLayout_Quickly(this.SizeZeroQuery);
                if (query.Accepts(result))
                {
                    return(result);
                }
                return(null);
            }

            // check whether we've previously saved the result
            if (!query.Debug)
            {
                if (this.true_queryResults.TryGetValue(query, out result) || this.inferred_queryResults.TryGetValue(query, out result))
                {
                    if (result != null)
                    {
                        return(result);
                    }
                    return(null);
                }
            }
            // the result wasn't saved, so we need to delegate the layout query
            // However, we might first be able to make the query more strict

            LayoutQuery_And_Response broadened = this.Find_LargerQuery(query);

            if (broadened != null)
            {
                if (query.Debug)
                {
                    LayoutQuery debugQuery = query.Clone();
                    debugQuery.Debug = true;
                    SpecificLayout correct_subLayout = this.Query_SubLayout(debugQuery);
                    if (broadened.Query.PreferredLayout(broadened.Response, correct_subLayout) != broadened.Response)
                    {
                        ErrorReporter.ReportParadox("Error; incorrect result for broadened query: broadened query " + broadened.Query + " returned " + broadened.Response +
                                                    " whereas the response from the sublayout for debug query " + debugQuery + " is " + correct_subLayout);
                        LayoutQuery debugQuery2 = broadened.Query.DebugClone();
                        debugQuery2.ProposedSolution_ForDebugging = correct_subLayout;
                        this.GetBestLayout(debugQuery2);
                    }
                }
                return(this.inferredLayout(query, broadened.Response));
            }
            LayoutQuery_And_Response shrunken = this.FindExample(query);

            if (query.Debug)
            {
                if (shrunken != null)
                {
                    LayoutQuery debugQuery = shrunken.Query.Clone();
                    debugQuery.Debug = true;
                    SpecificLayout correct_subLayout = this.Query_SubLayout(debugQuery);
                    if (shrunken.Query.PreferredLayout(shrunken.Response, correct_subLayout) != shrunken.Response)
                    {
                        ErrorReporter.ReportParadox("Error; incorrect result for shrunken query");
                    }
                }
            }

            if (shrunken != null)
            {
                // If the existing example is already at the extreme, then use it
                if (query.MaximizesScore())
                {
                    if (shrunken.Response.Width >= query.MaxWidth && shrunken.Response.Height >= query.MaxHeight)
                    {
                        return(this.inferredLayout(query, shrunken.Response));
                    }
                }
                if (query.MinimizesWidth())
                {
                    if (shrunken.Response.Width <= 0)
                    {
                        return(this.inferredLayout(query, shrunken.Response));
                    }
                }
                if (query.MinimizesHeight())
                {
                    if (shrunken.Response.Height <= 0)
                    {
                        return(this.inferredLayout(query, shrunken.Response));
                    }
                }
            }
            // if we couldn't immediately return a result using the cache, we can still put a bound on the results we might get
            // They have to be at least as good as the sample we found
            if (shrunken != null)
            {
                // First, see if we can improve past what we currently have
                LayoutQuery strictlyImprovedQuery = query.OptimizedPastExample(shrunken.Response);
                bool        allowCache            = !strictlyImprovedQuery.Accepts(shrunken.Response);

                // Ask the sublayout for this result (or use the cache if we've already asked)
                if (allowCache)
                {
                    result = this.GetBestLayout_Quickly(strictlyImprovedQuery);
                }
                else
                {
                    result = this.Query_SubLayout(strictlyImprovedQuery);
                }
                if (result == null)
                {
                    result = shrunken.Response;
                }
                return(this.inferredLayout(query, result));
            }
            else
            {
                result = this.Query_SubLayout(query);
            }

            if (result == null)
            {
                if (shrunken != null && query.Accepts(shrunken.Response))
                {
                    ErrorReporter.ReportParadox("Error: cache contains an acceptable value for the current query, but the layout claims there are none");
                    result = shrunken.Response;
                }
            }

            // record that this is the exact answer to this query
            LayoutQuery_And_Response queryAndResponse = new LayoutQuery_And_Response(query, result);

            this.orderedResponses.Add(queryAndResponse);


            //this.debugCheck(queryAndResponse);

            if (result != null)
            {
                result = result.Clone();
            }
            return(result);
        }
예제 #30
0
        // tests that the layout satisfies all of the queries consistently
        public void DebugCheck(LayoutChoice_Set layout)
        {
            int i, j;
            int maxWidth, maxHeight;

            maxWidth  = 127;
            maxHeight = 127;
            LayoutDimensions[,] maxScore_dimensions  = new LayoutDimensions[maxWidth, maxHeight];
            LayoutDimensions[,] minWidth_dimensions  = new LayoutDimensions[maxWidth, maxHeight];
            LayoutDimensions[,] minHeight_dimensions = new LayoutDimensions[maxWidth, maxHeight];
            for (i = 0; i < maxWidth; i++)
            {
                System.Diagnostics.Debug.WriteLine(i.ToString() + " of " + maxWidth.ToString());
                for (j = 0; j < maxHeight; j++)
                {
                    int width  = i + 29;
                    int height = j;

                    // find the maximum score of all layouts that fit in these dimensions
                    LayoutQuery    maxScoreQuery   = new MaxScore_LayoutQuery(width, height, LayoutScore.Minimum, this.visualDefaults.LayoutDefaults);
                    SpecificLayout maxScore_layout = layout.GetBestLayout(maxScoreQuery);
                    maxScore_dimensions[i, j] = maxScore_layout.Dimensions;


                    // find the layout of minimum width having at least this score
                    LayoutQuery    minWidthQuery   = new MinWidth_LayoutQuery(width, height, maxScore_layout.Score, this.visualDefaults.LayoutDefaults);
                    SpecificLayout minWidth_layout = layout.GetBestLayout(minWidthQuery);
                    if (minWidth_layout != null)
                    {
                        minWidth_dimensions[i, j] = minWidth_layout.Dimensions;
                    }

                    // find the layout of minimum height having at least this score
                    LayoutQuery    minHeightQuery   = new MinHeight_LayoutQuery(width, height, maxScore_layout.Score, this.visualDefaults.LayoutDefaults);
                    SpecificLayout minHeight_layout = layout.GetBestLayout(minHeightQuery);
                    if (minHeight_layout != null)
                    {
                        minHeight_dimensions[i, j] = minHeight_layout.Dimensions;
                    }
                    if (i > 0)
                    {
                        if (maxScore_dimensions[i, j].Score.CompareTo(maxScore_dimensions[i - 1, j].Score) < 0)
                        {
                            System.Diagnostics.Debug.WriteLine("Error: inconsistency between (" + i.ToString() + ", " + j.ToString() + ") and (" + (i - 1).ToString() + ", " + j.ToString() + ")");
                        }
                    }
                    if (j > 0)
                    {
                        if (maxScore_dimensions[i, j].Score.CompareTo(maxScore_dimensions[i, j - 1].Score) < 0)
                        {
                            System.Diagnostics.Debug.WriteLine("Error: inconsistency between (" + i.ToString() + ", " + j.ToString() + ") and (" + i.ToString() + ", " + (j - 1).ToString() + ")");
                        }
                    }
                    if ((width == 0 || height == 0) && maxScore_dimensions[i, j].Score.CompareTo(LayoutScore.Zero) > 0)
                    {
                        System.Diagnostics.Debug.WriteLine("Error: clipping not noticed at (" + i.ToString() + ", " + j.ToString() + ")");
                    }
                    if (minWidth_dimensions[i, j] == null)
                    {
                        System.Diagnostics.Debug.WriteLine("Error: minWidth query for (" + i.ToString() + ", " + j.ToString() + ") returned null");
                        minWidthQuery.Debug = true;
                        layout.GetBestLayout(minWidthQuery.Clone());
                    }
                    if (minHeight_dimensions[i, j] == null)
                    {
                        System.Diagnostics.Debug.WriteLine("Error: minHeight query for (" + i.ToString() + ", " + j.ToString() + ") returned null");
                    }
                    if (i > 0 && minWidth_dimensions[i, j] != null && minWidth_dimensions[i, j] != null)
                    {
                        if (minWidth_dimensions[i, j].Score.CompareTo(minWidth_dimensions[i - 1, j].Score) == 0)
                        {
                            if (minWidth_dimensions[i, j].Width != minWidth_dimensions[i - 1, j].Width)
                            {
                                System.Diagnostics.Debug.WriteLine("Error: width is wrong in minWidth query between (" + i.ToString() + ", " + j.ToString() + ") and (" + (i - 1).ToString() + ", " + j.ToString() + ")");
                            }
                        }
                    }
                    if (j > 0 && minHeight_dimensions[i, j] != null && minHeight_dimensions[i, j] != null)
                    {
                        if (minHeight_dimensions[i, j].Score.CompareTo(minHeight_dimensions[i, j - 1].Score) == 0)
                        {
                            if (minHeight_dimensions[i, j].Height != minHeight_dimensions[i, j - 1].Height)
                            {
                                System.Diagnostics.Debug.WriteLine("Error: height is wrong in minHeight query between (" + i.ToString() + ", " + j.ToString() + ") and (" + i.ToString() + ", " + (j - 1).ToString() + ")");
                                minHeightQuery.Debug = true;
                                layout.GetBestLayout(minHeightQuery.Clone());
                            }
                        }
                    }
                }
            }
            System.Diagnostics.Debug.WriteLine("done with debugCheck");

            /*
             * System.Diagnostics.Debug.WriteLine("checking minWidth queries");
             * for (i = 1; i < maxWidth; i++)
             * {
             *  for (j = 1; j < maxHeight; j++)
             *  {
             *      if (maxScore_dimensions[i, j].Score.CompareTo(maxScore_dimensions[i - 1, j] < 0))
             *          System.Diagnostics.Debug.WriteLine("Error: inconsistency between (" + i.ToString() + ", " + j.ToString() + ") and (" + (i - 1).ToString() + ", " + j.ToString());
             *      if (maxScore_dimensions[i, j].Score.CompareTo(maxScore_dimensions[i, j - 1] < 0))
             *          System.Diagnostics.Debug.WriteLine("Error: inconsistency between (" + i.ToString() + ", " + j.ToString() + ") and (" + i.ToString() + ", " + (j - 1).ToString());
             *  }
             * }*/
        }