From b68f13d70d8e11a4558806ed56c0c5019c6637ac Mon Sep 17 00:00:00 2001 From: Brandon Li Date: Sat, 20 Jul 2024 15:35:29 -0400 Subject: [PATCH 1/5] move `Layout Controls` section to `containers.md` --- src/SUMMARY.md | 1 + src/en/robust-toolbox/user-interface.md | 20 ------ .../user-interface/containers.md | 72 +++++++++++++++++++ 3 files changed, 73 insertions(+), 20 deletions(-) create mode 100644 src/en/robust-toolbox/user-interface/containers.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 825ae259e..214492024 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -78,6 +78,7 @@ Robust Toolbox - [General](en/robust-toolbox/toolshed/commands/general.md) - [Miscellaneous](en/robust-toolbox/toolshed/commands/misc.md) - [User Interface](en/robust-toolbox/user-interface.md) + - [Containers](en/robust-toolbox/user-interface/containers.md) - [IoC](en/robust-toolbox/ioc.md) - [Rendering]() - [Lighting and FoV](en/robust-toolbox/rendering/lighting-and-fov.md) diff --git a/src/en/robust-toolbox/user-interface.md b/src/en/robust-toolbox/user-interface.md index 29a999465..b02d8924f 100644 --- a/src/en/robust-toolbox/user-interface.md +++ b/src/en/robust-toolbox/user-interface.md @@ -142,26 +142,6 @@ There are other useful layout properties you can use to influence layout of an i * `SetSize`/`SetWidth`/`SetHeight`: Allows you to set a specific size for a control. * `Margin`: Allows you to set a margin of blank space around a control. -## Layout Controls - -There are many controls whose sole purpose is to lay their children out in a certain way, and otherwise be invisible. This section will go over some of them. - -### `BoxContainer` - -`BoxContainer` is perhaps one of the simplest layout controls there is. It lays out its children sequentially in a certain `Orientation`, either vertically or horizontally. Controls do not overlap. - -### `GridContainer` - -`GridContainer` lays out its children in a configurable grid. - -### `ScrollContainer` - -TODO - -### `LayoutContainer` - -TODO - ## Common Attributes These attributes are present on most layout controls. ### Margin diff --git a/src/en/robust-toolbox/user-interface/containers.md b/src/en/robust-toolbox/user-interface/containers.md new file mode 100644 index 000000000..1c0c2e651 --- /dev/null +++ b/src/en/robust-toolbox/user-interface/containers.md @@ -0,0 +1,72 @@ +# Container Controls + +There are many controls whose sole purpose is to lay their children out in a certain way, and otherwise be invisible. This section will go over some of them. + +This is not a complete list, but it does cover the most commonly used ones. If you would like to complete this list and PR it that would be appreciated :). + +## `BoxContainer` + +`BoxContainer` is perhaps one of the simplest layout controls there is. It lays out its children sequentially in a certain `Orientation`, either vertically or horizontally. Controls do not overlap. + +```admonish warning +You MUST include a `Orientation` for the `BoxContainer` to work. +``` + +| Field | Type | Effective Default Value | Description | +| -------------------- | ------------------- | ----------------------- | ----------------------------------------------------------- | +| `Orientation` | `LayoutOrientation` | | Whether to arrange the elements horizontally or vertically. | +| `Align` | `AlignMode` | | The alignment of the children along the orientation axis. | +| `SeparationOverride` | `int` | `0` | The separation between elements. | + +## `GridContainer` + +`GridContainer` lays out its children in a configurable grid. + +| Field | Type | Effective Default Value | Description | +| --------------------- | ------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| `Columns` | `int` | | The number of columns to organize the children into. | +| `Rows` | `int` | | The number of rows to organize the children into. | +| `MaxGridWidth` | `float` | | The maximum width of the grid of elements, and dynamically determines the number of columns based on the size of the elements. | +| `MaxGridHeight` | `float` | | The maximum height of the grid, and dynamically determines the number of rows based on the size of the elements | +| `VSeparationOverride` | `int` | `0` | The vertical separation between elements. | +| `HSeparationOverride` | `int` | `0` | The horizontal separation between elements. | +| `ExpandBackwards` | `bool` | `false` | Whether to expand the grid backwards, i.e. from the bottom-right to the top-left. | + +## `ScrollContainer` + +`ScrollContainer` is a container that shows a slice of its children, with scrollbars to scroll through the rest. You've seen a scrollbar before you know what this is. + +| Field | Type | Effective Default Value | Description | +| ----------------------- | ------ | ----------------------- | --------------------------------------------------------------------------- | +| `FallbackDeltaScroll` | `bool` | `false` | If true, if we have a y-axis scroll it will convert it to an x-axis scroll. | +| `ScrollSpeedX` | `int` | `50` | The scroll speed in the x-direction. | +| `ScrollSpeedY` | `int` | `50` | The scroll speed in the y-direction. | +| `ReserveScrollbarSpace` | `bool` | `true` | Whether the scrollbar will take up space in the layout | +| `ReturnMeasure` | `bool` | `false` | _TODO: I do not know what this does_ | +| `VScrollEnabled` | `bool` | `true` | Whether vertical scrolling is enabled. | +| `HScrollEnabled` | `bool` | `true` | Whether horizontal scrolling is enabled. | + +### `LayoutContainer` + +`LayoutContainer` helps in complicated layouts by arranging its children. + +| Field | Type | Effective Default Value | Description | +| --------------------- | ------- | ----------------------- | ------------------------------------------------------------------------------------------ | +| `AnchorBegin` | `float` | `0` | The value of an anchor that is at the beginning of the layout. | +| `AnchorEnd` | `float` | `1` | The value of an anchor that is at the end of the layout. | +| `InheritChildMeasure` | `bool` | `true` | If true, measurements of this control will be at least the size of any contained controls. | + +Then children of the `LayoutContainer` may use to following fields to control their layout: + +| Field | Type | +| ---------------- | ------- | +| `MarginLeft` | `float` | +| `MarginTop` | `float` | +| `MarginRight` | `float` | +| `MarginBottom` | `float` | +| `AnchorLeft` | `float` | +| `AnchorTop` | `float` | +| `AnchorRight` | `float` | +| `AnchorBottom` | `float` | +| `GrowHorizontal` | `bool` | +| `GrowVertical` | `bool` | From 96a16e714b8c656d2aa64624b8ed3ad2c28b043b Mon Sep 17 00:00:00 2001 From: Brandon Li Date: Sat, 20 Jul 2024 15:35:55 -0400 Subject: [PATCH 2/5] add convention warning --- src/en/robust-toolbox/user-interface.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/en/robust-toolbox/user-interface.md b/src/en/robust-toolbox/user-interface.md index b02d8924f..0e18e8c48 100644 --- a/src/en/robust-toolbox/user-interface.md +++ b/src/en/robust-toolbox/user-interface.md @@ -1,5 +1,9 @@ # User Interface +```admonish warning +The information on this page may not completely conform to conventions in Space Station 14 code. +``` + I can't be bothered to think of an elegant opening paragraph for this page. This is the UI tutorial. ```admonish info From f3a86367e9f8936f1dd14108a2f3bd628952257b Mon Sep 17 00:00:00 2001 From: Brandon Li Date: Sun, 21 Jul 2024 18:40:07 -0400 Subject: [PATCH 3/5] update ui docs --- src/SUMMARY.md | 4 +- src/en/ss14-by-example/ui-and-you.md | 474 ++++++++++++++++++ .../ss14-by-example/ui-and-you/ui-cookbook.md | 23 + src/en/ss14-by-example/ui-survival-guide.md | 2 + 4 files changed, 502 insertions(+), 1 deletion(-) create mode 100644 src/en/ss14-by-example/ui-and-you.md create mode 100644 src/en/ss14-by-example/ui-and-you/ui-cookbook.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 214492024..60a866259 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -51,7 +51,9 @@ SS14 By Example - [Porting Appearance Visualizers](en/ss14-by-example/making-a-sprite-dynamic/porting-appearance-visualizers.md) - [Basic Networking and You](en/ss14-by-example/basic-networking-and-you.md) - [Fluent and Localization](en/ss14-by-example/fluent-and-localization.md) -- [UI Survival Guide](en/ss14-by-example/ui-survival-guide.md) +- [UI and You](en/ss14-by-example/ui-and-you.md) + - [UI Cookbook](en/ss14-by-example/ui-and-you/ui-cookbook.md) +- [UI Survival Guide](en/ss14-by-example/ui-survival-guide.md) Robust Toolbox diff --git a/src/en/ss14-by-example/ui-and-you.md b/src/en/ss14-by-example/ui-and-you.md new file mode 100644 index 000000000..748612baa --- /dev/null +++ b/src/en/ss14-by-example/ui-and-you.md @@ -0,0 +1,474 @@ +# UI and You + +Or how I learned to stop worrying and love Sheetlets. + +```admonish note +The UI system in SS14 has been through several iterations, and much of the +current UI code is very much antiquated. When creating UI, it is generally very +helpful to reference other code, however when referencing code when making +your UI, please keep the age of the code in mind. + +If you find some code that is not up to the current conventions, refactors are +always appreciated! +``` + +Before learning how it should be done in SS14, it's important to understand how +the engine handles UI. Please reference the [user interface documentation](../robust-toolbox/user-interface.md) +first. + +## Okay, but how do I make it fancy? + +### `FancyWindow` + +`DefaultWindow` is depreciated. Unless you're making your own custom window, +`FancyWindow` should be used in all circumstances. It has additional properties +that integrate with SS14 better than `DefaultWindow`. + +The `Stylesheet` property allows you to give a window to take styles from a +certain stylesheet. The default stylesheet is `Nanotransen`, but in certain +circumstances you may want to use others. Currently there are the following +stylesheets: + +- `Nanotransen` - The default stylesheet. Used for any standard player-facing Uis +- `System` - Primarily used for admin and sandbox UIs +- `Syndicate` (COMING SOON™) - Used for any UIs affiliated with the syndicate + +### `StyleClass` + +Any styles classes that can be reused must be defined in `Content.Client/Stylesheets/StyleClass.cs`. +This is to centralize the location of all available style classes, for ease of +access and prevention of duplicate style classes. + +Any style classes that are generic / can be used for more than one element are +defined at the top. For example, the style class `positive` affects `Button`, +`Panel`, and `Label`. + +The rest of the style classes are defined for a specific generic UI element. +Some common style classes are as follows: + +- `OpenLeft`: Makes the button flat on its left side +- `OpenRight`: Makes the button flat on its right side +- `OpenBoth`: Makes the button flat on both sides; square +- `LabelSubtext`: Makes the label smaller and a more muted color +- `LabelKeyText`: Makes the label bold and a highlight color +- `LabelWeak`: Weak is the opposite of strong; makes the label a more muted color + +There are many more than this, but if you want to know exactly what a given label +does, its as simple as looking at the field's usages, and reading the style rule definition. +This is where it may be helpful to use the Rider IDE, as it has a fantastic implementation of this feature, +but its probably possible in other IDEs as well. + +```admonish tip +In general, if you are doing UI dev, I would recommend using the Rider IDE. It +eats up quite a bit of RAM, but it provides autocomplete in XAML files, a lot +of really nice auto-refactoring and searching features, and very decent git +integration. Give it a shot! +``` + +## Writing Styles + +This section concerns style rules. For most UIs, editing these will be unnecessary, +however you should ALWAYS prefer to use style classes instead of hardcoding colors +or resources that could be commonly used. + +### All hail the mighty `Sheetlet` + +It's important to understand that basically, a stylesheet is a massive list of +every single style rule. Instead of manually +making a giant list of style rules (because that would be ridiculous... haha... ha....), +the responsibility of chipping into this list is distributed between many Sheetlets. +Each Sheetlet returns a small chunk of style rules, which is agglomerated into the +final list at the end. + +```admonish note +Previously every single style rule was in one giant list: `StyleNano.cs`, a 1600 +line pit of despair where dreams went to die. +``` + +There are, primarily, two types of Sheetlets: + +- **Generic Sheetlets**: These go in `Content.Client/Stylesheets/Sheetlets`. + These stylesheets concern generic UI elements used in many different UIs, and + should be written generically to work with any stylesheet. +- **Specific Sheetlets**: These go along with the `*.xaml` files they are associated + with. These stylesheets concern UI elements that are specific to a single UI, + and should be written to work with the specific stylesheet they are associated + with. + +We will go into more detail about the specific conventions to follow for both of +these later. + +All sheetlets should have the `[CommonSheetlet]` attribute. This is used so +stylesheets can find all the sheetlets that have this attribute and add their +styles to their list. + +```admonish tip +Do not forget the `[CommonSheetlet]` attribute. +``` + +### Style Rules + +Each style rule +has a few different components to it (This will look familiar to anyone who knows CSS): + +**The selector**: This limits the elements that a style rule can affect. This is +made up of a few different parts: + +- `Type`: The type of element this rule affects. Anything inheriting from this + type will be affected by this rule. This is similar to the element selector + in css. +- `StyleClasses`: The classes that the element must have to be affected by this + rule. The element must have all of these classes to be affected by this rule. +- `StyleIdentifier`: The identifier of the element. This is a unique identifier + that can be used to target a specific element. This should be used sparingly, + when there is only one instance of the element that needs to be styled in a + highly specific manner. There may only be one of these specified. +- `PseudoClasses`: These are special classes that can be used to target elements + in a specific state. For example, this is used to style buttons differently + when hovered or pressed or whatever. + +Selectors that specify more of these parts are more "specific", and will take +priority over less specific elements. + +**The properties**: Any elements matching the selector will then have their properties +modified by the style rule. These are the same properties you would define in +the XAML. + +To assist with constructing these style rules, there are helper methods defined in +`Content.Client/Stylesheets/StylesheetHelpers`. + +I think it's best to show an examples of style rules instead of describing all +their intricacies since the code is pretty self-explanatory. + +```cs +// you need this using statement to use the helper methods +using static Content.Client.Stylesheets.Redux.StylesheetHelpers; + +var rules = +[ + // select any element... + E() + // ...with the class "negative" + .Class(StyleClass.Negative) + // ...and set its font color to the text color from the negative palette + .FontColor(sheet.NegativePalette.Text), + + // select any `Label`... + E