Adds fire/air alarms (#5018)
Co-authored-by: Vera Aguilera Puerto <6766154+Zumorica@users.noreply.github.com> Co-authored-by: E F R <602406+Efruit@users.noreply.github.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
36
Content.Client/Atmos/Monitor/UI/Widgets/PumpControl.xaml
Normal file
36
Content.Client/Atmos/Monitor/UI/Widgets/PumpControl.xaml
Normal file
@@ -0,0 +1,36 @@
|
||||
<BoxContainer xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Orientation="Vertical" Margin="2 0 2 4">
|
||||
<Collapsible Orientation="Vertical">
|
||||
<CollapsibleHeading Name="CAddress" />
|
||||
<!-- Upper row: toggle, direction, checks -->
|
||||
<CollapsibleBody>
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Orientation="Horizontal" Margin ="0 0 0 2">
|
||||
<CheckBox Name="CEnableDevice" Text="{Loc 'air-alarm-ui-widget-enable'}" />
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Horizontal" Margin="0 0 0 2" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'air-alarm-ui-vent-pump-label'}" Margin="0 0 0 1" />
|
||||
<OptionButton Name="CPumpDirection" />
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'air-alarm-ui-vent-pressure-label'}" Margin="0 0 0 1" />
|
||||
<OptionButton Name="CPressureCheck" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
<!-- Lower row: pressure bounds -->
|
||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'air-alarm-ui-vent-external-bound-label'}" Margin="0 0 0 1" />
|
||||
<FloatSpinBox Name="CExternalBound" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'air-alarm-ui-vent-internal-bound-label'}" Margin="0 0 0 1" />
|
||||
<FloatSpinBox Name="CInternalBound" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</CollapsibleBody>
|
||||
</Collapsible>
|
||||
</BoxContainer>
|
||||
103
Content.Client/Atmos/Monitor/UI/Widgets/PumpControl.xaml.cs
Normal file
103
Content.Client/Atmos/Monitor/UI/Widgets/PumpControl.xaml.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using Content.Shared.Atmos.Monitor;
|
||||
using Content.Shared.Atmos.Monitor.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Client.Atmos.Monitor.UI.Widgets
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public partial class PumpControl : BoxContainer
|
||||
{
|
||||
private GasVentPumpData _data;
|
||||
private string _address;
|
||||
|
||||
public event Action<string, IAtmosDeviceData>? PumpDataChanged;
|
||||
|
||||
private CheckBox _enabled => CEnableDevice;
|
||||
private CollapsibleHeading _addressLabel => CAddress;
|
||||
private OptionButton _pumpDirection => CPumpDirection;
|
||||
private OptionButton _pressureCheck => CPressureCheck;
|
||||
private FloatSpinBox _externalBound => CExternalBound;
|
||||
private FloatSpinBox _internalBound => CInternalBound;
|
||||
|
||||
public PumpControl(GasVentPumpData data, string address)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
this.Name = address;
|
||||
|
||||
_data = data;
|
||||
_address = address;
|
||||
|
||||
_addressLabel.Title = Loc.GetString("air-alarm-ui-atmos-net-device-label", ("address", $"{address}"));
|
||||
|
||||
_enabled.Pressed = data.Enabled;
|
||||
_enabled.OnToggled += _ =>
|
||||
{
|
||||
_data.Enabled = _enabled.Pressed;
|
||||
PumpDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
|
||||
_internalBound.Value = (float) _data.InternalPressureBound!;
|
||||
_internalBound.OnValueChanged += _ =>
|
||||
{
|
||||
_data.InternalPressureBound = _internalBound.Value;
|
||||
PumpDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
_internalBound.IsValid += value => value >= 0;
|
||||
|
||||
_externalBound.Value = (float) _data.ExternalPressureBound!;
|
||||
_externalBound.OnValueChanged += _ =>
|
||||
{
|
||||
_data.ExternalPressureBound = _externalBound.Value;
|
||||
PumpDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
_externalBound.IsValid += value => value >= 0;
|
||||
|
||||
foreach (var value in Enum.GetValues<VentPumpDirection>())
|
||||
_pumpDirection.AddItem(Loc.GetString($"{value}"), (int) value);
|
||||
|
||||
_pumpDirection.SelectId((int) _data.PumpDirection!);
|
||||
_pumpDirection.OnItemSelected += args =>
|
||||
{
|
||||
_pumpDirection.SelectId(args.Id);
|
||||
_data.PumpDirection = (VentPumpDirection) args.Id;
|
||||
PumpDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
|
||||
foreach (var value in Enum.GetValues<VentPressureBound>())
|
||||
_pressureCheck.AddItem(Loc.GetString($"{value}"), (int) value);
|
||||
|
||||
_pressureCheck.SelectId((int) _data.PressureChecks!);
|
||||
_pressureCheck.OnItemSelected += args =>
|
||||
{
|
||||
_pressureCheck.SelectId(args.Id);
|
||||
_data.PressureChecks = (VentPressureBound) args.Id;
|
||||
PumpDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
}
|
||||
|
||||
public void ChangeData(GasVentPumpData data)
|
||||
{
|
||||
_data.Enabled = data.Enabled;
|
||||
_enabled.Pressed = _data.Enabled!;
|
||||
|
||||
_data.PumpDirection = data.PumpDirection;
|
||||
_pumpDirection.SelectId((int) _data.PumpDirection!);
|
||||
|
||||
_data.PressureChecks = data.PressureChecks;
|
||||
_pressureCheck.SelectId((int) _data.PressureChecks!);
|
||||
|
||||
_data.ExternalPressureBound = data.ExternalPressureBound;
|
||||
_externalBound.Value = (float) _data.ExternalPressureBound!;
|
||||
|
||||
_data.InternalPressureBound = data.InternalPressureBound;
|
||||
_internalBound.Value = (float) _data.InternalPressureBound!;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Content.Client/Atmos/Monitor/UI/Widgets/ScrubberControl.xaml
Normal file
35
Content.Client/Atmos/Monitor/UI/Widgets/ScrubberControl.xaml
Normal file
@@ -0,0 +1,35 @@
|
||||
<BoxContainer xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Orientation="Vertical" Margin="2 0 2 4">
|
||||
<Collapsible Orientation="Vertical">
|
||||
<CollapsibleHeading Name="CAddress" />
|
||||
<CollapsibleBody>
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Orientation="Horizontal" Margin="0 0 0 2">
|
||||
<CheckBox Name="CEnableDevice" Text="{Loc 'air-alarm-ui-widget-enable'}" />
|
||||
</BoxContainer>
|
||||
<!-- Upper row: toggle, direction, volume rate, widenet -->
|
||||
<BoxContainer Orientation="Horizontal" Margin="0 0 0 2" HorizontalExpand="True">
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'air-alarm-ui-scrubber-pump-direction-label'}" Margin="0 0 0 1"/>
|
||||
<OptionButton Name="CPumpDirection" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'air-alarm-ui-scrubber-volume-rate-label'}" Margin="0 0 0 1" />
|
||||
<FloatSpinBox Name="CVolumeRate" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
<BoxContainer>
|
||||
<CheckBox Name="CWideNet" Text="{Loc 'air-alarm-ui-scrubber-wide-net-label'}" />
|
||||
</BoxContainer>
|
||||
<!-- Lower row: every single gas -->
|
||||
<Collapsible Orientation="Vertical" Margin="2 2 2 2">
|
||||
<CollapsibleHeading Title="Gas filters" />
|
||||
<CollapsibleBody>
|
||||
<GridContainer HorizontalExpand="True" Name="CGasContainer" Columns="3" />
|
||||
</CollapsibleBody>
|
||||
</Collapsible>
|
||||
</BoxContainer>
|
||||
</CollapsibleBody>
|
||||
</Collapsible>
|
||||
</BoxContainer>
|
||||
123
Content.Client/Atmos/Monitor/UI/Widgets/ScrubberControl.xaml.cs
Normal file
123
Content.Client/Atmos/Monitor/UI/Widgets/ScrubberControl.xaml.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Monitor;
|
||||
using Content.Shared.Atmos.Monitor.Components;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Client.Atmos.Monitor.UI.Widgets
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public partial class ScrubberControl : BoxContainer
|
||||
{
|
||||
private GasVentScrubberData _data;
|
||||
private string _address;
|
||||
|
||||
public event Action<string, IAtmosDeviceData>? ScrubberDataChanged;
|
||||
|
||||
private CheckBox _enabled => CEnableDevice;
|
||||
private CollapsibleHeading _addressLabel => CAddress;
|
||||
private OptionButton _pumpDirection => CPumpDirection;
|
||||
private FloatSpinBox _volumeRate => CVolumeRate;
|
||||
private CheckBox _wideNet => CWideNet;
|
||||
|
||||
private GridContainer _gases => CGasContainer;
|
||||
private Dictionary<Gas, Button> _gasControls = new();
|
||||
|
||||
public ScrubberControl(GasVentScrubberData data, string address)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
this.Name = address;
|
||||
|
||||
_data = data;
|
||||
_address = address;
|
||||
|
||||
_addressLabel.Title = Loc.GetString("air-alarm-ui-atmos-net-device-label", ("address", $"{address}"));
|
||||
|
||||
_enabled.Pressed = data.Enabled;
|
||||
_enabled.OnToggled += _ =>
|
||||
{
|
||||
_data.Enabled = _enabled.Pressed;
|
||||
ScrubberDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
|
||||
_wideNet.Pressed = data.WideNet;
|
||||
_wideNet.OnToggled += _ =>
|
||||
{
|
||||
_data.WideNet = _wideNet.Pressed;
|
||||
ScrubberDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
|
||||
_volumeRate.Value = (float) _data.VolumeRate!;
|
||||
_volumeRate.OnValueChanged += _ =>
|
||||
{
|
||||
_data.VolumeRate = _volumeRate.Value;
|
||||
ScrubberDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
_volumeRate.IsValid += value => value >= 0;
|
||||
|
||||
foreach (var value in Enum.GetValues<ScrubberPumpDirection>())
|
||||
_pumpDirection.AddItem(Loc.GetString($"{value}"), (int) value);
|
||||
|
||||
_pumpDirection.SelectId((int) _data.PumpDirection!);
|
||||
_pumpDirection.OnItemSelected += args =>
|
||||
{
|
||||
_pumpDirection.SelectId(args.Id);
|
||||
_data.PumpDirection = (ScrubberPumpDirection) args.Id;
|
||||
ScrubberDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
|
||||
foreach (var value in Enum.GetValues<Gas>())
|
||||
{
|
||||
var gasButton = new Button
|
||||
{
|
||||
Name = value.ToString(),
|
||||
Text = Loc.GetString($"{value}"),
|
||||
ToggleMode = true,
|
||||
HorizontalExpand = true,
|
||||
Pressed = _data.FilterGases!.Contains(value)
|
||||
};
|
||||
gasButton.OnToggled += args =>
|
||||
{
|
||||
if (args.Pressed)
|
||||
_data.FilterGases.Add(value);
|
||||
else
|
||||
_data.FilterGases.Remove(value);
|
||||
|
||||
ScrubberDataChanged?.Invoke(_address, _data);
|
||||
};
|
||||
_gasControls.Add(value, gasButton);
|
||||
_gases.AddChild(gasButton);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void ChangeData(GasVentScrubberData data)
|
||||
{
|
||||
_data.Enabled = data.Enabled;
|
||||
_enabled.Pressed = _data.Enabled;
|
||||
|
||||
_data.PumpDirection = data.PumpDirection;
|
||||
_pumpDirection.SelectId((int) _data.PumpDirection!);
|
||||
|
||||
_data.VolumeRate = data.VolumeRate;
|
||||
_volumeRate.Value = (float) _data.VolumeRate!;
|
||||
|
||||
_data.WideNet = data.WideNet;
|
||||
_wideNet.Pressed = _data.WideNet;
|
||||
|
||||
var intersect = _data.FilterGases!.Intersect(data.FilterGases!);
|
||||
|
||||
foreach (var value in Enum.GetValues<Gas>())
|
||||
if (!intersect.Contains(value))
|
||||
_gasControls[value].Pressed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<BoxContainer xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Orientation="Vertical" Margin="0 0 0 4">
|
||||
<Collapsible Orientation="Vertical">
|
||||
<CollapsibleHeading Name="CName" />
|
||||
<CollapsibleBody>
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<CheckBox Name="CIgnore" Text="{Loc 'Ignore'}" />
|
||||
</BoxContainer>
|
||||
<!-- Upper row: Danger bounds -->
|
||||
<BoxContainer Name="CDangerBounds" Orientation="Horizontal" Margin="0 0 0 2"/>
|
||||
<!-- Lower row: Warning bounds -->
|
||||
<BoxContainer Name="CWarningBounds" Orientation="Horizontal" Margin="0 0 0 2"/>
|
||||
</BoxContainer>
|
||||
</CollapsibleBody>
|
||||
</Collapsible>
|
||||
</BoxContainer>
|
||||
294
Content.Client/Atmos/Monitor/UI/Widgets/ThresholdControl.xaml.cs
Normal file
294
Content.Client/Atmos/Monitor/UI/Widgets/ThresholdControl.xaml.cs
Normal file
@@ -0,0 +1,294 @@
|
||||
using System;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Monitor;
|
||||
using Content.Shared.Atmos.Monitor.Components;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
|
||||
namespace Content.Client.Atmos.Monitor.UI.Widgets
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public partial class ThresholdControl : BoxContainer
|
||||
{
|
||||
private AtmosAlarmThreshold _threshold;
|
||||
private AtmosMonitorThresholdType _type;
|
||||
private Gas? _gas;
|
||||
|
||||
public event Action<AtmosMonitorThresholdType, AtmosAlarmThreshold, Gas?>? ThresholdDataChanged;
|
||||
|
||||
private CollapsibleHeading _name => CName;
|
||||
private CheckBox _ignore => CIgnore;
|
||||
private BoxContainer _dangerBounds => CDangerBounds;
|
||||
private BoxContainer _warningBounds => CWarningBounds;
|
||||
private ThresholdBoundControl _upperBoundControl;
|
||||
private ThresholdBoundControl _lowerBoundControl;
|
||||
private ThresholdBoundControl _upperWarningBoundControl;
|
||||
private ThresholdBoundControl _lowerWarningBoundControl;
|
||||
|
||||
// i have played myself by making threshold values nullable to
|
||||
// indicate validity/disabled status, with several layers of side effect
|
||||
// dependent on the other three values when you change one :HECK:
|
||||
public ThresholdControl(string name, AtmosAlarmThreshold threshold, AtmosMonitorThresholdType type, Gas? gas = null, float modifier = 1)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
_threshold = threshold;
|
||||
_type = type;
|
||||
_gas = gas;
|
||||
|
||||
_name.Title = name;
|
||||
|
||||
// i miss rust macros
|
||||
|
||||
_upperBoundControl = new ThresholdBoundControl("upper-bound", _threshold.UpperBound, modifier);
|
||||
_upperBoundControl.OnBoundChanged += value =>
|
||||
{
|
||||
// a lot of threshold logic is baked into the properties,
|
||||
// so setting this just returns if a change occurred or not
|
||||
_threshold.TrySetPrimaryBound(AtmosMonitorThresholdBound.Upper, value);
|
||||
return _threshold.UpperBound;
|
||||
};
|
||||
_upperBoundControl.OnBoundEnabled += () =>
|
||||
{
|
||||
var value = 0f;
|
||||
|
||||
if (_threshold.LowerWarningBound != null)
|
||||
value = (float) _threshold.LowerWarningBound + 0.1f;
|
||||
else if (_threshold.LowerBound != null)
|
||||
value = (float) _threshold.LowerBound + 0.1f;
|
||||
|
||||
return value;
|
||||
};
|
||||
_upperBoundControl.OnValidBoundChanged += () =>
|
||||
{
|
||||
ThresholdDataChanged!.Invoke(_type, _threshold, _gas);
|
||||
};
|
||||
_dangerBounds.AddChild(_upperBoundControl);
|
||||
|
||||
_lowerBoundControl = new ThresholdBoundControl("lower-bound", _threshold.LowerBound, modifier);
|
||||
_lowerBoundControl.OnBoundChanged += value =>
|
||||
{
|
||||
_threshold.TrySetPrimaryBound(AtmosMonitorThresholdBound.Lower, value);
|
||||
return _threshold.LowerBound;
|
||||
};
|
||||
_lowerBoundControl.OnBoundEnabled += () =>
|
||||
{
|
||||
var value = 0f;
|
||||
|
||||
if (_threshold.UpperWarningBound != null)
|
||||
value = (float) _threshold.UpperWarningBound - 0.1f;
|
||||
else if (_threshold.UpperBound != null)
|
||||
value = (float) _threshold.UpperBound - 0.1f;
|
||||
|
||||
return value;
|
||||
};
|
||||
_lowerBoundControl.OnValidBoundChanged += () =>
|
||||
ThresholdDataChanged!.Invoke(_type, _threshold, _gas);
|
||||
_dangerBounds.AddChild(_lowerBoundControl);
|
||||
|
||||
_upperWarningBoundControl = new ThresholdBoundControl("upper-warning-bound", _threshold.UpperWarningBound, modifier);
|
||||
_upperWarningBoundControl.OnBoundChanged += value =>
|
||||
{
|
||||
_threshold.TrySetWarningBound(AtmosMonitorThresholdBound.Upper, value);
|
||||
return _threshold.UpperWarningBound;
|
||||
};
|
||||
_upperWarningBoundControl.OnBoundEnabled += () =>
|
||||
{
|
||||
var value = 0f;
|
||||
|
||||
if (_threshold.LowerWarningBound != null)
|
||||
value = (float) _threshold.LowerWarningBound + 0.1f;
|
||||
else if (_threshold.LowerBound != null)
|
||||
value = (float) _threshold.LowerBound + 0.1f;
|
||||
|
||||
return value;
|
||||
};
|
||||
_upperWarningBoundControl.OnValidBoundChanged += () =>
|
||||
ThresholdDataChanged!.Invoke(_type, _threshold, _gas);
|
||||
_warningBounds.AddChild(_upperWarningBoundControl);
|
||||
|
||||
_lowerWarningBoundControl = new ThresholdBoundControl("lower-warning-bound", _threshold.LowerWarningBound, modifier);
|
||||
_lowerWarningBoundControl.OnBoundChanged += value =>
|
||||
{
|
||||
_threshold.TrySetWarningBound(AtmosMonitorThresholdBound.Lower, value);
|
||||
return _threshold.LowerWarningBound;
|
||||
};
|
||||
_lowerWarningBoundControl.OnBoundEnabled += () =>
|
||||
{
|
||||
var value = 0f;
|
||||
|
||||
if (_threshold.UpperWarningBound != null)
|
||||
value = (float) _threshold.UpperWarningBound - 0.1f;
|
||||
else if (_threshold.UpperBound != null)
|
||||
value = (float) _threshold.UpperBound - 0.1f;
|
||||
|
||||
return value;
|
||||
};
|
||||
_lowerWarningBoundControl.OnValidBoundChanged += () =>
|
||||
ThresholdDataChanged!.Invoke(_type, _threshold, _gas);
|
||||
|
||||
_warningBounds.AddChild(_lowerWarningBoundControl);
|
||||
|
||||
_ignore.OnToggled += args =>
|
||||
{
|
||||
_threshold.Ignore = args.Pressed;
|
||||
ThresholdDataChanged!.Invoke(_type, _threshold, _gas);
|
||||
};
|
||||
_ignore.Pressed = _threshold.Ignore;
|
||||
}
|
||||
|
||||
public void UpdateThresholdData(AtmosAlarmThreshold threshold)
|
||||
{
|
||||
_upperBoundControl.SetValue(threshold.UpperBound);
|
||||
_lowerBoundControl.SetValue(threshold.LowerBound);
|
||||
_upperWarningBoundControl.SetValue(threshold.UpperWarningBound);
|
||||
_lowerWarningBoundControl.SetValue(threshold.LowerWarningBound);
|
||||
_ignore.Pressed = threshold.Ignore;
|
||||
}
|
||||
|
||||
|
||||
private class ThresholdBoundControl : BoxContainer
|
||||
{
|
||||
// raw values to use in thresholds, prefer these
|
||||
// over directly setting Modified(Value/LastValue)
|
||||
// when working with the FloatSpinBox
|
||||
private float? _value;
|
||||
private float _lastValue;
|
||||
|
||||
// convenience thing for getting multiplied values
|
||||
// and also setting value to a usable value
|
||||
private float? ModifiedValue
|
||||
{
|
||||
get => _value * _modifier;
|
||||
set => _value = value / _modifier;
|
||||
}
|
||||
|
||||
private float ModifiedLastValue
|
||||
{
|
||||
get => _lastValue * _modifier;
|
||||
set => _lastValue = value / _modifier;
|
||||
}
|
||||
|
||||
private float _modifier;
|
||||
|
||||
private FloatSpinBox _bound;
|
||||
private CheckBox _boundEnabled;
|
||||
|
||||
public event Action? OnValidBoundChanged;
|
||||
public Func<float?, float?>? OnBoundChanged;
|
||||
public Func<float>? OnBoundEnabled;
|
||||
|
||||
public void SetValue(float? value)
|
||||
{
|
||||
_value = value;
|
||||
|
||||
if (_value == null)
|
||||
{
|
||||
_boundEnabled.Pressed = false;
|
||||
_bound.Value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_boundEnabled.Pressed = true;
|
||||
_bound.Value = (float) ModifiedValue!;
|
||||
}
|
||||
}
|
||||
|
||||
// Modifier indicates what factor the value should be multiplied by.
|
||||
// Mostly useful to convert tiny decimals to human-readable 'percentages'
|
||||
// (yes it's still a float, but floatspinbox unfucks that)
|
||||
public ThresholdBoundControl(string name, float? value, float modifier = 1)
|
||||
{
|
||||
_modifier = modifier > 0 ? modifier : 1;
|
||||
_value = value;
|
||||
|
||||
this.HorizontalExpand = true;
|
||||
this.Orientation = LayoutOrientation.Vertical;
|
||||
|
||||
this.AddChild(new Label { Text = Loc.GetString($"air-alarm-ui-thresholds-{name}") });
|
||||
_bound = new FloatSpinBox(.01f, 2);
|
||||
this.AddChild(_bound);
|
||||
|
||||
_boundEnabled = new CheckBox
|
||||
{
|
||||
Text = Loc.GetString("Enabled")
|
||||
};
|
||||
this.AddChild(_boundEnabled);
|
||||
|
||||
_bound.Value = ModifiedValue ?? 0;
|
||||
_lastValue = _value ?? 0;
|
||||
_boundEnabled.Pressed = _value != null;
|
||||
|
||||
_bound.OnValueChanged += ChangeValue;
|
||||
_bound.IsValid += ValidateThreshold;
|
||||
_boundEnabled.OnToggled += ToggleBound;
|
||||
}
|
||||
|
||||
private void ChangeValue(FloatSpinBox.FloatSpinBoxEventArgs args)
|
||||
{
|
||||
// ensure that the value in the spinbox is transformed
|
||||
ModifiedValue = args.Value;
|
||||
// set the value in the scope above
|
||||
var value = OnBoundChanged!(_value);
|
||||
// is the value not null, or has it changed?
|
||||
if (value != null || value != _lastValue)
|
||||
{
|
||||
_value = value;
|
||||
_lastValue = (float) value!;
|
||||
OnValidBoundChanged!.Invoke();
|
||||
}
|
||||
// otherwise, just set it to the last known value
|
||||
else
|
||||
{
|
||||
_value = _lastValue;
|
||||
_bound.Value = ModifiedLastValue;
|
||||
}
|
||||
}
|
||||
|
||||
private void ToggleBound(BaseButton.ButtonToggledEventArgs args)
|
||||
{
|
||||
if (args.Pressed)
|
||||
{
|
||||
var value = OnBoundChanged!(_lastValue);
|
||||
|
||||
if (value != _lastValue)
|
||||
{
|
||||
value = OnBoundChanged!(OnBoundEnabled!());
|
||||
|
||||
if (value == null || value < 0)
|
||||
{
|
||||
// TODO: Improve UX here, this is ass
|
||||
// basically this implies that the bound
|
||||
// you currently have is too aggressive
|
||||
// for the other set of values, so a
|
||||
// default value (which is +/-0.1) can't
|
||||
// be used
|
||||
_boundEnabled.Pressed = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_value = value;
|
||||
|
||||
_bound.Value = (float) ModifiedValue!;
|
||||
_lastValue = (float) _value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_value = null;
|
||||
_bound.Value = 0f;
|
||||
OnBoundChanged!(_value);
|
||||
}
|
||||
|
||||
OnValidBoundChanged!.Invoke();
|
||||
}
|
||||
|
||||
private bool ValidateThreshold(float value) => (_value != null) && (value >= 0);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user