Recommended way to customize a widget

Composing a widget from elements

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.