Terminal & Code: components 321-340
This commit is contained in:
108 files changed
+8733
-1
No files matched your search
+176
@@ -0,0 +1,176 @@
|
||||
package mujica
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"mujicaui/internal"
|
||||
"mujicaui/theme"
|
||||
)
|
||||
|
||||
// codeSize is the design size of code and terminal text.
|
||||
const codeSize float32 = 13
|
||||
|
||||
// codeFont is the scaled monospace code font.
|
||||
func codeFont(c *ui.Context) ui.Font {
|
||||
return ui.Font{Family: theme.MonoFont, Size: FontSize(c, codeSize)}
|
||||
}
|
||||
|
||||
// codeMono is a single-line monospace text.
|
||||
func codeMono(c *ui.Context, s string) *ui.Element {
|
||||
return ui.Text(c, s).Font(theme.MonoFont).FontSize(FontSize(c, codeSize)).SingleLine()
|
||||
}
|
||||
|
||||
// codeCaption is muted caption text.
|
||||
func codeCaption(c *ui.Context, s string) *ui.Element {
|
||||
return ui.Text(c, s).FontSize(FontSize(c, theme.CaptionSize)).TextColor(Tokens(c).TextMuted).SingleLine()
|
||||
}
|
||||
|
||||
// codeTokenColor colors a syntax token kind.
|
||||
func codeTokenColor(k theme.Tokens, kind internal.TokenKind) ui.Color {
|
||||
switch kind {
|
||||
case internal.TokKeyword:
|
||||
return k.AccentText
|
||||
case internal.TokString:
|
||||
return k.Success
|
||||
case internal.TokNumber:
|
||||
return k.Warning
|
||||
case internal.TokComment:
|
||||
return k.TextMuted
|
||||
case internal.TokType:
|
||||
return k.Info
|
||||
}
|
||||
return k.Text
|
||||
}
|
||||
|
||||
// codeAnsiColor maps a terminal color onto the theme.
|
||||
func codeAnsiColor(k theme.Tokens, a internal.AnsiColor) ui.Color {
|
||||
switch a.Kind {
|
||||
case internal.AnsiRGB:
|
||||
return ui.RGB(a.R, a.G, a.B)
|
||||
case internal.AnsiIndexed:
|
||||
if a.Index < 16 {
|
||||
base := [8]ui.Color{k.TextMuted, k.Danger, k.Success, k.Warning, k.Info, k.AccentText, k.Info.Mix(k.Success, 0.5), k.Text}
|
||||
return base[a.Index%8]
|
||||
}
|
||||
if a.Index >= 232 {
|
||||
v := uint8(8 + 10*int(a.Index-232))
|
||||
return ui.RGB(v, v, v)
|
||||
}
|
||||
i := int(a.Index) - 16
|
||||
step := func(n int) uint8 {
|
||||
if n == 0 {
|
||||
return 0
|
||||
}
|
||||
return uint8(55 + 40*n)
|
||||
}
|
||||
return ui.RGB(step(i/36), step(i/6%6), step(i%6))
|
||||
}
|
||||
return ui.Color{}
|
||||
}
|
||||
|
||||
// codeAnsiSpans turns ANSI text into themed spans.
|
||||
func codeAnsiSpans(c *ui.Context, line string) []ui.Span {
|
||||
k := Tokens(c)
|
||||
parts, _ := internal.ParseAnsi(line, internal.AnsiStyle{})
|
||||
spans := make([]ui.Span, 0, len(parts))
|
||||
for _, p := range parts {
|
||||
s := ui.Span{Text: p.Text, Color: codeAnsiColor(k, p.Style.FG), Underline: p.Style.Underline, Strikethrough: p.Style.Strike, Italic: p.Style.Italic}
|
||||
if p.Style.Bold {
|
||||
s.Weight = 700
|
||||
}
|
||||
if bg := codeAnsiColor(k, p.Style.BG); bg.A > 0 {
|
||||
s.Background = bg.Alpha(0.3)
|
||||
}
|
||||
spans = append(spans, s)
|
||||
}
|
||||
return spans
|
||||
}
|
||||
|
||||
// codeMatchSpans marks each query match in text.
|
||||
func codeMatchSpans(c *ui.Context, text, query string) []ui.Span {
|
||||
if query == "" {
|
||||
return []ui.Span{{Text: text}}
|
||||
}
|
||||
k := Tokens(c)
|
||||
lower, q := strings.ToLower(text), strings.ToLower(query)
|
||||
var spans []ui.Span
|
||||
for {
|
||||
i := strings.Index(lower, q)
|
||||
if i < 0 {
|
||||
break
|
||||
}
|
||||
if i > 0 {
|
||||
spans = append(spans, ui.Span{Text: text[:i]})
|
||||
}
|
||||
spans = append(spans, ui.Span{Text: text[i : i+len(q)], Background: k.Selection, Underline: true, DecorationColor: k.AccentText, Weight: 600})
|
||||
text, lower = text[i+len(q):], lower[i+len(q):]
|
||||
}
|
||||
if text != "" {
|
||||
spans = append(spans, ui.Span{Text: text})
|
||||
}
|
||||
return spans
|
||||
}
|
||||
|
||||
// codePanel is a framed surface holding a code tool.
|
||||
func codePanel(c *ui.Context) *ui.Element {
|
||||
k := Tokens(c)
|
||||
return ui.Column(c).MinHeight(0).Background(k.Surface).Border(theme.BorderWidth, k.Border).Radius(theme.ControlRadius).Clip()
|
||||
}
|
||||
|
||||
// codeHeader is a panel's top strip of tools.
|
||||
func codeHeader(c *ui.Context, fn func()) *ui.Element {
|
||||
k := Tokens(c)
|
||||
u := Density(c).Unit()
|
||||
return ui.Row(c).Shrink(0).MinHeight(theme.MinHitSize+2*u).Padding(u, u*2).Gap(u*2).AlignItems(ui.Center).
|
||||
BorderWidth(0, 0, theme.BorderWidth, 0).BorderColor(k.Border).Children(fn)
|
||||
}
|
||||
|
||||
// codeSelectMark draws a chosen row's diamond.
|
||||
func codeSelectMark(c *ui.Context, on bool) {
|
||||
k := Tokens(c)
|
||||
ui.Box(c).Size(8, 8).Shrink(0).Role(ui.RoleNone).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
if on {
|
||||
p.FillPath(internal.Diamond(internal.Snap(p, r.X+r.W/2), internal.Snap(p, r.Y+r.H/2), r.W), k.AccentText)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// codeRows builds a growing virtual list with marks.
|
||||
func codeRows(c *ui.Context, s *ui.ListState, n int, row func(i int)) *ui.Element {
|
||||
d := Density(c)
|
||||
restore := dataSelectTheme(c, 0)
|
||||
defer restore()
|
||||
e := ui.List(c, s, n, func(i int) {
|
||||
ui.Row(c).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() {
|
||||
codeSelectMark(c, s.Selected != nil && *s.Selected == i)
|
||||
row(i)
|
||||
})
|
||||
})
|
||||
k := Tokens(c)
|
||||
internal.Ring(e, k.Focus, theme.ControlRadius)
|
||||
return e.Grow(1).MinHeight(d.ControlHeight() * 3)
|
||||
}
|
||||
|
||||
// codeBadge is a kind letter in a framed square.
|
||||
func codeBadge(c *ui.Context, letter string, col ui.Color) {
|
||||
ui.Box(c).Size(18, 18).Shrink(0).Center().Radius(theme.ControlRadius).Border(theme.BorderWidth, col).
|
||||
Role(ui.RoleNone).Children(func() {
|
||||
ui.Text(c, letter).Font(theme.MonoFont).FontSize(FontSize(c, 11)).FontWeight(700).TextColor(col)
|
||||
})
|
||||
}
|
||||
|
||||
// codeRule draws a pixel-aligned 1 DIP line.
|
||||
func codeRule(p *ui.Painter, x0, x1, y float32, c ui.Color) {
|
||||
s := float64(p.Scale())
|
||||
yy := float32((math.Floor(float64(y)*s) + 0.5) / s)
|
||||
p.Line(x0, yy, x1, yy, 1, c)
|
||||
}
|
||||
|
||||
// codeTextWidth returns the width of s in the code font.
|
||||
func codeTextWidth(c *ui.Context, s string) float32 {
|
||||
w, _ := c.MeasureText(0, ui.Span{Text: s, Font: theme.MonoFont, Size: FontSize(c, codeSize)})
|
||||
return w
|
||||
}
|
||||
Reference in new issue
Block a user