diff --git a/MareSynchronos/UI/CompactUI.cs b/MareSynchronos/UI/CompactUI.cs index 4b52688..126183a 100644 --- a/MareSynchronos/UI/CompactUI.cs +++ b/MareSynchronos/UI/CompactUI.cs @@ -71,7 +71,7 @@ public class CompactUi : WindowMediatorSubscriberBase _groupPanel = new(this, uiShared, _pairManager, uidDisplayHandler, _serverManager); _selectGroupForPairUi = new(tagHandler, uidDisplayHandler); _selectPairsForGroupUi = new(tagHandler, uidDisplayHandler); - _pairGroupsUi = new(configService, tagHandler, apiController, _selectPairsForGroupUi); + _pairGroupsUi = new(configService, tagHandler, uidDisplayHandler, apiController, _selectPairsForGroupUi); #if DEBUG string dev = "Dev Build"; diff --git a/MareSynchronos/UI/Components/DrawPairBase.cs b/MareSynchronos/UI/Components/DrawPairBase.cs index a9c98cb..e893e15 100644 --- a/MareSynchronos/UI/Components/DrawPairBase.cs +++ b/MareSynchronos/UI/Components/DrawPairBase.cs @@ -22,6 +22,7 @@ public abstract class DrawPairBase _displayHandler = uIDDisplayHandler; } + public string ImGuiID => _id; public string UID => _pair.UserData.UID; public void DrawPairedClient() @@ -30,6 +31,20 @@ public abstract class DrawPairBase var pauseIconSize = UiSharedService.GetIconButtonSize(FontAwesomeIcon.Play); var textSize = ImGui.CalcTextSize(_pair.UserData.AliasOrUID); + var startPos = ImGui.GetCursorStartPos(); + + var framePadding = ImGui.GetStyle().FramePadding; + var lineHeight = textSize.Y + framePadding.Y * 2; + + var off = startPos.Y; + var height = UiSharedService.GetWindowContentRegionHeight(); + + if ((originalY + off) < -lineHeight || (originalY + off) > height) + { + ImGui.Dummy(new System.Numerics.Vector2(0f, lineHeight)); + return; + } + var textPosY = originalY + pauseIconSize.Y / 2 - textSize.Y / 2; DrawLeftSide(textPosY, originalY); ImGui.SameLine(); diff --git a/MareSynchronos/UI/Components/GroupPanel.cs b/MareSynchronos/UI/Components/GroupPanel.cs index e8fb3f7..3daaf47 100644 --- a/MareSynchronos/UI/Components/GroupPanel.cs +++ b/MareSynchronos/UI/Components/GroupPanel.cs @@ -395,63 +395,56 @@ internal sealed class GroupPanel ImGui.Indent(20); if (_expandedGroupState[groupDto.GID]) { - var visibleUsers = pairsInGroup.Where(u => u.IsVisible) + var sortedPairs = pairsInGroup .OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal)) .ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator()) .ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned()) - .ThenBy(u => u.GetNote() ?? u.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase) - .Select(c => new DrawGroupPair(groupDto.GID + c.UserData.UID, c, ApiController, _mainUi.Mediator, groupDto, c.GroupPair.Single(g => GroupDataComparer.Instance.Equals(g.Key.Group, groupDto.Group)).Value, - _uidDisplayHandler)) - .ToList(); - var onlineUsers = pairsInGroup.Where(u => u.IsOnline && !u.IsVisible) - .OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal)) - .ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator()) - .ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned()) - .ThenBy(u => u.GetNote() ?? u.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase) - .Select(c => new DrawGroupPair(groupDto.GID + c.UserData.UID, c, ApiController, _mainUi.Mediator, groupDto, c.GroupPair.Single(g => GroupDataComparer.Instance.Equals(g.Key.Group, groupDto.Group)).Value, - _uidDisplayHandler)) - .ToList(); - var offlineUsers = pairsInGroup.Where(u => !u.IsOnline && !u.IsVisible) - .OrderByDescending(u => string.Equals(u.UserData.UID, groupDto.OwnerUID, StringComparison.Ordinal)) - .ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsModerator()) - .ThenByDescending(u => u.GroupPair[groupDto].GroupPairStatusInfo.IsPinned()) - .ThenBy(u => u.GetNote() ?? u.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase) - .Select(c => new DrawGroupPair(groupDto.GID + c.UserData.UID, c, ApiController, _mainUi.Mediator, groupDto, c.GroupPair.Single(g => GroupDataComparer.Instance.Equals(g.Key.Group, groupDto.Group)).Value, - _uidDisplayHandler)) - .ToList(); + .ThenBy(u => u.GetNote() ?? u.UserData.AliasOrUID, StringComparer.OrdinalIgnoreCase); - if (visibleUsers.Any()) + var visibleUsers = new List(); + var onlineUsers = new List(); + var offlineUsers = new List(); + + foreach (var pair in sortedPairs) { - ImGui.Text("Visible"); - ImGui.Separator(); - foreach (var entry in visibleUsers) - { - using (ImRaii.PushId(groupDto.GID + entry.UID)) entry.DrawPairedClient(); - } + var drawPair = new DrawGroupPair( + groupDto.GID + pair.UserData.UID, pair, + ApiController, _mainUi.Mediator, groupDto, + pair.GroupPair.Single( + g => GroupDataComparer.Instance.Equals(g.Key.Group, groupDto.Group) + ).Value, + _uidDisplayHandler); + + if (pair.IsVisible) + visibleUsers.Add(drawPair); + else if (pair.IsOnline) + onlineUsers.Add(drawPair); + else + offlineUsers.Add(drawPair); } - if (onlineUsers.Any()) + if (visibleUsers.Count > 0) { - ImGui.Text("Online"); + ImGui.TextUnformatted("Visible"); ImGui.Separator(); - foreach (var entry in onlineUsers) - { - using (ImRaii.PushId(groupDto.GID + entry.UID)) entry.DrawPairedClient(); - } + _uidDisplayHandler.RenderPairList(visibleUsers); } - if (offlineUsers.Any()) + if (onlineUsers.Count > 0) { - ImGui.Text("Offline/Unknown"); + ImGui.TextUnformatted("Online"); ImGui.Separator(); - foreach (var entry in offlineUsers) - { - using (ImRaii.PushId(groupDto.GID + entry.UID)) entry.DrawPairedClient(); - } + _uidDisplayHandler.RenderPairList(onlineUsers); + } + + if (offlineUsers.Count > 0) + { + ImGui.TextUnformatted("Offline/Unknown"); + ImGui.Separator(); + _uidDisplayHandler.RenderPairList(offlineUsers); } ImGui.Separator(); - ImGui.Unindent(ImGui.GetStyle().ItemSpacing.X / 2); } ImGui.Unindent(20); } diff --git a/MareSynchronos/UI/Components/PairGroupsUi.cs b/MareSynchronos/UI/Components/PairGroupsUi.cs index 690e066..09fa376 100644 --- a/MareSynchronos/UI/Components/PairGroupsUi.cs +++ b/MareSynchronos/UI/Components/PairGroupsUi.cs @@ -15,11 +15,13 @@ public class PairGroupsUi private readonly MareConfigService _mareConfig; private readonly SelectPairForGroupUi _selectGroupForPairUi; private readonly TagHandler _tagHandler; + private readonly UidDisplayHandler _uidDisplayHandler; - public PairGroupsUi(MareConfigService mareConfig, TagHandler tagHandler, ApiController apiController, SelectPairForGroupUi selectGroupForPairUi) + public PairGroupsUi(MareConfigService mareConfig, TagHandler tagHandler, UidDisplayHandler uidDisplayHandler, ApiController apiController, SelectPairForGroupUi selectGroupForPairUi) { _mareConfig = mareConfig; _tagHandler = tagHandler; + _uidDisplayHandler = uidDisplayHandler; _apiController = apiController; _selectGroupForPairUi = selectGroupForPairUi; } @@ -182,10 +184,7 @@ public class PairGroupsUi private void DrawPairs(string tag, IEnumerable availablePairsInThisCategory) { // These are all the OtherUIDs that are tagged with this tag - foreach (var pair in availablePairsInThisCategory) - { - using (ImRaii.PushId($"tag-{tag}-pair-${pair.UID}")) pair.DrawPairedClient(); - } + _uidDisplayHandler.RenderPairList(availablePairsInThisCategory); ImGui.Separator(); } diff --git a/MareSynchronos/UI/Handlers/UidDisplayHandler.cs b/MareSynchronos/UI/Handlers/UidDisplayHandler.cs index 7b57907..a91cec1 100644 --- a/MareSynchronos/UI/Handlers/UidDisplayHandler.cs +++ b/MareSynchronos/UI/Handlers/UidDisplayHandler.cs @@ -6,6 +6,7 @@ using MareSynchronos.Services.ServerConfiguration; using MareSynchronos.MareConfiguration; using ImGuiScene; using MareSynchronos.Services.Mediator; +using MareSynchronos.UI.Components; namespace MareSynchronos.UI.Handlers; @@ -32,6 +33,31 @@ public class UidDisplayHandler _mareConfigService = mareConfigService; } + public void RenderPairList(IEnumerable pairs) + { + var textHeight = ImGui.GetFontSize(); + var style = ImGui.GetStyle(); + var framePadding = style.FramePadding; + var spacing = style.ItemSpacing; + var lineHeight = textHeight + framePadding.Y * 2 + spacing.Y; + var startY = ImGui.GetCursorStartPos().Y; + var cursorY = ImGui.GetCursorPosY(); + var contentHeight = UiSharedService.GetWindowContentRegionHeight(); + + foreach (var entry in pairs) + { + if ((startY + cursorY) < -lineHeight || (startY + cursorY) > contentHeight) + { + cursorY += lineHeight; + ImGui.SetCursorPosY(cursorY); + continue; + } + + using (ImRaii.PushId(entry.ImGuiID)) entry.DrawPairedClient(); + cursorY += lineHeight; + } + } + public void DrawPairText(string id, Pair pair, float textPosX, float originalY, Func editBoxWidth) { ImGui.SameLine(textPosX); diff --git a/MareSynchronos/UI/UISharedService.cs b/MareSynchronos/UI/UISharedService.cs index 475c0de..47bbf32 100644 --- a/MareSynchronos/UI/UISharedService.cs +++ b/MareSynchronos/UI/UISharedService.cs @@ -326,6 +326,11 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase return ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X; } + public static float GetWindowContentRegionHeight() + { + return ImGui.GetWindowContentRegionMax().Y - ImGui.GetWindowContentRegionMin().Y; + } + public static Vector2 GetNormalizedIconTextButtonSize(FontAwesomeIcon icon, string text, float? width = null, bool isInPopup = false) { var iconData = GetIconData(icon);