View on GitHub

Mazarin

All-Go Operating System For ARM64, RISC-V and x86_64

impl

import "mazzy/mazarin/mancini/impl"

Package impl provides the base “classes” that concrete interactors embed. These types are not used directly by application code — they exist to factor out the common machinery of layout, drawing, theming, and child management.

Embedding Hierarchy

The four types form a layered hierarchy via Go struct embedding:

[Interactor]                       — root base; stores backpointer, layout, DC
    └─ [ThemedInteractor]          — adds [mancini.Theme] (palette, fonts)
[Parent]                           — mixin for child discovery
[Decorator]                        — embeds Interactor + Parent; single-child wrapper

Concrete interactor types in mazzy/mazarin/mancini/std embed one of:

The Backpointer Pattern

Go’s struct embedding promotes methods but does not support virtual dispatch: if ThemedInteractor.Draw calls self.DC(), the call resolves to Interactor.DC(), not to an override on the concrete type. Mancini solves this by storing a backpointer to the outermost concrete type.

Interactor.Init takes an “owner” parameter of type [mancini.Interactor]:

func (i *Interactor) Init(owner mancini.Interactor, layout *mancini.LayoutAttributes)

Every concrete type passes itself as the owner during construction:

b := &Button{Depth: Raised, Radius: 8.0}
b.ThemedInteractor.Init(b, layout, theme)  // b is the owner

The Draw protocol then passes this backpointer as the “self” parameter:

func (b *Button) Draw(self mancini.Interactor, x, y, w, h int64)

This ensures that self.DC(), self.Visible(), etc. always resolve through the concrete type, enabling correct polymorphic behavior across the embedding chain.

Construction Sequence

Depending on which base is embedded, the required initialization calls are:

For ThemedInteractor embedders:

t.ThemedInteractor.Init(t, layout, theme)

This calls Interactor.Init internally, which registers the interactor in the global registry.

For Interactor + Parent embedders:

c.Interactor.Init(c, layout)
c.Parent.InitParent(&c.Interactor)

Parent.InitParent must be called after Interactor.Init because it needs the Interactor’s layout name for child discovery.

For Decorator embedders:

d.Decorator.InitDecorator(d, layout, top, right, bottom, left)

This calls both Interactor.Init and Parent.InitParent internally.

Index

type Decorator

Decorator is a single-child parent interactor that draws visual decoration (shadows, title bars, etc.) around its child. It uses inside-out sizing: the Decorator’s Width and Height are determined by the child’s size plus the decoration insets (set up via constraint programs, not in Decorator itself).

Decoration Customization

The decoration is drawn by the [mancini.Decoratable.Decorate] method. The default Decorator.Decorate draws a thick black box. Concrete types override it:

Inside\-Out Sizing

The child owns its Width and Height. The Decorator’s dimensions come from constraint programs that add the insets: Decorator.Width = child.Width + Left + Right, etc.

Draw Sequence

Decorator.Draw proceeds in three steps:

  1. [DecorateIfNeeded] — calls Decorate via virtual dispatch if the decorator’s or child’s BoundsHash has changed since the last frame.
  2. Positions the child at (x+Left, y+Top).
  3. Propagates [mancini.DrawContext] and calls the child’s Draw.

Decorator embeds Parent for GetChildren but does NOT use DrawChildren — it handles its single child directly in Draw.

Initialization

Concrete types call [InitDecorator], which internally calls Interactor.Init and Parent.InitParent:

n.Decorator.InitDecorator(n, layout, top, right, bottom, left)
type Decorator struct {
    Interactor
    Parent
    Top, Right, Bottom, Left int64
    // contains filtered or unexported fields
}

func (*Decorator) Decorate

func (d *Decorator) Decorate(self mancini.Interactor, x, y, w, h int64)

Decorate draws the default thick box decoration. Concrete types override this method to customize the visual decoration:

func (*Decorator) DecorateIfNeeded

func (d *Decorator) DecorateIfNeeded(self mancini.Interactor, x, y, w, h int64)

DecorateIfNeeded checks whether the decoration needs to be redrawn by comparing the decorator’s own BoundsHash and its child’s BoundsHash against saved values. If either has changed (or this is the first frame), it calls Decorate via virtual dispatch and updates the saved hashes. If neither has changed, Decorate is skipped entirely — the previous frame’s pixels are still in the framebuffer.

func (*Decorator) Draw

func (d *Decorator) Draw(self mancini.Interactor, x, y, w, h int64)

Draw implements mancini.NewDrawer.

  1. Calls DecorateIfNeeded — skips Decorate when the decorator’s and child’s BoundsHash are unchanged from the previous frame.
  2. Positions the child by setting its layout X/Y to (x+Left, y+Top) and passes computed child bounds to the child’s Draw.
  3. Propagates the DrawContext to the child and calls its Draw.

Note: the child’s Width and Height are NOT set here. They are owned by the child (inside-out sizing). The Decorator’s own Width/Height come from constraint programs that read child.Width + Left + Right, etc.

func (*Decorator) InitDecorator

func (d *Decorator) InitDecorator(owner any, layout *mancini.LayoutAttributes, top, right, bottom, left int64)

InitDecorator wires the backpointer, layout, and decoration insets. It calls Interactor.Init (registering in the global registry) and Parent.InitParent internally. The owner parameter must be the outermost concrete type (the backpointer).

Constraint-based sizing (Width = child.Width + Left + Right, etc.) is set up separately by the concrete type’s constructor via [mancini.NewDecoratorLayout] or [mancini.NewDecoratorLayoutByParentName].

type Interactor

Interactor is the root base type for all UI elements in the Mancini toolkit. Concrete interactor types embed this struct (directly or via ThemedInteractor) to inherit position, size, visibility, and drawing context accessors.

Embedding Interactor promotes: X, Y, W, H, Visible, DC, SetDC, Owner, Layout, and GetLayout.

Backpointer

Interactor stores a backpointer (“owner”) to the outermost concrete type. This enables virtual dispatch in the Draw protocol: when a parent calls child.Draw(child, …), the child parameter is the concrete type, so self.DC() and self.Visible() resolve correctly. See [Init] for how the backpointer is established.

Embedding Hierarchy

Concrete types embed one of:

type Interactor struct {
    // contains filtered or unexported fields
}

func (*Interactor) DC

func (i *Interactor) DC() mancini.DrawContext

func (*Interactor) GetLayout

func (i *Interactor) GetLayout() *mancini.LayoutAttributes

GetLayout satisfies the [mancini.Layouter] interface, returning the [mancini.LayoutAttributes] that publish this interactor’s position, size, and visibility in the constraint network.

func (*Interactor) H

func (i *Interactor) H() int64

func (*Interactor) Init

func (i *Interactor) Init(owner mancini.Interactor, layout *mancini.LayoutAttributes)

Init wires the backpointer and layout attributes. Must be called from the concrete type’s constructor, passing the concrete type as owner:

b := &Button{...}
b.Interactor.Init(b, layout)   // b is the backpointer

Init also registers the interactor in the global registry (see [mancini.RegisterInteractor]) keyed by the layout’s constraint-system name, enabling child discovery by Parent.GetChildren.

For themed interactors, call ThemedInteractor.Init instead, which calls this method internally.

func (*Interactor) Layout

func (i *Interactor) Layout() *mancini.LayoutAttributes

Layout returns the underlying [mancini.LayoutAttributes] for direct constraint access. Callers should prefer GetLayout for interface compatibility.

func (*Interactor) Owner

func (i *Interactor) Owner() mancini.Interactor

Owner returns the backpointer to the outermost concrete type. Used internally by Decorator.DecorateIfNeeded to perform virtual dispatch on the [mancini.Decoratable] interface.

func (*Interactor) SetDC

func (i *Interactor) SetDC(dc mancini.DrawContext)

SetDC sets the [mancini.DrawContext] for this interactor. Called by parent interactors during the draw pass to propagate the drawing surface down the tree before calling Draw.

func (*Interactor) Visible

func (i *Interactor) Visible() bool

func (*Interactor) W

func (i *Interactor) W() int64

func (*Interactor) X

func (i *Interactor) X() int64

func (*Interactor) Y

func (i *Interactor) Y() int64

type Parent

Parent is a mixin for interactors that have children. It implements [mancini.Parent] by discovering children through the constraint network: each child’s Parent layout attribute names this interactor, and GetChildren uses the global interactor registry (see [mancini.FindChildren]) to return them in construction order.

Embedding

Container interactors embed both Interactor and Parent:

type Column struct {
    impl.Interactor  // X(), Y(), W(), H(), DC(), ...
    impl.Parent      // GetChildren(), DrawChildren()
    // ...
}

Decorator embeds Parent internally, so decorator types do not need to embed it separately.

Initialization

InitParent must be called after Interactor.Init, because it needs the Interactor’s layout name to discover children:

c.Interactor.Init(c, layout)
c.Parent.InitParent(&c.Interactor)

Concrete Types That Use Parent

[std.Column], [std.Row], [std.ColumnOutsideIn] (embed Parent directly). [std.NeuBox], [std.NeuCircle], [std.AppWindow], [std.FreeFloatingWindow] (via Decorator).

type Parent struct {
    // contains filtered or unexported fields
}

func (*Parent) DrawChildren

func (p *Parent) DrawChildren(self mancini.Interactor, x, y, w, h int64)

DrawChildren is the default child-drawing implementation. For each child discovered by GetChildren, it propagates the [mancini.DrawContext] from self via SetDC, then calls the child’s [mancini.NewDrawer.Draw] method. Children receive the parent’s own bounds (x, y, w, h) — they fill the parent in this default implementation.

Container interactors like [std.Column] and [std.Row] override this with custom layout logic that computes per-child positions. Decorator does not use DrawChildren at all — it handles its single child directly in Decorator.Draw.

func (*Parent) GetChildren

func (p *Parent) GetChildren() []mancini.Interactor

GetChildren discovers children via the constraint network. Returns all [mancini.Interactor] instances whose Parent layout attribute matches this interactor’s constraint-system name, sorted by registration sequence number (construction order).

func (*Parent) InitParent

func (p *Parent) InitParent(i *Interactor)

InitParent wires the back-pointer to the embedding Interactor. Must be called after Interactor.Init so the layout name is available for child discovery.

type ThemedInteractor

ThemedInteractor embeds Interactor and adds [mancini.Theme] support. It is the standard base type for leaf interactors and controls that need palette colors, font resolution, and neumorphic parameters.

From Interactor: X, Y, W, H, Visible, DC, SetDC, Owner, Layout, GetLayout.

Added by ThemedInteractor: Theme, BgColor, FgColor, Font, DefaultFont, DefaultSize, and Draw (background clear).

Draw as Super Call

ThemedInteractor.Draw clears the background to the theme’s surface color. Concrete types that want a background clear call it as a “super” method before rendering their own content:

func (l *Label) Draw(self mancini.Interactor, x, y, w, h int64) {
    l.ThemedInteractor.Draw(self, x, y, w, h) // clear background
    // ... render label text ...
}

Many interactors (Button, Checkbox, Scrollbar, etc.) skip the super call because [std.NeuBoxWith] fills the background as part of the neumorphic shadow pipeline.

Concrete Types That Embed ThemedInteractor

[std.Button], [std.Checkbox], [std.CheckboxWithLabel], [std.Label], [std.ConsoleLabel], [std.SingleLineText], [std.Scrollbar], [std.NOfMChooser], [std.RadialNOfMChooser], [std.RadialMenu].

type ThemedInteractor struct {
    Interactor // X(), Y(), W(), H(), DC(), Visible() — all promoted
    // contains filtered or unexported fields
}

func (*ThemedInteractor) BgColor

func (t *ThemedInteractor) BgColor() color.NRGBA

func (*ThemedInteractor) DefaultFont

func (t *ThemedInteractor) DefaultFont() *mancini.FontConfig

func (*ThemedInteractor) DefaultSize

func (t *ThemedInteractor) DefaultSize() int64

func (*ThemedInteractor) Draw

func (t *ThemedInteractor) Draw(self mancini.Interactor, x, y, w, h int64)

Draw clears the interactor’s background to the [mancini.Palette]’s Surface color. If the background is fully transparent (alpha == 0), the fill is skipped.

Concrete types that want a background clear before rendering their own content call this as a super method:

l.ThemedInteractor.Draw(self, x, y, w, h)

Interactors whose neumorphic rendering already fills the background (via [std.NeuBoxWith] or similar) skip this call entirely.

func (*ThemedInteractor) FgColor

func (t *ThemedInteractor) FgColor() color.NRGBA

func (*ThemedInteractor) Font

func (t *ThemedInteractor) Font(feature mancini.Feature, size int64) *mancini.FontConfig

func (*ThemedInteractor) Init

func (t *ThemedInteractor) Init(owner mancini.Interactor, layout *mancini.LayoutAttributes, theme mancini.Theme)

Init wires the backpointer, layout, and theme. Must be called from the concrete type’s constructor, passing the concrete type as owner:

b := &Button{...}
b.ThemedInteractor.Init(b, layout, theme)

This calls Interactor.Init internally, which registers the interactor in the global registry.

func (*ThemedInteractor) Theme

func (t *ThemedInteractor) Theme() mancini.Theme

Generated by gomarkdoc