Skip to content

Commit

Permalink
MaterialListBox Improved Scrolling
Browse files Browse the repository at this point in the history
Improved the scrolling functionality of MaterialListBox to allow for SmoothScrolling up and down (fixes items clipping off the bottom). This option can be enabled/disabled through the new SmoothScrolling bool property.
  • Loading branch information
Taiizor committed Nov 29, 2024
1 parent 2150c46 commit 1dd1aa4
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 12 deletions.
8 changes: 4 additions & 4 deletions demo/ReaLTaiizor.UI/ReaLTaiizor.UI/ReaLTaiizor.UI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="ReaLTaiizor" Version="3.8.0.8" />
<!--<Reference Include="ReaLTaiizor">
<HintPath>..\..\..\src\ReaLTaiizor\bin\Release\$(TargetFramework)\ReaLTaiizor.dll</HintPath>
</Reference>-->
<!--<PackageReference Include="ReaLTaiizor" Version="3.8.0.8" />-->
<Reference Include="ReaLTaiizor">
<HintPath>..\..\..\src\ReaLTaiizor\bin\Release\$(TargetFramework)\ReaLTaiizor.dll</HintPath>
</Reference>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='GitHub|AnyCPU'">
<GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
Expand Down
68 changes: 60 additions & 8 deletions src/ReaLTaiizor/Controls/ListBox/MaterialListBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class MaterialListBox : Control, MaterialControlI
private bool _multiKeyDown;
private int _hoveredItem;
private MaterialScrollBar _scrollBar;
private bool _smoothScrolling = true;
private bool _updating = false;
private int _itemHeight;
private bool _showBorder;
Expand Down Expand Up @@ -238,6 +239,19 @@ public MaterialItemDensity Density
}
}

[Category("Material"), DefaultValue(true)]
[Description("Enables Smoothly Scrolling")]
public bool SmoothScrolling
{
get => _smoothScrolling;
set
{
_smoothScrolling = value;
UpdateItemSpecs();
Invalidate();
}
}

#endregion Properties

#region Constructors
Expand Down Expand Up @@ -312,19 +326,20 @@ private void UpdateItemSpecs()
if (_style == ListBoxStyle.TwoLine)
{
_secondaryTextTopPadding = 4;

if (_density == MaterialItemDensity.Dense)
{
_itemHeight = 60;
_secondaryTextBottomPadding = 10;
_primaryTextBottomPadding = 2;
_secondaryTextBottomPadding = 10;
_primaryFont = SkinManager.GetFontByType(MaterialSkinManager.FontType.Body1);
_secondaryFont = SkinManager.GetFontByType(MaterialSkinManager.FontType.Body2);
}
else
{
_itemHeight = 72;
_secondaryTextBottomPadding = 16;
_primaryTextBottomPadding = 4;
_secondaryTextBottomPadding = 16;
_primaryFont = SkinManager.GetFontByType(MaterialSkinManager.FontType.Subtitle1);
_secondaryFont = SkinManager.GetFontByType(MaterialSkinManager.FontType.Body1);
}
Expand All @@ -333,6 +348,7 @@ private void UpdateItemSpecs()
{
_primaryTextBottomPadding = 4;
_secondaryTextTopPadding = 4;

if (_density == MaterialItemDensity.Dense)
{
_itemHeight = 76;
Expand Down Expand Up @@ -381,9 +397,16 @@ protected override void OnPaint(PaintEventArgs e)
g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
Rectangle mainRect = new(0, 0, Width - (ShowBorder ? 1 : 0), Height - (ShowBorder ? 1 : 0));

int lastItem = (_scrollBar.Value / _itemHeight) + (Height / _itemHeight) + 1 > Items.Count ? Items.Count : (_scrollBar.Value / _itemHeight) + (Height / _itemHeight) + 1;
int firstItem = _scrollBar.Value / _itemHeight < 0 ? 0 : (_scrollBar.Value / _itemHeight);

// Account for partially visible items.
int itemOffset = SmoothScrolling ? _scrollBar.Value - (firstItem * _itemHeight) : 0;

// Calculate the last item
int lastItem = (_scrollBar.Value / _itemHeight) + ((Height + itemOffset) / _itemHeight) + 1 > Items.Count ?
Items.Count :
(_scrollBar.Value / _itemHeight) + ((Height + itemOffset) / _itemHeight) + 1;

g.FillRectangle(Enabled ? SkinManager.BackgroundBrush : SkinManager.BackgroundDisabledBrush, mainRect);

//Set TextAlignFlags
Expand Down Expand Up @@ -418,7 +441,7 @@ protected override void OnPaint(PaintEventArgs e)
string itemText = Items[i].Text;
string itemSecondaryText = Items[i].SecondaryText;

Rectangle itemRect = new(0, (i - firstItem) * _itemHeight, Width - (_showScrollBar && _scrollBar.Visible ? _scrollBar.Width : 0), _itemHeight);
Rectangle itemRect = new Rectangle(0, (i - firstItem) * _itemHeight - itemOffset, Width - (_showScrollBar && _scrollBar.Visible ? _scrollBar.Width : 0), _itemHeight);

if (MultiSelect && _indicates.Count != 0)
{
Expand Down Expand Up @@ -538,10 +561,12 @@ public void AddItems(MaterialListBoxItem[] newItems)
{
_updating = true;
_scrollBar.BeginUpdate();

foreach (MaterialListBoxItem str in newItems)
{
AddItem(str);
}

_scrollBar.EndUpdate();
_updating = false;

Expand All @@ -553,10 +578,12 @@ public void AddItems(string[] newItems)
{
_updating = true;
_scrollBar.BeginUpdate();

foreach (string str in newItems)
{
AddItem(str);
}

_scrollBar.EndUpdate();
_updating = false;

Expand All @@ -571,6 +598,7 @@ public void RemoveItemAt(int index)
_selectedIndex -= 1;
update_selection();
}

Items.RemoveAt(index);
InvalidateScroll(this, null);
ItemsCountChanged?.Invoke(this, new EventArgs());
Expand All @@ -583,6 +611,7 @@ public void RemoveItem(MaterialListBoxItem item)
_selectedIndex -= 1;
update_selection();
}

Items.Remove(item);
InvalidateScroll(this, null);
ItemsCountChanged?.Invoke(this, new EventArgs());
Expand All @@ -597,6 +626,7 @@ public void RemoveItems(MaterialListBoxItem[] itemsToRemove)
{
_updating = true;
_scrollBar.BeginUpdate();

foreach (MaterialListBoxItem item in itemsToRemove)
{
if (Items.IndexOf(item) <= _selectedIndex)
Expand All @@ -606,6 +636,7 @@ public void RemoveItems(MaterialListBoxItem[] itemsToRemove)
}
Items.Remove(item);
}

_scrollBar.EndUpdate();
_updating = false;

Expand Down Expand Up @@ -633,13 +664,16 @@ public void Clear()
{
_updating = true;
_scrollBar.BeginUpdate();

for (int i = Items.Count - 1; i >= 0; i += -1)
{
Items.RemoveAt(i);
}

_scrollBar.EndUpdate();
_updating = false;
_selectedIndex = -1;

update_selection();

InvalidateScroll(this, null);
Expand Down Expand Up @@ -684,15 +718,19 @@ protected override void OnSizeChanged(EventArgs e)
{
InvalidateScroll(this, e);
InvalidateLayout();

base.OnSizeChanged(e);
}

protected override void OnMouseDown(MouseEventArgs e)
{
Focus();

if (e.Button == MouseButtons.Left)
{
int index = (_scrollBar.Value / _itemHeight) + (e.Location.Y / _itemHeight);
int itemOffset = SmoothScrolling ? _scrollBar.Value % _itemHeight : 0;
int index = _scrollBar.Value / _itemHeight + (e.Location.Y + itemOffset) / _itemHeight;

if (index >= 0 && index < Items.Count)
{
if (MultiSelect && _multiKeyDown)
Expand All @@ -712,8 +750,10 @@ protected override void OnMouseDown(MouseEventArgs e)
SelectedValueChanged?.Invoke(this, _selectedItem);
}
}

Invalidate();
}

base.OnMouseDown(e);
}

Expand All @@ -733,8 +773,12 @@ private void InvalidateScroll(object sender, EventArgs e)
_scrollBar.SmallChange = _itemHeight;
_scrollBar.LargeChange = Height;
_scrollBar.Visible = (Items.Count * _itemHeight) > Height;

if (Items.Count == 0)
{ _scrollBar.Value = 0; }
{
_scrollBar.Value = 0;
}

Invalidate();
}

Expand All @@ -747,6 +791,7 @@ private void InvalidateLayout()
{
_scrollBar.Size = new Size(12, Height - (ShowBorder ? 2 : 0));
_scrollBar.Location = new Point(Width - (_scrollBar.Width + (ShowBorder ? 1 : 0)), ShowBorder ? 1 : 0);

Invalidate();
}

Expand Down Expand Up @@ -810,7 +855,9 @@ protected override bool IsInputKey(Keys keyData)
}
break;
}

Invalidate();

return base.IsInputKey(keyData);
}

Expand All @@ -825,7 +872,8 @@ protected override void OnMouseMove(MouseEventArgs e)

private void _updateHoveredItem(MouseEventArgs e)
{
int index = (_scrollBar.Value / _itemHeight) + (e.Location.Y / _itemHeight);
int itemOffset = SmoothScrolling ? _scrollBar.Value % _itemHeight : 0;
int index = _scrollBar.Value / _itemHeight + (e.Location.Y + itemOffset) / _itemHeight;

if (index >= Items.Count)
{
Expand All @@ -836,22 +884,25 @@ private void _updateHoveredItem(MouseEventArgs e)
{
_hoveredItem = index;
}

}

protected override void OnMouseLeave(EventArgs e)
{
_hoveredItem = -1;
Cursor = Cursors.Default;

Invalidate();

base.OnMouseLeave(e);
}

protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);

_scrollBar.Size = new Size(12, Height - (ShowBorder ? 2 : 0));
_scrollBar.Location = new Point(Width - (_scrollBar.Width + (ShowBorder ? 1 : 0)), ShowBorder ? 1 : 0);

InvalidateScroll(this, e);
}

Expand All @@ -872,6 +923,7 @@ protected override void WndProc(ref Message m)
m.Result = IntPtr.Zero;
return;
}

base.WndProc(ref m);
}
}
Expand Down

0 comments on commit 1dd1aa4

Please sign in to comment.