* Apply patch 1777eea9a4..6b32bb2b14
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* make red squiggly line go away
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Add todo list
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Add palette to `TextureButton`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Rename `PalettedButtonSheetlet` to `NTButtonSheetlet` and move useful methods to `ButtonSheetlet`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* migrate `ContextMenu` styles
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Update todo
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* tweak NT colors
* New stylesheet: `InterfaceStylesheet` & `InterfaceTooltipSheetlet`
* Move inheritance of `IButtonConfig` to `NanotransenStylesheet.Buttons`
* move `MenuButtonSheetlet` & actually implement `InterfaceStylesheet` correctly
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* tweak color & update todo
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* chat is this real (update chat palette)
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Update todo
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* `SmallButton` and remove some obsolete things from `StyleNano`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* rename `StyleClasses` to `StyleClass` so `Stylesheets.Redux.StyleClasses` syntax is dead
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* replace `ButtonColorGreen` with `Positive`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* `Placeholder`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Examine popup buttons
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* move over more things & cleanup `StyleNano` more (under 1000 lines!!!!)
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Remove some more redundant stuff
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Undo style change for chat window
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* paper editing works now
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* `OptionButton` styles
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* `ListContainer`, move `DefaultWindow` styles (for now) & more cleanup
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* fix `ActionButton` not having highlighting
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* remove imports of `Robust.Client.UserInterface.StylesheetHelpers` & format
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* `ButtonBig` and more cleanup
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Move items inheriting from `ISheetletConfig` into their own directory
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Cleanup & move `Label` styles
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Action search box styles
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Moved, stuff is
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* rename `LabelSubtext` to `LabelSubText` & move more stuff (were almost there!!)
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* yap & move over MORE stuff (just like one thing left!!!)
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Change status classes to appropriate existing classes
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* remove remaining references to `StyleNano`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Fix some hardcoding & broken code, `GetFromControl`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Scrollbars!
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* chores
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* clean up `StyleClass.cs`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* `ItemListSheetlet` refactor
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* more chores!
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Consistency w/ directory structure
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Move `MainMenuSheetlet`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* `ColorPalette`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* whoopsie
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Remove most sheet-specific sheetlets
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* fix warnings, cleanup, & fix scrollbar (this is why we fix warnings boys)
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* yap
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* MASSIVE resharper skill issue
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* actually use `ISheetletConfig`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* have specific sheetlet be specific
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* `GetResourceOr`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* cleanup & move / remove `IPalette`s
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* actually do specific stylesheets correctly & fix tooltips
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* cleanup & logging
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* Move `FontKind` and `FontKindExtensions` to their own files
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* rename `InterfaceStylesheet` to `SystemStylesheet`
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* change `ButtonHovered` etc to `PseudoHovered` etc
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* give the palettes fun names
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* `StyleSpace` is no more
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* It should compile now! I am now going to bed (fr) if it fails it fails
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* make squiggly red line go away
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
* add additional type restrictions to sheetlets
* `CommonStylesheet`
* minor cleanup
* Make `GetSheetletRules` not horrible
* wait this was duplicating style rules. oops!
* move some sheetlets to their associated xamls
* oh wait apparently that was important
* review pass 1
* review pass 2 (font & color stuff)
* review pass 3: remove unused stuff / filename fix
* fix warnings & "replace cast with explicit variable type"
* move `Palette` stuff to its own directory
* tweak colors (they're different now that I actually fixed the OKlab thing)
* review pass 4: little things
* make window close button grey before hovering
* refactor `HLine` to make it less terrible and allow it to be styled
* fix `NanoHeading` (it's been broken for a while whoops) and cleanup hardcoding
* band-aid missing references in `StyleNano`
* move `StyleBox` generating functions out of `IButtonSheetlet` into `StyleBoxHelper`
* remove dictionary field from `IStylesheetManager`
* Add check for unloaded sheetlets
* style tweaks to satisfy OCD
* I somehow missed this: `Caution` styleclass replaced with `negative`, refactor `PowerChargeWindow`
* tweak palettes for like the fourth time
* construct `StyleNano` / `StyleSpace` in `StylesheetManager` and mark them as obsolete
* rename `BackgroundPanel` classes for consistency
* tweak window / `ListContainer`
* oh right you use `///` not `/**`
* font system is bad, make it temporary
* acknowledge Divider funkyness
* remove use of class `Disabled`
* `ColorPalette` allow overriding colors with brace initialization
* review pass again
* tweak disabled button colors
* `StatusPalette` tweaks
* typo
* Make squiggly red line go away
* Delete `Redux`
* Remove all references to `Redux`
* make red less radioactive
* Store stylesheet name inside stylesheet class
* fix merge errors
* use RT's Oklab support instead
* shuffle around `StylesheetManager` fields
* apply stylesheets based off `StylesheetComponent`
* simplify `ColorPalette` construction
* add todo for `SheetletConfigType`
* `OptionButton` has a background color now
* fix disabled buttons
* sigh (red color palette fixed)
* make `ItemList` use primary palette
* Revert "apply stylesheets based off `StylesheetComponent`"
This reverts commit c05b147da845f6e04ff33d1cbd91a18a92c676d7.
* dead code removal
* buttons are green when pressed (we need togglebuttons)
---------
Signed-off-by: Brandon Li <sirbrandonthenerd@gmail.com>
Co-authored-by: Janet Blackquill <uhhadd@gmail.com>
452 lines
16 KiB
C#
452 lines
16 KiB
C#
using Content.Client.Stylesheets;
|
||
using Content.Client.UserInterface.Controls;
|
||
using Content.Shared.Access;
|
||
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.Prototypes;
|
||
using System.Linq;
|
||
using System.Numerics;
|
||
|
||
namespace Content.Client.Access.UI;
|
||
|
||
[GenerateTypedNameReferences]
|
||
public sealed partial class GroupedAccessLevelChecklist : BoxContainer
|
||
{
|
||
private static readonly ProtoId<AccessGroupPrototype> GeneralAccessGroup = "General";
|
||
|
||
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||
|
||
private bool _isMonotone;
|
||
private string? _labelStyleClass;
|
||
|
||
// Access data
|
||
private HashSet<ProtoId<AccessGroupPrototype>> _accessGroups = new();
|
||
private HashSet<ProtoId<AccessLevelPrototype>> _accessLevels = new();
|
||
private HashSet<ProtoId<AccessLevelPrototype>> _activeAccessLevels = new();
|
||
|
||
// Button groups
|
||
private readonly ButtonGroup _accessGroupsButtons = new();
|
||
|
||
// Temp values
|
||
private int _accessGroupTabIndex = 0;
|
||
private bool _canInteract = false;
|
||
private List<AccessLevelPrototype> _accessLevelsForTab = new();
|
||
private readonly List<AccessLevelEntry> _accessLevelEntries = new();
|
||
private readonly Dictionary<AccessGroupPrototype, List<AccessLevelPrototype>> _groupedAccessLevels = new();
|
||
|
||
// Events
|
||
public event Action<HashSet<ProtoId<AccessLevelPrototype>>, bool>? OnAccessLevelsChangedEvent;
|
||
|
||
/// <summary>
|
||
/// Creates a UI control for changing access levels.
|
||
/// Access levels are organized under a list of tabs by their associated access group.
|
||
/// </summary>
|
||
public GroupedAccessLevelChecklist()
|
||
{
|
||
RobustXamlLoader.Load(this);
|
||
IoCManager.InjectDependencies(this);
|
||
}
|
||
|
||
private void ArrangeAccessControls()
|
||
{
|
||
// Create a list of known access groups with which to populate the UI
|
||
_groupedAccessLevels.Clear();
|
||
|
||
foreach (var accessGroup in _accessGroups)
|
||
{
|
||
if (!_protoManager.Resolve(accessGroup, out var accessGroupProto))
|
||
continue;
|
||
|
||
_groupedAccessLevels.Add(accessGroupProto, new());
|
||
}
|
||
|
||
// Ensure that the 'general' access group is added to handle
|
||
// misc. access levels that aren't associated with any group
|
||
if (_protoManager.Resolve(GeneralAccessGroup, out var generalAccessProto))
|
||
_groupedAccessLevels.TryAdd(generalAccessProto, new());
|
||
|
||
// Assign known access levels with their associated groups
|
||
foreach (var accessLevel in _accessLevels)
|
||
{
|
||
if (!_protoManager.Resolve(accessLevel, out var accessLevelProto))
|
||
continue;
|
||
|
||
var assigned = false;
|
||
|
||
foreach (var (accessGroup, accessLevels) in _groupedAccessLevels)
|
||
{
|
||
if (!accessGroup.Tags.Contains(accessLevelProto.ID))
|
||
continue;
|
||
|
||
assigned = true;
|
||
_groupedAccessLevels[accessGroup].Add(accessLevelProto);
|
||
}
|
||
|
||
if (!assigned && generalAccessProto != null)
|
||
_groupedAccessLevels[generalAccessProto].Add(accessLevelProto);
|
||
}
|
||
|
||
// Remove access groups that have no assigned access levels
|
||
foreach (var (group, accessLevels) in _groupedAccessLevels)
|
||
{
|
||
if (accessLevels.Count == 0)
|
||
_groupedAccessLevels.Remove(group);
|
||
}
|
||
}
|
||
|
||
private bool TryRebuildAccessGroupControls()
|
||
{
|
||
AccessGroupList.RemoveAllChildren();
|
||
AccessLevelChecklist.RemoveAllChildren();
|
||
|
||
// No access level prototypes were assigned to any of the access level groups.
|
||
// Either the turret controller has no assigned access levels or their names were invalid.
|
||
if (_groupedAccessLevels.Count == 0)
|
||
return false;
|
||
|
||
// Reorder the access groups alphabetically
|
||
var orderedAccessGroups = _groupedAccessLevels.Keys.OrderBy(x => x.GetAccessGroupName()).ToList();
|
||
|
||
// Add group access buttons to the UI
|
||
foreach (var accessGroup in orderedAccessGroups)
|
||
{
|
||
var accessGroupButton = CreateAccessGroupButton();
|
||
|
||
// Button styling
|
||
if (_groupedAccessLevels.Count > 1)
|
||
{
|
||
if (AccessGroupList.ChildCount == 0)
|
||
accessGroupButton.AddStyleClass(StyleClass.ButtonOpenLeft);
|
||
else if (_groupedAccessLevels.Count > 1 && AccessGroupList.ChildCount == (_groupedAccessLevels.Count - 1))
|
||
accessGroupButton.AddStyleClass(StyleClass.ButtonOpenRight);
|
||
else
|
||
accessGroupButton.AddStyleClass(StyleClass.ButtonOpenBoth);
|
||
}
|
||
|
||
accessGroupButton.Pressed = _accessGroupTabIndex == orderedAccessGroups.IndexOf(accessGroup);
|
||
|
||
// Label text and styling
|
||
if (_labelStyleClass != null)
|
||
accessGroupButton.Label.SetOnlyStyleClass(_labelStyleClass);
|
||
|
||
var accessLevelPrototypes = _groupedAccessLevels[accessGroup];
|
||
var prefix = accessLevelPrototypes.All(x => _activeAccessLevels.Contains(x))
|
||
? "»"
|
||
: accessLevelPrototypes.Any(x => _activeAccessLevels.Contains(x))
|
||
? "›"
|
||
: " ";
|
||
|
||
var text = Loc.GetString(
|
||
"turret-controls-window-access-group-label",
|
||
("prefix", prefix),
|
||
("label", accessGroup.GetAccessGroupName())
|
||
);
|
||
|
||
accessGroupButton.Text = text;
|
||
|
||
// Button events
|
||
accessGroupButton.OnPressed += _ => OnAccessGroupChanged(accessGroupButton.GetPositionInParent());
|
||
|
||
AccessGroupList.AddChild(accessGroupButton);
|
||
}
|
||
|
||
// Adjust the current tab index so it remains in range
|
||
if (_accessGroupTabIndex >= _groupedAccessLevels.Count)
|
||
_accessGroupTabIndex = _groupedAccessLevels.Count - 1;
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Rebuilds the checkbox list for the access level controls.
|
||
/// </summary>
|
||
public void RebuildAccessLevelsControls()
|
||
{
|
||
AccessLevelChecklist.RemoveAllChildren();
|
||
_accessLevelEntries.Clear();
|
||
|
||
// No access level prototypes were assigned to any of the access level groups
|
||
// Either turret controller has no assigned access levels, or their names were invalid
|
||
if (_groupedAccessLevels.Count == 0)
|
||
return;
|
||
|
||
// Reorder the access groups alphabetically
|
||
var orderedAccessGroups = _groupedAccessLevels.Keys.OrderBy(x => x.GetAccessGroupName()).ToList();
|
||
|
||
// Get the access levels associated with the current tab
|
||
var selectedAccessGroupTabProto = orderedAccessGroups[_accessGroupTabIndex];
|
||
_accessLevelsForTab = _groupedAccessLevels[selectedAccessGroupTabProto];
|
||
_accessLevelsForTab = _accessLevelsForTab.OrderBy(x => x.GetAccessLevelName()).ToList();
|
||
|
||
// Add an 'all' checkbox as the first child of the list if it has more than one access level
|
||
// Toggling this checkbox on will mark all other boxes below it on/off
|
||
var allCheckBox = CreateAccessLevelCheckbox();
|
||
allCheckBox.Text = Loc.GetString("turret-controls-window-all-checkbox");
|
||
|
||
if (_labelStyleClass != null)
|
||
allCheckBox.Label.SetOnlyStyleClass(_labelStyleClass);
|
||
|
||
// Add the 'all' checkbox events
|
||
allCheckBox.OnPressed += args =>
|
||
{
|
||
SetCheckBoxPressedState(_accessLevelEntries, allCheckBox.Pressed);
|
||
|
||
var accessLevels = new HashSet<ProtoId<AccessLevelPrototype>>();
|
||
|
||
foreach (var accessLevel in _accessLevelsForTab)
|
||
{
|
||
accessLevels.Add(accessLevel);
|
||
}
|
||
|
||
OnAccessLevelsChangedEvent?.Invoke(accessLevels, allCheckBox.Pressed);
|
||
};
|
||
|
||
AccessLevelChecklist.AddChild(allCheckBox);
|
||
|
||
// Hide the 'all' checkbox if the tab has only one access level
|
||
var allCheckBoxVisible = _accessLevelsForTab.Count > 1;
|
||
|
||
allCheckBox.Visible = allCheckBoxVisible;
|
||
allCheckBox.Disabled = !_canInteract;
|
||
|
||
// Add any remaining missing access level buttons to the UI
|
||
foreach (var accessLevel in _accessLevelsForTab)
|
||
{
|
||
// Create the entry
|
||
var accessLevelEntry = new AccessLevelEntry(_isMonotone);
|
||
|
||
accessLevelEntry.AccessLevel = accessLevel;
|
||
accessLevelEntry.CheckBox.Text = accessLevel.GetAccessLevelName();
|
||
accessLevelEntry.CheckBox.Pressed = _activeAccessLevels.Contains(accessLevel);
|
||
accessLevelEntry.CheckBox.Disabled = !_canInteract;
|
||
|
||
if (_labelStyleClass != null)
|
||
accessLevelEntry.CheckBox.Label.SetOnlyStyleClass(_labelStyleClass);
|
||
|
||
// Set the checkbox linkage lines
|
||
var isEndOfList = _accessLevelsForTab.IndexOf(accessLevel) == (_accessLevelsForTab.Count - 1);
|
||
|
||
var lines = new List<(Vector2, Vector2)>
|
||
{
|
||
(new Vector2(0.5f, 0f), new Vector2(0.5f, isEndOfList ? 0.5f : 1f)),
|
||
(new Vector2(0.5f, 0.5f), new Vector2(1f, 0.5f)),
|
||
};
|
||
|
||
accessLevelEntry.UpdateCheckBoxLink(lines);
|
||
accessLevelEntry.CheckBoxLink.Visible = allCheckBoxVisible;
|
||
accessLevelEntry.CheckBoxLink.Modulate = !_canInteract ? Color.Gray : Color.White;
|
||
|
||
// Add checkbox events
|
||
accessLevelEntry.CheckBox.OnPressed += args =>
|
||
{
|
||
// If the checkbox and its siblings are checked, check the 'all' checkbox too
|
||
allCheckBox.Pressed = AreAllCheckBoxesPressed(_accessLevelEntries.Select(x => x.CheckBox));
|
||
|
||
OnAccessLevelsChangedEvent?.Invoke([accessLevelEntry.AccessLevel], accessLevelEntry.CheckBox.Pressed);
|
||
};
|
||
|
||
AccessLevelChecklist.AddChild(accessLevelEntry);
|
||
_accessLevelEntries.Add(accessLevelEntry);
|
||
}
|
||
|
||
// Press the 'all' checkbox if all others are pressed
|
||
allCheckBox.Pressed = AreAllCheckBoxesPressed(_accessLevelEntries.Select(x => x.CheckBox));
|
||
}
|
||
|
||
private bool AreAllCheckBoxesPressed(IEnumerable<CheckBox> checkBoxes)
|
||
{
|
||
foreach (var checkBox in checkBoxes)
|
||
{
|
||
if (!checkBox.Pressed)
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
private void SetCheckBoxPressedState(List<AccessLevelEntry> accessLevelEntries, bool pressed)
|
||
{
|
||
foreach (var accessLevelEntry in accessLevelEntries)
|
||
{
|
||
accessLevelEntry.CheckBox.Pressed = pressed;
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Provides the UI with a list of access groups using which list of tabs should be populated.
|
||
/// </summary>
|
||
public void SetAccessGroups(HashSet<ProtoId<AccessGroupPrototype>> accessGroups)
|
||
{
|
||
_accessGroups = accessGroups;
|
||
|
||
ArrangeAccessControls();
|
||
|
||
if (TryRebuildAccessGroupControls())
|
||
RebuildAccessLevelsControls();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Provides the UI with a list of access levels with which it can populate the currently selected tab.
|
||
/// </summary>
|
||
public void SetAccessLevels(HashSet<ProtoId<AccessLevelPrototype>> accessLevels)
|
||
{
|
||
_accessLevels = accessLevels;
|
||
|
||
ArrangeAccessControls();
|
||
|
||
if (TryRebuildAccessGroupControls())
|
||
RebuildAccessLevelsControls();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Sets which access level checkboxes should be marked on the UI.
|
||
/// </summary>
|
||
public void SetActiveAccessLevels(HashSet<ProtoId<AccessLevelPrototype>> activeAccessLevels)
|
||
{
|
||
_activeAccessLevels = activeAccessLevels;
|
||
|
||
if (TryRebuildAccessGroupControls())
|
||
RebuildAccessLevelsControls();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Sets whether the local player can interact with the checkboxes.
|
||
/// </summary>
|
||
public void SetLocalPlayerAccessibility(bool canInteract)
|
||
{
|
||
_canInteract = canInteract;
|
||
|
||
if (TryRebuildAccessGroupControls())
|
||
RebuildAccessLevelsControls();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Sets whether the UI should use monotone buttons and checkboxes.
|
||
/// </summary>
|
||
public void SetMonotone(bool monotone)
|
||
{
|
||
_isMonotone = monotone;
|
||
|
||
if (TryRebuildAccessGroupControls())
|
||
RebuildAccessLevelsControls();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Applies the specified style to the labels on the UI buttons and checkboxes.
|
||
/// </summary>
|
||
public void SetLabelStyleClass(string? styleClass)
|
||
{
|
||
_labelStyleClass = styleClass;
|
||
|
||
if (TryRebuildAccessGroupControls())
|
||
RebuildAccessLevelsControls();
|
||
}
|
||
|
||
private void OnAccessGroupChanged(int newTabIndex)
|
||
{
|
||
if (newTabIndex == _accessGroupTabIndex)
|
||
return;
|
||
|
||
_accessGroupTabIndex = newTabIndex;
|
||
|
||
if (TryRebuildAccessGroupControls())
|
||
RebuildAccessLevelsControls();
|
||
}
|
||
|
||
private Button CreateAccessGroupButton()
|
||
{
|
||
var button = _isMonotone ? new MonotoneButton() : new Button();
|
||
|
||
button.ToggleMode = true;
|
||
button.Group = _accessGroupsButtons;
|
||
button.Label.HorizontalAlignment = HAlignment.Left;
|
||
|
||
return button;
|
||
}
|
||
|
||
private CheckBox CreateAccessLevelCheckbox()
|
||
{
|
||
var checkbox = _isMonotone ? new MonotoneCheckBox() : new CheckBox();
|
||
|
||
checkbox.Margin = new Thickness(0, 0, 0, 3);
|
||
checkbox.ToggleMode = true;
|
||
checkbox.ReservesSpace = false;
|
||
|
||
return checkbox;
|
||
}
|
||
|
||
private sealed class AccessLevelEntry : BoxContainer
|
||
{
|
||
public ProtoId<AccessLevelPrototype> AccessLevel;
|
||
public readonly CheckBox CheckBox;
|
||
public readonly LineRenderer CheckBoxLink;
|
||
|
||
public AccessLevelEntry(bool monotone)
|
||
{
|
||
HorizontalExpand = true;
|
||
|
||
CheckBoxLink = new LineRenderer
|
||
{
|
||
SetWidth = 22,
|
||
VerticalExpand = true,
|
||
Margin = new Thickness(0, -1),
|
||
ReservesSpace = false,
|
||
};
|
||
|
||
AddChild(CheckBoxLink);
|
||
|
||
CheckBox = monotone ? new MonotoneCheckBox() : new CheckBox();
|
||
CheckBox.ToggleMode = true;
|
||
CheckBox.Margin = new Thickness(0f, 0f, 0f, 3f);
|
||
|
||
AddChild(CheckBox);
|
||
}
|
||
|
||
public void UpdateCheckBoxLink(List<(Vector2, Vector2)> lines)
|
||
{
|
||
CheckBoxLink.Lines = lines;
|
||
}
|
||
}
|
||
|
||
private sealed class LineRenderer : Control
|
||
{
|
||
/// <summary>
|
||
/// List of lines to render (their start and end x-y coordinates).
|
||
/// Position (0,0) is the top left corner of the control and
|
||
/// position (1,1) is the bottom right corner.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// The color of the lines is inherited from the control.
|
||
/// </remarks>
|
||
public List<(Vector2, Vector2)> Lines;
|
||
|
||
public LineRenderer()
|
||
{
|
||
Lines = new List<(Vector2, Vector2)>();
|
||
}
|
||
|
||
public LineRenderer(List<(Vector2, Vector2)> lines)
|
||
{
|
||
Lines = lines;
|
||
}
|
||
|
||
protected override void Draw(DrawingHandleScreen handle)
|
||
{
|
||
foreach (var line in Lines)
|
||
{
|
||
var start = PixelPosition +
|
||
new Vector2(PixelWidth * line.Item1.X, PixelHeight * line.Item1.Y);
|
||
|
||
var end = PixelPosition +
|
||
new Vector2(PixelWidth * line.Item2.X, PixelHeight * line.Item2.Y);
|
||
|
||
handle.DrawLine(start, end, ActualModulateSelf);
|
||
}
|
||
}
|
||
}
|
||
}
|