Widgets must implement conflicting requirements:
In the tile library, widgets are a composition of primitive elements to achieve the desired style.
For example, a simple button contains a text label element included within a padding element that is enclosed within a border element.
Sounds complicated, but the code chain looks simple:
label := labelview.New("Click me", ...)
margin := margin.New(label, ...)
button := box.New(margin, ...)
return button
To be part of a composition, each chain element must implement a Viewer interface:
type Viewer interface {
Size(size image.Point) image.Point
Draw(w *impress.Window, rect image.Rectangle)
}
To customize the button's style (by adding a shadow, for example), you need to implement a new element that matches the interface.
module shadow
type Shadow struct {
view.Viewer
... // any custom parameters
}
func New(viewer view.Viewer, ...) *Shadow {
return &Shadow{
Viewer: viewer,
...
}
}
func (v *Shadow) Draw(w *impress.Window, rect image.Rectangle) {
v.Viewer.Draw(w, rect)
... // any extra drawing
}
And extend the code chain to create a new button:
var button view.Viewer
button = labelview.New("Click me", ...)
button = margin.New(button, ...)
button = box.New(button, ...)
button = shadow.New(button, ...)
return button
The new element can be used to customize the style of any other widgets.
The widget composition code must be part of the application, not the widget library.
See a collection of widget element as a starting point.