mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Fix scrolling on lists.
This commit is contained in:
parent
c3d0d24713
commit
fb909aaf87
1 changed files with 82 additions and 61 deletions
|
|
@ -8,17 +8,19 @@ namespace Glamourer.Gui
|
||||||
{
|
{
|
||||||
public class ComboWithFilter<T>
|
public class ComboWithFilter<T>
|
||||||
{
|
{
|
||||||
private readonly string _label;
|
private readonly string _label;
|
||||||
private readonly string _filterLabel;
|
private readonly string _filterLabel;
|
||||||
private readonly string _listLabel;
|
private readonly string _listLabel;
|
||||||
private string _currentFilter = string.Empty;
|
private string _currentFilter = string.Empty;
|
||||||
private string _currentFilterLower = string.Empty;
|
private string _currentFilterLower = string.Empty;
|
||||||
private bool _focus;
|
private bool _focus;
|
||||||
private readonly float _size;
|
private readonly float _size;
|
||||||
private float _previewSize;
|
private float _previewSize;
|
||||||
private readonly IReadOnlyList<T> _items;
|
private readonly IReadOnlyList<T> _items;
|
||||||
private readonly IReadOnlyList<string> _itemNamesLower;
|
private readonly IReadOnlyList<(string, int)> _itemNamesLower;
|
||||||
private readonly Func<T, string> _itemToName;
|
private readonly Func<T, string> _itemToName;
|
||||||
|
private IReadOnlyList<(string, int)> _currentItemNames;
|
||||||
|
private bool _needsClear;
|
||||||
|
|
||||||
public Action? PrePreview;
|
public Action? PrePreview;
|
||||||
public Action? PostPreview;
|
public Action? PostPreview;
|
||||||
|
|
@ -32,6 +34,22 @@ namespace Glamourer.Gui
|
||||||
public ImGuiComboFlags Flags { get; set; } = ImGuiComboFlags.None;
|
public ImGuiComboFlags Flags { get; set; } = ImGuiComboFlags.None;
|
||||||
public int ItemsAtOnce { get; set; } = 12;
|
public int ItemsAtOnce { get; set; } = 12;
|
||||||
|
|
||||||
|
private void UpdateFilter(string newFilter)
|
||||||
|
{
|
||||||
|
if (newFilter == _currentFilter)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var lower = newFilter.ToLowerInvariant();
|
||||||
|
if (_currentFilterLower.Any() && lower.Contains(_currentFilterLower))
|
||||||
|
_currentItemNames = _currentItemNames.Where(p => p.Item1.Contains(lower)).ToArray();
|
||||||
|
else if (lower.Any())
|
||||||
|
_currentItemNames = _itemNamesLower.Where(p => p.Item1.Contains(lower)).ToArray();
|
||||||
|
else
|
||||||
|
_currentItemNames = _itemNamesLower;
|
||||||
|
_currentFilter = newFilter;
|
||||||
|
_currentFilterLower = lower;
|
||||||
|
}
|
||||||
|
|
||||||
public ComboWithFilter(string label, float size, float previewSize, IReadOnlyList<T> items, Func<T, string> itemToName)
|
public ComboWithFilter(string label, float size, float previewSize, IReadOnlyList<T> items, Func<T, string> itemToName)
|
||||||
{
|
{
|
||||||
_label = label;
|
_label = label;
|
||||||
|
|
@ -42,26 +60,28 @@ namespace Glamourer.Gui
|
||||||
_size = size;
|
_size = size;
|
||||||
_previewSize = previewSize;
|
_previewSize = previewSize;
|
||||||
|
|
||||||
_itemNamesLower = _items.Select(i => _itemToName(i).ToLowerInvariant()).ToList();
|
_itemNamesLower = _items.Select((i, idx) => (_itemToName(i).ToLowerInvariant(), idx)).ToArray();
|
||||||
|
_currentItemNames = _itemNamesLower;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComboWithFilter(string label, ComboWithFilter<T> other)
|
public ComboWithFilter(string label, ComboWithFilter<T> other)
|
||||||
{
|
{
|
||||||
_label = label;
|
_label = label;
|
||||||
_filterLabel = $"##_{label}_filter";
|
_filterLabel = $"##_{label}_filter";
|
||||||
_listLabel = $"##_{label}_list";
|
_listLabel = $"##_{label}_list";
|
||||||
_itemToName = other._itemToName;
|
_itemToName = other._itemToName;
|
||||||
_items = other._items;
|
_items = other._items;
|
||||||
_itemNamesLower = other._itemNamesLower;
|
_itemNamesLower = other._itemNamesLower;
|
||||||
_size = other._size;
|
_currentItemNames = other._currentItemNames;
|
||||||
_previewSize = other._previewSize;
|
_size = other._size;
|
||||||
PrePreview = other.PrePreview;
|
_previewSize = other._previewSize;
|
||||||
PostPreview = other.PostPreview;
|
PrePreview = other.PrePreview;
|
||||||
CreateSelectable = other.CreateSelectable;
|
PostPreview = other.PostPreview;
|
||||||
PreList = other.PreList;
|
CreateSelectable = other.CreateSelectable;
|
||||||
PostList = other.PostList;
|
PreList = other.PreList;
|
||||||
HeightPerItem = other.HeightPerItem;
|
PostList = other.PostList;
|
||||||
Flags = other.Flags;
|
HeightPerItem = other.HeightPerItem;
|
||||||
|
Flags = other.Flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool DrawList(string currentName, out int numItems, out int nodeIdx, ref T? value)
|
private bool DrawList(string currentName, out int numItems, out int nodeIdx, ref T? value)
|
||||||
|
|
@ -83,7 +103,6 @@ namespace Glamourer.Gui
|
||||||
_focus = true;
|
_focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var scrollY = Math.Max((int) (ImGui.GetScrollY() / _heightPerItem) - 1, 0);
|
var scrollY = Math.Max((int) (ImGui.GetScrollY() / _heightPerItem) - 1, 0);
|
||||||
var restHeight = scrollY * _heightPerItem;
|
var restHeight = scrollY * _heightPerItem;
|
||||||
numItems = 0;
|
numItems = 0;
|
||||||
|
|
@ -92,38 +111,34 @@ namespace Glamourer.Gui
|
||||||
if (restHeight > 0)
|
if (restHeight > 0)
|
||||||
ImGui.Dummy(Vector2.UnitY * restHeight);
|
ImGui.Dummy(Vector2.UnitY * restHeight);
|
||||||
|
|
||||||
for (var i = scrollY; i < _items.Count; ++i)
|
for (var i = scrollY; i < _currentItemNames.Count; ++i)
|
||||||
{
|
{
|
||||||
if (!_itemNamesLower[i].Contains(_currentFilterLower))
|
if (++numItems > ItemsAtOnce + 2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
++numItems;
|
nodeIdx = _currentItemNames[i].Item2;
|
||||||
if (numItems <= ItemsAtOnce + 2)
|
var item = _items[nodeIdx]!;
|
||||||
|
bool success;
|
||||||
|
if (CreateSelectable != null)
|
||||||
{
|
{
|
||||||
nodeIdx = i;
|
success = CreateSelectable(item);
|
||||||
var item = _items[i]!;
|
}
|
||||||
bool success;
|
else
|
||||||
if (CreateSelectable != null)
|
{
|
||||||
{
|
var name = _itemToName(item);
|
||||||
success = CreateSelectable(item);
|
success = ImGui.Selectable(name, name == currentName);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
var name = _itemToName(item);
|
|
||||||
success = ImGui.Selectable(name, name == currentName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
value = item;
|
value = item;
|
||||||
ImGui.CloseCurrentPopup();
|
ImGui.CloseCurrentPopup();
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numItems > ItemsAtOnce + 2)
|
if (_currentItemNames.Count > ItemsAtOnce + 2)
|
||||||
ImGui.Dummy(Vector2.UnitY * (numItems - ItemsAtOnce - 2) * _heightPerItem);
|
ImGui.Dummy(Vector2.UnitY * (_currentItemNames.Count - ItemsAtOnce - 2 - scrollY) * _heightPerItem);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
@ -143,13 +158,18 @@ namespace Glamourer.Gui
|
||||||
PrePreview?.Invoke();
|
PrePreview?.Invoke();
|
||||||
if (!ImGui.BeginCombo(_label, currentName, Flags))
|
if (!ImGui.BeginCombo(_label, currentName, Flags))
|
||||||
{
|
{
|
||||||
_focus = false;
|
if (_needsClear)
|
||||||
_currentFilter = string.Empty;
|
{
|
||||||
_currentFilterLower = string.Empty;
|
_needsClear = false;
|
||||||
|
_focus = false;
|
||||||
|
UpdateFilter(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
PostPreview?.Invoke();
|
PostPreview?.Invoke();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_needsClear = true;
|
||||||
PostPreview?.Invoke();
|
PostPreview?.Invoke();
|
||||||
|
|
||||||
_heightPerItem = HeightPerItem ?? ImGui.GetTextLineHeightWithSpacing();
|
_heightPerItem = HeightPerItem ?? ImGui.GetTextLineHeightWithSpacing();
|
||||||
|
|
@ -158,8 +178,9 @@ namespace Glamourer.Gui
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ImGui.SetNextItemWidth(-1);
|
ImGui.SetNextItemWidth(-1);
|
||||||
if (ImGui.InputTextWithHint(_filterLabel, "Filter...", ref _currentFilter, 255))
|
var tmp = _currentFilter;
|
||||||
_currentFilterLower = _currentFilter.ToLowerInvariant();
|
if (ImGui.InputTextWithHint(_filterLabel, "Filter...", ref tmp, 255))
|
||||||
|
UpdateFilter(tmp);
|
||||||
|
|
||||||
var isFocused = ImGui.IsItemActive();
|
var isFocused = ImGui.IsItemActive();
|
||||||
if (!_focus)
|
if (!_focus)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue