Skip to content
Jakub Sobon edited this page Nov 28, 2020 · 6 revisions

Doc Status

The widgetapi package exposes an interface that is implemented by all Termdash widgets. This package allows developers to create their own widgets outside of the Termdash repository.

This documentation introduces the Widget's API and the surrounding types. See also the developing a new widget document for more details on widget development.

The widgetapi.Widget is the interface implemented by all widgets. The infrastructure calls the widgetapi.Draw method on every screen redraw. See the Termdash API for details about screen redraw. Each call to the widgetapi.Draw method os preceded by a call to the widgetapi.Options method. This is how the infrastructure asks the widget for its preferences regarding canvas size and events. The widgetapi.Keyboard and widgetapi.Mouse methods are how the infrastructure delivers keyboard and mouse events to the widget.

The widget uses the widgetapi.Options type to specify its preferences to the infrastructure.

Aspect ratio

The widget can request the infrastructure to ensure that the canvas provided to widgetapi.Draw will have a specific aspect ratio. A zero value point image.ZP indicates that widget doesn't have any preferences regarding aspect ratio. Specifying any other value guarantees the requested aspect ratio.

E.g. if the widget returns:

Options{
  Ratio: image.Point{4, 3},
}

All canvases delivered to the widget will have the specified aspect ratio 4:3 of columns : rows. If the actual ratio of the outer container is different, the infrastructure decreases the size of the canvas to the next smaller size that meets this ratio requirement.

Minimum size

Widgets can specify the smallest canvas size they are willing to accept. This protects the widget's widgetapi.Draw method. The infrastructure guarantees not to call this method if the canvas would be smaller than the specified size. If this happens, the infrastructure draws a unicode rune '⇄' indicating that the size is too small.

To specify a minimum size of 10 columns and 5 rows, the widget can return the following options:

Options{
  MinimumSize: image.Point{10, 5},
}

The left container in the following diagram resulted in a canvas smaller than the widget's minimum size:

Maximum size

When the terminal size changes, the infrastructure recalculates sizes of all containers according to the configured terminal layout (the container splits). See Terminal layout for more details.

Widgets placed in containers are automatically stretched to fill the full space available in the container. Widgets can specify an option to limit the canvas size to a maximum in which case the infrastructure never stretches a widget above this limit.

To specify a maximum size of 10 columns and 5 rows, the widget can return the following options:

Options{
  MaximumSize: image.Point{10, 5},
}

Keyboard events

Widgets can choose whether they want to subscribe to keyboard events. Unless this is specifically requested, the widget won't receive any keyboard events, so its widgetapi.Keyboard method won't be called.

Widgets can request keyboard events by specifying the WantKeyboard option:

Options{
  WantKeyboard: KeyScopeFocused,
}

Widgets can request to receive keyboard events at different scopes.

This type is used by the widget to specify the scope at which it wants to receive keyboard events. The following scopes are available:

  1. KeyScopeNone is the default scope and indicates the widget doesn't want any keyboard events.
  2. KeyScopeFocused indicates that the widget wants to receive keyboard events when its container is focused. See Keyboard focus for more details.
  3. KeyScopeGlobal indicates that the widget wants to receive all keyboard events, even if its container isn't focused.

Receiving keyboard events exclusively

Without other configuration, keyboard events can be delivered to multiple widgets, e.g. a widget that registered for KeyScopeFocused and is currently focused and all other widgets that registered for KeyScopeGlobal. A widget can request to receive keyboard events exclusively while focused by specifying the ExclusiveKeyboardOnFocus:

Options{
  WantKeyboard: KeyScopeFocused,
  ExclusiveKeyboardOnFocus: true,
}

This can be useful for widgets like the textinput which don't want to trigger keyboard shortcuts of other widgets when the user is typing text.

Mouse events

Widgets can choose whether they want to subscribe to mouse events. Unless this is specifically requested, the widget won't receive any mouse events, so its widgetapi.Mouse method won't be called.

Widgets can request mouse events by specifying the WantMouse option:

Options{
  WantMouse: MouseScopeWidget,
}

Widgets can request to receive mouse events at different scopes.

This type is used by the widget to specify the scope at which it wants to receive mouse events. The following scopes are available:

  1. MouseScopeNone is the default scope and indicates the widget doesn't want any mouse events.
  2. MouseScopeWidget indicates that the widget wants to receive mouse events as long as they fall on the area of its canvas.
  3. MouseScopeContainer indicates that the widget wants to receive mouse events as long as they fall on the area of its container including its padding and border.
  4. MouseScopeGlobal indicates that the widget wants to receive all mouse events, regardless where on the terminal they fall on.