minigui is a smallish GUI widget library, aiming to be on par with at least HTML4 forms and a few other expected gui components. It uses native controls on Windows and does its own thing on Linux (Mac is not currently supported but may be later, and should use native controls) to keep size down. The Linux appearance is similar to Windows 95 and avoids using images to maintain network efficiency on remote X connections, though you can customize that.

Public Imports

public import arsd.simpledisplay;
Undocumented in source.



alias DefaultTheme = DefaultLightTheme

This is your entry point to create your own visual theme for custom widgets.

alias EventHandler = void delegate(Widget handlerAttachedTo, Event event)
alias LabeledLineEdit = Labeled!LineEdit

A line edit box with an associated label.

alias LabeledPasswordEdit = Labeled!PasswordEdit

A labeled password edit.

alias Rectangle = arsd.color.Rectangle

Convenience import to override the Windows GDI Rectangle function (you can still use it through fully-qualified imports)

alias scriptable = arsd_jsvar_compatible

Methods marked with this are available from scripts if added to the arsd.script engine.


class Action

An Action represents some kind of user action they can trigger through menu options, toolbars, hotkeys, and similar mechanisms. The text label, icon, and handlers are centrally held here instead of repeated in each UI element.

class ArrowButton
class AutomaticDialog(T)

This is the implementation for dialog. None of its details are guaranteed stable and may change at any time; the stable interface is just the dialog function at this time.

class BaseVisualTheme

Interface to a custom visual theme which is able to access and use style hint properties, draw stylistic elements, and even completely override existing class' paint methods (though I'd note that can be a lot harder than it may seem due to the various little details of state you need to reflect visually, so that should be your last result!)

class BlurEvent
class Button

Creates a push button with unbounded size. When it is clicked, it emits a triggered event.

class ChangeEvent(T)

Single-value widgets (that is, ones with a programming interface that just expose a value that the user has control over) should emit this after their value changes.

class ChangeEventBase

You should generally use a ChangeEvent!Type instead of this directly. See ChangeEvent for more information.

class CharEvent

Indicates that a character has been typed by the user. Normally dispatched to the currently focused widget.

class Checkbox

A basic checked or not checked box with an attached label.

class ClickEvent

Indicates that the user has worked with the mouse over your widget. For available properties, see MouseEventBase.

class ClosedEvent

ClosingEvent is fired when a user is attempting to close a window. You can preventDefault to cancel the close.

class ClosingEvent

ClosingEvent is fired when a user is attempting to close a window. You can preventDefault to cancel the close.

class CollapsableSidebar

A collapsable sidebar is a container that shows if its assigned width is greater than its minimum and otherwise shows as a button.

class ComboBox

A combination of free entry with a list below it.

class ComboboxBase
class CommandButton

A button with a consistent size, suitable for user commands like OK and CANCEL.

class CommandEvent

Command Events are used with a widget wants to issue a higher-level, yet loosely coupled command do its parents and other interested listeners, for example, "scroll up".

class CommandEventWithArgs(Args...)

A CommandEvent is typically actually an instance of these to hold the strongly-typed arguments.

class ContainerWidget

A widget specifically designed to hold other widgets.

class DataControllerWidget(T)

The data controller widget is created by reflecting over the given data type. You can use ControlledBy as a UDA on a struct or just let it create things automatically.

class DetailsView

A custom widget similar to the HTML5 <details> tag.

class Dialog

A dialog is a transient window that intends to get information from the user before being dismissed.

class DoubleClickEvent

Indicates that the user has worked with the mouse over your widget. For available properties, see MouseEventBase.

class DpiChangedEvent
class DropDownSelection

A drop-down list where the user must select one of the given options. Like <select> in HTML.

class EditableTextWidget

Contains the implementation of text editing

class Event

Represents an event that is currently being processed.

class Fieldset

Creates the fieldset (also known as a group box) with the given label. A fieldset is generally used a container for mutually exclusive Radioboxs.

class FixedPosition

FixedPosition is like StaticPosition, but its coordinates are always relative to the viewport, meaning they do not scroll with the parent content.

class FocusEvent
class FocusInEvent
class FocusOutEvent

FocusInEvent is a FocusEvent that propagates, while FocusOutEvent is a BlurEvent that propagates.

class FreeEntrySelection

A text box with a drop down arrow listing selections. The user can choose from the list, or type their own.

class GridLayout
class HeaderClickedEvent

This is emitted by the TableView when a user clicks on a column header.

class HorizontalLayout

Stacks the widgets horizontally, taking all the available height for each child.

class HorizontalRule

Draws a line

class HorizontalSlider
class HorizontalSpacer

Adds empty space to a layout.

class ImageBox
class IndefiniteProgressBar

Displays an in-progress indicator without known values

class InlineBlockLayout

Makes all children minimum width and height, placing them down left to right, top to bottom.

class KeyDownEvent

Indicates that the user has pressed a key on the keyboard, or if they've been holding it long enough to repeat (key down events are sent both on the initial press then repeated by the OS on its own time.) For available properties, see KeyEventBase.

class KeyEventBase

Contains shared properties for KeyDownEvents and KeyUpEvents.

class KeyUpEvent

Indicates that the user has released a key on the keyboard. For available properties, see KeyEventBase.

class Labeled(T)
class Layout
class LineEdit
class ListWidget

A list widget contains a list of strings that the user can examine and select.

class MainWindow

A MainWindow is a window that includes turnkey support for a menu bar, tool bar, and status bar automatically positioned around a client area where you put your widgets.

class Menu
class MenuBar

You can make one of thse yourself but it is generally easer to use MainWindow.setMenuAndToolbarFromAnnotatedCode.

class MenuItem

A MenuItem belongs to a Menu - use Menu.addItem to add one - and calls an Action when it is clicked.

class MessageBox
class MouseActivatedWidget

A "mouse activiated widget" is really just an abstract variant of button.

class MouseDownEvent
class MouseEnterEvent

Indicates that the user has worked with the mouse over your widget. For available properties, see MouseEventBase.

class MouseEventBase

Contains shared properties for various mouse events;

class MouseLeaveEvent
class MouseMoveEvent
class MouseOutEvent
class MouseOverEvent

Indicates that the user has worked with the mouse over your widget. For available properties, see MouseEventBase.

class MouseTrackingWidget

A mouse tracking widget is one that follows the mouse when dragged inside it.

class MouseUpEvent

Indicates that the user has worked with the mouse over your widget. For available properties, see MouseEventBase.

class NestedChildWindowWidget

A helper to make widgets out of other native windows.

class OpenGlWidget

Nests an opengl capable window inside this window as a widget.

class PageWidget

A page widget is basically a tab widget with hidden tabs. It is also sometimes called a "StackWidget".

class PasswordEdit

A LineEdit that displays * in place of the actual characters.

class ProgressBar

A progress bar with a known endpoint and completion amount

class Radiobox

Creates a radio button with an associated label. These are usually put inside a Fieldset.

class ScrollEvent
class ScrollMessageWidget

A widget that takes your widget, puts scroll bars around it, and sends messages to it when the user scrolls. Unlike ScrollableWidget, it makes no effort to automatically scroll or clip its child widgets - it just sends the messages.

class ScrollableContainerWidget

A widget meant to contain other widgets that may need to scroll.

class ScrollableWidget

A widget that tries (with, at best, limited success) to offer scrolling that is transparent to the inner.

class ScrollbarBase
class Slider

A slider, also known as a trackbar control, is commonly used in applications like volume controls where you want the user to select a value between a min and a max without needing a specific value or otherwise precise input.

class StateChanged(alias field)

Event fired when an Observeable variable changes. You will want to add an event listener referencing the field like widget.addEventListener((scope StateChanged!(Whatever.field) ev) { });

class StaticLayout

Bypasses automatic layout for its children, using manual positioning and sizing only. While you need to manually position them, you must ensure they are inside the StaticLayout's bounding box to avoid undefined behavior.

class StaticPosition

Bypasses automatic positioning when being laid out. It is your responsibility to make room for this widget in the parent layout.

class StatusBar

Status bars appear at the bottom of a MainWindow. They are made out of Parts, with a width and content.

class TabMessageWidget

A TabMessageWidget is a clickable row of tabs followed by a content area, very similar to the TabWidget. The difference is the TabMessageWidget only sends messages, whereas the TabWidget will automatically change pages of child widgets.

class TabWidget

A tab widget is a set of clickable tab buttons followed by a content area.

class TabWidgetPage
class TableView

A TableView is a widget made to display a table of data strings.

class TextDisplay

A read-only text display

class TextEdit
class TextLabel
class ToolBar

Toolbars are lists of buttons (typically icons) that appear under the menu. Each button ought to correspond to a menu item, represented by Action objects.

class ToolButton

An implementation helper for ToolBar. Generally, you shouldn't create these yourself and instead just pass Actions to ToolBar's constructor and let it create the buttons for you.

class VerticalLayout

Stacks the widgets vertically, taking all the available width for each child.

class VerticalRule

Draws a line

class VerticalSlider
class VerticalSpacer

Adds empty space to a layout.

class VisualTheme(CRTP)

This is your entry point to create your own visual theme for custom widgets.

class Widget

The Widget is the base class for minigui's functionality, ranging from UI components like checkboxes or text displays to abstract groupings of other widgets like a layout container or a html <div>. You will likely want to use pre-made widgets as well as creating your own.

class WidgetContainer


class Window


enum ArrowDirection
enum EventType

The purpose of this enum was to give a compile-time checked version of various standard event strings.

enum GenericIcons
enum MessageBoxButton

Identifies the button the user pressed on a message box.

enum MessageBoxIcon
enum MessageBoxStyle
enum ScrollBarShowPolicy

For ScrollableWidget, determines when to show the scroll bar to the user.


auto ControlledBy(Args args)

User-defined attribute you can add to struct members contrlled by addDataControllerWidget or dialog to tell which widget you want created for them.

DataControllerWidget!T addDataControllerWidget(Widget parent, T* t, Widget redrawOnChange)

Intended for UFCS action like window.addDataControllerWidget(new MyObject());

DataControllerWidget!T addDataControllerWidget(Widget parent, T t, Widget redrawOnChange)

Intended for UFCS action like window.addDataControllerWidget(new MyObject());

void addWhenTriggered(Widget w, void delegate() dg)

Convenience function to add a triggered event listener.

EventListener consumesCommand(WidgetType w, void delegate(Args) handler)

Declares that the given widget consumes a command identified by the CommandString AND containing Args. Your handler is called with the arguments, then the event's propagation is stopped, so it will not be seen by the consumer's parents.

void createWin32Window(Widget p, const(wchar)[] className, string windowText, DWORD style, DWORD extStyle)

Calls MS Windows' CreateWindowExW function to create a native backing for the given widget. It will create needed mappings, window procedure hooks, and other private member variables needed to tie it into the rest of minigui's expectations.

void dialog(void delegate(T) onOK, void delegate() onCancel, string title)
void dialog(T initialData, void delegate(T) onOK, void delegate() onCancel, string title)

Creates a dialog based on a data structure.

void emitCommand(WidgetType w, Args args)

Emits a command to the sender widget's parents with the given CommandString and args. You have no way of knowing if it was ever actually consumed due to the loose coupling. Instead, the consumer may broadcast a state update back toward you.

void getOpenFileName(void delegate(string) onOK, string prefilledName, string[] filters, void delegate() onCancel, string initialDirectory)
void getSaveFileName(void delegate(string) onOK, string prefilledName, string[] filters, void delegate() onCancel, string initialDirectory)

Gets a file name for an open or save operation, calling your onOK function when the user has selected one. This function may or may not block depending on the operating system, you MUST assume it will complete asynchronously.

MessageBoxButton messageBox(string title, string message, MessageBoxStyle style, MessageBoxIcon icon)
int messageBox(string message, MessageBoxStyle style, MessageBoxIcon icon)

Displays a modal message box, blocking until the user dismisses it.

ObjectInspectionWindow objectInspectionWindow(T t)

Observes and allows inspection of an object via automatic gui


interface ReflectableProperties
Undocumented in source.

Mixin templates

mixintemplate Beautiful95Theme()
mixintemplate DefaultDarkTheme()
mixintemplate DefaultLightTheme()

This is your entry point to create your own visual theme for custom widgets.

mixintemplate Emits(EventType)
mixintemplate Emits(string eventString)

This lets you statically verify you send the events you claim you send and gives you a hook to document them.

mixintemplate Margin(string code)

Convenience mixin for overriding all four sides of margin or padding in a Widget with the same code. It mixes in the given string as the return value of the four overridden methods.

mixintemplate Observable(T, string name)

Observable varables can be added to widgets and when they are changed, it fires off a StateChanged event so you can react to it.

mixintemplate Padding(string code)

Convenience mixin for overriding all four sides of margin or padding in a Widget with the same code. It mixes in the given string as the return value of the four overridden methods.


struct ControlledBy_(T, Args...)

Implementation detail of the ControlledBy UDA.

struct EventListener

This is an opaque type you can use to disconnect an event handler when you're no longer interested.

struct FileName(alias storage = previousFileReferenced, string[] filters = null, FileDialogType type = FileDialogType.Automatic)

Used in automatic menu functions to indicate that the user should be able to browse for a file.

struct ImageLabel
struct StyleInformation

Get this through Widget.getComputedStyle. It provides access to the Widget.Style style hints and Widget layout hints, possibly modified through the VisualTheme, through a unifed interface.

struct WidgetBackground

Structure to represent a collection of background hints. New features can be added here, so make sure you use the provided constructors and factories for maximum compatibility.

struct WidgetPainter

Encapsulates the simpledisplay ScreenPainter for use on a Widget, with VisualTheme and invalidated area awareness.

struct accelerator

Program-wide keyboard shortcut to trigger the action

struct hotkey

Group: generating_from_code

struct icon

Group: generating_from_code

struct label

Group: generating_from_code

struct menu

tells which menu the action will be on

struct separator

This item in the menu will be preceded by a separator line

struct tip

Group: generating_from_code

struct toolbar

Describes which toolbar section the action appears on


template Container(CArgs...)

This is a helper for addDataControllerWidget. You can use it as a UDA on the type. See for more information.

Detailed Description

minigui's only required dependencies are arsd.simpledisplay and arsd.color, on which it is built. simpledisplay provides the low-level interfaces and minigui builds the concept of widgets inside the windows on top of it.

Its #1 goal is to be useful without being large and complicated like GTK and Qt. It isn't hugely concerned with appearance - on Windows, it just uses the native controls and native theme, and on Linux, it keeps it simple and I may change that at any time, though after May 2021, you can customize some things with css-inspired Widget.Style classes. (On Windows, if you compile with -version=custom_widgets, you can use the custom implementation there too, but... you shouldn't.)

The event model is similar to what you use in the browser with Javascript and the layout engine tries to automatically fit things in, similar to a css flexbox.

FOR BEST RESULTS: be sure to link with the appropriate subsystem command -L/SUBSYSTEM:WINDOWS:5.0, for example, because otherwise you'll get a console and other visual bugs.

HTML To Classes

HTML CodeMinigui Class
<input type="text">LineEdit
<input type="checkbox">Checkbox
<input type="radio">Radiobox

Stretchiness: The default is 4. You can use larger numbers for things that should consume a lot of space, and lower numbers for ones that are better at smaller sizes.

Overlapped input

COMING EVENTUALLY: minigui will include a little bit of I/O functionality that just works with the event loop. If you want to get fancy, I suggest spinning up another thread and posting events back and forth.

Add ons

See the minigui_addons directory in the arsd repo for some add on widgets you can import separately too.

XML definitions

If you use arsd.minigui_xml, you can create widget trees from XML at runtime.


minigui is compatible with arsd.script. If you see @scriptable on a method in this documentation, it means you can call it from the script language.

Tip: to allow easy creation of widget trees from script, import arsd.minigui_xml and make arsd.minigui_xml.makeWidgetFromString available to your script:

import arsd.minigui_xml;
import arsd.script;

var globals = var.emptyObject;
globals.makeWidgetFromString = &makeWidgetFromString;

// this now works
interpret(`var window = makeWidgetFromString("<MainWindow />");`, globals);

More to come.


This hello world sample will have an oversized button, but that's ok, you see your first window!

import arsd.minigui;

void main() {
	auto window = new MainWindow();

	// note the parent widget is almost always passed as the last argument to a constructor
	auto hello = new TextLabel("Hello, world!", TextAlignment.Center, window);
	auto button = new Button("Close", window);


This example shows one way you can partition your window into a header and sidebar. Here, the header and sidebar have a fixed width, while the rest of the content sizes with the window.

It might be a new way of thinking about window layout to do things this way - perhaps GridLayout more matches your style of thought - but the concept here is to partition the window into sub-boxes with a particular size, then partition those boxes into further boxes.

The example window has a header across the top

So to make the header, start with a child layout that has a max height. It will use that space from the top, then the remaining children will split the remaining area, meaning you can think of is as just being another box you can split again. Keep splitting until you have the look you desire.

import arsd.minigui;

// This helper class is just to help make the layout boxes visible.
// think of it like a <div style="background-color: whatever;"></div> in HTML.
class ColorWidget : Widget {
	this(Color color, Widget parent) {
		this.color = color;
	Color color;
	class Style : Widget.Style {
		override WidgetBackground background() { return WidgetBackground(color); }
	mixin OverrideStyle!Style;

void main() {
	auto window = new Window;

	// the key is to give it a max height. This is one way to do it:
	auto header = new class HorizontalLayout {
		this() { super(window); }
		override int maxHeight() { return 50; }
	// this next line is a shortcut way of doing it too, but it only works
	// for HorizontalLayout and VerticalLayout, and is less explicit, so it
	// is good to know how to make a new class like above anyway.
	// auto header = new HorizontalLayout(50, window);

	auto bar = new HorizontalLayout(window);

	// or since this is so common, VerticalLayout and HorizontalLayout both
	// can just take an argument in their constructor for max width/height respectively

	// (could have tone this above too, but I wanted to demo both techniques)
	auto left = new VerticalLayout(100, bar);

	// and this is the main section's container. A plain Widget instance is good enough here.
	auto container = new Widget(bar);

	// and these just add color to the containers we made above for the screenshot.
	// in a real application, you can just add your actual controls instead of these.
	auto headerColorBox = new ColorWidget(Color.teal, header);
	auto leftColorBox = new ColorWidget(, left);
	auto rightColorBox = new ColorWidget(Color.purple, container);




Minigui had mostly additive changes or bug fixes since its inception until May 2021.

In May 2021 (dub v10.0), minigui got an overhaul. If it was versioned independently, I'd tag this as version 2.0.

Among the changes:

  • The event model changed to prefer strongly-typed events, though the Javascript string style ones still work, using properties off them is deprecated. It will still compile and function, but you should change the handler to use the classes in its argument list. I adapted my code to use the new model in just a few minutes, so it shouldn't too hard.

    See Event for details.

  • A DoubleClickEvent was added. Previously, you'd get two rapidly repeated click events. Now, you get one click event followed by a double click event. If you must recreate the old way exactly, you can listen for a DoubleClickEvent, set a flag upon receiving one, then send yourself a synthetic ClickEvent on the next MouseUpEvent, but your program might be better served just working with MouseDownEvents instead.

    See DoubleClickEvent for details.

  • Styling hints were added, and the few that existed before have been moved to a new helper class. Deprecated forwarders exist for the (few) old properties to help you transition. Note that most of these only affect a custom_events build, which is the default on Linux, but opt in only on Windows.

    See Widget.Style for details.

    // * A widget must now opt in to receiving keyboard focus, rather than opting out.

  • Widgets now draw their keyboard focus by default instead of opt in. You may wish to set tabStop = false; if it wasn't supposed to receive it.
  • Most Widget constructors no longer have a default parent argument. You must pass the parent to almost all widgets, or in rare cases, an explict null, but more often than not, you need the parent so the default argument was not very useful at best and misleading to a crash at worst.
  • LabeledLineEdit changed its default layout to vertical instead of horizontal. You can restore the old behavior by passing a TextAlignment argument to the constructor.
  • Several conversions of public fields to properties, deprecated, or made private. It is unlikely this will affect you, but the compiler will tell you if it does.
  • Various non-breaking additions.