private Row GetRow(int forIndex) { // If there are no rows available in the cache, create one from scratch if (_rowCache.Count == 0) { var newRow = CreateRow(); PopulateRow(forIndex, newRow); return(newRow); } var data = _itemList[forIndex]; Row row = null; Row altRow = null; // Determine if the row we're looking for is an alt row var target = forIndex % 2; // Try and find a row which previously had this data, so we can reuse it for (var i = 0; i < _rowCache.Count; i++) { row = _rowCache[i]; // If this row previously represented this data, just use that one. if (row.Data == data) { _rowCache.RemoveAt(i); PopulateRow(forIndex, row); break; } // Cache a row which is was the same alt state as the row we're looking for, in case // we don't find an exact match. if (row.Index % 2 == target) { altRow = row; } // Didn't match, reset to null row = null; } // If an exact match wasn't found, but a row with the same alt-status was found, use that one. if (row == null && altRow != null) { _rowCache.Remove(altRow); row = altRow; PopulateRow(forIndex, row); } else if (row == null) { // No match found, use the last added item in the cache row = _rowCache.PopLast(); PopulateRow(forIndex, row); } return(row); }
/// <summary> /// Invalidate a single row (before removing, or changing selection status) /// </summary> /// <param name="itemIndex"></param> protected void InvalidateItem(int itemIndex) { if (!_visibleItemList.Contains(itemIndex)) { return; } _visibleItemList.Remove(itemIndex); for (var i = 0; i < _visibleRows.Count; i++) { if (_visibleRows[i].Index == itemIndex) { RecycleRow(_visibleRows[i]); _visibleRows.RemoveAt(i); break; } } }
public void RemoveItem(object item) { if (SelectedItem == item) { SelectedItem = null; } var index = _itemList.IndexOf(item); InvalidateItem(index); _itemList.Remove(item); RefreshIndexCache(); SetDirty(); }
protected void ScrollUpdate() { if (!Application.isPlaying) { return; } //Debug.Log("[SRConsole] ScrollUpdate {0}".Fmt(Time.frameCount)); var pos = rectTransform.anchoredPosition; var startY = pos.y; var viewHeight = ((RectTransform)ScrollRect.transform).rect.height; // Determine the range of rows that should be visible var rowRangeLower = Mathf.FloorToInt(startY / (ItemHeight + Spacing)); var rowRangeHigher = Mathf.CeilToInt((startY + viewHeight) / (ItemHeight + Spacing)); // Apply padding to reduce pop-in rowRangeLower -= RowPadding; rowRangeHigher += RowPadding; rowRangeLower = Mathf.Max(0, rowRangeLower); rowRangeHigher = Mathf.Min(_itemList.Count, rowRangeHigher); var isDirty = false; #if PROFILE Profiler.BeginSample("Visible Rows Cull"); #endif for (var i = 0; i < _visibleRows.Count; i++) { var row = _visibleRows[i]; // Move on if row is still visible if (row.Index >= rowRangeLower && row.Index <= rowRangeHigher) { continue; } _visibleItemList.Remove(row.Index); _visibleRows.Remove(row); RecycleRow(row); isDirty = true; } #if PROFILE Profiler.EndSample(); Profiler.BeginSample("Item Visible Check"); #endif for (var i = rowRangeLower; i < rowRangeHigher; ++i) { if (i >= _itemList.Count) { break; } // Move on if row is already visible if (_visibleItemList.Contains(i)) { continue; } var row = GetRow(i); _visibleRows.Add(row); _visibleItemList.Add(i); isDirty = true; } #if PROFILE Profiler.EndSample(); #endif // If something visible has explicitly been changed, or the visible row count has changed if (isDirty || _visibleItemCount != _visibleRows.Count) { //Debug.Log("[SRConsole] IsDirty {0}".Fmt(Time.frameCount)); LayoutRebuilder.MarkLayoutForRebuild(rectTransform); } _visibleItemCount = _visibleRows.Count; }