diff --git a/docs/Guides/User Interface/robust-xaml.md b/docs/Guides/User Interface/robust-xaml.md new file mode 100644 index 0000000..3831d6b --- /dev/null +++ b/docs/Guides/User Interface/robust-xaml.md @@ -0,0 +1,428 @@ +--- +authors: [portfiend] +tags: + - guides + - ui + +slug: /Guides/UserInterface/robust-xaml +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Robust XAML + +According to Wizard's Den's [Conventions](https://docs.spacestation14.com/en/general-development/codebase-info/conventions.html#xaml-and-c-defined-uis) documentation, all new UI controls should be defined in Robust XAML rather than entirely via C#. Robust XAML is our engine's way of being able to define the structure of UI controls in `.xaml` files, which is then generated and given logic by an accompanying `.xaml.cs` file. + +This guide covers making new controls using Robust XAML, that is to say, the actual visual elements of an interface that are displayed to players. It does not cover how to create an entire new interface from scratch and handle opening/closing it - but we recommend looking into `UIController` and `BoundUserInterface` if you want to learn how to do this. + +**Relevant reading:** +- [User Interface - Space Wizards Development Wiki](https://docs.spacestation14.com/en/robust-toolbox/user-interface.html) +- [User Interface - Containers - Space Wizards Development Wiki](https://docs.spacestation14.com/en/robust-toolbox/user-interface/containers.html) + +## Controls + +A "Control" is a unit of a user interface in Space Station 14 and Robust Toolbox (our engine). This unit ranges from individual buttons or text (Labels) to an entire UI window - controls can contain other controls. + +When you open the "Options" window, it has tabs, buttons, labels, and checkboxes, sorted into containers to arrange their layout. All of these individually are controls. The options window itself, which contains these controls, is also a control. + +![A screenshot of the SS14 options window. It has multiple tabs, labels, buttons, and checkbox inputs, among other things - all of these are considered controls.](/img/docs/guides/robust-xaml-options-menu.png) + +Controls are defined as classes in C# code. All controls extend another control class - at the most base level, a control may inherit from `Control`, the most bare-minimum representation of a UI control. `OptionsMenu` is an example of a control defined with Robust XAML - it has a `OptionsMenu.xaml.cs` and an `OptionsMenu.xaml` file, both found at `Content.Client/Options/UI/`. + + + + +```cs +// Content.Client/Options/UI/OptionsMenu.xaml.cs +namespace Content.Client.Options.UI; + +[GenerateTypedNameReferences] +public sealed partial class OptionsMenu : DefaultWindow +``` + + + + +```xml + + + + + + + + + + + +``` + + + + +## XAML + +XAML stands for **[Extensible Application Markup Language](https://en.wikipedia.org/wiki/Extensible_Application_Markup_Language)** - it's the language we use to describe the basic structure and properties of a UI control in Robust Toolbox. You may be familiar with **HTML**, the language used to define the structure of webpages, which are then stylized using CSS stylesheets and given functionality via Javascript, PHP, or other programming languages. XAML, and Robust XAML, takes on a similar structure. + +XAML markup is defined as **elements**, defined by tags enclosed in angle brackets (`<>`). The closing tag must have a `/` after the opening (`<`) bracket. Whitespace doesn't matter - you can use line breaks, indentation, and spacing to visually organize the code of these elements. + +Elements may be declared as a single, self-closing tag by ending it in `/>`, for elements that do not contain other elements. + +```xml + + + +``` + +XAML elements may have **attributes**, defined in the opening tag as an attribute name that equals (`=`) some value. In Robust XAML, XAML attributes are used to modify the value of fields. + +```xml + +``` + +Top-level XAML elements (that is: the XAML element that contains all other elements in the XAML file) have a special type of attribute known as a **namespace**. These are defined in the `xmlns` property, or `xmlns:[name]` if you want to add additional namespaces, such as the `OptionsMenu` above: + +```xml + +``` + +All Space Station 14 Robust XAML controls need to have a namespace of `xmlns="https://spacestation14.io"`. If you define additional namespaces, controls from those namespaces can be used by prefixing it with the namespace ID behind a colon (`:`): + +```xml + +``` + +Finally, comments can be defined with ``: + +```xml + +``` + +## Making a Robust XAML control + +All UI work is done in the `Content.Client` directory. All controls can technically be defined in pure C#, but as mentioned, this is against convention for new UI work - so let's try defining a new Robust XAML control. + +Here is a bare-minimum example of a UI control - for the sake of example, this is found at `Content.Client/_MACRO/Test/UI/`. + + + + +```cs +// Content.Client/_MACRO/Test/UI/NewControl.xaml.cs +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._MACRO.Test.UI; + +public sealed partial class NewControl : Label +{ + public NewControl() + { + RobustXamlLoader.Load(this); + } +} +``` + + + + +```xml + + + + +Our features of note here: +- In the XAML file, we are using the `xmlns="https://spacestation14.io"` namespace. This is required. +- The namespace of `NewControl` must match the directory path that it is found in. +- `NewControl` extends the `Label` UI control. This must match the top-level control of the XAML file. +- `NewControl` must have a constructor with empty parameters (`public NewControl()`) if you would like to use it in other `.xaml` files, as Robust XAML does not allow you to initiate controls with parameters. +- `NewControl` must call `RobustXamlLoader.Load(this);` to pull XAML data from its accompanying `.xaml` file. + +This class doesn't have to be `partial` (for now), but it's highly recommended to make it `partial` anyway, as this makes UI work on downstreams easier and also allows you to use `[GenerateTypedNameReferences]`. + +### Named Controls + +All controls support a `Name` field, which can be used in C# logic with the `[GenerateTypedNameReferences]` to reference that control. Imagine that all named controls are assigned to fields implicitly. Controls with the `[GenerateTypedNameReferences]` attribute *must* be `partial`. + +For example: + + + + +```cs +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client._MACRO.Test.UI; + +[GenerateTypedNameReferences] +public sealed partial class NewControl : BoxContainer +{ + public NewControl() + { + RobustXamlLoader.Load(this); + + // TitleLabel is derived from Name="TitleLabel" + TitleLabel.Text = Loc.GetString("ui-new-control-title"); + } +} +``` + + + + +```xml + + +``` + + + + +:::tip + +You can populate label values with localized strings without using C#, as so: + +```xml +