IDisposable IItemContainerGenerator.StartAt( GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { return(this.StartAt(position, direction, allowStartAtRealizedItem)); }
protected override Line CreateLine(GeneratorDirection direction, int extentOffset, int breadthOffset, int availableBreadth, RecyclerView.Recycler recycler, RecyclerView.State state, Uno.UI.IndexPath nextVisibleItem, bool isNewGroup ) { var item = GetFlatItemIndex(nextVisibleItem); var view = recycler.GetViewForPosition(item, state); if (!(view is SelectorItem)) { throw new InvalidOperationException($"Expected {nameof(SelectorItem)} but received {view?.GetType().ToString() ?? "<null>"}"); } var size = AddViewAtOffset(view, direction, extentOffset, breadthOffset, availableBreadth); var physicalSize = size.LogicalToPhysicalPixels(); var breadth = (int)(ScrollOrientation == Orientation.Vertical ? physicalSize.Width : physicalSize.Height); return(new Line { NumberOfViews = 1, Extent = (int)(ScrollOrientation == Orientation.Vertical ? physicalSize.Height : physicalSize.Width), FirstItem = nextVisibleItem, LastItem = nextVisibleItem, Breadth = breadth }); }
private void StartAtHelper(GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { NoesisGUI_PINVOKE.ItemContainerGenerator_StartAtHelper(swigCPtr, ref position, (int)direction, allowStartAtRealizedItem); if (NoesisGUI_PINVOKE.SWIGPendingException.Pending) { throw NoesisGUI_PINVOKE.SWIGPendingException.Retrieve(); } }
IDisposable IItemContainerGenerator.StartAt(GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { if (Status == GeneratorStatus.GeneratingContainers) { throw new InvalidOperationException("Generation already in progress"); } StartAtHelper(position, direction, allowStartAtRealizedItem); return(new Generator(this)); }
protected override Line CreateLine(GeneratorDirection fillDirection, double extentOffset, double availableBreadth, Uno.UI.IndexPath nextVisibleItem) { var item = GetFlatItemIndex(nextVisibleItem); var view = Generator.DequeueViewForItem(item); AddView(view, fillDirection, extentOffset, 0); return(new Line(new[] { view }, nextVisibleItem, nextVisibleItem, item)); }
void GenerateBackFromEnd() { //<SnippetGenerateBackwardFromEndCODE> // Start generating items backward from the end of the item list GeneratorPosition position = new GeneratorPosition(-1, 0); GeneratorDirection direction = GeneratorDirection.Backward; IItemContainerGenerator generator = (IItemContainerGenerator)this.itemsControl.ItemContainerGenerator; generator.StartAt(position, direction); //</SnippetGenerateBackwardFromEndCODE> }
void GenerateForwardFromBeginning() { //<SnippetGenerateForwardFromBeginningCODE> // Start generating items forward from the beginning of the item list GeneratorPosition position = new GeneratorPosition(-1, 0); GeneratorDirection direction = GeneratorDirection.Forward; IItemContainerGenerator generator = (IItemContainerGenerator)this.itemsControl.ItemContainerGenerator; generator.StartAt(position, direction); //</SnippetGenerateForwardFromBeginningCODE> }
public void AddLine(Line newLine, GeneratorDirection fillDirection) { if (fillDirection == GeneratorDirection.Forward) { _lines.AddToBack(newLine); } else { _lines.AddToFront(newLine); Start -= newLine.Extent; } }
public void AddLine(Line newLine, GeneratorDirection fillDirection) { Debug.Assert(_lines.None(l => l.FirstItem == newLine.FirstItem), "Duplicate line detected"); if (fillDirection == GeneratorDirection.Forward) { _lines.AddToBack(newLine); } else { _lines.AddToFront(newLine); Start -= newLine.Extent; } }
public void RemoveTrailingLine(GeneratorDirection fillDirection) { if (fillDirection == GeneratorDirection.Forward) { var removed = _lines.RemoveFromFront(); //Move Start forward because we are removing a line from the start Start += removed.Extent; } else { _lines.RemoveFromBack(); } }
protected override Line CreateLine(GeneratorDirection fillDirection, double extentOffset, double availableBreadth, Uno.UI.IndexPath nextVisibleItem) { if (ShouldInsertReorderingView(extentOffset) && GetAndUpdateReorderingIndex() is { } reorderingIndex) { nextVisibleItem = reorderingIndex; } var item = GetFlatItemIndex(nextVisibleItem); var view = Generator.DequeueViewForItem(item); AddView(view, fillDirection, extentOffset, 0); return(new Line(item, (view, nextVisibleItem))); }
void GenerateForwardFromMiddle() { //<SnippetGenerateForwardFromMiddleCODE> // Start generating items forward, // starting with the first unrealized item (offset of 1), // after the 5th realized item // (the item with index 4 among all realized items) in the list GeneratorPosition position = new GeneratorPosition(4, 1); GeneratorDirection direction = GeneratorDirection.Forward; IItemContainerGenerator generator = (IItemContainerGenerator)this.itemsControl.ItemContainerGenerator; generator.StartAt(position, direction); //</SnippetGenerateForwardFromMiddleCODE> }
internal IDisposable StartAt(GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { if (GenerationState != null) { throw new InvalidOperationException("Cannot call StartAt while a generation operation is in progress"); } GenerationState = new GenerationState { AllowStartAtRealizedItem = allowStartAtRealizedItem, Direction = direction, Position = position, Generator = this }; return(GenerationState); }
public static Vector2i ToVector2i(GeneratorDirection dir) { switch (dir) { case GeneratorDirection.Up: return(new Vector2i(0, 1)); case GeneratorDirection.Down: return(new Vector2i(0, -1)); case GeneratorDirection.Left: return(new Vector2i(-1, 0)); case GeneratorDirection.Right: return(new Vector2i(1, 0)); default: throw new System.Exception("Invalid switch value."); } }
protected override Line CreateLine(GeneratorDirection direction, int extentOffset, int breadthOffset, int availableBreadth, RecyclerView.Recycler recycler, RecyclerView.State state, IndexPath nextVisibleItem, bool isNewGroup ) { var itemsInLine = ResolveMaximumItemsInLine(availableBreadth); var firstItemInLine = nextVisibleItem; //Find first item in line, since the item we are passed is the last if (direction == GeneratorDirection.Backward) { // We are recreating the last line of the group - it may be truncated (if the total items are not an even multiple // of the items-per-line). if (isNewGroup) { itemsInLine = XamlParent.GetItemsOnLastLine(firstItemInLine.Section, itemsInLine); } for (int i = 0; i < itemsInLine - 1; i++) { firstItemInLine = GetNextUnmaterializedItem(GeneratorDirection.Backward, firstItemInLine).Value; var isCorrectGroup = firstItemInLine.Section == nextVisibleItem.Section; if (!isCorrectGroup) { //TODO: fix bug that makes this happen (#47229) } Debug.Assert(isCorrectGroup, GetAssertMessage("First item should not be from a different group")); } } IndexPath lastItemInLine = firstItemInLine; IndexPath?currentItem = firstItemInLine; var availableWidth = ResolveAvailableWidth(availableBreadth); var availableHeight = ResolveAvailableHeight(availableBreadth); int usedBreadth = 0; for (int i = 0; i < itemsInLine; i++) { var view = recycler.GetViewForPosition(GetFlatItemIndex(currentItem.Value), state); if (!(view is SelectorItem)) { throw new InvalidOperationException($"Expected {nameof(SelectorItem)} but received {view?.GetType().ToString() ?? "<null>"}"); } //Add view before we measure it, this ensures that DP inheritances are correctly applied AddView(view, direction); var slotSize = new Windows.Foundation.Size(availableWidth, availableHeight).PhysicalToLogicalPixels(); var measuredSize = _layouter.MeasureChild(view, slotSize); var physicalMeasuredSize = measuredSize.LogicalToPhysicalPixels(); var measuredWidth = (int)physicalMeasuredSize.Width; var measuredHeight = (int)physicalMeasuredSize.Height; if (_implicitItemWidth == null) { //Set these values to dimensions of first materialised item _implicitItemWidth = measuredWidth; _implicitItemHeight = measuredHeight; // When an item dimension is not fixed, we need to arrange based on the measured size, // otherwise the arrange will be passed a dimension that is too large and the first // few items will not be visible if (double.IsNaN(ItemWidth)) { slotSize.Width = ViewHelper.PhysicalToLogicalPixels(_implicitItemWidth.Value); } if (double.IsNaN(ItemHeight)) { slotSize.Height = ViewHelper.PhysicalToLogicalPixels(_implicitItemHeight.Value); } availableWidth = ResolveAvailableWidth(availableBreadth); availableHeight = ResolveAvailableHeight(availableBreadth); itemsInLine = ResolveMaximumItemsInLine(availableBreadth); } LayoutChild(view, GeneratorDirection.Forward, //We always lay out view 'top down' so that it is aligned correctly if its height is less than the line height direction == GeneratorDirection.Forward ? extentOffset : extentOffset - ResolveItemExtent().Value, breadthOffset + usedBreadth, slotSize ); usedBreadth += ResolveItemBreadth().Value; lastItemInLine = currentItem.Value; currentItem = GetNextUnmaterializedItem(GeneratorDirection.Forward, currentItem); if (currentItem == null || currentItem.Value.Section != firstItemInLine.Section) { itemsInLine = i + 1; break; } } return(new Line { NumberOfViews = itemsInLine, Extent = ResolveItemExtent().Value, Breadth = usedBreadth, FirstItem = firstItemInLine, LastItem = lastItemInLine }); }
public Uno.UI.IndexPath GetTrailingMaterializedItem(GeneratorDirection fillDirection) { return(fillDirection == GeneratorDirection.Forward ? GetFirstLine().FirstItem : GetLastLine().LastItem); }
/// <summary> Begin generating at the given position and direction </summary> /// <remarks> /// This method must be called before calling GenerateNext. It returns an /// IDisposable object that tracks the lifetime of the generation loop. /// This method sets the generator's status to GeneratingContent; when /// the IDisposable is disposed, the status changes to ContentReady or /// Error, as appropriate. /// </remarks> IDisposable IItemContainerGenerator.StartAt(GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { if (_generator != null) throw new InvalidOperationException(SR.Get(SRID.GenerationInProgress)); _generator = new Generator(this, position, direction, allowStartAtRealizedItem); return _generator; }
// Set the AlternationIndex on a newly-realized container. Also, reset // the AlternationIndex on other containers to maintain the adjacency // criterion. void SetAlternationIndex(ItemBlock block, int offset, GeneratorDirection direction) { // If user doesn't request alternation, don't do anything if (_alternationCount <= 0) return; int index; RealizedItemBlock rib; // Proceed in the direction of generation. This tends to reach the // end sooner (often in one step). if (direction != GeneratorDirection.Backward) { // Forward. Back up one container to determine the starting index -- offset; while (offset < 0 || block is UnrealizedItemBlock) { block = block.Prev; offset = block.ContainerCount - 1; } rib = block as RealizedItemBlock; index = (block == _itemMap) ? -1 : ItemsControl.GetAlternationIndex(rib.ContainerAt(offset)); // loop through the remaining containers, resetting each AlternationIndex for (;;) { // advance to next realized container ++offset; while (offset == block.ContainerCount) { block = block.Next; offset = 0; } // exit if we've reached the end if (block == _itemMap) break; // advance the AlternationIndex index = (index + 1) % _alternationCount; // assign it to the container rib = block as RealizedItemBlock; ItemsControl.SetAlternationIndex(rib.ContainerAt(offset), index); } } else { // Backward. Advance one container to determine the starting index ++ offset; while (offset >= block.ContainerCount || block is UnrealizedItemBlock) { block = block.Next; offset = 0; } rib = block as RealizedItemBlock; // Get the alternation index for the advanced container. Use value 1 if no container // is found, so that 0 gets used for actual container in question. index = (block == _itemMap) ? 1 : ItemsControl.GetAlternationIndex(rib.ContainerAt(offset)); // loop through the remaining containers, resetting each AlternationIndex for (;;) { // retreat to next realized container --offset; while (offset < 0) { block = block.Prev; offset = block.ContainerCount - 1; } // exit if we've reached the end if (block == _itemMap) break; // retreat the AlternationIndex index = (_alternationCount + index - 1) % _alternationCount; // assign it to the container rib = block as RealizedItemBlock; ItemsControl.SetAlternationIndex(rib.ContainerAt(offset), index); } } }
//------------------------------------------------------ // // Constructors // //------------------------------------------------------ internal Generator(ItemContainerGenerator factory, GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { _factory = factory; _direction = direction; _factory.MapChanged += new MapChangedHandler(OnMapChanged); _factory.MoveToPosition(position, direction, allowStartAtRealizedItem, ref _cachedState); _done = (_factory.ItemsInternal.Count == 0); _factory.SetStatus(GeneratorStatus.GeneratingContainers); }
private void StartGenerator( GeneratorPosition startPos, GeneratorDirection direction ) { if( this.Status == GeneratorStatus.GeneratingContainers ) { throw new InvalidOperationException( "Cannot perform this operation while the generator is busy generating items" ); } //set the GeneratorStatus to "Generating" m_generatorStatus = GeneratorStatus.GeneratingContainers; //Initialize the Direction m_generatorDirection = direction; //retrieve the Index for the GeneratorPosition retrieved m_generatorCurrentGlobalIndex = this.IndexFromGeneratorPosition( startPos ); // case 117460: throw an exception if the GeneratorPosition is bad, but not if the itemcount is 0 //(and generator position maps to index 0 ). int itemCount = this.ItemCount; if( ( m_generatorCurrentGlobalIndex < 0 ) || ( ( itemCount > 0 ) && ( m_generatorCurrentGlobalIndex >= itemCount ) ) ) throw new ArgumentOutOfRangeException( "startPos", "The specified start position is outside the range of the Generator content." ); //case 117460: if the item count is 0, return without doing any check, GenerateNext will never process any content in that case. //Since the GeneratorNodeHelper is never created. if( itemCount == 0 ) return; //and create a node helper that will assist us during the Generation process... m_generatorNodeHelper = new GeneratorNodeHelper( m_startNode, 0, 0 ); // start index is always 0 //position the GeneratorNodeHelper to the appropriate node if( !m_generatorNodeHelper.FindNodeForIndex( m_generatorCurrentGlobalIndex ) ) //find index?!?! { //there was a problem moving the Node helper... throw new DataGridInternalException(); } //Calculate the offset m_generatorCurrentOffset = m_generatorCurrentGlobalIndex - m_generatorNodeHelper.Index; ItemsGeneratorNode itemsNode = m_generatorNodeHelper.CurrentNode as ItemsGeneratorNode; if( itemsNode != null ) { m_generatorCurrentDetail = itemsNode.GetDetailNodeForIndex( m_generatorCurrentOffset, out m_generatorCurrentOffset, out m_generatorCurrentDetailIndex, out m_generatorCurrentDetailNodeIndex ); } if( m_generatorCurrentDetail != null ) { m_generatorCurrentDetailDisposable = ( ( IItemContainerGenerator )m_generatorCurrentDetail.DetailGenerator ).StartAt( m_generatorCurrentDetail.DetailGenerator.GeneratorPositionFromIndex( m_generatorCurrentDetailIndex ), direction, true ); } }
public static GeneratorDirection Inverse(this GeneratorDirection generatorDirection) => generatorDirection switch {
private void StartAtHelper(GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { NoesisGUI_PINVOKE.ItemContainerGenerator_StartAtHelper(swigCPtr, ref position, (int)direction, allowStartAtRealizedItem); }
IDisposable IItemContainerGenerator.StartAt(GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { throw new Exception("The method or operation is not implemented."); }
IDisposable IItemContainerGenerator.StartAt (GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { return StartAt (position, direction, allowStartAtRealizedItem); }
internal IDisposable StartAt (GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { if (GenerationState != null) throw new InvalidOperationException ("Cannot call StartAt while a generation operation is in progress"); GenerationState = new GenerationState { AllowStartAtRealizedItem = allowStartAtRealizedItem, Direction = direction, Position = position, Generator = this }; return GenerationState; }
/// <summary> /// Get the index of the next item that has not yet been materialized in the nominated fill direction. Returns null if there are no more available items in the source. /// </summary> protected IndexPath?GetNextUnmaterializedItem(GeneratorDirection fillDirection, IndexPath?currentMaterializedItem) { return(XamlParent?.GetNextItemIndex(currentMaterializedItem, fillDirection == GeneratorDirection.Forward ? 1 : -1)); }
IDisposable IItemContainerGenerator.StartAt (GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { throw new Exception ("The method or operation is not implemented."); }
IDisposable IItemContainerGenerator.StartAt( GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem ) { this.SetIsInUse(); if( this.Status == GeneratorStatus.GeneratingContainers ) { throw new InvalidOperationException( "Cannot perform this operation while the generator is busy generating items" ); } this.EnsureNodeTreeCreated(); if( ( !allowStartAtRealizedItem ) && ( position.Offset == 0 ) ) { if( direction == GeneratorDirection.Forward ) { position = this.FindNextUnrealizedGeneratorPosition( position ); } else { position = this.FindPreviousUnrealizedGeneratorPosition( position ); } } return new CustomItemContainerGeneratorDisposableDisposer( this, position, direction ); }
public Line GetLeadingLine(GeneratorDirection fillDirection) { return(fillDirection == GeneratorDirection.Forward ? GetLastLine() : GetFirstLine()); }
public CustomItemContainerGeneratorDisposableDisposer( CustomItemContainerGenerator generator, GeneratorPosition startGenPos, GeneratorDirection direction ) { if( generator == null ) { throw new ArgumentNullException( "generator" ); } m_generator = generator; m_generator.StartGenerator( startGenPos, direction ); }
/// <summary> /// Get the index of the next item that has not yet been materialized in the nominated fill direction. Returns null if there are no more available items in the source. /// </summary> protected Uno.UI.IndexPath?GetNextUnmaterializedItem(GeneratorDirection fillDirection, Uno.UI.IndexPath? currentMaterializedItem) { // TODO: adjust for reordering return(XamlParent?.GetNextItemIndex(currentMaterializedItem, fillDirection == GeneratorDirection.Forward ? 1 : -1)); }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ void MoveToPosition(GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem, ref GeneratorState state) { ItemBlock block = _itemMap; if (block == null) return; // this can happen in event-leapfrogging situations (Dev11 283413) int itemIndex = 0; // first move to the indexed (realized) item if (position.Index != -1) { // find the right block int itemCount = 0; int index = position.Index; block = block.Next; while (index >= block.ContainerCount) { itemCount += block.ItemCount; index -= block.ContainerCount; itemIndex += block.ItemCount; block = block.Next; } // set the position state.Block = block; state.Offset = index; state.Count = itemCount; state.ItemIndex = itemIndex + index; } else { state.Block = block; state.Offset = 0; state.Count = 0; state.ItemIndex = itemIndex - 1; } // adjust the offset - we always set the state so it points to the next // item to be generated. int offset = position.Offset; if (offset == 0 && (!allowStartAtRealizedItem || state.Block == _itemMap)) { offset = (direction == GeneratorDirection.Forward) ? 1 : -1; } // advance the state according to the offset if (offset > 0) { state.Block.MoveForward(ref state, true); -- offset; while (offset > 0) { offset -= state.Block.MoveForward(ref state, allowStartAtRealizedItem, offset); } } else if (offset < 0) { if (state.Block == _itemMap) { state.ItemIndex = state.Count = ItemsInternal.Count; } state.Block.MoveBackward(ref state, true); ++ offset; while (offset < 0) { offset += state.Block.MoveBackward(ref state, allowStartAtRealizedItem, -offset); } } }
public Uno.UI.IndexPath GetLeadingMaterializedItem(GeneratorDirection fillDirection, Func <Uno.UI.IndexPath, bool> condition) { return(fillDirection == GeneratorDirection.Forward ? GetLastLine(condition).LastItem : GetFirstLine(condition).FirstItem); }
/// <summary> Begin generating at the given position and direction </summary> /// <remarks> /// This method must be called before calling GenerateNext. It returns an /// IDisposable object that tracks the lifetime of the generation loop. /// This method sets the generator's status to GeneratingContent; when /// the IDisposable is disposed, the status changes to ContentReady or /// Error, as appropriate. /// </remarks> IDisposable IItemContainerGenerator.StartAt(GeneratorPosition position, GeneratorDirection direction) { return ((IItemContainerGenerator)this).StartAt(position, direction, false); }
public int GetLeadingEdge(GeneratorDirection fillDirection) { return(fillDirection == GeneratorDirection.Forward ? End : Start); }
IDisposable IItemContainerGenerator.StartAt(GeneratorPosition position, GeneratorDirection direction) { return(((IItemContainerGenerator)this).StartAt(position, direction, false)); }
public GeneratorChunk GetNeighbor(GeneratorDirection dir) { Vector2i loc = location + GeneratorDirections.ToVector2i(dir); return(grid.GetChunk(loc.x, loc.y)); }
IDisposable IItemContainerGenerator.StartAt(GeneratorPosition position, GeneratorDirection direction, bool allowStartAtRealizedItem) { StartAtHelper(position, direction, allowStartAtRealizedItem); return(new Generator(this)); }
public Line GetLeadingLine(GeneratorDirection fillDirection, Func <Uno.UI.IndexPath, bool> condition) { return(fillDirection == GeneratorDirection.Forward ? GetLastLine(condition) : GetFirstLine(condition)); }