Fixes category nodes going beyond the grid

This commit is contained in:
Shawrkie Williams
2026-01-11 11:48:54 -05:00
parent f15b585516
commit cd7a4c610b
2 changed files with 62 additions and 14 deletions
+23 -6
View File
@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Numerics; using System.Numerics;
using AetherBags.AddonLifecycles;
using AetherBags.Configuration; using AetherBags.Configuration;
using AetherBags.Helpers; using AetherBags.Helpers;
using AetherBags.Inventory; using AetherBags.Inventory;
@@ -43,8 +42,8 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow
protected virtual float MaxWindowHeight => 1000; protected virtual float MaxWindowHeight => 1000;
protected const float CategorySpacing = 12; protected const float CategorySpacing = 12;
protected const float ItemSize = 40; protected const float ItemSize = 42;
protected const float ItemPadding = 4; protected const float ItemPadding = 5;
protected const float FooterHeight = 28f; protected const float FooterHeight = 28f;
protected const float FooterTopSpacing = 4f; protected const float FooterTopSpacing = 4f;
protected const float SettingsButtonOffset = 48f; protected const float SettingsButtonOffset = 48f;
@@ -172,7 +171,7 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow
string dataFilter = config.SearchMode == SearchMode.Filter ? searchText : string.Empty; string dataFilter = config.SearchMode == SearchMode.Filter ? searchText : string.Empty;
var categories = InventoryState.GetCategories(dataFilter); var categories = InventoryState.GetCategories(dataFilter);
float maxContentWidth = MaxWindowWidth - (ContentStartPosition.X * 2); float maxContentWidth = CategoriesNode.Width > 0 ? CategoriesNode.Width : ContentSize.X;
int maxItemsPerLine = CalculateOptimalItemsPerLine(maxContentWidth); int maxItemsPerLine = CalculateOptimalItemsPerLine(maxContentWidth);
CategoriesNode.SyncWithListDataByKey<CategorizedInventory, InventoryCategoryNode, uint>( CategoriesNode.SyncWithListDataByKey<CategorizedInventory, InventoryCategoryNode, uint>(
@@ -181,10 +180,11 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow
getKeyFromNode: node => node.CategorizedInventory.Key, getKeyFromNode: node => node.CategorizedInventory.Key,
updateNode: (node, data) => updateNode: (node, data) =>
{ {
node.MaxWidth = maxContentWidth;
node.SetCategoryData(data, Math.Min(data.Items.Count, maxItemsPerLine)); node.SetCategoryData(data, Math.Min(data.Items.Count, maxItemsPerLine));
node.RefreshNodeVisuals(); node.RefreshNodeVisuals();
}, },
createNodeMethod: _ => CreateCategoryNode()); createNodeMethod: _ => CreateCategoryNode(maxContentWidth));
if (HasPinning) if (HasPinning)
{ {
@@ -254,11 +254,12 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow
BackgroundDropTarget.AttachNode(this); BackgroundDropTarget.AttachNode(this);
} }
protected virtual InventoryCategoryNode CreateCategoryNode() protected virtual InventoryCategoryNode CreateCategoryNode(float? maxWidth = null)
{ {
return new InventoryCategoryNode return new InventoryCategoryNode
{ {
Size = ContentSize with { Y = 120 }, Size = ContentSize with { Y = 120 },
MaxWidth = maxWidth,
OnRefreshRequested = ManualRefresh, OnRefreshRequested = ManualRefresh,
OnDragEnd = () => InventoryOrchestrator.RefreshAll(updateMaps: true), OnDragEnd = () => InventoryOrchestrator.RefreshAll(updateMaps: true),
}; };
@@ -340,6 +341,20 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow
CategoriesNode.Position = contentPos; CategoriesNode.Position = contentPos;
CategoriesNode.Size = new Vector2(contentSize.X, gridH); CategoriesNode.Size = new Vector2(contentSize.X, gridH);
UpdateCategoryMaxWidths(contentSize.X);
}
private void UpdateCategoryMaxWidths(float maxWidth)
{
foreach (var node in CategoriesNode.Nodes)
{
if (node is InventoryCategoryNode categoryNode && categoryNode.MaxWidth != maxWidth)
{
categoryNode.MaxWidth = maxWidth;
categoryNode.RecalculateSize();
}
}
} }
protected virtual void AutoSizeWindow() protected virtual void AutoSizeWindow()
@@ -376,6 +391,8 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow
CategoriesNode.Position = ContentStartPosition; CategoriesNode.Position = ContentStartPosition;
CategoriesNode.Size = new Vector2(contentWidth, gridBudget); CategoriesNode.Size = new Vector2(contentWidth, gridBudget);
UpdateCategoryMaxWidths(contentWidth);
CategoriesNode.RecalculateLayout(); CategoriesNode.RecalculateLayout();
float requiredGridHeight = CategoriesNode.GetRequiredHeight(); float requiredGridHeight = CategoriesNode.GetRequiredHeight();
@@ -30,6 +30,7 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase
private const float MinWidth = 40; private const float MinWidth = 40;
private float? _fixedWidth; private float? _fixedWidth;
private float? _maxWidth;
private int _hoverRefs; private int _hoverRefs;
private bool _headerSuppressed; private bool _headerSuppressed;
private bool _headerExpanded; private bool _headerExpanded;
@@ -40,6 +41,7 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase
private int _lastItemCount; private int _lastItemCount;
private ulong _lastItemsHash; private ulong _lastItemsHash;
private int _lastItemsPerLine; private int _lastItemsPerLine;
private float? _lastMaxWidth;
public event Action<InventoryCategoryNode, bool>? HeaderHoverChanged; public event Action<InventoryCategoryNode, bool>? HeaderHoverChanged;
public Action? OnRefreshRequested { get; set; } public Action? OnRefreshRequested { get; set; }
@@ -88,6 +90,7 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase
{ {
bool categoryChanged = data.Key != _lastCategoryKey; bool categoryChanged = data.Key != _lastCategoryKey;
bool itemsPerLineChanged = itemsPerLine != _lastItemsPerLine; bool itemsPerLineChanged = itemsPerLine != _lastItemsPerLine;
bool maxWidthChanged = _maxWidth != _lastMaxWidth;
ulong itemsHash = ComputeItemsHash(CollectionsMarshal.AsSpan(data.Items)); ulong itemsHash = ComputeItemsHash(CollectionsMarshal.AsSpan(data.Items));
bool itemsChanged = data.Items.Count != _lastItemCount || itemsHash != _lastItemsHash; bool itemsChanged = data.Items.Count != _lastItemCount || itemsHash != _lastItemsHash;
@@ -96,6 +99,7 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase
_lastItemCount = data.Items.Count; _lastItemCount = data.Items.Count;
_lastItemsHash = itemsHash; _lastItemsHash = itemsHash;
_lastItemsPerLine = itemsPerLine; _lastItemsPerLine = itemsPerLine;
_lastMaxWidth = _maxWidth;
_categorizedInventory = data; _categorizedInventory = data;
@@ -120,7 +124,7 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase
_itemGridNode.ItemsPerLine = itemsPerLine; _itemGridNode.ItemsPerLine = itemsPerLine;
} }
if (categoryChanged || itemsChanged || itemsPerLineChanged) if (categoryChanged || itemsChanged || itemsPerLineChanged || maxWidthChanged)
{ {
RecalculateSize(); RecalculateSize();
} }
@@ -160,6 +164,12 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase
} }
} }
public float? MaxWidth
{
get => _maxWidth;
set => _maxWidth = value;
}
public override bool IsPinnedInConfig => CategorizedInventory.Category?.IsPinned ?? false; public override bool IsPinnedInConfig => CategorizedInventory.Category?.IsPinned ?? false;
public void BeginHeaderHover() public void BeginHeaderHover()
@@ -224,13 +234,19 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase
} }
} }
private void RecalculateSize() public void RecalculateSize()
{ {
int itemCount = CategorizedInventory.Items.Count; int itemCount = CategorizedInventory.Items.Count;
float cellW = _itemGridNode.Nodes.Count > 0 ? _itemGridNode.Nodes[0].Width : FallbackItemSize;
float cellH = _itemGridNode.Nodes.Count > 0 ? _itemGridNode.Nodes[0].Height : FallbackItemSize;
float hPad = _itemGridNode.HorizontalPadding;
float vPad = _itemGridNode.VerticalPadding;
if (itemCount == 0) if (itemCount == 0)
{ {
float width = _fixedWidth ?? MinWidth; float width = _fixedWidth ?? MinWidth;
if (_maxWidth.HasValue) width = Math.Min(width, _maxWidth.Value);
Size = new Vector2(width, HeaderHeight); Size = new Vector2(width, HeaderHeight);
_baseHeaderWidth = width; _baseHeaderWidth = width;
_itemGridNode.Position = new Vector2(0, HeaderHeight); _itemGridNode.Position = new Vector2(0, HeaderHeight);
@@ -240,21 +256,36 @@ public class InventoryCategoryNode : InventoryCategoryNodeBase
} }
int itemsPerLine = Math.Max(1, _itemGridNode.ItemsPerLine); int itemsPerLine = Math.Max(1, _itemGridNode.ItemsPerLine);
float minUsableWidth = cellW;
if (_maxWidth.HasValue && _fixedWidth is null && _maxWidth.Value >= minUsableWidth)
{
int maxColumns = (int)MathF.Floor((_maxWidth.Value + hPad) / (cellW + hPad));
maxColumns = Math.Max(1, maxColumns);
float widthNeeded = maxColumns * cellW + (maxColumns - 1) * hPad;
if (widthNeeded > _maxWidth.Value && maxColumns > 1)
maxColumns--;
itemsPerLine = Math.Min(itemsPerLine, maxColumns);
}
int rows = (itemCount + itemsPerLine - 1) / itemsPerLine; int rows = (itemCount + itemsPerLine - 1) / itemsPerLine;
int actualColumns = Math.Min(itemCount, itemsPerLine); int actualColumns = Math.Min(itemCount, itemsPerLine);
float cellW = _itemGridNode.Nodes.Count > 0 ? _itemGridNode.Nodes[0].Width : FallbackItemSize;
float cellH = _itemGridNode.Nodes.Count > 0 ? _itemGridNode.Nodes[0].Height : FallbackItemSize;
float hPad = _itemGridNode.HorizontalPadding;
float vPad = _itemGridNode.VerticalPadding;
float calculatedWidth = _fixedWidth ?? Math.Max(MinWidth, actualColumns * cellW + (actualColumns - 1) * hPad); float calculatedWidth = _fixedWidth ?? Math.Max(MinWidth, actualColumns * cellW + (actualColumns - 1) * hPad);
if (_maxWidth.HasValue && _fixedWidth is null && _maxWidth.Value >= minUsableWidth)
calculatedWidth = Math.Min(calculatedWidth, _maxWidth.Value);
float height = HeaderHeight + rows * cellH + (rows - 1) * vPad; float height = HeaderHeight + rows * cellH + (rows - 1) * vPad;
Size = new Vector2(calculatedWidth, height); Size = new Vector2(calculatedWidth, height);
_itemGridNode.Position = new Vector2(0, HeaderHeight); _itemGridNode.Position = new Vector2(0, HeaderHeight);
_itemGridNode.Size = new Vector2(calculatedWidth, height - HeaderHeight); _itemGridNode.Size = new Vector2(calculatedWidth, height - HeaderHeight);
if (_itemGridNode.ItemsPerLine != itemsPerLine)
_itemGridNode.ItemsPerLine = itemsPerLine;
_baseHeaderWidth = calculatedWidth; _baseHeaderWidth = calculatedWidth;
ApplyHeaderVisualStateAndSize(); ApplyHeaderVisualStateAndSize();