Re-organize all projects (#4166)

This commit is contained in:
DrSmugleaf
2021-06-09 22:19:39 +02:00
committed by GitHub
parent 9f50e4061b
commit ff1a2d97ea
1773 changed files with 5258 additions and 5508 deletions

View File

@@ -0,0 +1,89 @@
using Content.Shared.Chemistry.Dispenser;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Localization;
using static Content.Shared.Chemistry.Components.SharedChemMasterComponent;
namespace Content.Client.Chemistry.UI
{
/// <summary>
/// Initializes a <see cref="ChemMasterWindow"/> and updates it when new server messages are received.
/// </summary>
[UsedImplicitly]
public class ChemMasterBoundUserInterface : BoundUserInterface
{
private ChemMasterWindow? _window;
public ChemMasterBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
{
}
/// <summary>
/// Called each time a chem master UI instance is opened. Generates the window and fills it with
/// relevant info. Sets the actions for static buttons.
/// </summary>
protected override void Open()
{
base.Open();
//Setup window layout/elements
_window = new ChemMasterWindow
{
Title = Loc.GetString("ChemMaster 4000"),
};
_window.OpenCentered();
_window.OnClose += Close;
//Setup static button actions.
_window.EjectButton.OnPressed += _ => PrepareData(UiAction.Eject, null, null, null);
_window.BufferTransferButton.OnPressed += _ => PrepareData(UiAction.Transfer, null, null, null);
_window.BufferDiscardButton.OnPressed += _ => PrepareData(UiAction.Discard, null, null, null);
_window.CreatePills.OnPressed += _ => PrepareData(UiAction.CreatePills, null, _window.PillAmount.Value, null);
_window.CreateBottles.OnPressed += _ => PrepareData(UiAction.CreateBottles, null, null, _window.BottleAmount.Value);
_window.OnChemButtonPressed += (args, button) => PrepareData(UiAction.ChemButton, button, null, null);
}
/// <summary>
/// Update the ui each time new state data is sent from the server.
/// </summary>
/// <param name="state">
/// Data of the <see cref="SharedReagentDispenserComponent"/> that this ui represents.
/// Sent from the server.
/// </param>
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
var castState = (ChemMasterBoundUserInterfaceState)state;
_window?.UpdateState(castState); //Update window state
}
private void PrepareData(UiAction action, ChemButton? button, int? pillAmount, int? bottleAmount)
{
if (button != null)
{
SendMessage(new UiActionMessage(action, button.Amount, button.Id, button.isBuffer, null, null));
}
else
{
SendMessage(new UiActionMessage(action, null, null, null, pillAmount, bottleAmount));
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_window?.Dispose();
}
}
}
}

View File

@@ -0,0 +1,439 @@
using System;
using System.Linq;
using Content.Client.Stylesheets;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using static Content.Shared.Chemistry.Components.SharedChemMasterComponent;
using static Robust.Client.UserInterface.Controls.BaseButton;
namespace Content.Client.Chemistry.UI
{
/// <summary>
/// Client-side UI used to control a <see cref="SharedChemMasterComponent"/>
/// </summary>
public class ChemMasterWindow : SS14Window
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
/// <summary>Contains info about the reagent container such as it's contents, if one is loaded into the dispenser.</summary>
private readonly VBoxContainer ContainerInfo;
private readonly VBoxContainer BufferInfo;
private readonly VBoxContainer PackagingInfo;
/// <summary>Ejects the reagent container from the dispenser.</summary>
public Button EjectButton { get; }
public Button BufferTransferButton { get; }
public Button BufferDiscardButton { get; }
public bool BufferModeTransfer = true;
public event Action<ButtonEventArgs, ChemButton>? OnChemButtonPressed;
public HBoxContainer PillInfo { get; set; }
public HBoxContainer BottleInfo { get; set; }
public SpinBox PillAmount { get; set; }
public SpinBox BottleAmount { get; set; }
public Button CreatePills { get; }
public Button CreateBottles { get; }
/// <summary>
/// Create and initialize the chem master UI client-side. Creates the basic layout,
/// actual data isn't filled in until the server sends data about the chem master.
/// </summary>
public ChemMasterWindow()
{
MinSize = SetSize = (400, 525);
IoCManager.InjectDependencies(this);
Contents.AddChild(new VBoxContainer
{
Children =
{
//Container
new HBoxContainer
{
Children =
{
new Label {Text = Loc.GetString("Container")},
new Control {HorizontalExpand = true},
(EjectButton = new Button {Text = Loc.GetString("Eject")})
}
},
//Wrap the container info in a PanelContainer so we can color it's background differently.
new PanelContainer
{
VerticalExpand = true,
SizeFlagsStretchRatio = 6,
MinSize = (0, 200),
PanelOverride = new StyleBoxFlat
{
BackgroundColor = new Color(27, 27, 30)
},
Children =
{
//Currently empty, when server sends state data this will have container contents and fill volume.
(ContainerInfo = new VBoxContainer
{
HorizontalExpand = true,
Children =
{
new Label
{
Text = Loc.GetString("No container loaded.")
}
}
}),
}
},
//Padding
new Control {MinSize = (0.0f, 10.0f)},
//Buffer
new HBoxContainer
{
Children =
{
new Label {Text = Loc.GetString("Buffer")},
new Control {HorizontalExpand = true},
(BufferTransferButton = new Button {Text = Loc.GetString("Transfer"), Pressed = BufferModeTransfer, StyleClasses = { StyleBase.ButtonOpenRight }}),
(BufferDiscardButton = new Button {Text = Loc.GetString("Discard"), Pressed = !BufferModeTransfer, StyleClasses = { StyleBase.ButtonOpenLeft }})
}
},
//Wrap the buffer info in a PanelContainer so we can color it's background differently.
new PanelContainer
{
VerticalExpand = true,
SizeFlagsStretchRatio = 6,
MinSize = (0, 100),
PanelOverride = new StyleBoxFlat
{
BackgroundColor = new Color(27, 27, 30)
},
Children =
{
//Buffer reagent list
(BufferInfo = new VBoxContainer
{
HorizontalExpand = true,
Children =
{
new Label
{
Text = Loc.GetString("Buffer empty.")
}
}
}),
}
},
//Padding
new Control {MinSize = (0.0f, 10.0f)},
//Packaging
new HBoxContainer
{
Children =
{
new Label {Text = Loc.GetString("Packaging ")},
}
},
//Wrap the packaging info in a PanelContainer so we can color it's background differently.
new PanelContainer
{
VerticalExpand = true,
SizeFlagsStretchRatio = 6,
MinSize = (0, 100),
PanelOverride = new StyleBoxFlat
{
BackgroundColor = new Color(27, 27, 30)
},
Children =
{
//Packaging options
(PackagingInfo = new VBoxContainer
{
HorizontalExpand = true,
}),
}
},
}
});
//Pills
PillInfo = new HBoxContainer
{
Children =
{
new Label
{
Text = Loc.GetString("Pills:")
},
},
};
PackagingInfo.AddChild(PillInfo);
var pillPadding = new Control {HorizontalExpand = true};
PillInfo.AddChild(pillPadding);
PillAmount = new SpinBox
{
HorizontalExpand = true,
Value = 1
};
PillAmount.InitDefaultButtons();
PillAmount.IsValid = (n) => (n > 0 && n <= 10);
PillInfo.AddChild(PillAmount);
var pillVolume = new Label
{
Text = " max 50u/each ",
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
};
PillInfo.AddChild((pillVolume));
CreatePills = new Button {Text = Loc.GetString("Create")};
PillInfo.AddChild(CreatePills);
//Bottles
BottleInfo = new HBoxContainer
{
Children =
{
new Label
{
Text = Loc.GetString("Bottles:")
},
},
};
PackagingInfo.AddChild(BottleInfo);
var bottlePadding = new Control {HorizontalExpand = true};
BottleInfo.AddChild(bottlePadding);
BottleAmount = new SpinBox
{
HorizontalExpand = true,
Value = 1
};
BottleAmount.InitDefaultButtons();
BottleAmount.IsValid = (n) => (n > 0 && n <= 10);
BottleInfo.AddChild(BottleAmount);
var bottleVolume = new Label
{
Text = " max 30u/each ",
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
};
BottleInfo.AddChild((bottleVolume));
CreateBottles = new Button {Text = Loc.GetString("Create")};
BottleInfo.AddChild(CreateBottles);
}
private ChemButton MakeChemButton(string text, ReagentUnit amount, string id, bool isBuffer, string styleClass)
{
var button = new ChemButton(text, amount, id, isBuffer, styleClass);
button.OnPressed += args
=> OnChemButtonPressed?.Invoke(args, button);
return button;
}
/// <summary>
/// Update the UI state when new state data is received from the server.
/// </summary>
/// <param name="state">State data sent by the server.</param>
public void UpdateState(BoundUserInterfaceState state)
{
var castState = (ChemMasterBoundUserInterfaceState) state;
Title = castState.DispenserName;
UpdatePanelInfo(castState);
if (Contents.Children != null)
{
SetButtonDisabledRecursive(Contents, !castState.HasPower);
EjectButton.Disabled = !castState.HasBeaker;
}
}
/// <summary>
/// This searches recursively through all the children of "parent"
/// and sets the Disabled value of any buttons found to "val"
/// </summary>
/// <param name="parent">The control which childrens get searched</param>
/// <param name="val">The value to which disabled gets set</param>
private void SetButtonDisabledRecursive(Control parent, bool val)
{
foreach (var child in parent.Children)
{
if (child is Button but)
{
but.Disabled = val;
continue;
}
if (child.Children != null)
{
SetButtonDisabledRecursive(child, val);
}
}
}
/// <summary>
/// Update the container, buffer, and packaging panels.
/// </summary>
/// <param name="state">State data for the dispenser.</param>
private void UpdatePanelInfo(ChemMasterBoundUserInterfaceState state)
{
BufferModeTransfer = state.BufferModeTransfer;
BufferTransferButton.Pressed = BufferModeTransfer;
BufferDiscardButton.Pressed = !BufferModeTransfer;
ContainerInfo.Children.Clear();
if (!state.HasBeaker)
{
ContainerInfo.Children.Add(new Label {Text = Loc.GetString("No container loaded.")});
return;
}
ContainerInfo.Children.Add(new HBoxContainer // Name of the container and its fill status (Ex: 44/100u)
{
Children =
{
new Label {Text = $"{state.ContainerName}: "},
new Label
{
Text = $"{state.BeakerCurrentVolume}/{state.BeakerMaxVolume}",
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
}
}
});
foreach (var reagent in state.ContainerReagents)
{
var name = Loc.GetString("Unknown reagent");
//Try to the prototype for the given reagent. This gives us it's name.
if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype? proto))
{
name = proto.Name;
}
if (proto != null)
{
ContainerInfo.Children.Add(new HBoxContainer
{
Children =
{
new Label {Text = $"{name}: "},
new Label
{
Text = $"{reagent.Quantity}u",
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
},
//Padding
new Control {HorizontalExpand = true},
MakeChemButton("1", ReagentUnit.New(1), reagent.ReagentId, false, StyleBase.ButtonOpenRight),
MakeChemButton("5", ReagentUnit.New(5), reagent.ReagentId, false, StyleBase.ButtonOpenBoth),
MakeChemButton("10", ReagentUnit.New(10), reagent.ReagentId, false, StyleBase.ButtonOpenBoth),
MakeChemButton("25", ReagentUnit.New(25), reagent.ReagentId, false, StyleBase.ButtonOpenBoth),
MakeChemButton("All", ReagentUnit.New(-1), reagent.ReagentId, false, StyleBase.ButtonOpenLeft),
}
});
}
}
BufferInfo.Children.Clear();
if (!state.BufferReagents.Any())
{
BufferInfo.Children.Add(new Label {Text = Loc.GetString("Buffer empty.")});
return;
}
var bufferHBox = new HBoxContainer();
BufferInfo.AddChild(bufferHBox);
var bufferLabel = new Label {Text = "buffer: "};
bufferHBox.AddChild(bufferLabel);
var bufferVol = new Label
{
Text = $"{state.BufferCurrentVolume}",
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
};
bufferHBox.AddChild(bufferVol);
foreach (var reagent in state.BufferReagents)
{
var name = Loc.GetString("Unknown reagent");
//Try to the prototype for the given reagent. This gives us it's name.
if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype? proto))
{
name = proto.Name;
}
if (proto != null)
{
BufferInfo.Children.Add(new HBoxContainer
{
//SizeFlagsHorizontal = SizeFlags.ShrinkEnd,
Children =
{
new Label {Text = $"{name}: "},
new Label
{
Text = $"{reagent.Quantity}u",
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
},
//Padding
new Control {HorizontalExpand = true},
MakeChemButton("1", ReagentUnit.New(1), reagent.ReagentId, true, StyleBase.ButtonOpenRight),
MakeChemButton("5", ReagentUnit.New(5), reagent.ReagentId, true, StyleBase.ButtonOpenBoth),
MakeChemButton("10", ReagentUnit.New(10), reagent.ReagentId, true, StyleBase.ButtonOpenBoth),
MakeChemButton("25", ReagentUnit.New(25), reagent.ReagentId, true, StyleBase.ButtonOpenBoth),
MakeChemButton("All", ReagentUnit.New(-1), reagent.ReagentId, true, StyleBase.ButtonOpenLeft),
}
});
}
}
}
}
public class ChemButton : Button
{
public ReagentUnit Amount { get; set; }
public bool isBuffer = true;
public string Id { get; set; }
public ChemButton(string _text, ReagentUnit _amount, string _id, bool _isBuffer, string _styleClass)
{
AddStyleClass(_styleClass);
Text = _text;
Amount = _amount;
Id = _id;
isBuffer = _isBuffer;
}
}
}

View File

@@ -0,0 +1,126 @@
using System.Collections.Generic;
using System.Linq;
using Content.Shared.Chemistry.Dispenser;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects;
using Robust.Shared.Localization;
using static Content.Shared.Chemistry.Dispenser.SharedReagentDispenserComponent;
namespace Content.Client.Chemistry.UI
{
/// <summary>
/// Initializes a <see cref="ReagentDispenserWindow"/> and updates it when new server messages are received.
/// </summary>
[UsedImplicitly]
public class ReagentDispenserBoundUserInterface : BoundUserInterface
{
private ReagentDispenserWindow? _window;
private ReagentDispenserBoundUserInterfaceState? _lastState;
public ReagentDispenserBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
{
}
/// <summary>
/// Called each time a dispenser UI instance is opened. Generates the dispenser window and fills it with
/// relevant info. Sets the actions for static buttons.
/// <para>Buttons which can change like reagent dispense buttons have their actions set in <see cref="UpdateReagentsList"/>.</para>
/// </summary>
protected override void Open()
{
base.Open();
//Setup window layout/elements
_window = new ReagentDispenserWindow
{
Title = Loc.GetString("Reagent dispenser"),
};
_window.OpenCentered();
_window.OnClose += Close;
//Setup static button actions.
_window.EjectButton.OnPressed += _ => ButtonPressed(UiButton.Eject);
_window.ClearButton.OnPressed += _ => ButtonPressed(UiButton.Clear);
_window.DispenseButton1.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount1);
_window.DispenseButton5.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount5);
_window.DispenseButton10.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount10);
_window.DispenseButton15.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount15);
_window.DispenseButton20.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount20);
_window.DispenseButton25.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount25);
_window.DispenseButton30.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount30);
_window.DispenseButton50.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount50);
_window.DispenseButton100.OnPressed += _ => ButtonPressed(UiButton.SetDispenseAmount100);
}
/// <summary>
/// Update the ui each time new state data is sent from the server.
/// </summary>
/// <param name="state">
/// Data of the <see cref="SharedReagentDispenserComponent"/> that this ui represents.
/// Sent from the server.
/// </param>
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
var castState = (ReagentDispenserBoundUserInterfaceState)state;
_lastState = castState;
UpdateReagentsList(castState.Inventory); //Update reagents list & reagent button actions
_window?.UpdateState(castState); //Update window state
}
/// <summary>
/// Update the list of reagents that this dispenser can dispense on the UI.
/// </summary>
/// <param name="inventory">A list of the reagents which can be dispensed.</param>
private void UpdateReagentsList(List<ReagentDispenserInventoryEntry> inventory)
{
if (_window == null)
{
return;
}
_window.UpdateReagentsList(inventory);
for (var i = 0; i < _window.ChemicalList.Children.Count(); i++)
{
var button = (Button)_window.ChemicalList.Children.ElementAt(i);
var i1 = i;
button.OnPressed += _ => ButtonPressed(UiButton.Dispense, i1);
button.OnMouseEntered += _ =>
{
if (_lastState != null)
{
_window.UpdateContainerInfo(_lastState, inventory[i1].ID);
}
};
button.OnMouseExited += _ =>
{
if (_lastState != null)
{
_window.UpdateContainerInfo(_lastState);
}
};
}
}
private void ButtonPressed(UiButton button, int dispenseIndex = -1)
{
SendMessage(new UiButtonPressedMessage(button, dispenseIndex));
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_window?.Dispose();
}
}
}
}

View File

@@ -0,0 +1,331 @@
using System.Collections.Generic;
using Content.Client.Stylesheets;
using Content.Shared.Chemistry.Dispenser;
using Content.Shared.Chemistry.Reagent;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using static Content.Shared.Chemistry.Dispenser.SharedReagentDispenserComponent;
namespace Content.Client.Chemistry.UI
{
/// <summary>
/// Client-side UI used to control a <see cref="SharedReagentDispenserComponent"/>
/// </summary>
public class ReagentDispenserWindow : SS14Window
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
/// <summary>Contains info about the reagent container such as it's contents, if one is loaded into the dispenser.</summary>
private readonly VBoxContainer ContainerInfo;
/// <summary>Sets the dispense amount to 1 when pressed.</summary>
public Button DispenseButton1 { get; }
/// <summary>Sets the dispense amount to 5 when pressed.</summary>
public Button DispenseButton5 { get; }
/// <summary>Sets the dispense amount to 10 when pressed.</summary>
public Button DispenseButton10 { get; }
/// <summary>Sets the dispense amount to 15 when pressed.</summary>
public Button DispenseButton15 { get; }
/// <summary>Sets the dispense amount to 20 when pressed.</summary>
public Button DispenseButton20 { get; }
/// <summary>Sets the dispense amount to 25 when pressed.</summary>
public Button DispenseButton25 { get; }
/// <summary>Sets the dispense amount to 30 when pressed.</summary>
public Button DispenseButton30 { get; }
/// <summary>Sets the dispense amount to 50 when pressed.</summary>
public Button DispenseButton50 { get; }
/// <summary>Sets the dispense amount to 100 when pressed.</summary>
public Button DispenseButton100 { get; }
/// <summary>Ejects the reagent container from the dispenser.</summary>
public Button ClearButton { get; }
/// <summary>Removes all reagents from the reagent container.</summary>
public Button EjectButton { get; }
/// <summary>A grid of buttons for each reagent which can be dispensed.</summary>
public GridContainer ChemicalList { get; }
/// <summary>
/// Create and initialize the dispenser UI client-side. Creates the basic layout,
/// actual data isn't filled in until the server sends data about the dispenser.
/// </summary>
public ReagentDispenserWindow()
{
SetSize = MinSize = (590, 400);
IoCManager.InjectDependencies(this);
var dispenseAmountGroup = new ButtonGroup();
Contents.AddChild(new VBoxContainer
{
Children =
{
//First, our dispense amount buttons
new HBoxContainer
{
Children =
{
new Label {Text = Loc.GetString("Amount")},
//Padding
new Control {MinSize = (20, 0)},
(DispenseButton1 = new Button {Text = "1", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenRight }}),
(DispenseButton5 = new Button {Text = "5", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton10 = new Button {Text = "10", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton15 = new Button {Text = "15", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton20 = new Button {Text = "20", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton25 = new Button {Text = "25", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton30 = new Button {Text = "30", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton50 = new Button {Text = "50", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenBoth }}),
(DispenseButton100 = new Button {Text = "100", Group = dispenseAmountGroup, StyleClasses = { StyleBase.ButtonOpenLeft }}),
}
},
//Padding
new Control {MinSize = (0.0f, 10.0f)},
//Grid of which reagents can be dispensed.
(ChemicalList = new GridContainer
{
Columns = 5
}),
//Padding
new Control {MinSize = (0.0f, 10.0f)},
new HBoxContainer
{
Children =
{
new Label {Text = Loc.GetString("Container: ")},
(ClearButton = new Button {Text = Loc.GetString("Clear"), StyleClasses = {StyleBase.ButtonOpenRight}}),
(EjectButton = new Button {Text = Loc.GetString("Eject"), StyleClasses = {StyleBase.ButtonOpenLeft}})
}
},
//Wrap the container info in a PanelContainer so we can color it's background differently.
new PanelContainer
{
VerticalExpand = true,
SizeFlagsStretchRatio = 6,
MinSize = (0, 150),
PanelOverride = new StyleBoxFlat
{
BackgroundColor = new Color(27, 27, 30)
},
Children =
{
//Currently empty, when server sends state data this will have container contents and fill volume.
(ContainerInfo = new VBoxContainer
{
HorizontalExpand = true,
Children =
{
new Label
{
Text = Loc.GetString("No container loaded.")
}
}
}),
}
},
}
});
}
/// <summary>
/// Update the button grid of reagents which can be dispensed.
/// <para>The actions for these buttons are set in <see cref="ReagentDispenserBoundUserInterface.UpdateReagentsList"/>.</para>
/// </summary>
/// <param name="inventory">Reagents which can be dispensed by this dispenser</param>
public void UpdateReagentsList(List<ReagentDispenserInventoryEntry> inventory)
{
if (ChemicalList == null) return;
if (inventory == null) return;
ChemicalList.Children.Clear();
foreach (var entry in inventory)
{
if (_prototypeManager.TryIndex(entry.ID, out ReagentPrototype? proto))
{
ChemicalList.AddChild(new Button {Text = proto.Name});
}
else
{
ChemicalList.AddChild(new Button {Text = Loc.GetString("Reagent name not found")});
}
}
}
/// <summary>
/// This searches recursively through all the children of "parent"
/// and sets the Disabled value of any buttons found to "val"
/// </summary>
/// <param name="parent">The control which childrens get searched</param>
/// <param name="val">The value to which disabled gets set</param>
private void SetButtonDisabledRecursive(Control parent, bool val)
{
foreach (var child in parent.Children)
{
if (child is Button but)
{
but.Disabled = val;
continue;
}
if (child.Children != null)
{
SetButtonDisabledRecursive(child, val);
}
}
}
/// <summary>
/// Update the UI state when new state data is received from the server.
/// </summary>
/// <param name="state">State data sent by the server.</param>
public void UpdateState(BoundUserInterfaceState state)
{
var castState = (ReagentDispenserBoundUserInterfaceState) state;
Title = castState.DispenserName;
UpdateContainerInfo(castState);
// Disable all buttons if not powered
if (Contents.Children != null)
{
SetButtonDisabledRecursive(Contents, !castState.HasPower);
EjectButton.Disabled = false;
}
// Disable the Clear & Eject button if no beaker
if (!castState.HasBeaker)
{
ClearButton.Disabled = true;
EjectButton.Disabled = true;
}
switch (castState.SelectedDispenseAmount.Int())
{
case 1:
DispenseButton1.Pressed = true;
break;
case 5:
DispenseButton5.Pressed = true;
break;
case 10:
DispenseButton10.Pressed = true;
break;
case 15:
DispenseButton15.Pressed = true;
break;
case 20:
DispenseButton20.Pressed = true;
break;
case 25:
DispenseButton25.Pressed = true;
break;
case 30:
DispenseButton30.Pressed = true;
break;
case 50:
DispenseButton50.Pressed = true;
break;
case 100:
DispenseButton100.Pressed = true;
break;
}
}
/// <summary>
/// Update the fill state and list of reagents held by the current reagent container, if applicable.
/// <para>Also highlights a reagent if it's dispense button is being mouse hovered.</para>
/// </summary>
/// <param name="state">State data for the dispenser.</param>
/// <param name="highlightedReagentId">Prototype id of the reagent whose dispense button is currently being mouse hovered.</param>
public void UpdateContainerInfo(ReagentDispenserBoundUserInterfaceState state, string highlightedReagentId = "")
{
ContainerInfo.Children.Clear();
if (!state.HasBeaker)
{
ContainerInfo.Children.Add(new Label {Text = Loc.GetString("No container loaded.")});
return;
}
ContainerInfo.Children.Add(new HBoxContainer // Name of the container and its fill status (Ex: 44/100u)
{
Children =
{
new Label {Text = $"{state.ContainerName}: "},
new Label
{
Text = $"{state.BeakerCurrentVolume}/{state.BeakerMaxVolume}",
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
}
}
});
if (state.ContainerReagents == null)
{
return;
}
foreach (var reagent in state.ContainerReagents)
{
var name = Loc.GetString("Unknown reagent");
//Try to the prototype for the given reagent. This gives us it's name.
if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype? proto))
{
name = proto.Name;
}
//Check if the reagent is being moused over. If so, color it green.
if (proto != null && proto.ID == highlightedReagentId)
{
ContainerInfo.Children.Add(new HBoxContainer
{
Children =
{
new Label
{
Text = $"{name}: ",
StyleClasses = {StyleNano.StyleClassPowerStateGood}
},
new Label
{
Text = $"{reagent.Quantity}u",
StyleClasses = {StyleNano.StyleClassPowerStateGood}
}
}
});
}
else //Otherwise, color it the normal colors.
{
ContainerInfo.Children.Add(new HBoxContainer
{
Children =
{
new Label {Text = $"{name}: "},
new Label
{
Text = $"{reagent.Quantity}u",
StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
}
}
});
}
}
}
}
}