예제 #1
0
        private bool ShouldContinueFillingUpSpace(
            int index,
            GenerateDirection direction)
        {
            bool shouldContinue = false;

            if (!IsVirtualizingContext)
            {
                shouldContinue = true;
            }
            else
            {
                var realizationRect = _context.RealizationRect;
                var elementBounds   = _elementManager.GetLayoutBoundsForDataIndex(index);

                var elementMajorStart = _orientation.MajorStart(elementBounds);
                var elementMajorEnd   = _orientation.MajorEnd(elementBounds);
                var rectMajorStart    = _orientation.MajorStart(realizationRect);
                var rectMajorEnd      = _orientation.MajorEnd(realizationRect);

                var elementMinorStart = _orientation.MinorStart(elementBounds);
                var elementMinorEnd   = _orientation.MinorEnd(elementBounds);
                var rectMinorStart    = _orientation.MinorStart(realizationRect);
                var rectMinorEnd      = _orientation.MinorEnd(realizationRect);

                // Ensure that both minor and major directions are taken into consideration so that if the scrolling direction
                // is the same as the flow direction we still stop at the end of the viewport rectangle.
                shouldContinue =
                    (direction == GenerateDirection.Forward && elementMajorStart < rectMajorEnd && elementMinorStart < rectMinorEnd) ||
                    (direction == GenerateDirection.Backward && elementMajorEnd > rectMajorStart && elementMinorEnd > rectMinorStart);
            }

            return(shouldContinue);
        }
예제 #2
0
파일: Cortex.cs 프로젝트: wkallhof/hakon
        private List <Node> Generate(List <Node> phraseNodes, GenerateDirection direction)
        {
            var targetNode = direction == GenerateDirection.Backward
                ? phraseNodes.FirstOrDefault()
                : phraseNodes.LastOrDefault();

            if (targetNode == null)
            {
                return(phraseNodes);
            }

            var links = direction == GenerateDirection.Backward
                ? this._network.GetLinksToNode(targetNode.Id)
                : this._network.GetLinksFromNode(targetNode.Id);

            var nodeSelection = new List <Node>();

            foreach (var link in links)
            {
                var nextNode = direction == GenerateDirection.Backward
                    ? this._network.GetNodeById(link.From)
                    : this._network.GetNodeById(link.To);

                if (nextNode == null || nextNode.Classification != NodeClassification.Word)
                {
                    continue;
                }

                var activation = Math.Max(nextNode.ActivationValue, 1);
                var count      = phraseNodes.Count(x => x.Label.Equals(nextNode.Label));
                if (count * nextNode.Label.Length <= 5 * 3)
                {
                    var rep = 1 + count * count * nextNode.Label.Length;
                    nextNode.InfluenceWeight = (int)(link.Weight * activation / rep);
                    nodeSelection.Add(nextNode);
                }
                //nodeSelection.Add(nextNode);
            }

            if (nodeSelection.Count == 0)
            {
                return(phraseNodes);
            }

            var word = this.RandomElementByWeight(nodeSelection, (x) => x.InfluenceWeight);

            if (direction == GenerateDirection.Backward)
            {
                phraseNodes.Insert(0, word);
            }
            else
            {
                phraseNodes.Add(word);
            }

            return(this.Generate(phraseNodes, direction));
        }
예제 #3
0
        private void Generate(
            GenerateDirection direction,
            int anchorIndex,
            Size availableSize,
            double minItemSpacing,
            double lineSpacing,
            int maxItemsPerLine,
            string layoutId)
        {
            if (anchorIndex != -1)
            {
                int  step                = (direction == GenerateDirection.Forward) ? 1 : -1;
                int  previousIndex       = anchorIndex;
                int  currentIndex        = anchorIndex + step;
                var  anchorBounds        = _elementManager.GetLayoutBoundsForDataIndex(anchorIndex);
                var  lineOffset          = _orientation.MajorStart(anchorBounds);
                var  lineMajorSize       = _orientation.MajorSize(anchorBounds);
                var  countInLine         = 1;
                int  count               = 0;
                bool lineNeedsReposition = false;

                while (_elementManager.IsIndexValidInData(currentIndex) &&
                       ShouldContinueFillingUpSpace(previousIndex, direction))
                {
                    // Ensure layout element.
                    _elementManager.EnsureElementRealized(direction == GenerateDirection.Forward, currentIndex, layoutId);
                    var currentElement = _elementManager.GetRealizedElement(currentIndex);
                    var desiredSize    = MeasureElement(currentElement, currentIndex, availableSize, _context);
                    ++count;

                    // Lay it out.
                    var previousElement       = _elementManager.GetRealizedElement(previousIndex);
                    var currentBounds         = new Rect(0, 0, desiredSize.Width, desiredSize.Height);
                    var previousElementBounds = _elementManager.GetLayoutBoundsForDataIndex(previousIndex);

                    if (direction == GenerateDirection.Forward)
                    {
                        double remainingSpace = _orientation.Minor(availableSize) - (_orientation.MinorStart(previousElementBounds) + _orientation.MinorSize(previousElementBounds) + minItemSpacing + _orientation.Minor(desiredSize));
                        if (countInLine >= maxItemsPerLine || _algorithmCallbacks.Algorithm_ShouldBreakLine(currentIndex, remainingSpace))
                        {
                            // No more space in this row. wrap to next row.
                            _orientation.SetMinorStart(ref currentBounds, 0);
                            _orientation.SetMajorStart(ref currentBounds, _orientation.MajorStart(previousElementBounds) + lineMajorSize + lineSpacing);

                            if (lineNeedsReposition)
                            {
                                // reposition the previous line (countInLine items)
                                for (int i = 0; i < countInLine; i++)
                                {
                                    var dataIndex = currentIndex - 1 - i;
                                    var bounds    = _elementManager.GetLayoutBoundsForDataIndex(dataIndex);
                                    _orientation.SetMajorSize(ref bounds, lineMajorSize);
                                    _elementManager.SetLayoutBoundsForDataIndex(dataIndex, bounds);
                                }
                            }

                            // Setup for next line.
                            lineMajorSize       = _orientation.MajorSize(currentBounds);
                            lineOffset          = _orientation.MajorStart(currentBounds);
                            lineNeedsReposition = false;
                            countInLine         = 1;
                        }
                        else
                        {
                            // More space is available in this row.
                            _orientation.SetMinorStart(ref currentBounds, _orientation.MinorStart(previousElementBounds) + _orientation.MinorSize(previousElementBounds) + minItemSpacing);
                            _orientation.SetMajorStart(ref currentBounds, lineOffset);
                            lineMajorSize       = Math.Max(lineMajorSize, _orientation.MajorSize(currentBounds));
                            lineNeedsReposition = _orientation.MajorSize(previousElementBounds) != _orientation.MajorSize(currentBounds);
                            countInLine++;
                        }
                    }
                    else
                    {
                        // Backward
                        double remainingSpace = _orientation.MinorStart(previousElementBounds) - (_orientation.Minor(desiredSize) + minItemSpacing);
                        if (countInLine >= maxItemsPerLine || _algorithmCallbacks.Algorithm_ShouldBreakLine(currentIndex, remainingSpace))
                        {
                            // Does not fit, wrap to the previous row
                            var availableSizeMinor = _orientation.Minor(availableSize);

                            _orientation.SetMinorStart(ref currentBounds, !double.IsInfinity(availableSizeMinor) ? availableSizeMinor - _orientation.Minor(desiredSize) : 0);
                            _orientation.SetMajorStart(ref currentBounds, lineOffset - _orientation.Major(desiredSize) - lineSpacing);

                            if (lineNeedsReposition)
                            {
                                var previousLineOffset = _orientation.MajorStart(_elementManager.GetLayoutBoundsForDataIndex(currentIndex + countInLine + 1));
                                // reposition the previous line (countInLine items)
                                for (int i = 0; i < countInLine; i++)
                                {
                                    var dataIndex = currentIndex + 1 + i;
                                    if (dataIndex != anchorIndex)
                                    {
                                        var bounds = _elementManager.GetLayoutBoundsForDataIndex(dataIndex);
                                        _orientation.SetMajorStart(ref bounds, previousLineOffset - lineMajorSize - lineSpacing);
                                        _orientation.SetMajorSize(ref bounds, lineMajorSize);
                                        _elementManager.SetLayoutBoundsForDataIndex(dataIndex, bounds);
                                    }
                                }
                            }

                            // Setup for next line.
                            lineMajorSize       = _orientation.MajorSize(currentBounds);
                            lineOffset          = _orientation.MajorStart(currentBounds);
                            lineNeedsReposition = false;
                            countInLine         = 1;
                        }
                        else
                        {
                            // Fits in this row. put it in the previous position
                            _orientation.SetMinorStart(ref currentBounds, _orientation.MinorStart(previousElementBounds) - _orientation.Minor(desiredSize) - minItemSpacing);
                            _orientation.SetMajorStart(ref currentBounds, lineOffset);
                            lineMajorSize       = Math.Max(lineMajorSize, _orientation.MajorSize(currentBounds));
                            lineNeedsReposition = _orientation.MajorSize(previousElementBounds) != _orientation.MajorSize(currentBounds);
                            countInLine++;
                        }
                    }

                    _elementManager.SetLayoutBoundsForDataIndex(currentIndex, currentBounds);
                    previousIndex = currentIndex;
                    currentIndex += step;
                }

                // If we did not reach the top or bottom of the extent, we realized one
                // extra item before we knew we were outside the realization window. Do not
                // account for that element in the indicies inside the realization window.
                if (count > 0)
                {
                    if (direction == GenerateDirection.Forward)
                    {
                        int dataCount = _context.ItemCount;
                        _lastRealizedDataIndexInsideRealizationWindow = previousIndex == dataCount - 1 ? dataCount - 1 : previousIndex - 1;
                        _lastRealizedDataIndexInsideRealizationWindow = Math.Max(0, _lastRealizedDataIndexInsideRealizationWindow);
                    }
                    else
                    {
                        int dataCount = _context.ItemCount;
                        _firstRealizedDataIndexInsideRealizationWindow = previousIndex == 0 ? 0 : previousIndex + 1;
                        _firstRealizedDataIndexInsideRealizationWindow = Math.Min(dataCount - 1, _firstRealizedDataIndexInsideRealizationWindow);
                    }
                }

                _elementManager.DiscardElementsOutsideWindow(direction == GenerateDirection.Forward, currentIndex);
            }
        }
예제 #4
0
        void Generate(
            GenerateDirection direction,
            int anchorIndex,
            Size availableSize,
            double minItemSpacing,
            double lineSpacing,
            uint maxItemsPerLine,
            bool disableVirtualization,
            string layoutId)
        {
            if (anchorIndex != -1)
            {
                int step = (direction == GenerateDirection.Forward) ? 1 : -1;

                REPEATER_TRACE_INFO("%*s: \tGenerating %ls from anchor %d. \n",
                                    m_context.Indent,
                                    layoutId,
                                    direction == GenerateDirection.Forward ? "forward" : "backward",
                                    anchorIndex);

                int    previousIndex       = anchorIndex;
                int    currentIndex        = anchorIndex + step;
                var    anchorBounds        = m_elementManager.GetLayoutBoundsForDataIndex(anchorIndex);
                double lineOffset          = MajorStart(anchorBounds);
                double lineMajorSize       = MajorSize(anchorBounds);
                int    countInLine         = 1;
                bool   lineNeedsReposition = false;

                while (m_elementManager.IsIndexValidInData(currentIndex) &&
                       (disableVirtualization || ShouldContinueFillingUpSpace(previousIndex, direction)))
                {
                    // Ensure layout element.
                    m_elementManager.EnsureElementRealized(direction == GenerateDirection.Forward, currentIndex, layoutId);
                    var currentElement = m_elementManager.GetRealizedElement(currentIndex);
                    var desiredSize    = MeasureElement(currentElement, currentIndex, availableSize, m_context);

                    // Lay it out.
                    var  previousElement       = m_elementManager.GetRealizedElement(previousIndex);
                    Rect currentBounds         = new Rect(0, 0, desiredSize.Width, desiredSize.Height);
                    var  previousElementBounds = m_elementManager.GetLayoutBoundsForDataIndex(previousIndex);

                    if (direction == GenerateDirection.Forward)
                    {
                        double remainingSpace = Minor(availableSize) - (MinorStart(previousElementBounds) + MinorSize(previousElementBounds) + minItemSpacing + Minor(desiredSize));
                        if (countInLine >= maxItemsPerLine || m_algorithmCallbacks.Algorithm_ShouldBreakLine(currentIndex, remainingSpace))
                        {
                            // No more space in this row. wrap to next row.
                            SetMinorStart(ref currentBounds, 0);
                            SetMajorStart(ref currentBounds, MajorStart(previousElementBounds) + lineMajorSize + (float)(lineSpacing));

                            if (lineNeedsReposition)
                            {
                                // reposition the previous line (countInLine items)
                                for (int i = 0; i < countInLine; i++)
                                {
                                    var dataIndex = currentIndex - 1 - i;
                                    var bounds    = m_elementManager.GetLayoutBoundsForDataIndex(dataIndex);
                                    SetMajorSize(ref bounds, lineMajorSize);
                                    m_elementManager.SetLayoutBoundsForDataIndex(dataIndex, bounds);
                                }
                            }

                            // Setup for next line.
                            lineMajorSize       = MajorSize(currentBounds);
                            lineOffset          = MajorStart(currentBounds);
                            lineNeedsReposition = false;
                            countInLine         = 1;
                        }
                        else
                        {
                            // More space is available in this row.
                            SetMinorStart(ref currentBounds, MinorStart(previousElementBounds) + MinorSize(previousElementBounds) + (float)(minItemSpacing));
                            SetMajorStart(ref currentBounds, lineOffset);
                            lineMajorSize       = Math.Max(lineMajorSize, MajorSize(currentBounds));
                            lineNeedsReposition = MajorSize(previousElementBounds) != MajorSize(currentBounds);
                            countInLine++;
                        }
                    }
                    else
                    {
                        // Backward
                        double remainingSpace = MinorStart(previousElementBounds) - (Minor(desiredSize) + (float)(minItemSpacing));
                        if (countInLine >= maxItemsPerLine || m_algorithmCallbacks.Algorithm_ShouldBreakLine(currentIndex, remainingSpace))
                        {
                            // Does not fit, wrap to the previous row
                            var availableSizeMinor = Minor(availableSize);
                            SetMinorStart(ref currentBounds, _Double.IsFinite(availableSizeMinor) ? availableSizeMinor - Minor(desiredSize) : 0.0f);
                            SetMajorStart(ref currentBounds, lineOffset - Major(desiredSize) - (float)(lineSpacing));

                            if (lineNeedsReposition)
                            {
                                var previousLineOffset = MajorStart(m_elementManager.GetLayoutBoundsForDataIndex(currentIndex + countInLine + 1));
                                // reposition the previous line (countInLine items)
                                for (uint i = 0; i < countInLine; i++)
                                {
                                    var dataIndex = currentIndex + 1 + (int)i;
                                    if (dataIndex != anchorIndex)
                                    {
                                        var bounds = m_elementManager.GetLayoutBoundsForDataIndex(dataIndex);
                                        SetMajorStart(ref bounds, previousLineOffset - lineMajorSize - (float)(lineSpacing));
                                        SetMajorSize(ref bounds, lineMajorSize);
                                        m_elementManager.SetLayoutBoundsForDataIndex(dataIndex, bounds);
                                        REPEATER_TRACE_INFO("%*s: \t Corrected Layout bounds of element %d are (%.0f,%.0f,%.0f,%.0f). \n",
                                                            m_context.Indent,
                                                            layoutId,
                                                            dataIndex,
                                                            bounds.X, bounds.Y, bounds.Width, bounds.Height);
                                    }
                                }
                            }

                            // Setup for next line.
                            lineMajorSize       = MajorSize(currentBounds);
                            lineOffset          = MajorStart(currentBounds);
                            lineNeedsReposition = false;
                            countInLine         = 1;
                        }
                        else
                        {
                            // Fits in this row. put it in the previous position
                            SetMinorStart(ref currentBounds, MinorStart(previousElementBounds) - Minor(desiredSize) - (float)(minItemSpacing));
                            SetMajorStart(ref currentBounds, lineOffset);
                            lineMajorSize       = Math.Max(lineMajorSize, MajorSize(currentBounds));
                            lineNeedsReposition = MajorSize(previousElementBounds) != MajorSize(currentBounds);
                            countInLine++;
                        }
                    }

                    m_elementManager.SetLayoutBoundsForDataIndex(currentIndex, currentBounds);

                    REPEATER_TRACE_INFO("%*s: \tLayout bounds of element %d are (%.0f,%.0f,%.0f,%.0f). \n",
                                        m_context.Indent,
                                        layoutId,
                                        currentIndex,
                                        currentBounds.X, currentBounds.Y, currentBounds.Width, currentBounds.Height);
                    previousIndex = currentIndex;
                    currentIndex += step;
                }

                // If we did not reach the top or bottom of the extent, we realized one
                // extra item before we knew we were outside the realization window. Do not
                // account for that element in the indicies inside the realization window.
                if (direction == GenerateDirection.Forward)
                {
                    int dataCount = m_context.ItemCount;
                    m_lastRealizedDataIndexInsideRealizationWindow = previousIndex == dataCount - 1 ? dataCount - 1 : previousIndex - 1;
                    m_lastRealizedDataIndexInsideRealizationWindow = Math.Max(0, m_lastRealizedDataIndexInsideRealizationWindow);
                }
                else
                {
                    int dataCount = m_context.ItemCount;
                    m_firstRealizedDataIndexInsideRealizationWindow = previousIndex == 0 ? 0 : previousIndex + 1;
                    m_firstRealizedDataIndexInsideRealizationWindow = Math.Min(dataCount - 1, m_firstRealizedDataIndexInsideRealizationWindow);
                }

                m_elementManager.DiscardElementsOutsideWindow(direction == GenerateDirection.Forward, currentIndex);
            }
        }
예제 #5
0
        private void Generate(
            GenerateDirection direction,
            int anchorIndex,
            Size availableSize,
            double minItemSpacing,
            double lineSpacing,
            int maxItemsPerLine,
            bool disableVirtualization,
            string?layoutId)
        {
            if (anchorIndex != -1)
            {
                int step = (direction == GenerateDirection.Forward) ? 1 : -1;

                Logger.TryGet(LogEventLevel.Verbose, "Repeater")?.Log(this, "{LayoutId}: Generating {Direction} from anchor {Anchor}",
                                                                      layoutId,
                                                                      direction,
                                                                      anchorIndex);

                int  previousIndex       = anchorIndex;
                int  currentIndex        = anchorIndex + step;
                var  anchorBounds        = _elementManager.GetLayoutBoundsForDataIndex(anchorIndex);
                var  lineOffset          = _orientation.MajorStart(anchorBounds);
                var  lineMajorSize       = _orientation.MajorSize(anchorBounds);
                var  countInLine         = 1;
                int  count               = 0;
                bool lineNeedsReposition = false;

                while (_elementManager.IsIndexValidInData(currentIndex) &&
                       (disableVirtualization || ShouldContinueFillingUpSpace(previousIndex, direction)))
                {
                    // Ensure layout element.
                    _elementManager.EnsureElementRealized(direction == GenerateDirection.Forward, currentIndex, layoutId);
                    var currentElement = _elementManager.GetRealizedElement(currentIndex);
                    var desiredSize    = MeasureElement(currentElement !, currentIndex, availableSize, _context !);
                    ++count;

                    // Lay it out.
                    var previousElement       = _elementManager.GetRealizedElement(previousIndex);
                    var currentBounds         = new Rect(0, 0, desiredSize.Width, desiredSize.Height);
                    var previousElementBounds = _elementManager.GetLayoutBoundsForDataIndex(previousIndex);

                    if (direction == GenerateDirection.Forward)
                    {
                        double remainingSpace = _orientation.Minor(availableSize) - (_orientation.MinorStart(previousElementBounds) + _orientation.MinorSize(previousElementBounds) + minItemSpacing + _orientation.Minor(desiredSize));
                        if (countInLine >= maxItemsPerLine || _algorithmCallbacks !.Algorithm_ShouldBreakLine(currentIndex, remainingSpace))
                        {
                            // No more space in this row. wrap to next row.
                            _orientation.SetMinorStart(ref currentBounds, 0);
                            _orientation.SetMajorStart(ref currentBounds, _orientation.MajorStart(previousElementBounds) + lineMajorSize + lineSpacing);

                            if (lineNeedsReposition)
                            {
                                // reposition the previous line (countInLine items)
                                for (int i = 0; i < countInLine; i++)
                                {
                                    var dataIndex = currentIndex - 1 - i;
                                    var bounds    = _elementManager.GetLayoutBoundsForDataIndex(dataIndex);
                                    _orientation.SetMajorSize(ref bounds, lineMajorSize);
                                    _elementManager.SetLayoutBoundsForDataIndex(dataIndex, bounds);
                                }
                            }

                            // Setup for next line.
                            lineMajorSize       = _orientation.MajorSize(currentBounds);
                            lineOffset          = _orientation.MajorStart(currentBounds);
                            lineNeedsReposition = false;
                            countInLine         = 1;
                        }
                        else
                        {
                            // More space is available in this row.
                            _orientation.SetMinorStart(ref currentBounds, _orientation.MinorStart(previousElementBounds) + _orientation.MinorSize(previousElementBounds) + minItemSpacing);
                            _orientation.SetMajorStart(ref currentBounds, lineOffset);
                            lineMajorSize       = Math.Max(lineMajorSize, _orientation.MajorSize(currentBounds));
                            lineNeedsReposition = _orientation.MajorSize(previousElementBounds) != _orientation.MajorSize(currentBounds);
                            countInLine++;
                        }
                    }
                    else
                    {
                        // Backward
                        double remainingSpace = _orientation.MinorStart(previousElementBounds) - (_orientation.Minor(desiredSize) + minItemSpacing);
                        if (countInLine >= maxItemsPerLine || _algorithmCallbacks !.Algorithm_ShouldBreakLine(currentIndex, remainingSpace))
                        {
                            // Does not fit, wrap to the previous row
                            var availableSizeMinor = _orientation.Minor(availableSize);

                            _orientation.SetMinorStart(ref currentBounds, !double.IsInfinity(availableSizeMinor) ? availableSizeMinor - _orientation.Minor(desiredSize) : 0);
                            _orientation.SetMajorStart(ref currentBounds, lineOffset - _orientation.Major(desiredSize) - lineSpacing);

                            if (lineNeedsReposition)
                            {
                                var previousLineOffset = _orientation.MajorStart(_elementManager.GetLayoutBoundsForDataIndex(currentIndex + countInLine + 1));
                                // reposition the previous line (countInLine items)
                                for (int i = 0; i < countInLine; i++)
                                {
                                    var dataIndex = currentIndex + 1 + i;
                                    if (dataIndex != anchorIndex)
                                    {
                                        var bounds = _elementManager.GetLayoutBoundsForDataIndex(dataIndex);
                                        _orientation.SetMajorStart(ref bounds, previousLineOffset - lineMajorSize - lineSpacing);
                                        _orientation.SetMajorSize(ref bounds, lineMajorSize);
                                        _elementManager.SetLayoutBoundsForDataIndex(dataIndex, bounds);
                                        Logger.TryGet(LogEventLevel.Verbose, "Repeater")?.Log(this, "{LayoutId}: Corrected Layout bounds of element {Index} are ({Bounds})",
                                                                                              layoutId,
                                                                                              dataIndex,
                                                                                              bounds);
                                    }
                                }
                            }

                            // Setup for next line.
                            lineMajorSize       = _orientation.MajorSize(currentBounds);
                            lineOffset          = _orientation.MajorStart(currentBounds);
                            lineNeedsReposition = false;
                            countInLine         = 1;
                        }