Table of Contents

Class UIElement

Namespace
BSGameLib.UI.Controls.Base
Assembly
BSGameLib.UI.dll

The base of every control in a view. Subclasses are the controls the view file names, such as Label and Button.

public abstract class UIElement : DrawableComponent, IUpdateable, IEquatable<IUpdateable>, IDrawable, IIdentifiable<Guid>, IEquatable<IDrawable>, IDisposable
Inheritance
UIElement
Implements
Derived
Inherited Members

Constructors

UIElement(ILogger, View, string)

Creates a control in view. A null id gives the control a generated ControlId.

protected UIElement(ILogger logger, View view, string id = null)

Parameters

logger ILogger
view View
id string

Properties

BorderColor

The colour of the border drawn around the control, or null for none.

public Color? BorderColor { get; set; }

Property Value

Color?

BorderThickness

The border's width in pixels. A border is drawn only when this is above 0 and BorderColor is set.

public int BorderThickness { get; set; }

Property Value

int

Bounds

The rectangle the control occupies: Location and Size. A control can override this to include something it draws beyond that rectangle.

public virtual Rectangle Bounds { get; }

Property Value

Rectangle

ControlId

The control's name: the view's Id, or a generated GUID when the view gave none.

public string ControlId { get; }

Property Value

string

DeclaredSize

The width and height the view declared for this control, per axis; null for an axis the view left unset. Unlike Size, layout does not change it.

public Vector2? DeclaredSize { get; set; }

Property Value

Vector2?

Disabled

Whether the control is switched off. A disabled control does not respond to input. Use IsEffectivelyDisabled to include a disabled container above it.

public bool Disabled { get; set; }

Property Value

bool

FillColor

A flat colour drawn behind the control, or null for none. It is drawn over Bounds, so it needs no texture.

public Color? FillColor { get; set; }

Property Value

Color?

FillGradient

A gradient fill, drawn in place of FillColor when both are set. Null for none.

public Gradient FillGradient { get; set; }

Property Value

Gradient

FillMesh

The tessellated fill, for a control that paints it over something other than its own whole Bounds - a progress bar filling the left portion of its track.

protected GradientMesh FillMesh { get; }

Property Value

GradientMesh

GlobalBounds

Where the control is on screen, in the view's space - the same rectangle hit-testing uses for the control itself, without any overlay a control adds to Bounds (an open dropdown, say).

public Rectangle GlobalBounds { get; }

Property Value

Rectangle

Remarks

Location is already in view space: every layout arranges its children from its own location, not from zero. This used to add each parent's location on top, which counted every container's offset twice and put anything nested somewhere it was not.

HasDeclaredHeight

True when the view declared a height.

public bool HasDeclaredHeight { get; }

Property Value

bool

HasDeclaredWidth

True when the view declared a width.

public bool HasDeclaredWidth { get; }

Property Value

bool

HasFillOrBorder

Whether any of the fill, border or shadow is set, so that something is drawn for the control.

public bool HasFillOrBorder { get; }

Property Value

bool

HoverKey

A name for what the pointer is resting on when it is over this element, which the game asks the view for with HoverKeyAt(Vector2): an item's place, say, to describe it.

public string HoverKey { get; set; }

Property Value

string

IsEffectivelyDisabled

Whether this control is switched off, or sits inside something that is.

public bool IsEffectivelyDisabled { get; }

Property Value

bool

Remarks

The same inheritance, for the same reason: disabling a group is the natural way to say "none of this is available right now", and a flat ring would otherwise let every control inside it carry on taking input.

IsEffectivelyVisible

Whether this control is on screen and every container above it is too.

public bool IsEffectivelyVisible { get; }

Property Value

bool

Remarks

Drawing gets this for free, because a hidden layout returns before drawing its children and they are never asked. Hit-testing does not: it walks a flat ring of controls, where a button inside a hidden group still reports IsVisible true, because nothing ever told it otherwise. That is the whole of the tabbed-screen bug -- the hidden tab's buttons kept taking clicks at the bounds they were last arranged at.

IsPanelTitle

Pressing this, away from a control, and dragging moves the panel it is in.

public bool IsPanelTitle { get; set; }

Property Value

bool

IsVisible

Whether the control is shown. Setting it invalidates the layout that holds the control.

public bool IsVisible { get; set; }

Property Value

bool

Location

The top-left corner of the control, in the view's space. Set by the layout that arranges it.

public Vector2 Location { get; }

Property Value

Vector2

Logger

The logger the control writes to.

protected ILogger Logger { get; }

Property Value

ILogger

Margin

The space the parent layout reserves around this control. None by default.

public Spacing Margin { get; set; }

Property Value

Spacing

Owner

The view this control belongs to.

public View Owner { get; protected set; }

Property Value

View

Parent

The layout that holds this control, or null when it is not in one.

public UIElement Parent { get; }

Property Value

UIElement

Shadow

A soft drop shadow drawn behind the fill, or null for none.

public BoxShadow Shadow { get; set; }

Property Value

BoxShadow

ShowDebugBounds

Whether every control draws an outline of its Bounds. Off by default; the UI render host turns it on to check layout.

public static bool ShowDebugBounds { get; set; }

Property Value

bool

Size

The size of the control in pixels. Set by the layout that arranges it, and by controls that size themselves from their content.

public Vector2 Size { get; }

Property Value

Vector2

Methods

Dispose()

Releases what the control holds. A control that holds resources overrides this and calls the base.

public virtual void Dispose()

DrawBounds()

Draws an outline of Bounds when ShowDebugBounds is on. Does nothing otherwise.

protected void DrawBounds()

DrawFillAndBorder()

Draws FillColor and BorderColor over this control's current Bounds. Call it before drawing content so the fill lands behind.

protected void DrawFillAndBorder()

Remarks

Shapes and sprites share one command buffer that preserves submission order across both kinds (see RenderEncoderCommandBuffer.Flush), so this composes correctly with sprite draws without touching ZIndex - which would flip the whole view into sorting mode and scramble painter's order everywhere else.

DrawFillAndBorder(Rectangle)

As DrawFillAndBorder(), but over an explicit rect rather than the whole control - for a control whose chrome covers only part of its bounds, such as a checkbox whose box sits beside its label.

protected void DrawFillAndBorder(Rectangle bounds)

Parameters

bounds Rectangle

Initialize()

Does nothing. The framework does not call it on controls, so a subclass that needs setup overrides it.

public virtual void Initialize()

InvalidateLayout()

Tells the containers above this control that they need to arrange again.

public void InvalidateLayout()

Remarks

The whole chain, not just the immediate parent. A layout that sizes itself to its contents changes size when a descendant does, which changes where its parent has to put it -- so stopping at one level leaves every container above that one arranged for the size things used to be.

Found in Odyssey: a repeater sitting in an auto-height panel, itself centred in the window, grew from nothing to one row when the player created their first character. The panel re-arranged; the centring stack above it did not, so the panel kept the position and extent it had when the list was empty and the new row drew over the message of the day below it. Rebuilding the screen fixed it, because a fresh layout pass computed everything at once -- which is the signature of a missed invalidation rather than a wrong measurement.

Px(float)

One of a control's own built-in pixel measurements - an inset, a gap, a default font size - at the scale its view was built at. Everything a view declares is scaled as it is built; this is for the numbers written into the control itself, which would otherwise stay the same size while everything around them grew or shrank.

protected float Px(float pixels)

Parameters

pixels float

Returns

float

RequireEncoderScope()

The render encoder of the view that owns this control.

protected IRenderEncoderScope RequireEncoderScope()

Returns

IRenderEncoderScope

Exceptions

InvalidOperationException

The control is drawn outside its view's render scope.

Set<T>(ref T, T, string)

Stores value in field when it differs from the current value. Returns true when it changed.

protected bool Set<T>(ref T field, T value, string propertyName = null)

Parameters

field T
value T
propertyName string

Returns

bool

Type Parameters

T