189 lines
4.5 KiB
Go
189 lines
4.5 KiB
Go
package gel
|
|
|
|
import (
|
|
"image"
|
|
"image/color"
|
|
|
|
"gioui.org/font"
|
|
l "gioui.org/layout"
|
|
"gioui.org/op"
|
|
"gioui.org/op/clip"
|
|
"gioui.org/op/paint"
|
|
"gioui.org/text"
|
|
"gioui.org/unit"
|
|
|
|
"golang.org/x/image/math/fixed"
|
|
)
|
|
|
|
// Label is text drawn inside an empty box
|
|
type Label struct {
|
|
*Window
|
|
// Face defines the text style.
|
|
font font.Font
|
|
// Color is the text color.
|
|
color color.NRGBA
|
|
// Alignment specify the text alignment.
|
|
alignment text.Alignment
|
|
// MaxLines limits the number of lines. Zero means no limit.
|
|
maxLines int
|
|
text string
|
|
textSize unit.Sp
|
|
shaper *text.Shaper
|
|
}
|
|
|
|
// Fn renders the label as specified
|
|
func (lbl *Label) Fn(gtx l.Context) l.Dimensions {
|
|
cs := gtx.Constraints
|
|
textSize := fixed.I(gtx.Sp(lbl.textSize))
|
|
|
|
lbl.shaper.LayoutString(text.Parameters{
|
|
Font: lbl.font,
|
|
PxPerEm: textSize,
|
|
MaxLines: lbl.maxLines,
|
|
Alignment: lbl.alignment,
|
|
MaxWidth: cs.Max.X,
|
|
MinWidth: cs.Min.X,
|
|
Locale: gtx.Locale,
|
|
}, lbl.text)
|
|
|
|
// Record the material (color) for text
|
|
m := op.Record(gtx.Ops)
|
|
paint.ColorOp{Color: lbl.color}.Add(gtx.Ops)
|
|
textMaterial := m.Stop()
|
|
|
|
m2 := op.Record(gtx.Ops)
|
|
viewport := image.Rectangle{Max: cs.Max}
|
|
it := GlyphIterator{
|
|
Viewport: viewport,
|
|
MaxLines: lbl.maxLines,
|
|
Material: textMaterial,
|
|
}
|
|
var glyphs [32]text.Glyph
|
|
line := glyphs[:0]
|
|
for g, ok := lbl.shaper.NextGlyph(); ok; g, ok = lbl.shaper.NextGlyph() {
|
|
var ok bool
|
|
if line, ok = it.PaintGlyph(gtx, lbl.shaper, g, line); !ok {
|
|
break
|
|
}
|
|
}
|
|
call := m2.Stop()
|
|
viewport.Min = viewport.Min.Add(it.Padding.Min)
|
|
viewport.Max = viewport.Max.Add(it.Padding.Max)
|
|
clipStack := clip.Rect(viewport).Push(gtx.Ops)
|
|
call.Add(gtx.Ops)
|
|
dims := l.Dimensions{Size: it.Bounds.Size()}
|
|
dims.Size = cs.Constrain(dims.Size)
|
|
dims.Baseline = dims.Size.Y - it.Baseline
|
|
clipStack.Pop()
|
|
return dims
|
|
}
|
|
|
|
// Label creates a new label widget
|
|
func (w *Window) Label() *Label {
|
|
return &Label{
|
|
Window: w,
|
|
font: font.Font{},
|
|
color: w.Colors.GetNRGBAFromName("DocText"),
|
|
textSize: w.TextSize,
|
|
shaper: w.shaper,
|
|
}
|
|
}
|
|
|
|
// Text sets the label text
|
|
func (lbl *Label) Text(txt string) *Label {
|
|
lbl.text = txt
|
|
return lbl
|
|
}
|
|
|
|
// Color sets the text color
|
|
func (lbl *Label) Color(col string) *Label {
|
|
lbl.color = lbl.Theme.Colors.GetNRGBAFromName(col)
|
|
return lbl
|
|
}
|
|
|
|
// Font sets the font
|
|
func (lbl *Label) Font(fontName string) *Label {
|
|
if fnt, e := lbl.Theme.collection.Font(fontName); e == nil {
|
|
lbl.font = fnt
|
|
}
|
|
return lbl
|
|
}
|
|
|
|
// TextScale sets the text size as a scale factor
|
|
func (lbl *Label) TextScale(scale float32) *Label {
|
|
lbl.textSize = unit.Sp(float32(lbl.Theme.TextSize) * scale)
|
|
return lbl
|
|
}
|
|
|
|
// Alignment sets the text alignment
|
|
func (lbl *Label) Alignment(alignment text.Alignment) *Label {
|
|
lbl.alignment = alignment
|
|
return lbl
|
|
}
|
|
|
|
// MaxLines sets the maximum number of lines
|
|
func (lbl *Label) MaxLines(maxLines int) *Label {
|
|
lbl.maxLines = maxLines
|
|
return lbl
|
|
}
|
|
|
|
// H1 creates a large headline label
|
|
func (w *Window) H1(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["H1"])
|
|
}
|
|
|
|
// H2 creates a headline label
|
|
func (w *Window) H2(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["H2"])
|
|
}
|
|
|
|
// H3 creates a headline label
|
|
func (w *Window) H3(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["H3"])
|
|
}
|
|
|
|
// H4 creates a headline label
|
|
func (w *Window) H4(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["H4"])
|
|
}
|
|
|
|
// H5 creates a headline label
|
|
func (w *Window) H5(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["H5"])
|
|
}
|
|
|
|
// H6 creates a headline label
|
|
func (w *Window) H6(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["H6"])
|
|
}
|
|
|
|
// Subtitle1 creates a subtitle label
|
|
func (w *Window) Subtitle1(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["Subtitle1"])
|
|
}
|
|
|
|
// Subtitle2 creates a subtitle label
|
|
func (w *Window) Subtitle2(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["Subtitle2"])
|
|
}
|
|
|
|
// Body1 creates a body text label
|
|
func (w *Window) Body1(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["Body1"])
|
|
}
|
|
|
|
// Body2 creates a body text label
|
|
func (w *Window) Body2(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["Body2"])
|
|
}
|
|
|
|
// Caption creates a caption label
|
|
func (w *Window) Caption(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["Caption"])
|
|
}
|
|
|
|
// Overline creates an overline label
|
|
func (w *Window) Overline(txt string) *Label {
|
|
return w.Label().Text(txt).TextScale(Scales["Overline"])
|
|
}
|