--- /dev/null
+<BoxContainer xmlns="https://spacestation14.io"
+ Orientation="Vertical"
+ Margin="8 0 8 0">
+ <BoxContainer Name="Buttons"
+ Orientation="Vertical"
+ SeparationOverride="5">
+ <!-- Buttons are added here by code -->
+ </BoxContainer>
+</BoxContainer>
namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles
{
[GenerateTypedNameReferences]
- public sealed partial class GhostRolesEntry : BoxContainer
+ public sealed partial class GhostRoleButtonsBox : BoxContainer
{
private SpriteSystem _spriteSystem;
public event Action<GhostRoleInfo>? OnRoleSelected;
public event Action<GhostRoleInfo>? OnRoleFollow;
- public GhostRolesEntry(string name, string description, bool hasAccess, FormattedMessage? reason, IEnumerable<GhostRoleInfo> roles, SpriteSystem spriteSystem)
+ public GhostRoleButtonsBox(bool hasAccess, FormattedMessage? reason, IEnumerable<GhostRoleInfo> roles, SpriteSystem spriteSystem)
{
RobustXamlLoader.Load(this);
_spriteSystem = spriteSystem;
- Title.Text = name;
- Description.SetMessage(description);
-
foreach (var role in roles)
{
var button = new GhostRoleEntryButtons(role);
<BoxContainer xmlns="https://spacestation14.io"
- Orientation="Horizontal">
+ Orientation="Horizontal"
+ HorizontalAlignment="Stretch">
<Button Name="RequestButton"
Access="Public"
Text="{Loc 'ghost-roles-window-request-role-button'}"
StyleClasses="OpenRight"
- HorizontalAlignment="Left"
- SetWidth="300"/>
+ HorizontalExpand="True"
+ SizeFlagsStretchRatio="3"/>
<Button Name="FollowButton"
Access="Public"
Text="{Loc 'ghost-roles-window-follow-role-button'}"
StyleClasses="OpenLeft"
- HorizontalAlignment="Right"
- SetWidth="150"/>
+ HorizontalExpand="True"/>
</BoxContainer>
--- /dev/null
+<BoxContainer xmlns="https://spacestation14.io"
+ Orientation="Vertical">
+ <Label Name="Title"
+ StyleClasses="LabelKeyText"/>
+ <PanelContainer StyleClasses="HighDivider" />
+ <RichTextLabel Name="Description"
+ Margin="0 4"/>
+</BoxContainer>
--- /dev/null
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+
+namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles
+{
+ [GenerateTypedNameReferences]
+ public sealed partial class GhostRoleInfoBox : BoxContainer
+ {
+ public GhostRoleInfoBox(string name, string description)
+ {
+ RobustXamlLoader.Load(this);
+
+ Title.Text = name;
+ Description.SetMessage(description);
+ }
+ }
+}
+++ /dev/null
-<BoxContainer xmlns="https://spacestation14.io"
- Orientation="Vertical"
- HorizontalExpand="True"
- Margin="0 0 8 8">
- <Label Name="Title"
- StyleClasses="LabelKeyText"/>
- <PanelContainer StyleClasses="HighDivider" />
- <RichTextLabel Name="Description"
- Margin="0 4"/>
- <BoxContainer Name="Buttons"
- HorizontalAlignment="Left"
- Orientation="Vertical"
- SeparationOverride="5">
- <!-- Buttons are added here by code -->
- </BoxContainer>
-</BoxContainer>
using Content.Shared.Ghost.Roles;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
-using Robust.Shared.Utility;
namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles
{
if (state is not GhostRolesEuiState ghostState)
return;
+
+ // We must save BodyVisible state, so all Collapsible boxes will not close
+ // on adding new ghost role.
+ // Save the current state of each Collapsible box being visible or not
+ _window.SaveCollapsibleBoxesStates();
+
+ // Clearing the container before adding new roles
_window.ClearEntries();
var entityManager = IoCManager.Resolve<IEntityManager>();
var spriteSystem = sysManager.GetEntitySystem<SpriteSystem>();
var requirementsManager = IoCManager.Resolve<JobRequirementsManager>();
+ // TODO: role.Requirements value doesn't work at all as an equality key, this must be fixed
+ // Grouping roles
var groupedRoles = ghostState.GhostRoles.GroupBy(
role => (role.Name, role.Description, role.Requirements));
+
+ // Add a new entry for each role group
foreach (var group in groupedRoles)
{
var name = group.Key.Name;
var description = group.Key.Description;
- bool hasAccess = true;
- FormattedMessage? reason;
-
- if (!requirementsManager.CheckRoleRequirements(group.Key.Requirements, null, out reason))
- {
- hasAccess = false;
- }
+ var hasAccess = requirementsManager.CheckRoleRequirements(
+ group.Key.Requirements,
+ null,
+ out var reason);
+ // Adding a new role
_window.AddEntry(name, description, hasAccess, reason, group, spriteSystem);
}
+ // Restore the Collapsible box state if it is saved
+ _window.RestoreCollapsibleBoxesStates();
+
+ // Close the rules window if it is no longer needed
var closeRulesWindow = ghostState.GhostRoles.All(role => role.Identifier != _windowRulesId);
if (closeRulesWindow)
- {
_windowRules?.Close();
- }
}
}
}
+using System.Linq;
using Content.Shared.Ghost.Roles;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
+using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
+using Robust.Client.UserInterface.XAML;
using Robust.Shared.Utility;
namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles
public event Action<GhostRoleInfo>? OnRoleRequestButtonClicked;
public event Action<GhostRoleInfo>? OnRoleFollow;
+ private Dictionary<(string name, string description), Collapsible> _collapsibleBoxes = new();
+ private HashSet<(string name, string description)> _uncollapsedStates = new();
+
+ public GhostRolesWindow()
+ {
+ RobustXamlLoader.Load(this);
+ }
+
public void ClearEntries()
{
NoRolesMessage.Visible = true;
EntryContainer.DisposeAllChildren();
+ _collapsibleBoxes.Clear();
+ }
+
+ public void SaveCollapsibleBoxesStates()
+ {
+ _uncollapsedStates.Clear();
+ foreach (var (key, collapsible) in _collapsibleBoxes)
+ {
+ if (collapsible.BodyVisible)
+ {
+ _uncollapsedStates.Add(key);
+ }
+ }
+ }
+
+ public void RestoreCollapsibleBoxesStates()
+ {
+ foreach (var (key, collapsible) in _collapsibleBoxes)
+ {
+ collapsible.BodyVisible = _uncollapsedStates.Contains(key);
+ }
}
public void AddEntry(string name, string description, bool hasAccess, FormattedMessage? reason, IEnumerable<GhostRoleInfo> roles, SpriteSystem spriteSystem)
{
NoRolesMessage.Visible = false;
- var entry = new GhostRolesEntry(name, description, hasAccess, reason, roles, spriteSystem);
- entry.OnRoleSelected += OnRoleRequestButtonClicked;
- entry.OnRoleFollow += OnRoleFollow;
- EntryContainer.AddChild(entry);
+ var ghostRoleInfos = roles.ToList();
+ var rolesCount = ghostRoleInfos.Count;
+
+ var info = new GhostRoleInfoBox(name, description);
+ var buttons = new GhostRoleButtonsBox(hasAccess, reason, ghostRoleInfos, spriteSystem);
+ buttons.OnRoleSelected += OnRoleRequestButtonClicked;
+ buttons.OnRoleFollow += OnRoleFollow;
+
+ EntryContainer.AddChild(info);
+
+ if (rolesCount > 1)
+ {
+ var buttonHeading = new CollapsibleHeading(Loc.GetString("ghost-roles-window-available-button", ("rolesCount", rolesCount)));
+
+ buttonHeading.AddStyleClass(ContainerButton.StyleClassButton);
+ buttonHeading.Label.HorizontalAlignment = HAlignment.Center;
+ buttonHeading.Label.HorizontalExpand = true;
+
+ var body = new CollapsibleBody
+ {
+ Margin = new Thickness(0, 5, 0, 0),
+ };
+
+ // TODO: Add Requirements to this key when it'll be fixed and work as an equality key in GhostRolesEui
+ var key = (name, description);
+
+ var collapsible = new Collapsible(buttonHeading, body)
+ {
+ Orientation = BoxContainer.LayoutOrientation.Vertical,
+ Margin = new Thickness(0, 0, 0, 8),
+ };
+
+ body.AddChild(buttons);
+
+ EntryContainer.AddChild(collapsible);
+ _collapsibleBoxes.Add(key, collapsible);
+ }
+ else
+ {
+ EntryContainer.AddChild(buttons);
+ }
}
}
}
ghost-target-window-warp-to-most-followed = Warp to Most Followed
ghost-roles-window-title = Ghost Roles
+ghost-roles-window-available-button = Available ({$rolesCount})
ghost-roles-window-join-raffle-button = Join raffle
ghost-roles-window-raffle-in-progress-button =
Join raffle ({$time} left, { $players ->