]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Reagent dispenser UI (#27831)
authorBrandon Li <48413902+aspiringLich@users.noreply.github.com>
Fri, 10 May 2024 02:37:03 +0000 (22:37 -0400)
committerGitHub <noreply@github.com>
Fri, 10 May 2024 02:37:03 +0000 (19:37 -0700)
* reagent dispenser: fancy window

* reagent dispenser: dispense button grid

* reagent dispenser: rearrange containers & info

* reagent dispenser: remove `reagent-dispenser-window-container-label`

* reagent dispenser: add `Scrollcontainer` on right side

* reagent dispenser: get rid of pointless actions

* reagent dispenser: cleanup actions and `inventory` field on bound ui state

* reagent dispenser: cool reagent cards & finishing touches

* reagent dispenser: final cleanup and formatting

* reagent dispenser: `ButtonGrid` and `ReagentDispenserSetDispenseAmountMessage` refactor

* reagent dispenser: cleanup code & address minor concerns

* reagent dispenser: text in reagent cards no longer clips

* reagent dispenser: oh wait i forgot to change this and thats why the builds keep failing probably

* reagent dispenser mayybe this

* reagent dispenser: remove `using FastAccessors;`

Content.Client/Chemistry/UI/ButtonGrid.cs [new file with mode: 0644]
Content.Client/Chemistry/UI/ReagentCardControl.xaml [new file with mode: 0644]
Content.Client/Chemistry/UI/ReagentCardControl.xaml.cs [new file with mode: 0644]
Content.Client/Chemistry/UI/ReagentDispenserBoundUserInterface.cs
Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml
Content.Client/Chemistry/UI/ReagentDispenserWindow.xaml.cs
Content.Server/Chemistry/EntitySystems/ReagentDispenserSystem.cs
Content.Shared/Chemistry/SharedReagentDispenser.cs
Resources/Locale/en-US/chemistry/components/reagent-dispenser-component.ftl

diff --git a/Content.Client/Chemistry/UI/ButtonGrid.cs b/Content.Client/Chemistry/UI/ButtonGrid.cs
new file mode 100644 (file)
index 0000000..0abd9ef
--- /dev/null
@@ -0,0 +1,119 @@
+using System;
+using Robust.Client.Graphics;
+using Robust.Client.UserInterface.Controls;
+
+namespace Content.Client.Chemistry.UI;
+
+/// <summary>
+///     Creates a grid of buttons given a comma-seperated list of Text
+/// </summary>
+public sealed class ButtonGrid : GridContainer
+{
+    private string _buttonList = "";
+
+    /// <summary>
+    ///     A comma-seperated list of text to use for each button. These will be inserted sequentially.
+    /// </summary>
+    public string ButtonList
+    {
+        get => _buttonList;
+        set
+        {
+            _buttonList = value;
+            Update();
+        }
+    }
+
+    public bool RadioGroup { get; set; } = false;
+
+    private string? _selected;
+
+    /// <summary>
+    ///     Which button is currently selected. Only matters when <see cref="RadioGroup"/> is true.
+    /// </summary>
+    public string? Selected
+    {
+        get => _selected;
+        set
+        {
+            _selected = value;
+            Update();
+        }
+    }
+
+    public Action<string>? OnButtonPressed;
+
+    /// <summary>
+    ///     <see cref="GridContainer.Columns"/>
+    /// </summary>
+    public new int Columns
+    {
+        get => base.Columns;
+        set
+        {
+            base.Columns = value;
+            Update();
+        }
+    }
+
+    /// <summary>
+    ///     <see cref="GridContainer.Rows"/>
+    /// </summary>
+    public new int Rows
+    {
+        get => base.Rows;
+        set
+        {
+            base.Rows = value;
+            Update();
+        }
+    }
+
+    private void Update()
+    {
+        if (ButtonList == "")
+            return;
+
+        this.Children.Clear();
+        var i = 0;
+        var list = ButtonList.Split(",");
+
+        var group = new ButtonGroup();
+
+        foreach (var button in list)
+        {
+            var btn = new Button();
+            btn.Text = button;
+            btn.OnPressed += _ =>
+            {
+                if (RadioGroup)
+                    btn.Pressed = true;
+                Selected = button;
+                OnButtonPressed?.Invoke(button);
+            };
+            if (button == Selected)
+                btn.Pressed = true;
+            var sep = HSeparationOverride ?? 0;
+            // ReSharper disable once PossibleLossOfFraction
+            // btn.SetWidth = (this.PixelWidth - sep * (Columns - 1)) / 3;
+            btn.Group = group;
+
+            var row = i / Columns;
+            var col = i % Columns;
+            var last = i == list.Length - 1;
+            var lastCol = i == Columns - 1;
+            var lastRow = row == list.Length / Columns - 1;
+
+            if (row == 0 && (lastCol || last))
+                btn.AddStyleClass("OpenLeft");
+            else if (col == 0 && lastRow)
+                btn.AddStyleClass("OpenRight");
+            else
+                btn.AddStyleClass("OpenBoth");
+
+            this.Children.Add(btn);
+
+            i++;
+        }
+    }
+}
diff --git a/Content.Client/Chemistry/UI/ReagentCardControl.xaml b/Content.Client/Chemistry/UI/ReagentCardControl.xaml
new file mode 100644 (file)
index 0000000..966c730
--- /dev/null
@@ -0,0 +1,37 @@
+<Control xmlns="https://spacestation14.io">
+    <BoxContainer Name="MainContainer"
+                  Orientation="Horizontal"
+                  SetWidth="160">
+        <PanelContainer Name="ColorPanel"
+                        VerticalExpand="True"
+                        SetWidth="7"
+                        Margin="0 1 0 0" />
+        <Button Name="MainButton"
+                HorizontalExpand="True"
+                VerticalExpand="True"
+                StyleClasses="ButtonSquare"
+                Margin="-1 0 0 0">
+            <BoxContainer Orientation="Horizontal" HorizontalExpand="True">
+                <BoxContainer Orientation="Vertical"
+                              VerticalExpand="True"
+                              HorizontalExpand="True"
+                              Margin="-5 0 0 0">
+                    <Label Name="ReagentNameLabel"
+                           StyleClasses="LabelSubText" />
+                    <Label Name="FillLabel"
+                           StyleClasses="LabelSubText"
+                           Margin="0 -5 0 0" />
+                </BoxContainer>
+            </BoxContainer>
+        </Button>
+        <Button Name="EjectButton"
+                StyleClasses="OpenLeft"
+                VerticalExpand="True"
+                SetWidth="20">
+            <Label Name="EjectButtonIcon"
+                   VerticalAlignment="Center"
+                   HorizontalAlignment="Center"
+                   Margin="-7 -4 0 0" />
+        </Button>
+    </BoxContainer>
+</Control>
diff --git a/Content.Client/Chemistry/UI/ReagentCardControl.xaml.cs b/Content.Client/Chemistry/UI/ReagentCardControl.xaml.cs
new file mode 100644 (file)
index 0000000..6033614
--- /dev/null
@@ -0,0 +1,30 @@
+using Content.Shared.Chemistry;
+using Robust.Client.AutoGenerated;
+using Robust.Client.Graphics;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.XAML;
+
+namespace Content.Client.Chemistry.UI;
+
+[GenerateTypedNameReferences]
+public sealed partial class ReagentCardControl : Control
+{
+    public string StorageSlotId { get; }
+    public Action<string>? OnPressed;
+    public Action<string>? OnEjectButtonPressed;
+
+    public ReagentCardControl(ReagentInventoryItem item)
+    {
+        RobustXamlLoader.Load(this);
+
+        StorageSlotId = item.StorageSlotId;
+        ColorPanel.PanelOverride = new StyleBoxFlat { BackgroundColor = item.ReagentColor };
+        ReagentNameLabel.Text = item.ReagentLabel;
+        ReagentNameLabel.FontColorOverride = Color.White;
+        FillLabel.Text = item.StoredAmount;
+        EjectButtonIcon.Text = Loc.GetString("reagent-dispenser-window-eject-container-button");
+
+        MainButton.OnPressed += args => OnPressed?.Invoke(StorageSlotId);
+        EjectButton.OnPressed += args => OnEjectButtonPressed?.Invoke(StorageSlotId);
+    }
+}
index 8244e3e6edb31ec0a0f991951fbad7fe73a6fbe5..fce57a6ec5863bf10579534282c71d0888293f1e 100644 (file)
@@ -42,38 +42,11 @@ namespace Content.Client.Chemistry.UI
             // Setup static button actions.
             _window.EjectButton.OnPressed += _ => SendMessage(new ItemSlotButtonPressedEvent(SharedReagentDispenser.OutputSlotName));
             _window.ClearButton.OnPressed += _ => SendMessage(new ReagentDispenserClearContainerSolutionMessage());
-            _window.DispenseButton1.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U1));
-            _window.DispenseButton5.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U5));
-            _window.DispenseButton10.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U10));
-            _window.DispenseButton15.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U15));
-            _window.DispenseButton20.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U20));
-            _window.DispenseButton25.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U25));
-            _window.DispenseButton30.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U30));
-            _window.DispenseButton50.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U50));
-            _window.DispenseButton100.OnPressed += _ => SendMessage(new ReagentDispenserSetDispenseAmountMessage(ReagentDispenserDispenseAmount.U100));
 
-            // Setup reagent button actions.
-            _window.OnDispenseReagentButtonPressed += (args, button) => SendMessage(new ReagentDispenserDispenseReagentMessage(button.ReagentId));
-            _window.OnDispenseReagentButtonMouseEntered += (args, button) =>
-            {
-                if (_lastState is not null)
-                    _window.UpdateContainerInfo(_lastState);
-            };
-            _window.OnDispenseReagentButtonMouseExited += (args, button) =>
-            {
-                if (_lastState is not null)
-                    _window.UpdateContainerInfo(_lastState);
-            };
+            _window.AmountGrid.OnButtonPressed += s => SendMessage(new ReagentDispenserSetDispenseAmountMessage(s));
 
-            _window.OnEjectJugButtonPressed += (args, button) => SendMessage(new ItemSlotButtonPressedEvent(button.ReagentId));
-            _window.OnEjectJugButtonMouseEntered += (args, button) => {
-                if (_lastState is not null)
-                    _window.UpdateContainerInfo(_lastState);
-            };
-            _window.OnEjectJugButtonMouseExited += (args, button) => {
-                if (_lastState is not null)
-                    _window.UpdateContainerInfo(_lastState);
-            };
+            _window.OnDispenseReagentButtonPressed += (id) => SendMessage(new ReagentDispenserDispenseReagentMessage(id));
+            _window.OnEjectJugButtonPressed += (id) => SendMessage(new ItemSlotButtonPressedEvent(id));
         }
 
         /// <summary>
index 3b812ba56b21e0d18b321b77b58c0e0ab7e6a95b..c900d7ecf2d0e118ccb0af0a15066b8afc095838 100644 (file)
@@ -1,53 +1,77 @@
-<DefaultWindow xmlns="https://spacestation14.io"
-            xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
-            Title="{Loc 'reagent-dispenser-bound-user-interface-title'}"
-            MinSize="680 450">
-    <BoxContainer Orientation="Vertical">
-        <BoxContainer Orientation="Horizontal">
-            <Label Text="{Loc 'reagent-dispenser-window-amount-to-dispense-label'}"/>
-            <Control MinSize="20 0"></Control>
-            <Button Name="DispenseButton1" Access="Public" Text="1" StyleClasses="OpenRight"/>
-            <Button Name="DispenseButton5" Access="Public" Text="5" StyleClasses="OpenBoth"/>
-            <Button Name="DispenseButton10" Access="Public" Text="10" StyleClasses="OpenBoth"/>
-            <Button Name="DispenseButton15" Access="Public" Text="15" StyleClasses="OpenBoth"/>
-            <Button Name="DispenseButton20" Access="Public" Text="20" StyleClasses="OpenBoth"/>
-            <Button Name="DispenseButton25" Access="Public" Text="25" StyleClasses="OpenBoth"/>
-            <Button Name="DispenseButton30" Access="Public" Text="30" StyleClasses="OpenBoth"/>
-            <Button Name="DispenseButton50" Access="Public" Text="50" StyleClasses="OpenBoth"/>
-            <Button Name="DispenseButton100" Access="Public" Text="100" StyleClasses="OpenLeft"/>
+<controls:FancyWindow xmlns="https://spacestation14.io"
+                      xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
+                      xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
+                      xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
+                      xmlns:ui="clr-namespace:Content.Client.Chemistry.UI"
+                      Title="{Loc 'reagent-dispenser-bound-user-interface-title'}"
+                      MinSize="680 460">
+    <BoxContainer Orientation="Horizontal">
+        <BoxContainer Orientation="Vertical" MinWidth="170">
+            <Label Text="{Loc 'reagent-dispenser-window-amount-to-dispense-label'}" HorizontalAlignment="Center" />
+            <ui:ButtonGrid
+                Name="AmountGrid"
+                Access="Public"
+                Columns="3"
+                HorizontalAlignment="Center"
+                Margin="5"
+                ButtonList="1,5,10,15,20,25,30,50,100"
+                RadioGroup="True">
+            </ui:ButtonGrid>
+            <Control VerticalExpand="True" />
+            <Label Name="ContainerInfoName"
+                   Access="Public"
+                   Text=""
+                   HorizontalAlignment="Center" />
+            <Label Name="ContainerInfoFill"
+                   Access="Public"
+                   Text=""
+                   HorizontalAlignment="Center"
+                   StyleClasses="LabelSubText" />
+            <SpriteView Name="View"
+                        Scale="4 4"
+                        HorizontalAlignment="Center" />
+            <BoxContainer Orientation="Horizontal" HorizontalAlignment="Center">
+                <Button Name="ClearButton"
+                        Access="Public"
+                        Text="{Loc 'reagent-dispenser-window-clear-button'}"
+                        StyleClasses="OpenRight" />
+                <Button Name="EjectButton"
+                        Access="Public"
+                        Text="{Loc 'reagent-dispenser-window-eject-button'}"
+                        StyleClasses="OpenLeft" />
+            </BoxContainer>
         </BoxContainer>
-        <Control MinSize="0 10"/>
-        <GridContainer Name="ChemicalList" HorizontalExpand="True" VerticalExpand="True" Access="Public" Columns="6">
-        </GridContainer>
-        <Control MinSize="0 10"/>
-        <BoxContainer Orientation="Horizontal">
-            <Label Text="{Loc 'reagent-dispenser-window-container-label'}"/>
-            <Button Name="ClearButton"
-                    Access="Public"
-                    Text="{Loc 'reagent-dispenser-window-clear-button'}"
-                    StyleClasses="OpenRight"/>
-            <Button Name="EjectButton"
-                    Access="Public"
-                    Text="{Loc 'reagent-dispenser-window-eject-button'}"
-                    StyleClasses="OpenLeft"/>
-        </BoxContainer>
-        <Control MinSize="0 10"/>
-        <BoxContainer Orientation="Horizontal">
-            <SpriteView Name="View" Scale="4 4" MinSize="150 150"/>
-            <ScrollContainer HScrollEnabled="False" HorizontalExpand="True" VerticalExpand="True" MinSize="0 160">
-                <PanelContainer VerticalExpand="True"
-                                SizeFlagsStretchRatio="6"
-                                MinSize="0 150">
+        <SplitContainer Orientation="Vertical"
+                        HorizontalExpand="True"
+                        VerticalExpand="True">
+            <ScrollContainer HScrollEnabled="False"
+                             HorizontalExpand="True"
+                             VerticalExpand="True"
+                             MinHeight="50"
+                             SizeFlagsStretchRatio="2.5">
+                <GridContainer Name="ReagentList"
+                               HorizontalExpand="True"
+                               VerticalExpand="True"
+                               Access="Public"
+                               Columns="3" />
+            </ScrollContainer>
+            <ScrollContainer HScrollEnabled="False"
+                             HorizontalExpand="True"
+                             VerticalExpand="True"
+                             MinHeight="50">
+                <PanelContainer VerticalExpand="True">
                     <PanelContainer.PanelOverride>
                         <gfx:StyleBoxFlat BackgroundColor="#1b1b1e" />
                     </PanelContainer.PanelOverride>
                     <BoxContainer Name="ContainerInfo"
-                                Orientation="Vertical"
-                                HorizontalExpand="True">
-                        <Label Text="{Loc 'reagent-dispenser-window-no-container-loaded-text'}"/>
+                                  Orientation="Vertical"
+                                  HorizontalExpand="True"
+                                  VerticalExpand="True"
+                                  Margin="5">
+                        <Label Text="{Loc 'reagent-dispenser-window-no-container-loaded-text'}" />
                     </BoxContainer>
                 </PanelContainer>
             </ScrollContainer>
-        </BoxContainer>
+        </SplitContainer>
     </BoxContainer>
-</DefaultWindow>
+</controls:FancyWindow>
index 7fcf0191f2193495a53ef7638f599bcc02af66e4..305d39cdeb65956642498a1742cadd031ef599bc 100644 (file)
@@ -1,10 +1,9 @@
 using Content.Client.Stylesheets;
+using Content.Client.UserInterface.Controls;
 using Content.Shared.Chemistry;
 using Content.Shared.Chemistry.Reagent;
 using Robust.Client.AutoGenerated;
-using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
-using Robust.Client.UserInterface.CustomControls;
 using Robust.Client.UserInterface.XAML;
 using Robust.Shared.Prototypes;
 using static Robust.Client.UserInterface.Controls.BoxContainer;
@@ -15,17 +14,12 @@ namespace Content.Client.Chemistry.UI
     /// Client-side UI used to control a <see cref="ReagentDispenserComponent"/>.
     /// </summary>
     [GenerateTypedNameReferences]
-    public sealed partial class ReagentDispenserWindow : DefaultWindow
+    public sealed partial class ReagentDispenserWindow : FancyWindow
     {
         [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
         [Dependency] private readonly IEntityManager _entityManager = default!;
-        public event Action<BaseButton.ButtonEventArgs, DispenseReagentButton>? OnDispenseReagentButtonPressed;
-        public event Action<GUIMouseHoverEventArgs, DispenseReagentButton>? OnDispenseReagentButtonMouseEntered;
-        public event Action<GUIMouseHoverEventArgs, DispenseReagentButton>? OnDispenseReagentButtonMouseExited;
-
-        public event Action<BaseButton.ButtonEventArgs, EjectJugButton>? OnEjectJugButtonPressed;
-        public event Action<GUIMouseHoverEventArgs, EjectJugButton>? OnEjectJugButtonMouseEntered;
-        public event Action<GUIMouseHoverEventArgs, EjectJugButton>? OnEjectJugButtonMouseExited;
+        public event Action<string>? OnDispenseReagentButtonPressed;
+        public event Action<string>? OnEjectJugButtonPressed;
 
         /// <summary>
         /// Create and initialize the dispenser UI client-side. Creates the basic layout,
@@ -35,44 +29,27 @@ namespace Content.Client.Chemistry.UI
         {
             RobustXamlLoader.Load(this);
             IoCManager.InjectDependencies(this);
-
-            var dispenseAmountGroup = new ButtonGroup();
-            DispenseButton1.Group = dispenseAmountGroup;
-            DispenseButton5.Group = dispenseAmountGroup;
-            DispenseButton10.Group = dispenseAmountGroup;
-            DispenseButton15.Group = dispenseAmountGroup;
-            DispenseButton20.Group = dispenseAmountGroup;
-            DispenseButton25.Group = dispenseAmountGroup;
-            DispenseButton30.Group = dispenseAmountGroup;
-            DispenseButton50.Group = dispenseAmountGroup;
-            DispenseButton100.Group = dispenseAmountGroup;
         }
 
         /// <summary>
         /// Update the button grid of reagents which can be dispensed.
         /// </summary>
         /// <param name="inventory">Reagents which can be dispensed by this dispenser</param>
-        public void UpdateReagentsList(List<KeyValuePair<string, KeyValuePair<string, string>>> inventory)
+        public void UpdateReagentsList(List<ReagentInventoryItem> inventory)
         {
-            if (ChemicalList == null)
+            if (ReagentList == null)
                 return;
 
-            ChemicalList.Children.Clear();
+            ReagentList.Children.Clear();
             //Sort inventory by reagentLabel
-            inventory.Sort((x, y) => x.Value.Key.CompareTo(y.Value.Key));
+            inventory.Sort((x, y) => x.ReagentLabel.CompareTo(y.ReagentLabel));
 
-            foreach (KeyValuePair<string, KeyValuePair<string, string>> entry in inventory)
+            foreach (var item in inventory)
             {
-                var button = new DispenseReagentButton(entry.Key, entry.Value.Key, entry.Value.Value);
-                button.OnPressed += args => OnDispenseReagentButtonPressed?.Invoke(args, button);
-                button.OnMouseEntered += args => OnDispenseReagentButtonMouseEntered?.Invoke(args, button);
-                button.OnMouseExited += args => OnDispenseReagentButtonMouseExited?.Invoke(args, button);
-                ChemicalList.AddChild(button);
-                var ejectButton = new EjectJugButton(entry.Key);
-                ejectButton.OnPressed += args => OnEjectJugButtonPressed?.Invoke(args, ejectButton);
-                ejectButton.OnMouseEntered += args => OnEjectJugButtonMouseEntered?.Invoke(args, ejectButton);
-                ejectButton.OnMouseExited += args => OnEjectJugButtonMouseExited?.Invoke(args, ejectButton);
-                ChemicalList.AddChild(ejectButton);
+                var card = new ReagentCardControl(item);
+                card.OnPressed += OnDispenseReagentButtonPressed;
+                card.OnEjectButtonPressed += OnEjectJugButtonPressed;
+                ReagentList.Children.Add(card);
             }
         }
 
@@ -93,36 +70,7 @@ namespace Content.Client.Chemistry.UI
             ClearButton.Disabled = castState.OutputContainer is null;
             EjectButton.Disabled = castState.OutputContainer is null;
 
-            switch (castState.SelectedDispenseAmount)
-            {
-                case ReagentDispenserDispenseAmount.U1:
-                    DispenseButton1.Pressed = true;
-                    break;
-                case ReagentDispenserDispenseAmount.U5:
-                    DispenseButton5.Pressed = true;
-                    break;
-                case ReagentDispenserDispenseAmount.U10:
-                    DispenseButton10.Pressed = true;
-                    break;
-                case ReagentDispenserDispenseAmount.U15:
-                    DispenseButton15.Pressed = true;
-                    break;
-                case ReagentDispenserDispenseAmount.U20:
-                    DispenseButton20.Pressed = true;
-                    break;
-                case ReagentDispenserDispenseAmount.U25:
-                    DispenseButton25.Pressed = true;
-                    break;
-                case ReagentDispenserDispenseAmount.U30:
-                    DispenseButton30.Pressed = true;
-                    break;
-                case ReagentDispenserDispenseAmount.U50:
-                    DispenseButton50.Pressed = true;
-                    break;
-                case ReagentDispenserDispenseAmount.U100:
-                    DispenseButton100.Pressed = true;
-                    break;
-            }
+            AmountGrid.Selected = ((int)castState.SelectedDispenseAmount).ToString();
         }
 
         /// <summary>
@@ -137,23 +85,15 @@ namespace Content.Client.Chemistry.UI
 
             if (state.OutputContainer is null)
             {
+                ContainerInfoName.Text = "";
+                ContainerInfoFill.Text = "";
                 ContainerInfo.Children.Add(new Label { Text = Loc.GetString("reagent-dispenser-window-no-container-loaded-text") });
                 return;
             }
 
-            ContainerInfo.Children.Add(new BoxContainer // Name of the container and its fill status (Ex: 44/100u)
-            {
-                Orientation = LayoutOrientation.Horizontal,
-                Children =
-                {
-                    new Label {Text = $"{state.OutputContainer.DisplayName}: "},
-                    new Label
-                    {
-                        Text = $"{state.OutputContainer.CurrentVolume}/{state.OutputContainer.MaxVolume}",
-                        StyleClasses = {StyleNano.StyleClassLabelSecondaryColor}
-                    }
-                }
-            });
+            // Set Name of the container and its fill status (Ex: 44/100u)
+            ContainerInfoName.Text = state.OutputContainer.DisplayName;
+            ContainerInfoFill.Text = state.OutputContainer.CurrentVolume + "/" + state.OutputContainer.MaxVolume;
 
             foreach (var (reagent, quantity) in state.OutputContainer.Reagents!)
             {
index 3bcdd4b964f8d0c18cc1f8bd6730e706ced82cff..c48bf086d39b336e80b53774a8c10bd8133afde2 100644 (file)
@@ -81,9 +81,9 @@ namespace Content.Server.Chemistry.EntitySystems
             return null;
         }
 
-        private List<KeyValuePair<string, KeyValuePair<string, string>>> GetInventory(Entity<ReagentDispenserComponent> reagentDispenser)
+        private List<ReagentInventoryItem> GetInventory(Entity<ReagentDispenserComponent> reagentDispenser)
         {
-            var inventory = new List<KeyValuePair<string, KeyValuePair<string, string>>>();
+            var inventory = new List<ReagentInventoryItem>();
 
             for (var i = 0; i < reagentDispenser.Comp.NumSlots; i++)
             {
@@ -99,15 +99,17 @@ namespace Content.Server.Chemistry.EntitySystems
                 else
                     continue;
 
-                // Add volume remaining label
+                // Get volume remaining and color of solution
                 FixedPoint2 quantity = 0f;
+                var reagentColor = Color.White;
                 if (storedContainer != null && _solutionContainerSystem.TryGetDrainableSolution(storedContainer.Value, out _, out var sol))
                 {
                     quantity = sol.Volume;
+                    reagentColor = sol.GetColor(_prototypeManager);
                 }
                 var storedAmount = Loc.GetString("reagent-dispenser-window-quantity-label-text", ("quantity", quantity));
 
-                inventory.Add(new KeyValuePair<string, KeyValuePair<string, string>>(storageSlotId, new KeyValuePair<string, string>(reagentLabel, storedAmount)));
+                inventory.Add(new ReagentInventoryItem(storageSlotId, reagentLabel, storedAmount, reagentColor));
             }
 
             return inventory;
index 2b9c318c58dbae723013f5ccd474019f064be2eb..5de3f6cae352490da060b94dc3d06661c9798d95 100644 (file)
@@ -20,6 +20,46 @@ namespace Content.Shared.Chemistry
         {
             ReagentDispenserDispenseAmount = amount;
         }
+
+        /// <summary>
+        ///     Create a new instance from interpreting a String as an integer,
+        ///     throwing an exception if it is unable to parse.
+        /// </summary>
+        public ReagentDispenserSetDispenseAmountMessage(String s)
+        {
+            switch (s)
+            {
+                case "1":
+                    ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U1;
+                    break;
+                case "5":
+                    ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U5;
+                    break;
+                case "10":
+                    ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U10;
+                    break;
+                case "15":
+                    ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U15;
+                    break;
+                case "20":
+                    ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U20;
+                    break;
+                case "25":
+                    ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U25;
+                    break;
+                case "30":
+                    ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U30;
+                    break;
+                case "50":
+                    ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U50;
+                    break;
+                case "100":
+                    ReagentDispenserDispenseAmount = ReagentDispenserDispenseAmount.U100;
+                    break;
+                default:
+                    throw new Exception($"Cannot convert the string `{s}` into a valid ReagentDispenser DispenseAmount");
+            }
+        }
     }
 
     [Serializable, NetSerializable]
@@ -52,20 +92,30 @@ namespace Content.Shared.Chemistry
         U100 = 100,
     }
 
+    [Serializable, NetSerializable]
+    public sealed class ReagentInventoryItem(string storageSlotId, string reagentLabel, string storedAmount, Color reagentColor)
+    {
+        public string StorageSlotId = storageSlotId;
+        public string ReagentLabel = reagentLabel;
+        public string StoredAmount = storedAmount;
+        public Color ReagentColor = reagentColor;
+    }
+
     [Serializable, NetSerializable]
     public sealed class ReagentDispenserBoundUserInterfaceState : BoundUserInterfaceState
     {
         public readonly ContainerInfo? OutputContainer;
 
         public readonly NetEntity? OutputContainerEntity;
+
         /// <summary>
         /// A list of the reagents which this dispenser can dispense.
         /// </summary>
-        public readonly List<KeyValuePair<string, KeyValuePair<string, string>>> Inventory;
+        public readonly List<ReagentInventoryItem> Inventory;
 
         public readonly ReagentDispenserDispenseAmount SelectedDispenseAmount;
 
-        public ReagentDispenserBoundUserInterfaceState(ContainerInfo? outputContainer, NetEntity? outputContainerEntity, List<KeyValuePair<string, KeyValuePair<string, string>>> inventory, ReagentDispenserDispenseAmount selectedDispenseAmount)
+        public ReagentDispenserBoundUserInterfaceState(ContainerInfo? outputContainer, NetEntity? outputContainerEntity, List<ReagentInventoryItem> inventory, ReagentDispenserDispenseAmount selectedDispenseAmount)
         {
             OutputContainer = outputContainer;
             OutputContainerEntity = outputContainerEntity;
index 48ec8f521303f07e80d79c4c2b469abd76bd66a3..37697c45176a8287d8c31ac69ec43da0725e8550 100644 (file)
@@ -10,9 +10,9 @@ reagent-dispenser-bound-user-interface-title = Reagent dispenser
 ## UI
 
 reagent-dispenser-window-amount-to-dispense-label = Amount
-reagent-dispenser-window-container-label = Container:
 reagent-dispenser-window-clear-button = Clear
 reagent-dispenser-window-eject-button = Eject
+reagent-dispenser-window-eject-container-button = ⏏
 reagent-dispenser-window-no-container-loaded-text = No container loaded.
 reagent-dispenser-window-reagent-name-not-found-text = Reagent name not found
 reagent-dispenser-window-unknown-reagent-text = Unknown reagent