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); }
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)); }
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); } }
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); } }
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; }