core/menu/painter.go

Functions Structs Interfaces

Functions

func PaintMenu

PaintMenu renders a minimal popup menu panel.

func (p DefaultPainter) PaintMenu(canvas widget.Canvas, st *MenuPaintState) {
	if st.Bounds.IsEmpty() {
		return
	}

	// Menu background with shadow.
	shadowRect := geometry.Rect{
		Min:	geometry.Pt(st.Bounds.Min.X+dfltShadowOffset, st.Bounds.Min.Y+dfltShadowOffset),
		Max:	geometry.Pt(st.Bounds.Max.X+dfltShadowOffset, st.Bounds.Max.Y+dfltShadowOffset),
	}
	canvas.DrawRoundRect(shadowRect, dfltShadowColor, dfltMenuRadius)
	canvas.DrawRoundRect(st.Bounds, dfltMenuBg, dfltMenuRadius)
	canvas.StrokeRoundRect(st.Bounds, dfltMenuBorder, dfltMenuRadius, dfltBorderWidth)

	// Clip to menu bounds.
	canvas.PushClip(st.Bounds)
	defer canvas.PopClip()

	// Draw items.
	y := st.Bounds.Min.Y + dfltMenuPaddingV
	for i, item := range st.Items {
		if item.IsSeparator() {
			paintSeparator(canvas, st.Bounds.Min.X, y, st.Bounds.Width(), st.SeparatorHeight)
			y += st.SeparatorHeight
			continue
		}

		itemRect := geometry.Rect{
			Min:	geometry.Pt(st.Bounds.Min.X, y),
			Max:	geometry.Pt(st.Bounds.Max.X, y+st.ItemHeight),
		}

		// Highlight.
		if i == st.HighlightedIndex && !item.Disabled {
			canvas.DrawRect(itemRect, dfltItemHover)
		}

		// Label.
		textColor := dfltItemText
		if item.Disabled {
			textColor = dfltDisabledText
		}
		labelRect := geometry.Rect{
			Min:	geometry.Pt(itemRect.Min.X+dfltMenuItemPaddingH, itemRect.Min.Y),
			Max:	geometry.Pt(itemRect.Max.X-dfltShortcutAreaWidth-dfltMenuItemPaddingH, itemRect.Max.Y),
		}
		canvas.DrawText(item.Label, labelRect, dfltFontSize, textColor, false, widget.TextAlignLeft)

		// Shortcut text or submenu arrow.
		rightRect := geometry.Rect{
			Min:	geometry.Pt(itemRect.Max.X-dfltShortcutAreaWidth, itemRect.Min.Y),
			Max:	geometry.Pt(itemRect.Max.X-dfltMenuItemPaddingH, itemRect.Max.Y),
		}
		if item.HasChildren() {
			arrowColor := dfltSubMenuArrow
			if item.Disabled {
				arrowColor = dfltDisabledText
			}
			canvas.DrawText(rightArrowStr, rightRect, dfltFontSize, arrowColor, false, widget.TextAlignRight)
		} else if item.Shortcut != "" {
			shortcutColor := dfltShortcutText
			if item.Disabled {
				shortcutColor = dfltDisabledText
			}
			canvas.DrawText(item.Shortcut, rightRect, dfltShortcutFontSize, shortcutColor, false, widget.TextAlignRight)
		}

		y += st.ItemHeight
	}
}

func PaintMenuBar

PaintMenuBar renders a minimal menu bar.

func (p DefaultPainter) PaintMenuBar(canvas widget.Canvas, st *MenuBarPaintState) {
	if st.Bounds.IsEmpty() {
		return
	}

	// Bar background.
	canvas.DrawRect(st.Bounds, dfltBarBg)

	// Bottom border line.
	borderRect := geometry.Rect{
		Min:	geometry.Pt(st.Bounds.Min.X, st.Bounds.Max.Y-1),
		Max:	st.Bounds.Max,
	}
	canvas.DrawRect(borderRect, dfltBarBorder)

	// Draw each top-level menu label.
	for i, m := range st.Menus {
		if i >= len(st.MenuRects) {
			break
		}
		r := st.MenuRects[i]

		// Highlight background.
		switch i {
		case st.OpenIndex:
			canvas.DrawRect(r, dfltBarActiveItem)
		case st.HoveredIndex:
			canvas.DrawRect(r, dfltBarHoverItem)
		}

		// Label text.
		textColor := dfltBarTextColor
		if i == st.OpenIndex {
			textColor = dfltBarActiveText
		}
		textBounds := geometry.Rect{
			Min:	geometry.Pt(r.Min.X+dfltBarPaddingH, r.Min.Y),
			Max:	geometry.Pt(r.Max.X-dfltBarPaddingH, r.Max.Y),
		}
		canvas.DrawText(m.Label, textBounds, dfltFontSize, textColor, false, widget.TextAlignCenter)
	}
}

Structs

type MenuBarPaintState struct

MenuBarPaintState provides the current menu bar state to the painter.

type MenuBarPaintState struct {
	// Bounds is the menu bar's bounds.
	Bounds	geometry.Rect

	// Menus is the list of top-level menu definitions.
	Menus	[]TopMenu

	// MenuRects contains the bounding rectangles for each top-level menu label.
	MenuRects	[]geometry.Rect

	// OpenIndex is the index of the currently open top-level menu (-1 for none).
	OpenIndex	int

	// HoveredIndex is the index of the hovered top-level menu label (-1 for none).
	HoveredIndex	int

	// Focused is true if the menu bar has keyboard focus.
	Focused	bool

	// ColorScheme provides theme-derived colors. Zero value means use defaults.
	ColorScheme	MenuColorScheme
}

type MenuPaintState struct

MenuPaintState provides the current popup menu state to the painter.

type MenuPaintState struct {
	// Bounds is the menu panel's bounds in window coordinates.
	Bounds	geometry.Rect

	// Items is the list of menu items.
	Items	[]MenuItem

	// HighlightedIndex is the index of the currently highlighted item (-1 for none).
	HighlightedIndex	int

	// ItemHeight is the height of each regular item row.
	ItemHeight	float32

	// SeparatorHeight is the height of separator rows.
	SeparatorHeight	float32

	// SubMenuOpenIndex is the index of the item whose submenu is open (-1 for none).
	SubMenuOpenIndex	int

	// ColorScheme provides theme-derived colors. Zero value means use defaults.
	ColorScheme	MenuColorScheme
}

type MenuColorScheme struct

MenuColorScheme provides theme-derived colors for menu painting.

Zero value means the painter should use its built-in defaults.

type MenuColorScheme struct {
	BarBackground		widget.Color
	BarText			widget.Color
	BarHover		widget.Color
	BarActiveText		widget.Color
	MenuBackground		widget.Color
	MenuBorder		widget.Color
	ItemText		widget.Color
	ItemHover		widget.Color
	ItemDisabledText	widget.Color
	ShortcutText		widget.Color
	SeparatorColor		widget.Color
	SubMenuArrow		widget.Color
}

type DefaultPainter struct

DefaultPainter provides a minimal fallback painter for menus.

It draws simple rectangles and text without design system styling.

type DefaultPainter struct{}

Interfaces

type Painter interface

Painter draws the visual representation of menus and menu bars.

Each design system (Material 3, Fluent, Cupertino) provides its own

Painter implementation. If no Painter is set, [DefaultPainter] is used.

type Painter interface {
	// PaintMenuBar draws the horizontal menu bar background and top-level labels.
	PaintMenuBar(canvas widget.Canvas, state *MenuBarPaintState)

	// PaintMenu draws a popup menu panel with its items.
	PaintMenu(canvas widget.Canvas, state *MenuPaintState)
}