mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-20 04:10:00 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
166 lines
3.9 KiB
C#
166 lines
3.9 KiB
C#
using Sandbox.UI;
|
|
using System;
|
|
namespace Editor;
|
|
|
|
public partial class ListView
|
|
{
|
|
/// <summary>
|
|
/// Rebuild the scrollbars and layout for the visible items
|
|
/// </summary>
|
|
protected override void Rebuild()
|
|
{
|
|
if ( !IsValid )
|
|
return;
|
|
|
|
LayoutScrollbar();
|
|
LayoutItems();
|
|
Update();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Work out how big the scrollbars need to be and layout the current PVS
|
|
/// </summary>
|
|
protected virtual void LayoutScrollbar()
|
|
{
|
|
var rect = CanvasRect;
|
|
|
|
itemsPerRow = 1;
|
|
if ( ItemSize.x > 0 ) itemsPerRow = ((rect.Width + ItemSpacing.x) / (ItemSize.x + ItemSpacing.x)).FloorToInt();
|
|
itemsPerRow = Math.Max( 1, itemsPerRow );
|
|
|
|
rowHeight = (ItemSize.y + ItemSpacing.y).CeilToInt();
|
|
rowCount = ((float)_items.Count() / (float)itemsPerRow).CeilToInt();
|
|
|
|
var canvasHeight = rowCount * ItemSize.y;
|
|
|
|
if ( rowCount > 0 )
|
|
canvasHeight += (rowCount - 1) * ItemSpacing.y;
|
|
|
|
VerticalScrollbar.Minimum = 0;
|
|
VerticalScrollbar.Maximum = Math.Max( VerticalScrollbar.Minimum, (canvasHeight - rect.Height).CeilToInt() );
|
|
VerticalScrollbar.SingleStep = Math.Max( rowHeight, rect.Height * 0.33f ).CeilToInt();
|
|
VerticalScrollbar.PageStep = rect.Height.FloorToInt();
|
|
}
|
|
|
|
protected virtual void LayoutItems()
|
|
{
|
|
//
|
|
// Plenty of optimization here.
|
|
// Like on scroll we probably don't need to lay the items out unless the scroll differs by rowheight amount
|
|
// and this dictionary call here is probably pain.
|
|
// but ultimately the repaint is going to take as long as this, and it's still pretty fast, so fuck it for now.
|
|
//
|
|
|
|
var old = ItemLayouts.ToList();
|
|
ItemLayouts.Clear();
|
|
|
|
if ( _items.Count == 0 )
|
|
return;
|
|
|
|
var rect = CanvasRect;
|
|
|
|
float scrollOffset = VerticalScrollbar.Value - rect.Top;
|
|
|
|
float visibleHeight = Height;
|
|
float rowHeight = ItemSize.y + ItemSpacing.y;
|
|
float offset = scrollOffset % rowHeight;
|
|
int firstVisibleRow = (scrollOffset / rowHeight).FloorToInt();
|
|
if ( firstVisibleRow < 0 ) firstVisibleRow = 0;
|
|
int firstVisibleIndex = firstVisibleRow * itemsPerRow;
|
|
|
|
int visibleRows = ((visibleHeight + offset) / ItemSize.y).CeilToInt();
|
|
int visibleItems = visibleRows * itemsPerRow;
|
|
|
|
var subset = _items.Skip( firstVisibleIndex ).Take( visibleItems );
|
|
|
|
var itemRect = new Rect( 0, ItemSize );
|
|
if ( ItemSize.x <= 0 ) itemRect.Width = rect.Width;
|
|
|
|
var col = 0;
|
|
var row = 0;
|
|
|
|
float rowStart = 0;
|
|
float rowSpacing = ItemSpacing.x;
|
|
float spareSpace = (rect.Width + ItemSpacing.x) - (itemRect.Width + ItemSpacing.x) * itemsPerRow;
|
|
spareSpace = Math.Max( 0, spareSpace );
|
|
|
|
switch ( ItemAlign )
|
|
{
|
|
case Align.Stretch:
|
|
{
|
|
itemRect.Width += spareSpace / itemsPerRow;
|
|
break;
|
|
}
|
|
|
|
case Align.Center:
|
|
{
|
|
rowStart = spareSpace * 0.5f;
|
|
break;
|
|
}
|
|
|
|
case Align.SpaceAround:
|
|
{
|
|
rowSpacing = (spareSpace / (itemsPerRow));
|
|
rowStart = rowSpacing / 2.0f;
|
|
rowSpacing += ItemSpacing.x;
|
|
break;
|
|
}
|
|
|
|
case Align.SpaceBetween:
|
|
{
|
|
if ( itemsPerRow > 1 )
|
|
{
|
|
var items = Math.Min( _items.Count, itemsPerRow );
|
|
rowStart = 0;
|
|
rowSpacing = (rect.Width - items * ItemSize.x) / Math.Max( 1, (items - 1) );
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
foreach ( var item in subset )
|
|
{
|
|
itemRect.Position = new Vector2( rect.Left + rowStart + col * (itemRect.Width + rowSpacing), row * (ItemSize.y + ItemSpacing.y) - offset );
|
|
|
|
var lo = old.FirstOrDefault( x => x.Object.Equals( item ) );
|
|
|
|
if ( lo == null )
|
|
{
|
|
lo = new VirtualWidget();
|
|
lo.Selected = SelectedItems.Contains( item );
|
|
|
|
ItemScrollEnter?.Invoke( item );
|
|
}
|
|
else
|
|
{
|
|
old.Remove( lo );
|
|
}
|
|
|
|
lo.Object = item;
|
|
lo.Rect = itemRect;
|
|
lo.Row = firstVisibleRow + row;
|
|
lo.Column = col;
|
|
ItemLayouts.Add( lo );
|
|
|
|
col++;
|
|
if ( col >= itemsPerRow )
|
|
{
|
|
row++;
|
|
col = 0;
|
|
}
|
|
}
|
|
|
|
if ( ItemScrollExit is not null )
|
|
{
|
|
// culling callback
|
|
foreach ( var item in old )
|
|
{
|
|
ItemScrollExit.Invoke( item.Object );
|
|
}
|
|
}
|
|
}
|
|
}
|