Add sorting the admin player panel by clicking the headers (#7150)
This commit is contained in:
committed by
GitHub
parent
d744729b29
commit
995c02169e
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
player-tab-username = Username
|
||||||
|
player-tab-character = Character
|
||||||
|
player-tab-job = Job
|
||||||
|
player-tab-antagonist = Antagonist
|
||||||
Reference in New Issue
Block a user