theme/devtools/menu.go
Functions
func PaintMenu
func (p MenuPainter) PaintMenu(canvas widget.Canvas, st *menu.MenuPaintState) {
if st.Bounds.IsEmpty() {
return
}
colors := p.effectiveMenuColors(st.ColorScheme)
// Elevation shadow.
shadowRect := geometry.Rect{
Min: geometry.Pt(st.Bounds.Min.X+dtMenuShadowOffset, st.Bounds.Min.Y+dtMenuShadowOffset),
Max: geometry.Pt(st.Bounds.Max.X+dtMenuShadowOffset, st.Bounds.Max.Y+dtMenuShadowOffset),
}
canvas.DrawRoundRect(shadowRect, dtMenuShadowColor, dtMenuRadius)
// Menu surface.
canvas.DrawRoundRect(st.Bounds, colors.MenuBackground, dtMenuRadius)
canvas.StrokeRoundRect(st.Bounds, colors.MenuBorder, dtMenuRadius, dtMenuBorderWidth)
// Clip to menu bounds.
canvas.PushClip(st.Bounds)
defer canvas.PopClip()
// Draw items.
y := st.Bounds.Min.Y + dtMenuPaddingV
for i, item := range st.Items {
if item.IsSeparator() {
dtPaintMenuSeparator(canvas, st.Bounds.Min.X, y, st.Bounds.Width(), st.SeparatorHeight, colors.SeparatorColor)
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, colors.ItemHover)
}
// Label.
textColor := colors.ItemText
if item.Disabled {
textColor = colors.ItemDisabledText
}
labelRect := geometry.Rect{
Min: geometry.Pt(itemRect.Min.X+dtMenuItemPaddingH, itemRect.Min.Y),
Max: geometry.Pt(itemRect.Max.X-dtMenuShortcutWidth-dtMenuItemPaddingH, itemRect.Max.Y),
}
canvas.DrawText(item.Label, labelRect, dtMenuFontSize, textColor, false, widget.TextAlignLeft)
// Shortcut text or submenu arrow.
rightRect := geometry.Rect{
Min: geometry.Pt(itemRect.Max.X-dtMenuShortcutWidth, itemRect.Min.Y),
Max: geometry.Pt(itemRect.Max.X-dtMenuItemPaddingH, itemRect.Max.Y),
}
if item.HasChildren() {
arrowColor := colors.SubMenuArrow
if item.Disabled {
arrowColor = colors.ItemDisabledText
}
canvas.DrawText(dtMenuRightArrow, rightRect, dtMenuFontSize, arrowColor, false, widget.TextAlignRight)
} else if item.Shortcut != "" {
shortcutColor := colors.ShortcutText
if item.Disabled {
shortcutColor = colors.ItemDisabledText
}
canvas.DrawText(item.Shortcut, rightRect, dtMenuShortcutFontSize, shortcutColor, false, widget.TextAlignRight)
}
y += st.ItemHeight
}
}
func PaintMenuBar
PaintMenuBar renders a menu bar with DevTools surface and border styling.
func (p MenuPainter) PaintMenuBar(canvas widget.Canvas, st *menu.MenuBarPaintState) {
if st.Bounds.IsEmpty() {
return
}
colors := p.effectiveBarColors(st.ColorScheme)
// Bar background.
canvas.DrawRect(st.Bounds, colors.BarBackground)
// Bottom border.
borderRect := geometry.Rect{
Min: geometry.Pt(st.Bounds.Min.X, st.Bounds.Max.Y-dtMenuBorderWidth),
Max: st.Bounds.Max,
}
canvas.DrawRect(borderRect, colors.MenuBorder)
// 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, colors.ItemHover)
case st.HoveredIndex:
canvas.DrawRect(r, colors.BarHover)
}
// Label text.
textColor := colors.BarText
if i == st.OpenIndex {
textColor = colors.BarActiveText
}
textBounds := geometry.Rect{
Min: geometry.Pt(r.Min.X+dtMenuBarPaddingH, r.Min.Y),
Max: geometry.Pt(r.Max.X-dtMenuBarPaddingH, r.Max.Y),
}
canvas.DrawText(m.Label, textBounds, dtMenuFontSize, textColor, false, widget.TextAlignCenter)
}
}
Structs
type MenuPainter struct
MenuPainter renders menus and menu bars using DevTools design tokens.
DevTools menus use a dark popup (SurfaceElevated #393B40) with 8px radius,
1px border, 28px item height, right-aligned keyboard shortcut text in Gray9,
and a ControlHover (#43454A) highlight, matching JetBrains IDE menu styling.
If Theme is nil, MenuPainter falls back to the default DevTools dark palette.
type MenuPainter struct {
Theme *Theme // nil uses default DevTools dark fallback
}
PaintMenu renders a popup menu panel with DevTools elevated surface styling.