Add sorting the admin player panel by clicking the headers (#7150)

This commit is contained in:
Javier Guardia Fernández
2022-03-16 22:58:15 +01:00
committed by GitHub
parent d744729b29
commit 995c02169e
6 changed files with 209 additions and 24 deletions

View File

@@ -1,4 +1,6 @@
<Control xmlns="https://spacestation14.io"> <Control xmlns="https://spacestation14.io"
xmlns:pt="clr-namespace:Content.Client.Administration.UI.Tabs.PlayerTab"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls">
<BoxContainer Orientation="Vertical"> <BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal"> <BoxContainer Orientation="Horizontal">
<Label Name="PlayerCount" HorizontalExpand="True" SizeFlagsStretchRatio="0.50" <Label Name="PlayerCount" HorizontalExpand="True" SizeFlagsStretchRatio="0.50"
@@ -10,7 +12,10 @@
</BoxContainer> </BoxContainer>
<Control MinSize="0 5" /> <Control MinSize="0 5" />
<ScrollContainer HorizontalExpand="True" VerticalExpand="True"> <ScrollContainer HorizontalExpand="True" VerticalExpand="True">
<BoxContainer Orientation="Vertical" Name="PlayerList" /> <BoxContainer Orientation="Vertical" Name="PlayerList">
<pt:PlayerTabHeader Name="ListHeader" />
<cc:HSeparator />
</BoxContainer>
</ScrollContainer> </ScrollContainer>
</BoxContainer> </BoxContainer>
</Control> </Control>

View File

@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
using Content.Client.Administration.UI.CustomControls;
using Content.Shared.Administration; using Content.Shared.Administration;
using Robust.Client.AutoGenerated; using Robust.Client.AutoGenerated;
using Robust.Client.Graphics; using Robust.Client.Graphics;
@@ -8,16 +5,22 @@ using Robust.Client.Player;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface.XAML;
using Robust.Shared.GameObjects; using static Content.Client.Administration.UI.Tabs.PlayerTab.PlayerTabHeader;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
namespace Content.Client.Administration.UI.Tabs.PlayerTab namespace Content.Client.Administration.UI.Tabs.PlayerTab
{ {
[GenerateTypedNameReferences] [GenerateTypedNameReferences]
public sealed partial class PlayerTab : Control public sealed partial class PlayerTab : Control
{ {
private const string ArrowUp = "↑";
private const string ArrowDown = "↓";
private readonly Color _altColor = Color.FromHex("#292B38");
private readonly Color _defaultColor = Color.FromHex("#2F2F3B");
private readonly AdminSystem _adminSystem; private readonly AdminSystem _adminSystem;
private readonly List<PlayerTabEntry> _players = new();
private Header _headerClicked = Header.Username;
private bool _ascending = true;
public event Action<BaseButton.ButtonEventArgs>? OnEntryPressed; public event Action<BaseButton.ButtonEventArgs>? OnEntryPressed;
@@ -29,6 +32,9 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab
_adminSystem.PlayerListChanged += RefreshPlayerList; _adminSystem.PlayerListChanged += RefreshPlayerList;
OverlayButtonOn.OnPressed += _adminSystem.AdminOverlayOn; OverlayButtonOn.OnPressed += _adminSystem.AdminOverlayOn;
OverlayButtonOff.OnPressed += _adminSystem.AdminOverlayOff; OverlayButtonOff.OnPressed += _adminSystem.AdminOverlayOff;
ListHeader.BackgroundColorPanel.PanelOverride = new StyleBoxFlat(_altColor);
ListHeader.OnHeaderClicked += HeaderClicked;
} }
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
@@ -42,24 +48,20 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab
private void RefreshPlayerList(IReadOnlyList<PlayerInfo> players) private void RefreshPlayerList(IReadOnlyList<PlayerInfo> players)
{ {
PlayerList.RemoveAllChildren(); foreach (var control in _players)
{
PlayerList.RemoveChild(control);
}
_players.Clear();
var playerManager = IoCManager.Resolve<IPlayerManager>(); var playerManager = IoCManager.Resolve<IPlayerManager>();
PlayerCount.Text = $"Players: {playerManager.PlayerCount}"; PlayerCount.Text = $"Players: {playerManager.PlayerCount}";
var altColor = Color.FromHex("#292B38");
var defaultColor = Color.FromHex("#2F2F3B");
PlayerList.AddChild(new PlayerTabEntry("Username",
"Character",
"Job",
"Antagonist",
new StyleBoxFlat(altColor),
true));
PlayerList.AddChild(new HSeparator());
// Temporary until we can sort by <whatever>
var sortedPlayers = new List<PlayerInfo>(players); var sortedPlayers = new List<PlayerInfo>(players);
sortedPlayers.Sort((x, y) => string.Compare(x.Username, y.Username, StringComparison.Ordinal)); sortedPlayers.Sort(Compare);
UpdateHeaderSymbols();
var useAltColor = false; var useAltColor = false;
foreach (var player in sortedPlayers) foreach (var player in sortedPlayers)
@@ -68,14 +70,58 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab
player.CharacterName, player.CharacterName,
player.StartingJob, player.StartingJob,
player.Antag ? "YES" : "NO", player.Antag ? "YES" : "NO",
new StyleBoxFlat(useAltColor ? altColor : defaultColor), new StyleBoxFlat(useAltColor ? _altColor : _defaultColor),
player.Connected); player.Connected);
entry.PlayerUid = player.EntityUid; entry.PlayerUid = player.EntityUid;
entry.OnPressed += args => OnEntryPressed?.Invoke(args); entry.OnPressed += args => OnEntryPressed?.Invoke(args);
PlayerList.AddChild(entry); PlayerList.AddChild(entry);
_players.Add(entry);
useAltColor ^= true; useAltColor ^= true;
} }
} }
private void UpdateHeaderSymbols()
{
ListHeader.ResetHeaderText();
ListHeader.GetHeader(_headerClicked).Text += $" {(_ascending ? ArrowUp : ArrowDown)}";
}
private int Compare(PlayerInfo x, PlayerInfo y)
{
if (!_ascending)
{
(x, y) = (y, x);
}
return _headerClicked switch
{
Header.Username => Compare(x.Username, y.Username),
Header.Character => Compare(x.CharacterName, y.CharacterName),
Header.Job => Compare(x.StartingJob, y.StartingJob),
Header.Antagonist => x.Antag.CompareTo(y.Antag),
_ => 1
};
}
private int Compare(string x, string y)
{
return string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
}
private void HeaderClicked(Header header)
{
if (_headerClicked == header)
{
_ascending = !_ascending;
}
else
{
_headerClicked = header;
_ascending = true;
}
RefreshPlayerList(_adminSystem.PlayerList);
}
} }
} }

View File

@@ -2,7 +2,6 @@
using Robust.Client.Graphics; using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface.XAML;
using Robust.Shared.GameObjects;
namespace Content.Client.Administration.UI.Tabs.PlayerTab; namespace Content.Client.Administration.UI.Tabs.PlayerTab;

View File

@@ -0,0 +1,36 @@
<ContainerButton xmlns="https://spacestation14.io"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
EnableAllKeybinds="True">
<PanelContainer Name="BackgroundColorPanel" Access="Public"/>
<BoxContainer Orientation="Horizontal"
HorizontalExpand="True"
SeparationOverride="4">
<Label Name="UsernameLabel"
SizeFlagsStretchRatio="3"
HorizontalExpand="True"
ClipText="True"
Text="{Loc player-tab-username}"
MouseFilter="Pass"/>
<cc:VSeparator/>
<Label Name="CharacterLabel"
SizeFlagsStretchRatio="3"
HorizontalExpand="True"
ClipText="True"
Text="{Loc player-tab-character}"
MouseFilter="Pass"/>
<cc:VSeparator/>
<Label Name="JobLabel"
SizeFlagsStretchRatio="3"
HorizontalExpand="True"
ClipText="True"
Text="{Loc player-tab-job}"
MouseFilter="Pass"/>
<cc:VSeparator/>
<Label Name="AntagonistLabel"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True"
Text="{Loc player-tab-antagonist}"
MouseFilter="Pass"/>
</BoxContainer>
</ContainerButton>

View File

@@ -0,0 +1,95 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Input;
namespace Content.Client.Administration.UI.Tabs.PlayerTab;
[GenerateTypedNameReferences]
public sealed partial class PlayerTabHeader : ContainerButton
{
public event Action<Header>? OnHeaderClicked;
public PlayerTabHeader()
{
RobustXamlLoader.Load(this);
UsernameLabel.OnKeyBindDown += UsernameClicked;
CharacterLabel.OnKeyBindDown += CharacterClicked;
JobLabel.OnKeyBindDown += JobClicked;
AntagonistLabel.OnKeyBindDown += AntagonistClicked;
}
public Label GetHeader(Header header)
{
return header switch
{
Header.Username => UsernameLabel,
Header.Character => CharacterLabel,
Header.Job => JobLabel,
Header.Antagonist => AntagonistLabel,
_ => throw new ArgumentOutOfRangeException(nameof(header), header, null)
};
}
public void ResetHeaderText()
{
UsernameLabel.Text = Loc.GetString("player-tab-username");
CharacterLabel.Text = Loc.GetString("player-tab-character");
JobLabel.Text = Loc.GetString("player-tab-job");
AntagonistLabel.Text = Loc.GetString("player-tab-antagonist");
}
private void HeaderClicked(GUIBoundKeyEventArgs args, Header header)
{
if (args.Function != EngineKeyFunctions.UIClick)
{
return;
}
OnHeaderClicked?.Invoke(header);
args.Handle();
}
private void UsernameClicked(GUIBoundKeyEventArgs args)
{
HeaderClicked(args, Header.Username);
}
private void CharacterClicked(GUIBoundKeyEventArgs args)
{
HeaderClicked(args, Header.Character);
}
private void JobClicked(GUIBoundKeyEventArgs args)
{
HeaderClicked(args, Header.Job);
}
private void AntagonistClicked(GUIBoundKeyEventArgs args)
{
HeaderClicked(args, Header.Antagonist);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
UsernameLabel.OnKeyBindDown += UsernameClicked;
CharacterLabel.OnKeyBindDown += CharacterClicked;
JobLabel.OnKeyBindDown += JobClicked;
AntagonistLabel.OnKeyBindDown += AntagonistClicked;
}
}
public enum Header
{
Username,
Character,
Job,
Antagonist
}
}

View File

@@ -0,0 +1,4 @@
player-tab-username = Username
player-tab-character = Character
player-tab-job = Job
player-tab-antagonist = Antagonist