The OpenD Programming Language

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.

More...
class Widget : ReflectableProperties {
version(win32_widgets)
static
Widget[HWND] nativeMapping;
version(win32_widgets)
WNDPROC originalWindowProcedure;
version(win32_widgets)
SimpleWindow simpleWindowWrappingHwnd;
}

Constructors

this
this(Widget parent)

Creates the widget and adds it to the parent.

Members

Classes

Style
class Style

Style properties are defined as an accessory class so they can be referenced and overridden independently, but they are nested so you can refer to them easily by name (e.g. generic Widget.Style vs Button.Style and such).

Enums

DynamicState
enum DynamicState

List of dynamic states made available to the style engine, for cases like CSS pseudo-classes and also used by default paint methods. It is stored in a 64 bit variable attached to the widget that you can update. The style cache is aware of the fact that these can frequently change.

Functions

addChild
void addChild(Widget w, int position)

Adds a child to the given position. This is protected because you generally shouldn't be calling this directly. Instead, construct widgets with the parent directly.

addDirectEventListener
EventListener addDirectEventListener(string event, void delegate() handler, bool useCapture)
EventListener addDirectEventListener(string event, void delegate(Event) handler, bool useCapture)
EventListener addDirectEventListener(Handler handler, bool useCapture)
addEventListener
EventListener addEventListener(string event, void delegate() handler, bool useCapture)
EventListener addEventListener(Handler handler, bool useCapture)
EventListener addEventListener(string event, void delegate(Event) handler, bool useCapture)
EventListener addEventListener(string event, EventHandler handler, bool useCapture)

Events use a Javascript-esque model. See more details on the Event page.

addScrollPosition
void addScrollPosition(int x, int y)

If the widget is a scrollable container, this should add the current scroll position to the given coordinates so the mouse events can be dispatched correctly.

addedTo
void addedTo(Widget w)

Callback when the widget is added to another widget.

attachedToWindow
void attachedToWindow(Window w)

This is called when the widget is added to a window. It gives you a chance to set up event hooks.

borderBoxForContentBox
Rectangle borderBoxForContentBox(Rectangle contentBox)

Calculates the border box (that is, the full width/height of the widget, from border edge to border edge) for the given content box (the area between the padding)

currentDpi
int currentDpi(int assumedDpi)

Returns the current scaling factor as a logical dpi value for this widget. Generally speaking, this divided by 96 gives you the user scaling factor.

defaultEventHandler_blur
void defaultEventHandler_blur(Event event)
defaultEventHandler_change
void defaultEventHandler_change(Event event)
defaultEventHandler_char
void defaultEventHandler_char(CharEvent event)
defaultEventHandler_click
void defaultEventHandler_click(ClickEvent event)
defaultEventHandler_dblclick
void defaultEventHandler_dblclick(DoubleClickEvent event)
defaultEventHandler_focus
void defaultEventHandler_focus(Event event)
defaultEventHandler_focusin
void defaultEventHandler_focusin(Event event)
defaultEventHandler_focusout
void defaultEventHandler_focusout(Event event)
defaultEventHandler_keydown
void defaultEventHandler_keydown(KeyDownEvent event)
defaultEventHandler_keyup
void defaultEventHandler_keyup(KeyUpEvent event)
defaultEventHandler_mousedown
void defaultEventHandler_mousedown(MouseDownEvent event)
defaultEventHandler_mouseenter
void defaultEventHandler_mouseenter(MouseEnterEvent event)
defaultEventHandler_mouseleave
void defaultEventHandler_mouseleave(MouseLeaveEvent event)
defaultEventHandler_mousemove
void defaultEventHandler_mousemove(MouseMoveEvent event)
defaultEventHandler_mouseout
void defaultEventHandler_mouseout(MouseOutEvent event)
defaultEventHandler_mouseover
void defaultEventHandler_mouseover(MouseOverEvent event)
defaultEventHandler_mouseup
void defaultEventHandler_mouseup(MouseUpEvent event)
defaultEventHandler_triggered
void defaultEventHandler_triggered(Event event)

Default event handlers. These are called on the appropriate event unless Event.preventDefault is called on the event at some point through the bubbling process.

defaultTextHeight
int defaultTextHeight(int numberOfLines)
disabledBy
Widget disabledBy()

Returns the widget that disabled this. It might be this or one of its parents all the way up the chain, or null if the widget is not disabled by anything. You can check disabledReason on the return value (after the null check!) to get a hint to display to the user.

dpiChanged
void dpiChanged()

Virtual hook to update any caches or fonts you need on the event of a dpi scaling change.

draw
WidgetPainter draw()
emit
bool emit(Args args)
bool emit()

Allows a class to easily dispatch its own statically-declared event (see Emits). The main benefit of using this over constructing an event yourself is simply that you ensure you haven't sent something you haven't documented you can send.

encapsulatedChildren
bool encapsulatedChildren()

If encapsulatedChildren returns true, it changes the event handling mechanism to act as if events from the child widgets are actually targeted on this widget.

erase
void erase(WidgetPainter painter)

I don't actually like the name of this this draws a background on it

flexBasisHeight
int flexBasisHeight()

The initial size of the widget for layout calculations. Default is 0.

flexBasisWidth
int flexBasisWidth()

The initial size of the widget for layout calculations. Default is 0.

focus
void focus()
getByName
WidgetClass getByName(string name)

Finds the nearest descendant with the requested type and name. May return this.

getChildAtPosition
Widget getChildAtPosition(int x, int y)

Finds the child at the top of the z-order at the given coordinates (relative to the this widget's origin), or null if none are found.

getChildByName
Widget getChildByName(string name)

Calls getByName with the generic type of Widget. Meant for script interop where instantiating a template is impossible.

getComputedStyle
StyleInformation getComputedStyle()

Gets the computed style properties from the visual theme.

getPropertiesList
void getPropertiesList(void delegate(string name) sink)
getPropertyAsString
void getPropertyAsString(string name, void delegate(string name, scope const(char)[] value, bool valueIsJson) sink)

Implementations of ReflectableProperties interface. See the interface for details.

globalCoordinates
Point globalCoordinates()

Returns the coordinates of this widget on the screen, relative to the upper left corner of the whole screen.

handleWmCommand
void handleWmCommand(ushort cmd, ushort id)

Called when a WM_COMMAND is sent to the associated hwnd.

handleWmNotify
int handleWmNotify(NMHDR* hdr, int code, int mustReturn)

Called when a WM_NOTIFY is sent to the associated hwnd.

heightShrinkiness
int heightShrinkiness()

Where stretchiness will grow from the flex basis, this shrinkiness will let it get smaller if needed to make room for other items.

hidden
bool hidden()
hide
void hide()

Convenience method for showing = false

isFocused
bool isFocused()

Returns true if this is the current focused widget inside the parent window. Please note it may return true when the window itself is unfocused. In that case, it indicates this widget will receive focuse again when the window does.

newParentWindow
void newParentWindow(Window oldParent, Window newParent)

Called when the widget has been added to or remove from a parent window.

paint
void paint(WidgetPainter painter)

Responsible for actually painting the widget to the screen. The clip rectangle and coordinate translation in the WidgetPainter are pre-configured so you can draw independently.

paintContent
Rectangle paintContent(WidgetPainter painter, Rectangle bounds)

Responsible for drawing the content as the theme engine is responsible for other elements.

privatePaint
void privatePaint(WidgetPainter painter, int lox, int loy, Rectangle containment, bool force, bool invalidate)

This can be overridden by scroll things. It is responsible for actually calling paint. Do not override unless you've studied minigui.d's source code. There are no stability guarantees if you do override this; it can (and likely will) break without notice.

redraw
void redraw(string file, size_t line)
registerMovement
void registerMovement()

This function is called by the layout engine after it has updated the position (in variables x and y) and the size (in properties width and height) to give you a chance to update the actual position of the native child window (if there is one) or whatever.

removeAllChildren
void removeAllChildren()

Removes all child widgets from this. You should not use the removed widgets again.

removeEventListener
void removeEventListener(string event, EventHandler handler, bool useCapture)
void removeEventListener(EventListener listener)

Events use a Javascript-esque model. See more details on the Event page.

removeWidget
void removeWidget()

Removes this widget from its parent.

scaleWithDpi
int scaleWithDpi(int value, int assumedDpi)
Point scaleWithDpi(Point value, int assumedDpi)

Scales the given value to the system-reported DPI for the monitor on which the widget resides.

setDynamicState
void setDynamicState(ulong flags, bool state)

List of dynamic states made available to the style engine, for cases like CSS pseudo-classes and also used by default paint methods. It is stored in a 64 bit variable attached to the widget that you can update. The style cache is aware of the fact that these can frequently change.

setPropertyFromString
SetPropertyResult setPropertyFromString(string name, const(char)[] value, bool valueIsJson)

Implementations of ReflectableProperties interface. See the interface for details.

setupDefaultEventHandlers
void setupDefaultEventHandlers()

Default event handlers. These are called on the appropriate event unless Event.preventDefault is called on the event at some point through the bubbling process.

show
void show()

Convenience method for showing = true

showing
bool showing()
showing
void showing(bool s, bool recalculate)

Shows or hides the window. Meant to be assigned as a property. If recalculate is true (the default), it recalculates the layout of the parent widget to use the space this widget being hidden frees up or make space for this widget to appear again.

styleClassList
inout(ClassList) styleClassList()

Returns a "class list" that can be used by the visual theme's style engine via VisualTheme.getPropertyString if it chooses to do something like CSS.

styleTagName
string styleTagName()

Returns the style's tag name string this object uses.

subscribe
EventListener subscribe(void delegate(EventType) handler)

Does the same as addEventListener's delegate overload, but adds an additional check to ensure the event you are subscribing to is actually emitted by the static type you are using. Since it works on static types, if you have a generic Widget, this can only subscribe to events declared as Emits inside Widget itself, not any child classes nor any child elements. If this is too restrictive, simply use addEventListener instead.

useStyleProperties
void useStyleProperties(void delegate(scope Style props) dg)

You can override this by hand, or use the OverrideStyle helper which is a bit less verbose.

widgetRemoved
void widgetRemoved(size_t oldIndex, Widget oldReference)

Notifies the subclass that a widget was removed. If you keep auxillary data about your children, you can override this to help keep that data in sync.

widthShrinkiness
int widthShrinkiness()

Where stretchiness will grow from the flex basis, this shrinkiness will let it get smaller if needed to make room for other items.

Mixin templates

OverrideStyle
mixintemplate OverrideStyle(S...)

This mixin overrides the useStyleProperties method to direct it toward your own style class. The basic usage is simple:

Properties

children
inout(Widget)[] children [@property getter]

Returns the list of the widget's children.

disabledReason
string disabledReason [@property getter]
string disabledReason [@property setter]

If the widget is not enabled this string may be presented to the user when they try to use it. The exact manner and time it gets displayed is up to the implementation of the control.

dynamicState
ulong dynamicState [@property getter]
ulong dynamicState [@property setter]

List of dynamic states made available to the style engine, for cases like CSS pseudo-classes and also used by default paint methods. It is stored in a 64 bit variable attached to the widget that you can update. The style cache is aware of the fact that these can frequently change.

enabled
bool enabled [@property getter]
bool enabled [@property setter]

Determines whether the control is marked enabled. Disabled controls are generally displayed as greyed out and clicking on them does nothing. It is also possible for a control to be disabled because its parent is disabled, in which case this will still return true, but setting enabled = true may have no effect. Check disabledBy to see which parent caused it to be disabled.

height
int height [@property getter]

The widget's current size.

height
int height [@property setter]

Only the layout manager should be calling these.

parent
inout(Widget) parent [@property getter]

Returns the widget's parent.

parentWindow
inout(Window) parentWindow [@property getter]

Returns the window to which this widget is attached.

width
int width [@property getter]

The widget's current size.

width
int width [@property setter]

Only the layout manager should be calling these.

Structs

ClassList
struct ClassList

API for the styleClassList

Variables

defaultEventHandlers
EventHandler[string] defaultEventHandlers;

Default event handlers. These are called on the appropriate event unless Event.preventDefault is called on the event at some point through the bubbling process.

defaultMargin
Rectangle defaultMargin;
defaultPadding
Rectangle defaultPadding;

Not stable.

hwnd
HWND hwnd;

The native handle, if there is one.

name
string name;

The name is a string tag that is used to reference the widget from scripts, gui loaders, declarative ui templates, etc. Similar to a HTML id attribute. Names should be unique in a window.

statusTip
string statusTip;

This tip is displayed in the status bar (if there is one in the containing window) when the mouse moves over this widget.

tabOrder
int tabOrder;

The tab key cycles through widgets by the order of a.tabOrder < b.tabOrder. If they are equal, it does them in child order (which is typically the order they were added to the widget.)

tabStop
bool tabStop;

If true, this widget can be focused via keyboard control with the tab key.

x
int x;
y
int y;

Child's position relative to the parent's origin. only the layout manager should be modifying this and even reading it is of limited utility. It may be made private at some point in the future without advance notice. Do NOT depend on it being available unless you are writing a layout manager.

Inherited Members

From ReflectableProperties

getPropertiesList
void getPropertiesList(void delegate(string name) sink)

Iterates the event's properties as strings. Note that keys may be repeated and a get property request may call your sink with null. It it does, it means the key either doesn't request or cannot be represented by json in the current implementation.

getPropertyAsString
void getPropertyAsString(string name, void delegate(string name, scope const(char)[] value, bool valueIsJson) sink)

Requests a property to be delivered to you as a string, through your sink delegate.

setPropertyFromString
SetPropertyResult setPropertyFromString(string name, const(char)[] str, bool strIsJson)

Sets the given property, if it exists, to the given value, if possible. If strIsJson is true, it will json decode (if the implementation wants to) then apply the value, otherwise it will treat it as a plain string.

SetPropertyResult
enum SetPropertyResult

setPropertyFromString possible return values

RegisterSetters
mixintemplate RegisterSetters()

You can mix this in to get an implementation in child classes. This does setPropertyFromString.

RegisterGetters
mixintemplate RegisterGetters()

You can mix this in to get an implementation in child classes. This does getPropertyAsString and getPropertiesList.

Detailed Description

To create your own widget, you must inherit from it and create a constructor that passes a parent to super. Everything else after that is optional.

class MinimalWidget : Widget {
	this(Widget parent) {
		super(parent);
	}
}

Broadly, there's two kinds of widgets: leaf widgets, which are intended to be the direct user-interactive components, and container widgets, which organize, lay out, and aggregate other widgets in the object tree. A special case of a container widget is Window, which represents a separate top-level window on the screen. Both leaf and container widgets inherit from Widget, so this distinction is more conventional than formal.

Among the things you'll most likely want to change in your custom widget:

  • In your constructor, set tabStop = false; if the widget is not supposed to receive keyboard focus. (Please note its childen still can, so tabStop = false; is appropriate on most container widgets.)

    You may explicitly set tabStop = true; to ensure you get it, even against future changes to the library, though that's the default right now.

    Do this after calling the super constructor.

  • Override paint if you want full control of the widget's drawing area (except the area obscured by children!), or paintContent if you want to participate in the styling engine's system. You'll also possibly want to make a subclass of Style and use OverrideStyle to change the default hints given to the styling engine for widget.

    Generally, painting is a job for leaf widgets, since child widgets would obscure your drawing area anyway. However, it is your decision.

  • Override default event handlers with your behavior. For example defaultEventHandler_click may be overridden to make clicks do something. Again, this is generally a job for leaf widgets rather than containers; most events are dispatched to the lowest leaf on the widget tree, but they also pass through all their parents. See Event for more details about the event model.
  • You may also want to override the various layout hints like minWidth, maxHeight, etc. In particular Padding and Margin are often relevant for both container and leaf widgets and the default values of 0 are often not what you want.

On Microsoft Windows, many widgets are also based on native controls. You can also do this if static if(UsingWin32Widgets) passes. You should use the helper function createWin32Window to create the window and let minigui do what it needs to do to create its bridge structures. This will populate Widget.hwnd which you can access later for communcating with the native window. You may also consider overriding Widget.handleWmCommand and Widget.handleWmNotify for the widget to translate those messages into appropriate minigui Events.

It is also possible to embed a SimpleWindow-based native window inside a widget. See OpenGlWidget's source code as an example.

Your own custom-drawn and native system controls can exist side-by-side.

Later I'll add more complete examples, but for now TextLabel and LabeledPasswordEdit are both simple widgets you can view implementation to get some ideas.

Meta