diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs
new file mode 100644
index 0000000000..fffe60c9fd
--- /dev/null
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs
@@ -0,0 +1,73 @@
+using Content.Shared.DeviceNetwork;
+using JetBrains.Annotations;
+using Robust.Client.GameObjects;
+
+namespace Content.Client.NetworkConfigurator;
+
+public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
+{
+ private NetworkConfiguratorListMenu? _listMenu;
+ private NetworkConfiguratorConfigurationMenu? _configurationMenu;
+
+ public NetworkConfiguratorBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
+ {
+ }
+
+ public void OnRemoveButtonPressed(string address)
+ {
+ SendMessage(new NetworkConfiguratorRemoveDeviceMessage(address));
+ }
+
+ protected override void Open()
+ {
+ base.Open();
+
+ switch (UiKey)
+ {
+ case NetworkConfiguratorUiKey.List:
+ _listMenu = new NetworkConfiguratorListMenu(this);
+ _listMenu.OnClose += Close;
+ _listMenu.ClearButton.OnPressed += _ => OnClearButtonPressed();
+ _listMenu.OpenCentered();
+ break;
+ case NetworkConfiguratorUiKey.Configure:
+ _configurationMenu = new NetworkConfiguratorConfigurationMenu();
+ _configurationMenu.OnClose += Close;
+ _configurationMenu.Set.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Set);
+ _configurationMenu.Add.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Add);
+ //_configurationMenu.Edit.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Edit);
+ _configurationMenu.Clear.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Clear);
+ _configurationMenu.Copy.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Copy);
+ _configurationMenu.Show.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Show);
+ _configurationMenu.OpenCentered();
+ break;
+ }
+ }
+
+ protected override void UpdateState(BoundUserInterfaceState state)
+ {
+ base.UpdateState(state);
+
+ var castState = (NetworkConfiguratorUserInterfaceState) state;
+ _listMenu?.UpdateState(castState);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ if (!disposing) return;
+
+ _listMenu?.Dispose();
+ _configurationMenu?.Dispose();
+ }
+
+ private void OnClearButtonPressed()
+ {
+ SendMessage(new NetworkConfiguratorClearDevicesMessage());
+ }
+
+ private void OnConfigButtonPressed(NetworkConfiguratorButtonKey buttonKey)
+ {
+ SendMessage(new NetworkConfiguratorButtonPressedMessage(buttonKey));
+ }
+}
diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml b/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml
new file mode 100644
index 0000000000..0c1affe6a3
--- /dev/null
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs
new file mode 100644
index 0000000000..41acabc6ba
--- /dev/null
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs
@@ -0,0 +1,22 @@
+using Content.Client.Stylesheets;
+using Content.Client.UserInterface;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Client.Graphics;
+
+namespace Content.Client.NetworkConfigurator;
+
+[GenerateTypedNameReferences]
+public sealed partial class NetworkConfiguratorConfigurationMenu : FancyWindow
+{
+
+ public NetworkConfiguratorConfigurationMenu()
+ {
+ RobustXamlLoader.Load(this);
+
+ Clear.StyleClasses.Add(StyleBase.ButtonOpenLeft);
+ Clear.StyleClasses.Add(StyleNano.StyleClassButtonColorRed);
+ }
+}
diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml b/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml
new file mode 100644
index 0000000000..dbbbb35ddb
--- /dev/null
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs
new file mode 100644
index 0000000000..e32db2a519
--- /dev/null
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs
@@ -0,0 +1,67 @@
+using Content.Client.UserInterface;
+using Content.Shared.DeviceNetwork;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+
+namespace Content.Client.NetworkConfigurator;
+
+[GenerateTypedNameReferences]
+public sealed partial class NetworkConfiguratorListMenu : FancyWindow
+{
+ private readonly NetworkConfiguratorBoundUserInterface _ui;
+ public NetworkConfiguratorListMenu(NetworkConfiguratorBoundUserInterface ui)
+ {
+ RobustXamlLoader.Load(this);
+
+ _ui = ui;
+ }
+
+ public void UpdateState(NetworkConfiguratorUserInterfaceState state)
+ {
+ DeviceCountLabel.Text = Loc.GetString("network-configurator-ui-count-label", ("count", state.DeviceList.Count));
+ DeviceList.RemoveAllChildren();
+
+ foreach (var savedDevice in state.DeviceList)
+ {
+ DeviceList.AddChild(BuildDeviceListRow(savedDevice));
+ }
+ }
+
+ private BoxContainer BuildDeviceListRow((string address, string name) savedDevice)
+ {
+ var row = new BoxContainer()
+ {
+ Orientation = BoxContainer.LayoutOrientation.Horizontal,
+ Margin = new Thickness(8)
+ };
+
+ var name = new Label()
+ {
+ Text = savedDevice.name[..Math.Min(11, savedDevice.name.Length)],
+ SetWidth = 84
+ };
+
+ var address = new Label()
+ {
+ Text = savedDevice.address,
+ HorizontalExpand = true,
+ Align = Label.AlignMode.Center
+ };
+
+ var removeButton = new TextureButton()
+ {
+ StyleClasses = { "CrossButtonRed" },
+ VerticalAlignment = VAlignment.Center,
+ Scale = new Vector2(0.5f, 0.5f)
+ };
+
+ removeButton.OnPressed += _ => _ui.OnRemoveButtonPressed(savedDevice.address);
+
+ row.AddChild(name);
+ row.AddChild(address);
+ row.AddChild(removeButton);
+
+ return row;
+ }
+}
diff --git a/Content.Client/Stylesheets/StyleNano.cs b/Content.Client/Stylesheets/StyleNano.cs
index 33aa7ba2bf..c2333d5171 100644
--- a/Content.Client/Stylesheets/StyleNano.cs
+++ b/Content.Client/Stylesheets/StyleNano.cs
@@ -39,6 +39,7 @@ namespace Content.Client.Stylesheets
}
}
+
public sealed class StyleNano : StyleBase
{
public const string StyleClassBorderedWindowPanel = "BorderedWindowPanel";
@@ -93,6 +94,9 @@ namespace Content.Client.Stylesheets
public static readonly Color ButtonColorCautionPressed = Color.FromHex("#3e6c45");
public static readonly Color ButtonColorCautionDisabled = Color.FromHex("#602a2a");
+ public static readonly Color ButtonColorGoodDefault = Color.FromHex("#3E6C45");
+ public static readonly Color ButtonColorGoodHovered = Color.FromHex("#31843E");
+
// Context menu button colors
public static readonly Color ButtonColorContext = Color.FromHex("#1119");
public static readonly Color ButtonColorContextHover = Color.DarkSlateGray;
@@ -112,6 +116,14 @@ namespace Content.Client.Stylesheets
public const string StyleClassItemStatus = "ItemStatus";
+ //Background
+ public const string StyleClassBackgroundBaseDark = "PanelBackgroundBaseDark";
+
+ //Buttons
+ public const string StyleClassCrossButtonRed = "CrossButtonRed";
+ public const string StyleClassButtonColorRed = "ButtonColorRed";
+ public const string StyleClassButtonColorGreen = "ButtonColorGreen";
+
public override Stylesheet Stylesheet { get; }
public StyleNano(IResourceCache resCache) : base(resCache)
@@ -461,7 +473,7 @@ namespace Content.Client.Stylesheets
var directionIconArrowTex = resCache.GetTexture("/Textures/Interface/VerbIcons/drop.svg.192dpi.png");
var directionIconQuestionTex = resCache.GetTexture("/Textures/Interface/VerbIcons/information.svg.192dpi.png");
var directionIconHereTex = resCache.GetTexture("/Textures/Interface/VerbIcons/dot.svg.192dpi.png");
-
+
Stylesheet = new Stylesheet(BaseRules.Concat(new[]
{
// Window title.
@@ -1294,8 +1306,47 @@ namespace Content.Client.Stylesheets
.Prop("panel", new StyleBoxTexture(BaseButtonOpenLeft) { Padding = default })
.Prop(Control.StylePropertyModulateSelf, Color.FromHex("#1F1F23")),
- Element().Class("Inset")
- .Prop("panel", insetBack),
+ Element().Class("WindowHeadingBackgroundLight")
+ .Prop("panel", new StyleBoxTexture(BaseButtonOpenLeft) { Padding = default }),
+
+ //The lengths you have to go through to change a background color smh
+ Element().Class("PanelBackgroundBaseDark")
+ .Prop("panel", new StyleBoxTexture(BaseButtonOpenBoth) { Padding = default })
+ .Prop(Control.StylePropertyModulateSelf, Color.FromHex("#1F1F23")),
+
+ // X Texture button ---
+ Element().Class("CrossButtonRed")
+ .Prop(TextureButton.StylePropertyTexture, resCache.GetTexture("/Textures/Interface/Nano/cross.svg.png"))
+ .Prop(Control.StylePropertyModulateSelf, DangerousRedFore),
+
+ Element().Class("CrossButtonRed").Pseudo(TextureButton.StylePseudoClassHover)
+ .Prop(Control.StylePropertyModulateSelf, Color.FromHex("#7F3636")),
+
+ Element().Class("CrossButtonRed").Pseudo(TextureButton.StylePseudoClassHover)
+ .Prop(Control.StylePropertyModulateSelf, Color.FromHex("#753131")),
+ // ---
+
+ // Red Button ---
+ Element