PDA UI refactor and cartridges (#11335)
* Work on cartridges * Work on PDA UI * Work on PDA UIs program list * Work on PDA UI borders * Add DeviceNetworkingComponent to the pda base prototype * Fix submodule version * Fix cartridge loader ui key * Fix pda menu xaml * Implement relaying ui messages * Finish implementing the notekeeper cartridge * Fix submodule version * Fix errors from merging master * Fix test failing * Implement setting preinstalled programs * Add some documentation to CartridgeLoaderSystem * Add more doc comments * Add localization to program names * Implement review suggestions * Fix background programs receiving events twice when active
This commit is contained in:
19
Content.Client/PDA/PDABorderColorComponent.cs
Normal file
19
Content.Client/PDA/PDABorderColorComponent.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace Content.Client.PDA;
|
||||
|
||||
/// <summary>
|
||||
/// Used for specifying the pda windows border colors
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed class PDABorderColorComponent : Component
|
||||
{
|
||||
[DataField("borderColor", required: true)]
|
||||
public string? BorderColor;
|
||||
|
||||
|
||||
[DataField("accentHColor")]
|
||||
public string? AccentHColor;
|
||||
|
||||
|
||||
[DataField("accentVColor")]
|
||||
public string? AccentVColor;
|
||||
}
|
||||
@@ -1,17 +1,20 @@
|
||||
using Content.Client.Message;
|
||||
using Content.Client.CartridgeLoader;
|
||||
using Content.Shared.CartridgeLoader;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.CrewManifest;
|
||||
using Content.Shared.PDA;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Client.PDA
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class PDABoundUserInterface : BoundUserInterface
|
||||
public sealed class PDABoundUserInterface : CartridgeLoaderBoundUserInterface
|
||||
{
|
||||
[Dependency] private readonly IEntityManager? _entityManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
||||
|
||||
private PDAMenu? _menu;
|
||||
@@ -67,54 +70,52 @@ namespace Content.Client.PDA
|
||||
SendMessage(new PDAShowRingtoneMessage());
|
||||
};
|
||||
|
||||
_menu.OnProgramItemPressed += ActivateCartridge;
|
||||
_menu.OnInstallButtonPressed += InstallCartridge;
|
||||
_menu.OnUninstallButtonPressed += UninstallCartridge;
|
||||
_menu.ProgramCloseButton.OnPressed += _ => DeactivateActiveCartridge();
|
||||
|
||||
var borderColorComponent = GetBorderColorComponent();
|
||||
if (borderColorComponent == null)
|
||||
return;
|
||||
|
||||
_menu.BorderColor = borderColorComponent.BorderColor;
|
||||
_menu.AccentHColor = borderColorComponent.AccentHColor;
|
||||
_menu.AccentVColor = borderColorComponent.AccentVColor;
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
|
||||
if (_menu == null)
|
||||
{
|
||||
if (state is not PDAUpdateState updateState)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case PDAUpdateState msg:
|
||||
{
|
||||
_menu.FlashLightToggleButton.Pressed = msg.FlashlightEnabled;
|
||||
|
||||
if (msg.PDAOwnerInfo.ActualOwnerName != null)
|
||||
{
|
||||
_menu.PdaOwnerLabel.SetMarkup(Loc.GetString("comp-pda-ui-owner",
|
||||
("ActualOwnerName", msg.PDAOwnerInfo.ActualOwnerName)));
|
||||
}
|
||||
|
||||
|
||||
if (msg.PDAOwnerInfo.IdOwner != null || msg.PDAOwnerInfo.JobTitle != null)
|
||||
{
|
||||
_menu.IdInfoLabel.SetMarkup(Loc.GetString("comp-pda-ui",
|
||||
("Owner",msg.PDAOwnerInfo.IdOwner ?? Loc.GetString("comp-pda-ui-unknown")),
|
||||
("JobTitle",msg.PDAOwnerInfo.JobTitle ?? Loc.GetString("comp-pda-ui-unassigned"))));
|
||||
}
|
||||
else
|
||||
{
|
||||
_menu.IdInfoLabel.SetMarkup(Loc.GetString("comp-pda-ui-blank"));
|
||||
}
|
||||
|
||||
_menu.StationNameLabel.SetMarkup(Loc.GetString("comp-pda-ui-station", ("Station",msg.StationName ?? Loc.GetString("comp-pda-ui-unknown"))));
|
||||
|
||||
_menu.EjectIdButton.Visible = msg.PDAOwnerInfo.IdOwner != null || msg.PDAOwnerInfo.JobTitle != null;
|
||||
_menu.EjectPenButton.Visible = msg.HasPen;
|
||||
_menu.ActivateUplinkButton.Visible = msg.HasUplink;
|
||||
_menu.ActivateMusicButton.Visible = msg.CanPlayMusic;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
_menu?.UpdateState(updateState);
|
||||
}
|
||||
|
||||
|
||||
protected override void AttachCartridgeUI(Control cartridgeUIFragment, string? title)
|
||||
{
|
||||
_menu?.ProgramView.AddChild(cartridgeUIFragment);
|
||||
_menu?.ToProgramView(title ?? Loc.GetString("comp-pda-io-program-fallback-title"));
|
||||
}
|
||||
|
||||
protected override void DetachCartridgeUI(Control cartridgeUIFragment)
|
||||
{
|
||||
if (_menu is null)
|
||||
return;
|
||||
|
||||
_menu.ToHomeScreen();
|
||||
_menu.HideProgramHeader();
|
||||
_menu.ProgramView.RemoveChild(cartridgeUIFragment);
|
||||
}
|
||||
|
||||
protected override void UpdateAvailablePrograms(List<(EntityUid, CartridgeComponent)> programs)
|
||||
{
|
||||
_menu?.UpdateAvailablePrograms(programs);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
@@ -123,5 +124,10 @@ namespace Content.Client.PDA
|
||||
|
||||
_menu?.Dispose();
|
||||
}
|
||||
|
||||
private PDABorderColorComponent? GetBorderColorComponent()
|
||||
{
|
||||
return _entityManager?.GetComponentOrNull<PDABorderColorComponent>(Owner.Owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,32 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
Title="{Loc 'comp-pda-ui-menu-title'}"
|
||||
MinSize="576 256"
|
||||
SetSize="576 256">
|
||||
<TabContainer Name="MasterTabContainer">
|
||||
<pda:PDAWindow xmlns="https://spacestation14.io"
|
||||
xmlns:pda="clr-namespace:Content.Client.PDA"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="576 450"
|
||||
SetSize="576 450">
|
||||
<!-- This: (Margin="1 1 3 0") is necessary so the navigation bar doesn't sticks into the black content border. -->
|
||||
<BoxContainer Name="NavigationBar" HorizontalExpand="True" MinHeight="32" Margin="1 1 3 0">
|
||||
<pda:PDANavigationButton Name="HomeButton" SetWidth="32" CurrentTabBorderThickness="0 0 2 0" IsCurrent="True"/>
|
||||
<pda:PDANavigationButton Name="ProgramListButton" Access="Public" MinWidth="100" LabelText="{Loc 'comp-pda-io-program-list-button'}"/>
|
||||
<pda:PDANavigationButton Name="SettingsButton" MinWidth="100" LabelText="{Loc 'comp-pda-io-settings-button'}"/>
|
||||
|
||||
<pda:PDANavigationButton Name="ProgramTitle" Access="Public" BorderThickness="0 0 0 2" CurrentTabBorderThickness="2 0 0 2"
|
||||
ActiveBgColor="#202023" Visible="False"/>
|
||||
|
||||
<pda:PDANavigationButton HorizontalExpand="True"/>
|
||||
|
||||
<pda:PDANavigationButton Name="ProgramCloseButton" Access="Public" IconScale="0.5 0.5" BorderThickness="0 0 2 2"
|
||||
Visible="False" IsActive="False" SetWidth="32"/>
|
||||
|
||||
<pda:PDANavigationButton Name="FlashLightToggleButton" Access="Public" ToggleMode="True" ActiveFgColor="#EAEFBB" SetWidth="32"/>
|
||||
<pda:PDANavigationButton Name="EjectPenButton" Access="Public" SetWidth="32"/>
|
||||
<pda:PDANavigationButton Name="EjectIdButton" Access="Public" SetWidth="32"/>
|
||||
</BoxContainer>
|
||||
<BoxContainer Name="ViewContainer" HorizontalExpand="True" VerticalExpand="True" Access="Public">
|
||||
<BoxContainer Orientation="Vertical"
|
||||
VerticalExpand="True"
|
||||
HorizontalExpand="True"
|
||||
MinSize="50 50">
|
||||
MinSize="50 50"
|
||||
Margin="8">
|
||||
<RichTextLabel Name="PdaOwnerLabel" Access="Public" />
|
||||
<RichTextLabel Name="IdInfoLabel"
|
||||
Access="Public"
|
||||
@@ -16,37 +36,53 @@
|
||||
<RichTextLabel Name="StationNameLabel"
|
||||
Access="Public"
|
||||
HorizontalExpand="True" />
|
||||
<Button Name="EjectIdButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'comp-pda-ui-eject-id-button'}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
<Button Name="EjectPenButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'comp-pda-ui-eject-pen-button'}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
<Button Name="AccessRingtoneButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'comp-pda-ui-ringtone-button'}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
<Button Name="FlashLightToggleButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'comp-pda-ui-toggle-flashlight-button'}"
|
||||
ToggleMode="True" />
|
||||
<Button Name="CrewManifestButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'crew-manifest-button-label'}"
|
||||
Visible="False" />
|
||||
<Button Name="ActivateUplinkButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'pda-bound-user-interface-uplink-tab-title'}" />
|
||||
<Button Name="ActivateMusicButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'pda-bound-user-interface-music-button'}" />
|
||||
</BoxContainer>
|
||||
</TabContainer>
|
||||
</DefaultWindow>
|
||||
<ScrollContainer HorizontalExpand="True" VerticalExpand="True" HScrollEnabled="True">
|
||||
<BoxContainer Orientation="Vertical"
|
||||
VerticalExpand="True"
|
||||
HorizontalExpand="True"
|
||||
MinSize="50 50"
|
||||
Name="ProgramList"
|
||||
Margin="4"/>
|
||||
</ScrollContainer>
|
||||
<ScrollContainer HorizontalExpand="True" VerticalExpand="True" HScrollEnabled="True">
|
||||
<BoxContainer Orientation="Vertical"
|
||||
VerticalExpand="True"
|
||||
HorizontalExpand="True"
|
||||
MinSize="50 50"
|
||||
Name="Settings">
|
||||
<pda:PDASettingsButton Name="AccessRingtoneButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'comp-pda-ui-ringtone-button'}"
|
||||
Description="{Loc 'comp-pda-ui-ringtone-button-description'}"/>
|
||||
<pda:PDASettingsButton Name="CrewManifestButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'crew-manifest-button-label'}"
|
||||
Description="{Loc 'crew-manifest-button-description'}"
|
||||
Visible="False" />
|
||||
<pda:PDASettingsButton Name="ActivateUplinkButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'pda-bound-user-interface-uplink-tab-title'}"
|
||||
Description="{Loc 'pda-bound-user-interface-uplink-tab-description'}"/>
|
||||
<pda:PDASettingsButton Name="ActivateMusicButton"
|
||||
Access="Public"
|
||||
Text="{Loc 'pda-bound-user-interface-music-button'}"
|
||||
Description="{Loc 'pda-bound-user-interface-music-button-description'}"/>
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
<BoxContainer Orientation="Vertical"
|
||||
VerticalExpand="True"
|
||||
HorizontalExpand="True"
|
||||
Name="ProgramView"
|
||||
Access="Public">
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
<BoxContainer Name="ContentFooter" HorizontalExpand="True" SetHeight="28" Margin="1 0 2 1">
|
||||
<controls:StripeBack HasBottomEdge="False" HasMargins="False" HorizontalExpand="True">
|
||||
<Label Text="Robust#OS ™" VerticalAlignment="Center" Margin="6 0" StyleClasses="PDAContentFooterText"/>
|
||||
<Label Name="AddressLabel" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="6 0" StyleClasses="PDAContentFooterText"/>
|
||||
</controls:StripeBack>
|
||||
</BoxContainer>
|
||||
</pda:PDAWindow>
|
||||
|
||||
@@ -1,18 +1,252 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Content.Client.Message;
|
||||
using Content.Shared.CartridgeLoader;
|
||||
using Content.Shared.PDA;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.PDA
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class PDAMenu : DefaultWindow
|
||||
public sealed partial class PDAMenu : PDAWindow
|
||||
{
|
||||
public const int HomeView = 0;
|
||||
public const int ProgramListView = 1;
|
||||
public const int SettingsView = 2;
|
||||
public const int ProgramContentView = 3;
|
||||
|
||||
private int _currentView = 0;
|
||||
|
||||
public event Action<EntityUid>? OnProgramItemPressed;
|
||||
public event Action<EntityUid>? OnUninstallButtonPressed;
|
||||
public event Action<EntityUid>? OnInstallButtonPressed;
|
||||
public PDAMenu()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
MasterTabContainer.SetTabTitle(0, Loc.GetString("pda-bound-user-interface-main-menu-tab-title"));
|
||||
ViewContainer.OnChildAdded += control => control.Visible = false;
|
||||
|
||||
HomeButton.IconTexture = new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/home.png"));
|
||||
FlashLightToggleButton.IconTexture = new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/light.png"));
|
||||
EjectPenButton.IconTexture = new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/pencil.png"));
|
||||
EjectIdButton.IconTexture = new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/eject.png"));
|
||||
ProgramCloseButton.IconTexture = new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/Nano/cross.svg.png"));
|
||||
|
||||
|
||||
HomeButton.OnPressed += _ => ToHomeScreen();
|
||||
|
||||
ProgramListButton.OnPressed += _ =>
|
||||
{
|
||||
HomeButton.IsCurrent = false;
|
||||
ProgramListButton.IsCurrent = true;
|
||||
SettingsButton.IsCurrent = false;
|
||||
ProgramTitle.IsCurrent = false;
|
||||
|
||||
ChangeView(ProgramListView);
|
||||
};
|
||||
|
||||
|
||||
SettingsButton.OnPressed += _ =>
|
||||
{
|
||||
HomeButton.IsCurrent = false;
|
||||
ProgramListButton.IsCurrent = false;
|
||||
SettingsButton.IsCurrent = true;
|
||||
ProgramTitle.IsCurrent = false;
|
||||
|
||||
ChangeView(SettingsView);
|
||||
};
|
||||
|
||||
ProgramTitle.OnPressed += _ =>
|
||||
{
|
||||
HomeButton.IsCurrent = false;
|
||||
ProgramListButton.IsCurrent = false;
|
||||
SettingsButton.IsCurrent = false;
|
||||
ProgramTitle.IsCurrent = true;
|
||||
|
||||
ChangeView(ProgramContentView);
|
||||
};
|
||||
|
||||
ProgramCloseButton.OnPressed += _ =>
|
||||
{
|
||||
HideProgramHeader();
|
||||
ToHomeScreen();
|
||||
};
|
||||
|
||||
|
||||
HideAllViews();
|
||||
ToHomeScreen();
|
||||
}
|
||||
|
||||
public void UpdateState(PDAUpdateState state)
|
||||
{
|
||||
FlashLightToggleButton.IsActive = state.FlashlightEnabled;
|
||||
|
||||
if (state.PDAOwnerInfo.ActualOwnerName != null)
|
||||
{
|
||||
PdaOwnerLabel.SetMarkup(Loc.GetString("comp-pda-ui-owner",
|
||||
("ActualOwnerName", state.PDAOwnerInfo.ActualOwnerName)));
|
||||
}
|
||||
|
||||
|
||||
if (state.PDAOwnerInfo.IdOwner != null || state.PDAOwnerInfo.JobTitle != null)
|
||||
{
|
||||
IdInfoLabel.SetMarkup(Loc.GetString("comp-pda-ui",
|
||||
("Owner",state.PDAOwnerInfo.IdOwner ?? Loc.GetString("comp-pda-ui-unknown")),
|
||||
("JobTitle",state.PDAOwnerInfo.JobTitle ?? Loc.GetString("comp-pda-ui-unassigned"))));
|
||||
}
|
||||
else
|
||||
{
|
||||
IdInfoLabel.SetMarkup(Loc.GetString("comp-pda-ui-blank"));
|
||||
}
|
||||
|
||||
StationNameLabel.SetMarkup(Loc.GetString("comp-pda-ui-station", ("Station",state.StationName ?? Loc.GetString("comp-pda-ui-unknown"))));
|
||||
AddressLabel.Text = state.Address?.ToUpper() ?? " - ";
|
||||
|
||||
EjectIdButton.IsActive = state.PDAOwnerInfo.IdOwner != null || state.PDAOwnerInfo.JobTitle != null;
|
||||
EjectPenButton.IsActive = state.HasPen;
|
||||
ActivateUplinkButton.Visible = state.HasUplink;
|
||||
ActivateMusicButton.Visible = state.CanPlayMusic;
|
||||
}
|
||||
|
||||
public void UpdateAvailablePrograms(List<(EntityUid, CartridgeComponent)> programs)
|
||||
{
|
||||
ProgramList.RemoveAllChildren();
|
||||
|
||||
if (programs.Count == 0)
|
||||
{
|
||||
ProgramList.AddChild(new Label()
|
||||
{
|
||||
Text = Loc.GetString("comp-pda-io-no-programs-available"),
|
||||
HorizontalAlignment = HAlignment.Center,
|
||||
VerticalAlignment = VAlignment.Center,
|
||||
VerticalExpand = true
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var row = CreateProgramListRow();
|
||||
var itemCount = 1;
|
||||
ProgramList.AddChild(row);
|
||||
|
||||
foreach (var (uid, component) in programs)
|
||||
{
|
||||
//Create a new row every second program item starting from the first
|
||||
if (itemCount % 2 != 0)
|
||||
{
|
||||
row = CreateProgramListRow();
|
||||
ProgramList.AddChild(row);
|
||||
}
|
||||
|
||||
var item = new PDAProgramItem();
|
||||
|
||||
if (component.Icon is not null)
|
||||
item.Icon.SetFromSpriteSpecifier(component.Icon);
|
||||
|
||||
item.OnPressed += _ => OnProgramItemPressed?.Invoke(uid);
|
||||
|
||||
switch (component.InstallationStatus)
|
||||
{
|
||||
case InstallationStatus.Cartridge:
|
||||
item.InstallButton.Visible = true;
|
||||
item.InstallButton.Text = Loc.GetString("cartridge-bound-user-interface-install-button");
|
||||
item.InstallButton.OnPressed += _ => OnInstallButtonPressed?.Invoke(uid);
|
||||
break;
|
||||
case InstallationStatus.Installed:
|
||||
item.InstallButton.Visible = true;
|
||||
item.InstallButton.Text = Loc.GetString("cartridge-bound-user-interface-uninstall-button");
|
||||
item.InstallButton.OnPressed += _ => OnUninstallButtonPressed?.Invoke(uid);
|
||||
break;
|
||||
}
|
||||
|
||||
item.ProgramName.Text = Loc.GetString(component.ProgramName);
|
||||
item.SetHeight = 20;
|
||||
row.AddChild(item);
|
||||
|
||||
itemCount++;
|
||||
}
|
||||
|
||||
//Add a filler item to the last row when it only contains one item
|
||||
if (itemCount % 2 == 0)
|
||||
row.AddChild(new Control() { HorizontalExpand = true });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the current view to the home screen (view 0) and sets the tabs `IsCurrent` flag accordingly
|
||||
/// </summary>
|
||||
public void ToHomeScreen()
|
||||
{
|
||||
HomeButton.IsCurrent = true;
|
||||
ProgramListButton.IsCurrent = false;
|
||||
SettingsButton.IsCurrent = false;
|
||||
ProgramTitle.IsCurrent = false;
|
||||
|
||||
ChangeView(HomeView);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hides the program title and close button.
|
||||
/// </summary>
|
||||
public void HideProgramHeader()
|
||||
{
|
||||
ProgramTitle.IsCurrent = false;
|
||||
ProgramTitle.Visible = false;
|
||||
ProgramCloseButton.Visible = false;
|
||||
ProgramListButton.Visible = true;
|
||||
SettingsButton.Visible = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the current view to the program content view (view 3), sets the program title and sets the tabs `IsCurrent` flag accordingly
|
||||
/// </summary>
|
||||
public void ToProgramView(string title)
|
||||
{
|
||||
HomeButton.IsCurrent = false;
|
||||
ProgramListButton.IsCurrent = false;
|
||||
SettingsButton.IsCurrent = false;
|
||||
ProgramTitle.IsCurrent = false;
|
||||
ProgramTitle.IsCurrent = true;
|
||||
ProgramTitle.Visible = true;
|
||||
ProgramCloseButton.Visible = true;
|
||||
ProgramListButton.Visible = false;
|
||||
SettingsButton.Visible = false;
|
||||
|
||||
ProgramTitle.LabelText = title;
|
||||
ChangeView(ProgramContentView);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Changes the current view to the given view number
|
||||
/// </summary>
|
||||
public void ChangeView(int view)
|
||||
{
|
||||
if (ViewContainer.ChildCount <= view)
|
||||
return;
|
||||
|
||||
ViewContainer.GetChild(_currentView).Visible = false;
|
||||
ViewContainer.GetChild(view).Visible = true;
|
||||
_currentView = view;
|
||||
}
|
||||
|
||||
private BoxContainer CreateProgramListRow()
|
||||
{
|
||||
return new BoxContainer()
|
||||
{
|
||||
Orientation = BoxContainer.LayoutOrientation.Horizontal,
|
||||
HorizontalExpand = true
|
||||
};
|
||||
}
|
||||
|
||||
private void HideAllViews()
|
||||
{
|
||||
var views = ViewContainer.Children;
|
||||
foreach (var view in views)
|
||||
{
|
||||
view.Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
Content.Client/PDA/PDANavigationButton.xaml
Normal file
5
Content.Client/PDA/PDANavigationButton.xaml
Normal file
@@ -0,0 +1,5 @@
|
||||
<pda:PDANavigationButton xmlns="https://spacestation14.io" xmlns:pda="clr-namespace:Content.Client.PDA">
|
||||
<PanelContainer Name="Background"/>
|
||||
<AnimatedTextureRect Margin="0 0 0 2" Visible="False" Name="Icon" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<Label Visible="True" Name="Label" Margin="8 0 8 2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</pda:PDANavigationButton>
|
||||
108
Content.Client/PDA/PDANavigationButton.xaml.cs
Normal file
108
Content.Client/PDA/PDANavigationButton.xaml.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.PDA;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class PDANavigationButton : ContainerButton
|
||||
{
|
||||
|
||||
private bool _isCurrent;
|
||||
private bool _isActive = true;
|
||||
|
||||
private Thickness _borderThickness = new(0, 0, 0, 2);
|
||||
private Thickness _currentTabBorderThickness = new(2, 0, 2, 0);
|
||||
|
||||
private readonly StyleBoxFlat _styleBox = new()
|
||||
{
|
||||
BackgroundColor = Color.FromHex("#202023"),
|
||||
BorderColor = Color.FromHex("#5a5a5a"),
|
||||
BorderThickness = new Thickness(0, 0, 0, 2)
|
||||
};
|
||||
|
||||
public string InactiveBgColor { get; set; } = "#202023";
|
||||
public string ActiveBgColor { get; set; } = "#25252a";
|
||||
public string InactiveFgColor { get; set; } = "#5a5a5a";
|
||||
public string ActiveFgColor { get; set; } = "#FFFFFF";
|
||||
|
||||
public SpriteSpecifier? IconTexture
|
||||
{
|
||||
set
|
||||
{
|
||||
Icon.Visible = value != null;
|
||||
Label.Visible = value == null;
|
||||
|
||||
if (value is not null)
|
||||
Icon.SetFromSpriteSpecifier(value);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 IconScale
|
||||
{
|
||||
get => Icon.DisplayRect.TextureScale;
|
||||
set => Icon.DisplayRect.TextureScale = value;
|
||||
}
|
||||
|
||||
public string? LabelText
|
||||
{
|
||||
get => Label.Text;
|
||||
set => Label.Text = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the border thickness when the tab is not the currently active one
|
||||
/// </summary>
|
||||
public Thickness BorderThickness
|
||||
{
|
||||
get => _borderThickness;
|
||||
set
|
||||
{
|
||||
_borderThickness = value;
|
||||
_styleBox.BorderThickness = _isCurrent ? _currentTabBorderThickness : value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the border thickness when this tab is the currently active tab
|
||||
/// </summary>
|
||||
public Thickness CurrentTabBorderThickness
|
||||
{
|
||||
get => _currentTabBorderThickness;
|
||||
set
|
||||
{
|
||||
_currentTabBorderThickness = value;
|
||||
_styleBox.BorderThickness = _isCurrent ? value : _borderThickness;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsCurrent
|
||||
{
|
||||
get => _isCurrent;
|
||||
set
|
||||
{
|
||||
_isCurrent = value;
|
||||
_styleBox.BackgroundColor = Color.FromHex(value ? ActiveBgColor : InactiveBgColor);
|
||||
_styleBox.BorderThickness = value ? CurrentTabBorderThickness : BorderThickness;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get => _isActive;
|
||||
set
|
||||
{
|
||||
_isActive = value;
|
||||
Icon.Modulate = Color.FromHex(value ? ActiveFgColor : InactiveFgColor);
|
||||
Label.FontColorOverride = Color.FromHex(value ? ActiveFgColor : InactiveFgColor);
|
||||
}
|
||||
}
|
||||
|
||||
public PDANavigationButton()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
Background.PanelOverride = _styleBox;
|
||||
}
|
||||
}
|
||||
17
Content.Client/PDA/PDAProgramItem.xaml
Normal file
17
Content.Client/PDA/PDAProgramItem.xaml
Normal file
@@ -0,0 +1,17 @@
|
||||
<pda:PDAProgramItem HorizontalExpand="True" MinHeight="60" Margin="4"
|
||||
xmlns:pda="clr-namespace:Content.Client.PDA"
|
||||
xmlns="https://spacestation14.io">
|
||||
<PanelContainer Name="Panel"/>
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" VerticalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True" MinWidth="60">
|
||||
<AnimatedTextureRect HorizontalAlignment="Center" VerticalAlignment="Center" VerticalExpand="True" Name="Icon" Access="Public"/>
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
|
||||
<Label Name="ProgramName" Access="Public" VerticalExpand="True"/>
|
||||
<BoxContainer HorizontalExpand="True" SetHeight="28" Margin="0 0 4 4">
|
||||
<BoxContainer HorizontalExpand="True"/>
|
||||
<Button Name="InstallButton" Access="Public" Visible="False" SetWidth="90" HorizontalAlignment="Right" VerticalExpand="True"></Button>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</pda:PDAProgramItem>
|
||||
42
Content.Client/PDA/PDAProgramItem.xaml.cs
Normal file
42
Content.Client/PDA/PDAProgramItem.xaml.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Input;
|
||||
|
||||
namespace Content.Client.PDA;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class PDAProgramItem : ContainerButton
|
||||
{
|
||||
public const string StylePropertyBgColor = "backgroundColor";
|
||||
public const string NormalBgColor = "#313138";
|
||||
public const string HoverColor = "#3E6C45";
|
||||
|
||||
private readonly StyleBoxFlat _styleBox = new()
|
||||
{
|
||||
BackgroundColor = Color.FromHex("#25252a"),
|
||||
};
|
||||
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get => _styleBox.BackgroundColor;
|
||||
set => _styleBox.BackgroundColor = value;
|
||||
}
|
||||
|
||||
public PDAProgramItem()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
Panel.PanelOverride = _styleBox;
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleScreen handle)
|
||||
{
|
||||
base.Draw(handle);
|
||||
|
||||
if (TryGetStyleProperty<Color>(StylePropertyBgColor, out var bgColor))
|
||||
BackgroundColor = bgColor;
|
||||
|
||||
}
|
||||
}
|
||||
11
Content.Client/PDA/PDASettingsButton.xaml
Normal file
11
Content.Client/PDA/PDASettingsButton.xaml
Normal file
@@ -0,0 +1,11 @@
|
||||
<pda:PDASettingsButton xmlns="https://spacestation14.io"
|
||||
xmlns:pda="clr-namespace:Content.Client.PDA"
|
||||
HorizontalExpand="True"
|
||||
MinHeight="48"
|
||||
Margin="5 4 6 0">
|
||||
<PanelContainer Name="Panel"/>
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True" Margin="8 4 0 4">
|
||||
<Label Name="OptionName"/>
|
||||
<Label Name="OptionDescription"/>
|
||||
</BoxContainer>
|
||||
</pda:PDASettingsButton>
|
||||
69
Content.Client/PDA/PDASettingsButton.xaml.cs
Normal file
69
Content.Client/PDA/PDASettingsButton.xaml.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.PDA;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class PDASettingsButton : ContainerButton
|
||||
{
|
||||
public const string StylePropertyFgColor = "foregroundColor";
|
||||
public const string StylePropertyBgColor = "backgroundColor";
|
||||
public const string NormalBgColor = "#313138";
|
||||
public const string HoverColor = "#3E6C45";
|
||||
public const string PressedColor = "#3E6C45";
|
||||
public const string DisabledFgColor = "#5a5a5a";
|
||||
public const string EnabledFgColor = "#FFFFFF";
|
||||
|
||||
private readonly StyleBoxFlat _styleBox = new()
|
||||
{
|
||||
BackgroundColor = Color.FromHex("#25252a")
|
||||
};
|
||||
|
||||
public string? Text
|
||||
{
|
||||
get => OptionName.Text;
|
||||
set => OptionName.Text = value;
|
||||
}
|
||||
public string? Description
|
||||
{
|
||||
get => OptionDescription.Text;
|
||||
set => OptionDescription.Text = value;
|
||||
}
|
||||
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get => _styleBox.BackgroundColor;
|
||||
set => _styleBox.BackgroundColor = value;
|
||||
}
|
||||
|
||||
public Color? ForegroundColor
|
||||
{
|
||||
get => OptionName.FontColorOverride;
|
||||
|
||||
set
|
||||
{
|
||||
OptionName.FontColorOverride = value;
|
||||
OptionDescription.FontColorOverride = value;
|
||||
}
|
||||
}
|
||||
|
||||
public PDASettingsButton()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
Panel.PanelOverride = _styleBox;
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleScreen handle)
|
||||
{
|
||||
base.Draw(handle);
|
||||
|
||||
if (TryGetStyleProperty<Color>(StylePropertyBgColor, out var bgColor))
|
||||
BackgroundColor = bgColor;
|
||||
|
||||
if (TryGetStyleProperty<Color>(StylePropertyFgColor, out var fgColor))
|
||||
ForegroundColor = fgColor;
|
||||
|
||||
}
|
||||
}
|
||||
31
Content.Client/PDA/PDAWindow.xaml
Normal file
31
Content.Client/PDA/PDAWindow.xaml
Normal file
@@ -0,0 +1,31 @@
|
||||
<pda:PDAWindow xmlns="https://spacestation14.io"
|
||||
xmlns:pda="clr-namespace:Content.Client.PDA"
|
||||
MouseFilter="Stop">
|
||||
<PanelContainer Name="Background" Access="Public" StyleClasses="PDABackgroundRect" />
|
||||
<!-- The negative markin fixes a gap between the window edges and the decorative panel -->
|
||||
<PanelContainer Name="AccentH" Margin="-1 170 -2 170" Access="Public" StyleClasses="PDABackground" />
|
||||
<PanelContainer Name="AccentV" Margin="220 -1 220 -1" Access="Public" StyleClasses="PDABackground" />
|
||||
<PanelContainer Name="Border" StyleClasses="PDABorderRect" />
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
|
||||
<!--Heading-->
|
||||
<BoxContainer SetHeight="26" Margin="4 2 8 0" Orientation="Horizontal">
|
||||
<Control HorizontalExpand="True"/>
|
||||
<TextureButton Name="CloseButton" StyleClasses="windowCloseButton"
|
||||
VerticalAlignment="Center" Margin="0 4 4 0"/>
|
||||
</BoxContainer>
|
||||
<!--Content-->
|
||||
<Control Margin="18 0" RectClipContent="True" VerticalExpand="true"
|
||||
HorizontalExpand="True">
|
||||
<PanelContainer Name="ContentBorder" StyleClasses="PDABackground"/>
|
||||
<Control Margin="3 3">
|
||||
<PanelContainer Name="ContentBackground" StyleClasses="PDAContentBackground"/>
|
||||
<BoxContainer Access="Public" Name="ContentsContainer" Orientation="Vertical" StyleClasses="PDAContent"/>
|
||||
|
||||
</Control>
|
||||
</Control>
|
||||
<!--Footer-->
|
||||
<BoxContainer Orientation="Horizontal" SetHeight="28">
|
||||
<Label Text="Personal Digital Assistant" StyleClasses="PDAWindowFooterText" Margin="32 0 0 6"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</pda:PDAWindow>
|
||||
56
Content.Client/PDA/PDAWindow.xaml.cs
Normal file
56
Content.Client/PDA/PDAWindow.xaml.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.PDA;
|
||||
|
||||
[Virtual]
|
||||
[GenerateTypedNameReferences]
|
||||
public partial class PDAWindow : BaseWindow
|
||||
{
|
||||
|
||||
public string? BorderColor
|
||||
{
|
||||
get => Background.ActualModulateSelf.ToHex();
|
||||
|
||||
set => Background.ModulateSelfOverride = Color.FromHex(value, Color.White);
|
||||
}
|
||||
|
||||
public string? AccentHColor
|
||||
{
|
||||
get => AccentH.ActualModulateSelf.ToHex();
|
||||
|
||||
set
|
||||
{
|
||||
AccentH.ModulateSelfOverride = Color. FromHex(value, Color.White);
|
||||
AccentH.Visible = value != null;
|
||||
}
|
||||
}
|
||||
|
||||
public string? AccentVColor
|
||||
{
|
||||
get => AccentV.ActualModulateSelf.ToHex();
|
||||
|
||||
set
|
||||
{
|
||||
AccentV.ModulateSelfOverride = Color. FromHex(value, Color.White);
|
||||
AccentV.Visible = value != null;
|
||||
}
|
||||
}
|
||||
|
||||
public PDAWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
CloseButton.OnPressed += _ => Close();
|
||||
XamlChildren = ContentsContainer.Children;
|
||||
|
||||
AccentH.Visible = false;
|
||||
AccentV.Visible = false;
|
||||
}
|
||||
|
||||
protected override DragMode GetDragModeFor(Vector2 relativeMousePos)
|
||||
{
|
||||
return DragMode.Move;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user