Guidebook can POP OUT YAYYYY (#20268)
* Let them eat cake * Reviews * Change amoled theme to gray * Ok nevermind im big smart
This commit is contained in:
36
Content.Client/Guidebook/Controls/GuidebookControl.xaml
Normal file
36
Content.Client/Guidebook/Controls/GuidebookControl.xaml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<Control xmlns="https://spacestation14.io"
|
||||||
|
xmlns:fancyTree="clr-namespace:Content.Client.UserInterface.Controls.FancyTree"
|
||||||
|
xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||||
|
xmlns:graphics="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||||
|
SetSize="750 700"
|
||||||
|
MinSize="100 200">
|
||||||
|
<PanelContainer StyleClasses="BackgroundDark">
|
||||||
|
<SplitContainer Orientation="Horizontal" HorizontalExpand="True" Name="Split">
|
||||||
|
<!-- Guide select -->
|
||||||
|
<BoxContainer Orientation="Vertical" Name="TreeBox">
|
||||||
|
<fancyTree:FancyTree Name="Tree" VerticalExpand="True" HorizontalExpand="True" Access="Public"/>
|
||||||
|
<Button Name="PopOutButton" HorizontalAlignment="Left" VerticalAlignment="Bottom" Access="Public" Text="{Loc admin-logs-pop-out}"/>
|
||||||
|
<customControls:VSeparator StyleClasses="LowDivider" Margin="0 -2"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
|
||||||
|
<BoxContainer Name="SearchContainer" Visible="False" HorizontalExpand="True">
|
||||||
|
<LineEdit
|
||||||
|
Name="SearchBar"
|
||||||
|
PlaceHolder="{Loc 'guidebook-filter-placeholder-text'}"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
Margin="0 5 10 5">
|
||||||
|
</LineEdit>
|
||||||
|
</BoxContainer>
|
||||||
|
<ScrollContainer Name="Scroll" HScrollEnabled="False" HorizontalExpand="True" VerticalExpand="True">
|
||||||
|
<Control>
|
||||||
|
<BoxContainer Orientation="Vertical" Name="EntryContainer" Margin="5 5 5 5" Visible="False"/>
|
||||||
|
<BoxContainer Orientation="Vertical" Name="Placeholder" Margin="5 5 5 5">
|
||||||
|
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Loc 'guidebook-placeholder-text'}"/>
|
||||||
|
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Loc 'guidebook-placeholder-text-2'}"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</Control>
|
||||||
|
</ScrollContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</SplitContainer>
|
||||||
|
</PanelContainer>
|
||||||
|
</Control>
|
||||||
187
Content.Client/Guidebook/Controls/GuidebookControl.xaml.cs
Normal file
187
Content.Client/Guidebook/Controls/GuidebookControl.xaml.cs
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Client.Guidebook.RichText;
|
||||||
|
using Content.Client.UserInterface.ControlExtensions;
|
||||||
|
using Content.Client.UserInterface.Controls.FancyTree;
|
||||||
|
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.ContentPack;
|
||||||
|
|
||||||
|
namespace Content.Client.Guidebook.Controls;
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class GuidebookControl : Control, ILinkClickHandler
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IResourceManager _resourceManager = default!;
|
||||||
|
[Dependency] private readonly DocumentParsingManager _parsingMan = default!;
|
||||||
|
|
||||||
|
private Dictionary<string, GuideEntry> _entries = new();
|
||||||
|
|
||||||
|
public GuidebookControl()
|
||||||
|
{
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
|
Tree.OnSelectedItemChanged += OnSelectionChanged;
|
||||||
|
|
||||||
|
SearchBar.OnTextChanged += _ =>
|
||||||
|
{
|
||||||
|
HandleFilter();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private IClydeWindow? ClydeWindow { get; set; }
|
||||||
|
|
||||||
|
private void OnSelectionChanged(TreeItem? item)
|
||||||
|
{
|
||||||
|
if (item != null && item.Metadata is GuideEntry entry)
|
||||||
|
ShowGuide(entry);
|
||||||
|
else
|
||||||
|
ClearSelectedGuide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearSelectedGuide()
|
||||||
|
{
|
||||||
|
Placeholder.Visible = true;
|
||||||
|
EntryContainer.Visible = false;
|
||||||
|
SearchContainer.Visible = false;
|
||||||
|
EntryContainer.RemoveAllChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowGuide(GuideEntry entry)
|
||||||
|
{
|
||||||
|
Scroll.SetScrollValue(default);
|
||||||
|
Placeholder.Visible = false;
|
||||||
|
EntryContainer.Visible = true;
|
||||||
|
SearchBar.Text = "";
|
||||||
|
EntryContainer.RemoveAllChildren();
|
||||||
|
using var file = _resourceManager.ContentFileReadText(entry.Text);
|
||||||
|
|
||||||
|
SearchContainer.Visible = entry.FilterEnabled;
|
||||||
|
|
||||||
|
if (!_parsingMan.TryAddMarkup(EntryContainer, file.ReadToEnd()))
|
||||||
|
{
|
||||||
|
EntryContainer.AddChild(new Label() { Text = "ERROR: Failed to parse document." });
|
||||||
|
Logger.Error($"Failed to parse contents of guide document {entry.Id}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateGuides(
|
||||||
|
Dictionary<string, GuideEntry> entries,
|
||||||
|
List<string>? rootEntries = null,
|
||||||
|
string? forceRoot = null,
|
||||||
|
string? selected = null)
|
||||||
|
{
|
||||||
|
_entries = entries;
|
||||||
|
RepopulateTree(rootEntries, forceRoot);
|
||||||
|
ClearSelectedGuide();
|
||||||
|
|
||||||
|
Split.State = SplitContainer.SplitState.Auto;
|
||||||
|
if (entries.Count == 1)
|
||||||
|
{
|
||||||
|
TreeBox.Visible = false;
|
||||||
|
Split.ResizeMode = SplitContainer.SplitResizeMode.NotResizable;
|
||||||
|
selected = entries.Keys.First();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TreeBox.Visible = true;
|
||||||
|
Split.ResizeMode = SplitContainer.SplitResizeMode.RespectChildrenMinSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected != null)
|
||||||
|
{
|
||||||
|
var item = Tree.Items.FirstOrDefault(x => x.Metadata is GuideEntry entry && entry.Id == selected);
|
||||||
|
Tree.SetSelectedIndex(item?.Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<GuideEntry> GetSortedRootEntries(List<string>? rootEntries)
|
||||||
|
{
|
||||||
|
if (rootEntries == null)
|
||||||
|
{
|
||||||
|
HashSet<string> entries = new(_entries.Keys);
|
||||||
|
foreach (var entry in _entries.Values)
|
||||||
|
{
|
||||||
|
entries.ExceptWith(entry.Children);
|
||||||
|
}
|
||||||
|
rootEntries = entries.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootEntries
|
||||||
|
.Select(x => _entries[x])
|
||||||
|
.OrderBy(x => x.Priority)
|
||||||
|
.ThenBy(x => Loc.GetString(x.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RepopulateTree(List<string>? roots = null, string? forcedRoot = null)
|
||||||
|
{
|
||||||
|
Tree.Clear();
|
||||||
|
|
||||||
|
HashSet<string> addedEntries = new();
|
||||||
|
|
||||||
|
TreeItem? parent = forcedRoot == null ? null : AddEntry(forcedRoot, null, addedEntries);
|
||||||
|
foreach (var entry in GetSortedRootEntries(roots))
|
||||||
|
{
|
||||||
|
AddEntry(entry.Id, parent, addedEntries);
|
||||||
|
}
|
||||||
|
Tree.SetAllExpanded(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeItem? AddEntry(string id, TreeItem? parent, HashSet<string> addedEntries)
|
||||||
|
{
|
||||||
|
if (!_entries.TryGetValue(id, out var entry))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!addedEntries.Add(id))
|
||||||
|
{
|
||||||
|
Logger.Error($"Adding duplicate guide entry: {id}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var item = Tree.AddItem(parent);
|
||||||
|
item.Metadata = entry;
|
||||||
|
var name = Loc.GetString(entry.Name);
|
||||||
|
item.Label.Text = name;
|
||||||
|
|
||||||
|
foreach (var child in entry.Children)
|
||||||
|
{
|
||||||
|
AddEntry(child, item, addedEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleClick(string link)
|
||||||
|
{
|
||||||
|
if (!_entries.TryGetValue(link, out var entry))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Tree.TryGetIndexFromMetadata(entry, out var index))
|
||||||
|
{
|
||||||
|
Tree.ExpandParentEntries(index.Value);
|
||||||
|
Tree.SetSelectedIndex(index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ShowGuide(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleFilter()
|
||||||
|
{
|
||||||
|
var emptySearch = SearchBar.Text.Trim().Length == 0;
|
||||||
|
|
||||||
|
if (Tree.SelectedItem != null && Tree.SelectedItem.Metadata is GuideEntry entry && entry.FilterEnabled)
|
||||||
|
{
|
||||||
|
var foundElements = EntryContainer.GetSearchableControls();
|
||||||
|
|
||||||
|
foreach (var element in foundElements)
|
||||||
|
{
|
||||||
|
element.SetHiddenState(true, SearchBar.Text.Trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,34 +2,8 @@
|
|||||||
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||||
xmlns:fancyTree="clr-namespace:Content.Client.UserInterface.Controls.FancyTree"
|
xmlns:fancyTree="clr-namespace:Content.Client.UserInterface.Controls.FancyTree"
|
||||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
SetSize="750 700"
|
xmlns:controls1="clr-namespace:Content.Client.Guidebook.Controls"
|
||||||
MinSize="100 200"
|
|
||||||
Resizable="True"
|
Resizable="True"
|
||||||
Title="{Loc 'guidebook-window-title'}">
|
Title="{Loc 'guidebook-window-title'}">
|
||||||
<SplitContainer Orientation="Horizontal" HorizontalExpand="True" Name="Split">
|
<controls1:GuidebookControl Name="Guidebook" Access="Public"/>
|
||||||
<!-- Guide select -->
|
|
||||||
<BoxContainer Orientation="Horizontal" Name="TreeBox">
|
|
||||||
<fancyTree:FancyTree Name="Tree" VerticalExpand="True" HorizontalExpand="True" Access="Public"/>
|
|
||||||
<cc:VSeparator StyleClasses="LowDivider" Margin="0 -2"/>
|
|
||||||
</BoxContainer>
|
|
||||||
<BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
|
|
||||||
<BoxContainer Name="SearchContainer" Visible="False" HorizontalExpand="True">
|
|
||||||
<LineEdit
|
|
||||||
Name="SearchBar"
|
|
||||||
PlaceHolder="{Loc 'guidebook-filter-placeholder-text'}"
|
|
||||||
HorizontalExpand="True"
|
|
||||||
Margin="0 5 10 5">
|
|
||||||
</LineEdit>
|
|
||||||
</BoxContainer>
|
|
||||||
<ScrollContainer Name="Scroll" HScrollEnabled="False" HorizontalExpand="True" VerticalExpand="True">
|
|
||||||
<Control>
|
|
||||||
<BoxContainer Orientation="Vertical" Name="EntryContainer" Margin="5 5 5 5" Visible="False"/>
|
|
||||||
<BoxContainer Orientation="Vertical" Name="Placeholder" Margin="5 5 5 5">
|
|
||||||
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Loc 'guidebook-placeholder-text'}"/>
|
|
||||||
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Loc 'guidebook-placeholder-text-2'}"/>
|
|
||||||
</BoxContainer>
|
|
||||||
</Control>
|
|
||||||
</ScrollContainer>
|
|
||||||
</BoxContainer>
|
|
||||||
</SplitContainer>
|
|
||||||
</controls:FancyWindow>
|
</controls:FancyWindow>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Content.Client.UserInterface.Controls;
|
|||||||
using Content.Client.UserInterface.Controls.FancyTree;
|
using Content.Client.UserInterface.Controls.FancyTree;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
@@ -14,175 +15,6 @@ using Robust.Shared.ContentPack;
|
|||||||
namespace Content.Client.Guidebook.Controls;
|
namespace Content.Client.Guidebook.Controls;
|
||||||
|
|
||||||
[GenerateTypedNameReferences]
|
[GenerateTypedNameReferences]
|
||||||
public sealed partial class GuidebookWindow : FancyWindow, ILinkClickHandler
|
public sealed partial class GuidebookWindow : FancyWindow
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IResourceManager _resourceManager = default!;
|
|
||||||
[Dependency] private readonly DocumentParsingManager _parsingMan = default!;
|
|
||||||
|
|
||||||
private Dictionary<string, GuideEntry> _entries = new();
|
|
||||||
|
|
||||||
public GuidebookWindow()
|
|
||||||
{
|
|
||||||
RobustXamlLoader.Load(this);
|
|
||||||
IoCManager.InjectDependencies(this);
|
|
||||||
|
|
||||||
Tree.OnSelectedItemChanged += OnSelectionChanged;
|
|
||||||
|
|
||||||
SearchBar.OnTextChanged += _ =>
|
|
||||||
{
|
|
||||||
HandleFilter();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSelectionChanged(TreeItem? item)
|
|
||||||
{
|
|
||||||
if (item != null && item.Metadata is GuideEntry entry)
|
|
||||||
ShowGuide(entry);
|
|
||||||
else
|
|
||||||
ClearSelectedGuide();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearSelectedGuide()
|
|
||||||
{
|
|
||||||
Placeholder.Visible = true;
|
|
||||||
EntryContainer.Visible = false;
|
|
||||||
SearchContainer.Visible = false;
|
|
||||||
EntryContainer.RemoveAllChildren();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ShowGuide(GuideEntry entry)
|
|
||||||
{
|
|
||||||
Scroll.SetScrollValue(default);
|
|
||||||
Placeholder.Visible = false;
|
|
||||||
EntryContainer.Visible = true;
|
|
||||||
SearchBar.Text = "";
|
|
||||||
EntryContainer.RemoveAllChildren();
|
|
||||||
using var file = _resourceManager.ContentFileReadText(entry.Text);
|
|
||||||
|
|
||||||
SearchContainer.Visible = entry.FilterEnabled;
|
|
||||||
|
|
||||||
if (!_parsingMan.TryAddMarkup(EntryContainer, file.ReadToEnd()))
|
|
||||||
{
|
|
||||||
EntryContainer.AddChild(new Label() { Text = "ERROR: Failed to parse document." });
|
|
||||||
Logger.Error($"Failed to parse contents of guide document {entry.Id}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateGuides(
|
|
||||||
Dictionary<string, GuideEntry> entries,
|
|
||||||
List<string>? rootEntries = null,
|
|
||||||
string? forceRoot = null,
|
|
||||||
string? selected = null)
|
|
||||||
{
|
|
||||||
_entries = entries;
|
|
||||||
RepopulateTree(rootEntries, forceRoot);
|
|
||||||
ClearSelectedGuide();
|
|
||||||
|
|
||||||
Split.State = SplitContainer.SplitState.Auto;
|
|
||||||
if (entries.Count == 1)
|
|
||||||
{
|
|
||||||
TreeBox.Visible = false;
|
|
||||||
Split.ResizeMode = SplitContainer.SplitResizeMode.NotResizable;
|
|
||||||
selected = entries.Keys.First();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TreeBox.Visible = true;
|
|
||||||
Split.ResizeMode = SplitContainer.SplitResizeMode.RespectChildrenMinSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selected != null)
|
|
||||||
{
|
|
||||||
var item = Tree.Items.FirstOrDefault(x => x.Metadata is GuideEntry entry && entry.Id == selected);
|
|
||||||
Tree.SetSelectedIndex(item?.Index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<GuideEntry> GetSortedRootEntries(List<string>? rootEntries)
|
|
||||||
{
|
|
||||||
if (rootEntries == null)
|
|
||||||
{
|
|
||||||
HashSet<string> entries = new(_entries.Keys);
|
|
||||||
foreach (var entry in _entries.Values)
|
|
||||||
{
|
|
||||||
entries.ExceptWith(entry.Children);
|
|
||||||
}
|
|
||||||
rootEntries = entries.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return rootEntries
|
|
||||||
.Select(x => _entries[x])
|
|
||||||
.OrderBy(x => x.Priority)
|
|
||||||
.ThenBy(x => Loc.GetString(x.Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RepopulateTree(List<string>? roots = null, string? forcedRoot = null)
|
|
||||||
{
|
|
||||||
Tree.Clear();
|
|
||||||
|
|
||||||
HashSet<string> addedEntries = new();
|
|
||||||
|
|
||||||
TreeItem? parent = forcedRoot == null ? null : AddEntry(forcedRoot, null, addedEntries);
|
|
||||||
foreach (var entry in GetSortedRootEntries(roots))
|
|
||||||
{
|
|
||||||
AddEntry(entry.Id, parent, addedEntries);
|
|
||||||
}
|
|
||||||
Tree.SetAllExpanded(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TreeItem? AddEntry(string id, TreeItem? parent, HashSet<string> addedEntries)
|
|
||||||
{
|
|
||||||
if (!_entries.TryGetValue(id, out var entry))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (!addedEntries.Add(id))
|
|
||||||
{
|
|
||||||
Logger.Error($"Adding duplicate guide entry: {id}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var item = Tree.AddItem(parent);
|
|
||||||
item.Metadata = entry;
|
|
||||||
var name = Loc.GetString(entry.Name);
|
|
||||||
item.Label.Text = name;
|
|
||||||
|
|
||||||
foreach (var child in entry.Children)
|
|
||||||
{
|
|
||||||
AddEntry(child, item, addedEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleClick(string link)
|
|
||||||
{
|
|
||||||
if (!_entries.TryGetValue(link, out var entry))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Tree.TryGetIndexFromMetadata(entry, out var index))
|
|
||||||
{
|
|
||||||
Tree.ExpandParentEntries(index.Value);
|
|
||||||
Tree.SetSelectedIndex(index);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ShowGuide(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleFilter()
|
|
||||||
{
|
|
||||||
var emptySearch = SearchBar.Text.Trim().Length == 0;
|
|
||||||
|
|
||||||
if (Tree.SelectedItem != null && Tree.SelectedItem.Metadata is GuideEntry entry && entry.FilterEnabled)
|
|
||||||
{
|
|
||||||
var foundElements = EntryContainer.GetSearchableControls();
|
|
||||||
|
|
||||||
foreach (var element in foundElements)
|
|
||||||
{
|
|
||||||
element.SetHiddenState(true, SearchBar.Text.Trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Client.Guidebook.Controls;
|
|||||||
using Content.Client.Lobby;
|
using Content.Client.Lobby;
|
||||||
using Content.Client.UserInterface.Controls;
|
using Content.Client.UserInterface.Controls;
|
||||||
using Content.Shared.Input;
|
using Content.Shared.Input;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.UserInterface;
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controllers;
|
using Robust.Client.UserInterface.Controllers;
|
||||||
using static Robust.Client.UserInterface.Controls.BaseButton;
|
using static Robust.Client.UserInterface.Controls.BaseButton;
|
||||||
@@ -17,7 +18,11 @@ namespace Content.Client.UserInterface.Systems.Guidebook;
|
|||||||
public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyState>, IOnStateEntered<GameplayState>, IOnStateExited<LobbyState>, IOnStateExited<GameplayState>, IOnSystemChanged<GuidebookSystem>
|
public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyState>, IOnStateEntered<GameplayState>, IOnStateExited<LobbyState>, IOnStateExited<GameplayState>, IOnSystemChanged<GuidebookSystem>
|
||||||
{
|
{
|
||||||
[UISystemDependency] private readonly GuidebookSystem _guidebookSystem = default!;
|
[UISystemDependency] private readonly GuidebookSystem _guidebookSystem = default!;
|
||||||
|
[Dependency] private readonly IClyde _clyde = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
|
||||||
|
|
||||||
|
private IClydeWindow? ClydeWindow { get; set; }
|
||||||
|
|
||||||
private GuidebookWindow? _guideWindow;
|
private GuidebookWindow? _guideWindow;
|
||||||
private MenuButton? GuidebookButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.GuidebookButton;
|
private MenuButton? GuidebookButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.GuidebookButton;
|
||||||
@@ -40,6 +45,7 @@ public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyS
|
|||||||
_guideWindow = UIManager.CreateWindow<GuidebookWindow>();
|
_guideWindow = UIManager.CreateWindow<GuidebookWindow>();
|
||||||
_guideWindow.OnClose += OnWindowClosed;
|
_guideWindow.OnClose += OnWindowClosed;
|
||||||
_guideWindow.OnOpen += OnWindowOpen;
|
_guideWindow.OnOpen += OnWindowOpen;
|
||||||
|
_guideWindow.Guidebook.PopOutButton.OnPressed += _ => PopOut();
|
||||||
|
|
||||||
// setup keybinding
|
// setup keybinding
|
||||||
CommandBinds.Builder
|
CommandBinds.Builder
|
||||||
@@ -135,7 +141,12 @@ public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyS
|
|||||||
string? selected = null)
|
string? selected = null)
|
||||||
{
|
{
|
||||||
if (_guideWindow == null)
|
if (_guideWindow == null)
|
||||||
return;
|
{
|
||||||
|
_guideWindow = UIManager.CreateWindow<GuidebookWindow>();
|
||||||
|
_guideWindow.OnClose += OnWindowClosed;
|
||||||
|
_guideWindow.OnOpen += OnWindowOpen;
|
||||||
|
_guideWindow.Guidebook.PopOutButton.OnPressed += _ => PopOut();
|
||||||
|
}
|
||||||
|
|
||||||
if (_guideWindow.IsOpen)
|
if (_guideWindow.IsOpen)
|
||||||
{
|
{
|
||||||
@@ -161,11 +172,11 @@ public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_guideWindow.UpdateGuides(guides, rootEntries, forceRoot, selected);
|
_guideWindow.Guidebook.UpdateGuides(guides, rootEntries, forceRoot, selected);
|
||||||
|
|
||||||
// Expand up to depth-2.
|
// Expand up to depth-2.
|
||||||
_guideWindow.Tree.SetAllExpanded(false);
|
_guideWindow.Guidebook.Tree.SetAllExpanded(false);
|
||||||
_guideWindow.Tree.SetAllExpanded(true, 1);
|
_guideWindow.Guidebook.Tree.SetAllExpanded(true, 1);
|
||||||
|
|
||||||
_guideWindow.OpenCenteredRight();
|
_guideWindow.OpenCenteredRight();
|
||||||
}
|
}
|
||||||
@@ -208,4 +219,43 @@ public sealed class GuidebookUIController : UIController, IOnStateEntered<LobbyS
|
|||||||
RecursivelyAddChildren(child, guides);
|
RecursivelyAddChildren(child, guides);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private void PopOut()
|
||||||
|
{
|
||||||
|
if (_guideWindow == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var monitor = _clyde.EnumerateMonitors().First();
|
||||||
|
|
||||||
|
ClydeWindow = _clyde.CreateWindow(new WindowCreateParameters
|
||||||
|
{
|
||||||
|
Maximized = false,
|
||||||
|
Title = "Guidebook",
|
||||||
|
Monitor = monitor,
|
||||||
|
Width = 750,
|
||||||
|
Height = 700
|
||||||
|
});
|
||||||
|
var control = _guideWindow.Guidebook;
|
||||||
|
control.Orphan();
|
||||||
|
_guideWindow.Dispose();
|
||||||
|
_guideWindow = null;
|
||||||
|
|
||||||
|
ClydeWindow.RequestClosed += OnRequestClosed;
|
||||||
|
|
||||||
|
ClydeWindow.DisposeOnClose = true;
|
||||||
|
var Root = _uiManager.CreateWindowRoot(ClydeWindow);
|
||||||
|
Root.AddChild(control);
|
||||||
|
|
||||||
|
control.PopOutButton.Disabled = true;
|
||||||
|
control.PopOutButton.Visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRequestClosed(WindowRequestClosedEventArgs obj)
|
||||||
|
{
|
||||||
|
ClydeWindow = null;
|
||||||
|
_guideWindow = null;
|
||||||
|
if (GuidebookButton != null)
|
||||||
|
GuidebookButton.Pressed = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
defaultWindowTitle: Space Station 14
|
defaultWindowTitle: Space Station 14
|
||||||
windowIconSet: /Textures/Logo/icon
|
windowIconSet: /Textures/Logo/icon
|
||||||
splashLogo: /Textures/Logo/logo.png
|
splashLogo: /Textures/Logo/logo.png
|
||||||
|
multiWindow: true
|
||||||
|
|
||||||
# PJB PLEASE
|
# PJB PLEASE
|
||||||
|
|||||||
Reference in New Issue
Block a user