UI Toolbox logoUI Toolbox

Create windows

There are three ways to create a window. All three end in Workspace.RegisterWindow.

Video tutorial: Windows. All videos: Video tutorials.

Way Use it when
UXML Window The window is known at design time.
WindowDescriptor.Builder() The window is created at run time.
BuildAndRegister Same as the builder, in one call.

A registered window is closed until something opens it. Window ids must be unique in a workspace.

UXML: Window

Put Window elements inside an Workspace. The children of Window become the window content. On attach, the element registers the window and removes itself from the tree. It opens the window if the initial state is not closed.

In UI Builder, the element does not register. It draws the window with its title bar and its content at its initial position and size, so you can drop controls into it on the canvas.

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:tb="UIToolbox">
  <tb:Workspace name="workspace" theme-name="dark" style="flex-grow: 1;">
    <tb:Window id="Inventory" title="Inventory" width="400" height="300" initial-window-state="open">
      <ui:Label text="Items go here." />
    </tb:Window>
  </tb:Workspace>
</ui:UXML>

Window attributes:

Attribute Property Default Meaning
id WindowId empty Unique window id. Required.
title WindowTitle empty Title. The id is used when it is empty.
width, height InitialWidth, InitialHeight 420, 320 Size in pixels. Minimum 160 by 120.
x, y InitialX, InitialY -1 Position in the viewport. -1 uses the cascade position.
initial-window-state InitialWindowState closed A WindowState: open, closed, minimized or maximized. A window without this attribute stays closed until code or a toolbar button opens it.
template-uri TemplateUri null Chrome template. See Custom chrome templates.
enable-scrolling EnableScrolling true Wraps the content in a ScrollView. With false, the content fills the window, so a footer can stay at the bottom and a child such as a PropertyGrid scrolls on its own.
resizable (old name can-resize) CanResize true Allows resize. A resizable window gets resize handles, template chrome included, unless the template has its own.
show-min-button, show-max-button, show-close-button ShowMinButton, ShowMaxButton, ShowCloseButton true Shows the window buttons. The Kingdom example has a window without a close button, one without a maximize button and one with only a close button.
category Category empty A name that groups windows. See Window templates.
title-format TitleFormat empty Makes the title from the window data, such as {Name} ({Moons} moons). See Detail windows in UXML. Without data the window shows title.

Workspace attributes:

Attribute Property Default Meaning
auto-load-styles AutoLoadStyles true Loads WindowStyles.uss and the theme sheet.
theme-name ThemeName default Theme to load. See Theme API.
text-size TextSize Normal Text size: Normal, Large, Larger or Largest (100 to 200%). See Text size.
remember-window-states RememberWindowStates true Restores the session on attach. Saves it on state changes and on detach. Applies remembered bounds when a window opens.
animations-enabled AnimationsEnabled true Plays window transitions.
layout-name LayoutName Default Key prefix for saved layouts and the session. Use one value per workspace.
layout-presets LayoutPresetsPath empty A Resources folder of layout JSON files. Each file is a preset. See Layout presets.
keyboard-shortcuts KeyboardShortcutsEnabled true Handles the window shortcuts. See Keyboard shortcuts.
keyboard-step KeyboardStep 10 Pixels that one move or resize shortcut changes the focused window by.
input-actions InputActions none Input System asset with the UIToolbox shortcut map. None uses the default asset. Only with the Input System package.
tooltips TooltipsEnabled true Shows tooltip text in runtime panels. See Tooltips.
tooltip-delay TooltipDelayMs 500 Milliseconds before a tooltip shows.
no-merge-modifier NoMergeModifier Shift The key that stops a merge during a window drag. See Tab groups and dock zones.
no-snap-modifier NoSnapModifier Alt The key that stops the snap during a window drag or resize. See Snap and the snap keys.
align-snap-modifier AlignSnapModifier Control The key that snaps a window to the edge lines of windows that are far away.

Code: the builder

WindowDescriptor.Builder() returns a WindowDescriptor.WindowDescriptorBuilder.

Method Default Meaning
WithId(string) none Required. Build throws ArgumentException without it.
WithTitle(string) the id Title.
WithSize(float, float) 160, 120 Initial size. Values below 160 by 120 are raised to the minimum.
WithInitialPosition(float?, float?) null Position in the viewport. Null uses the cascade position.
WithContent(VisualElement?) null Window content.
WithDataSource(object?) null Data that the content binds to. See Data-bound windows.
WithTitleFromData(Func<object?, string>?) null Makes the title from the data. See Window templates.
WithCategory(string?) empty A name that groups windows.
WithInitialState(WindowState) Closed State applied on the first open.
WithTemplate(string?) null Chrome template.
WithEnableScrolling(bool) true Wraps the content in a ScrollView.
WithRememberState(bool) true Remember the bounds and state of this window.
WithCanResize(bool) true Allows resize, and adds eight resize handles to the chrome unless the template has its own.
WithButtons(bool, bool, bool) true, true, true Shows the minimize, maximize and close buttons.
Build() Returns the descriptor.
BuildAndRegister(Workspace, bool) Builds, registers, and opens when the second argument is true.

Important:

using UIToolbox;
using UnityEngine;
using UnityEngine.UIElements;

public class InventoryWindow : MonoBehaviour
{
    private void Start()
    {
        var workspace = GetComponent<UIDocument>().rootVisualElement.Q<Workspace>();

        var content = new VisualElement();
        content.Add(new Label("Items go here."));

        var window = WindowDescriptor.Builder()
            .WithId("Inventory")
            .WithTitle("Inventory")
            .WithSize(400, 300)
            .WithContent(content)
            .Build();

        window.Closing += args =>
        {
            if (HasUnsavedChanges()) args.Cancel = true;
        };

        workspace.RegisterWindow(window, openImmediately: true);
    }

    private static bool HasUnsavedChanges() => false;
}