View on GitHub

Mazarin

All-Go Operating System For ARM64 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.Initialize takes an “owner” parameter of type [mancini.Interactor]:

func (i *Interactor) Initialize(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.Initialize(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.Initialize(t, layout, theme)

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

For Interactor + Parent embedders:

c.Interactor.Initialize(c, layout)
c.Parent.Initialize(true, &c.Interactor)

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

For Decorator embedders:

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

This calls both Interactor.Initialize and Parent.Initialize 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 Decorator.Initialize, which internally calls Interactor.Initialize and Parent.Initialize:

n.Decorator.Initialize(n, layout, top, right, bottom, left)
type Decorator struct {
    Interactor
    Parent
    // Top, Right, Bottom, Left are the decoration insets in pixels.
    // The child is positioned and sized inside these insets.
    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, damage image.Rectangle)

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) Initialize

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

Initialize wires the backpointer, layout, and decoration insets. It calls Interactor.Initialize (registering in the global registry) and Parent.Initialize 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 [Initialize] for how the backpointer is established.

Embedding Hierarchy

Concrete types embed one of:

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

func (*Interactor) BoundsRect

func (i *Interactor) BoundsRect() image.Rectangle

BoundsRect returns the interactor’s bounds as an image.Rectangle computed from layout X, Y, Width, Height. Returns empty rect if no layout is available.

func (*Interactor) ClearDamage

func (i *Interactor) ClearDamage()

ClearDamage resets this interactor’s damage rectangle to empty. For leaves (value DamageRect), this directly clears the value. For parents (constraint DamageRect), this is a no-op — the constraint re-evaluates to empty when all children clear.

func (*Interactor) DC

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

DC returns the [mancini.DrawContext] last propagated to this interactor.

func (*Interactor) Damaged

func (i *Interactor) Damaged(damage image.Rectangle) bool

Damaged intersects the damage rectangle with this interactor’s bounds (from layout X, Y, Width, Height). Returns true if the intersection is non-empty — meaning this interactor overlaps the damaged region and should repaint.

func (*Interactor) DrawSelfOpaque

func (i *Interactor) DrawSelfOpaque(damage image.Rectangle, c color.NRGBA)

DrawSelfOpaque intersects the damage rectangle with this interactor’s bounds and fills the intersection with the given color. Designed for interactors that always show a painted background (themed controls, opaque containers).

func (*Interactor) FullDamage

func (i *Interactor) FullDamage()

FullDamage marks this interactor as needing a complete repaint. It sets the DamageRect to the interactor’s full Bounds. Called automatically by Initialize to ensure the first draw paints everything; also available for input handlers that need to force a full repaint (e.g., a clock face on tick).

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

H returns the interactor’s height from layout.

func (*Interactor) Initialize

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

Initialize 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.Initialize(b, layout)   // b is the backpointer

Initialize 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.

Initialize does NOT set up damage tracking. Leaf interactors must call [FullDamage] themselves (e.g. via ThemedInteractor.Initialize). Parent interactors get damage from Parent.Initialize, which installs a constraint that unions children’s damage rectangles.

For themed interactors, call ThemedInteractor.Initialize 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) Pick

func (i *Interactor) Pick(localX, localY int64) []mancini.Interactor

Pick performs hit testing in this interactor’s local coordinate frame. Returns front-to-back order (deepest children first).

The parent walks its children last-to-first (top z-order first). For each child the parent pre-filters against that child’s bounds in the parent’s coordinate frame: if the click does not overlap the child there is no reason to recurse into it. Invisible children are also skipped. When a child does overlap, the parent transforms the click into the child’s local frame (subtracting the child’s x,y within the parent) before recursing.

A child’s bounds may legitimately extend outside the parent’s own bounds (e.g. a GridTable divider whose marker overhangs above and below the grid). The parent still recurses into such children based on the child’s own bounds — it does NOT pre-filter by its own bounds.

Self is appended to the result only if the click is within this interactor’s local bounds and DetailedHit (if implemented) returns true.

Concrete types (e.g., Scroller) may override Pick to apply additional coordinate transforms before recursing into children.

func (*Interactor) ReInitializeOwner

func (i *Interactor) ReInitializeOwner(newOwner mancini.Interactor)

ReInitializeOwner replaces the backpointer and re-registers with the new owner. Used when a subclass wraps an already-initialized interactor and needs dispatch to resolve to the subclass’s methods.

func (*Interactor) ScreenCoordConvertFrom

func (i *Interactor) ScreenCoordConvertFrom(screenX, screenY int64) (int64, int64)

ScreenCoordConvertFrom converts screen-absolute coordinates to this interactor’s local coordinate frame.

func (*Interactor) ScreenCoordConvertTo

func (i *Interactor) ScreenCoordConvertTo(localX, localY int64) (int64, int64)

ScreenCoordConvertTo converts interactor-local coordinates to screen coordinates. (0,0) returns the screen position of this interactor’s top-left corner.

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) SetVisible

func (i *Interactor) SetVisible(v bool)

SetVisible sets the interactor’s Visible layout attribute.

func (*Interactor) SnapshotDamage

func (i *Interactor) SnapshotDamage()

SnapshotDamage copies current Bounds, Visible, and BoundsHash into “last-painted” mirror attributes. The parent damage constraint compares current state to LP state — when they match, ownDamage stays empty and child damage passes through untouched. Call this after drawing an interactor so the next evaluation sees no change.

func (*Interactor) UnionDamage

func (i *Interactor) UnionDamage(prev image.Rectangle) image.Rectangle

UnionDamage returns the union of prev (the interactor’s bounds before a size/position change) and the interactor’s current bounds. Use this when a child moves or resizes: save BoundsRect() before the change, perform the change, then call UnionDamage(saved) to get the damage rect that covers both old and new positions.

func (*Interactor) Visible

func (i *Interactor) Visible() bool

Visible reports whether the interactor is currently visible.

func (*Interactor) W

func (i *Interactor) W() int64

W returns the interactor’s width from layout.

func (*Interactor) X

func (i *Interactor) X() int64

X returns the interactor’s X position from layout.

func (*Interactor) Y

func (i *Interactor) Y() int64

Y returns the interactor’s Y position from layout.

type LatinTextFaceImpl

LatinTextFaceImpl implements [mancini.LatinTextFace] for Latin left-to-right text. Font opening is deferred to the first DrawFace call, since a DrawContext is typically not available at construction time.

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

func NewLatinTextFace

func NewLatinTextFace(fc *mancini.FontConfig, bold bool, fontSize int64, params mancini.TextAlignmentParams) *LatinTextFaceImpl

NewLatinTextFace creates a LatinTextFaceImpl from a [mancini.FontConfig]. Font opening is deferred to the first DrawFace call when a DrawContext is available. If fc is nil or the font path is empty, fontID falls back to fc.ShapedFontID.

func NewLatinTextFaceWithFontID

func NewLatinTextFaceWithFontID(fontID int32, params mancini.TextAlignmentParams) *LatinTextFaceImpl

NewLatinTextFaceWithFontID creates a LatinTextFaceImpl that uses a pre-opened fontID. No OpenFont call is ever made — the caller is responsible for ensuring the fontID is valid on whatever DrawContext the face will be rendered into. This is useful when the font was already opened on a shared glyph provider (e.g., the app’s main DC) and the face will be drawn on an overlay or child DC that shares the same provider.

func (*LatinTextFaceImpl) DrawFace

func (f *LatinTextFaceImpl) DrawFace(dc mancini.DrawContext, x, y, w, h float64)

DrawFace implements [mancini.Face]. It renders the current text into the rectangle (x, y, w, h) using the alignment from TextAlignmentParams. The caller must set the text color on dc before calling.

func (*LatinTextFaceImpl) MeasureText

func (f *LatinTextFaceImpl) MeasureText(text string) float64

MeasureText returns the advance width of text in pixels.

func (*LatinTextFaceImpl) SetText

func (f *LatinTextFaceImpl) SetText(text string)

SetText updates the text that DrawFace will render.

func (*LatinTextFaceImpl) Text

func (f *LatinTextFaceImpl) Text() string

Text returns the current text set on the face.

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

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

c.Interactor.Initialize(c, layout)
c.Parent.Initialize(true, &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) AddChildFirst

func (p *Parent) AddChildFirst(child mancini.Interactor)

AddChildFirst adds child as the first (lowest sequence number) child of this parent. If the child’s sequence number is already lower than all existing children, it is simply parented. Otherwise its sequence number is swapped with the current first child.

Panics if child already has a parent.

func (*Parent) AddChildLast

func (p *Parent) AddChildLast(child mancini.Interactor)

AddChildLast adds child as the last (highest sequence number) child of this parent. If the child’s sequence number is already higher than all existing children, it is simply parented. Otherwise its sequence number is swapped with the current last child.

Panics if child already has a parent.

func (*Parent) DeleteAllChildren

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

DeleteAllChildren removes all children from this parent by clearing each child’s Parent attribute. Returns the removed children in sequence order. Returns an empty (non-nil) slice if no children exist.

func (*Parent) DeleteChild

func (p *Parent) DeleteChild(child mancini.Interactor) mancini.Interactor

DeleteChild removes a specific child from this parent by clearing its Parent attribute. Returns the child, or nil if the child was not found among this parent’s children.

func (*Parent) DeleteFirst

func (p *Parent) DeleteFirst() mancini.Interactor

DeleteFirst removes the first child (lowest sequence number) from this parent and returns it. Returns nil if the parent has no children. The child’s Parent attribute is cleared.

func (*Parent) DeleteIthChild

func (p *Parent) DeleteIthChild(i int) mancini.Interactor

DeleteIthChild removes the i-th child (0-based, in sequence order) from this parent. Returns the removed child, or nil if i is out of range.

func (*Parent) DeleteLast

func (p *Parent) DeleteLast() mancini.Interactor

DeleteLast removes the last child (highest sequence number) from this parent and returns it. Returns nil if the parent has no children. The child’s Parent attribute is cleared.

func (*Parent) DrawChildren

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

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) DrawSelf

func (p *Parent) DrawSelf(dc mancini.DrawContext, rect image.Rectangle)

DrawSelf is the default no-op implementation for [mancini.SimpleParentDraw]. Parent interactors that need background clearing (themed parents, etc.) should override this method.

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) Initialize

func (p *Parent) Initialize(wantDefaultDamageConstraint bool, i *Interactor)

Initialize wires the back-pointer to the embedding Interactor. Must be called after Interactor.Initialize so the layout name is available for child discovery. If wantDefaultDamageConstraint is true, [mancini.InitDefaultParentDamage] is called on the interactor’s layout to set up a damage constraint that unions the parent’s own damage with the first child’s damage rectangle.

func (*Parent) IsRectSingleChild

func (p *Parent) IsRectSingleChild(rect image.Rectangle) mancini.Interactor

IsRectSingleChild tests whether any single child of this parent completely contains the given rectangle. If so, that child is returned — the parent can skip its own drawing and forward Draw directly to that child. Returns nil if no single child contains rect or if the parent has no children.

func (*Parent) SmallestDraw

func (p *Parent) SmallestDraw(rect image.Rectangle) []image.Rectangle

SmallestDraw computes the set of rectangles that cover the damaged region (rect) but do NOT overlap with any child. These are the “background strips” the parent needs to repaint — gaps between children, margins, etc.

The algorithm:

  1. Compute the minimal bounding rectangle of all children.
  2. Intersect rect with that bounding box as the starting area.
  3. Subtract each child’s bounds, collecting the remaining strips.
  4. Add back any parts of rect outside the children bounding box.

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

BgColor returns the theme palette’s Surface (background) color.

func (*ThemedInteractor) DefaultFont

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

DefaultFont returns the theme’s default [mancini.FontConfig].

func (*ThemedInteractor) DefaultSize

func (t *ThemedInteractor) DefaultSize() int64

DefaultSize returns the theme’s default font size in pixels.

func (*ThemedInteractor) Draw

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

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) DrawSelf

func (t *ThemedInteractor) DrawSelf(dc mancini.DrawContext, rect image.Rectangle)

DrawSelf implements [mancini.SimpleParentDraw]. Fills the intersection of rect with this interactor’s bounds using the theme’s Surface color.

func (*ThemedInteractor) FgColor

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

FgColor returns the theme palette’s Text (foreground) color.

func (*ThemedInteractor) Font

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

Font resolves a [mancini.FontConfig] from the theme for the given feature and size.

func (*ThemedInteractor) Initialize

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

Initialize 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.Initialize(b, layout, theme)

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

func (*ThemedInteractor) Theme

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

Theme returns the [mancini.Theme] in effect for this interactor.

Generated by gomarkdoc