98 lines
2.4 KiB
Go
98 lines
2.4 KiB
Go
package ui
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
|
|
"opslag.de/schobers/geom"
|
|
)
|
|
|
|
type Paragraph struct {
|
|
Label
|
|
|
|
width float32
|
|
lines CachedValue
|
|
}
|
|
|
|
func BuildParagraph(text string, fn func(*Paragraph)) *Paragraph {
|
|
var p = &Paragraph{}
|
|
p.Text = text
|
|
if fn != nil {
|
|
fn(p)
|
|
}
|
|
return p
|
|
}
|
|
|
|
func fastFormatFloat32(f float32) string { return strconv.FormatFloat(float64(f), 'b', 32, 32) }
|
|
|
|
func (p *Paragraph) desiredSize(ctx Context) interface{} {
|
|
font := p.ActualFont(ctx)
|
|
|
|
pad := p.ActualTextPadding(ctx)
|
|
lines := p.splitInLines(ctx, p.width-pad.Left-pad.Right)
|
|
return geom.PtF32(p.width, float32(len(lines))*font.Height()+pad.Top+pad.Bottom)
|
|
}
|
|
|
|
func (p *Paragraph) hashTextArranged(ctx Context) string {
|
|
return p.FontName(ctx) + p.Text + fastFormatFloat32(p.Bounds().Dx())
|
|
}
|
|
|
|
func (p *Paragraph) hashTextDesired(ctx Context) string {
|
|
return p.FontName(ctx) + p.Text + fastFormatFloat32(p.width)
|
|
}
|
|
|
|
func (p *Paragraph) splitInLines(ctx Context, width float32) []string {
|
|
font := p.ActualFont(ctx)
|
|
var lines []string
|
|
for _, line := range strings.Split(p.Text, "\n") {
|
|
if len(line) == 0 {
|
|
lines = append(lines, line)
|
|
continue
|
|
}
|
|
|
|
for len(line) > 0 {
|
|
clipped := fitTextWord(font, line, width)
|
|
lines = append(lines, clipped)
|
|
line = strings.TrimLeft(line[len(clipped):], " ")
|
|
}
|
|
}
|
|
return lines
|
|
}
|
|
|
|
func (p *Paragraph) updateLines(ctx Context) interface{} {
|
|
pad := p.ActualTextPadding(ctx)
|
|
return p.splitInLines(ctx, p.Bounds().Dx()-pad.Left-pad.Right)
|
|
}
|
|
|
|
func (p *Paragraph) DesiredSize(ctx Context, size geom.PointF32) geom.PointF32 {
|
|
// stores the given width, is used when calculating the new desired size (and thus used in the hash method as well)
|
|
p.width = size.X
|
|
return p.desired.GetContext(ctx, p.desiredSize, p.hashTextDesired).(geom.PointF32)
|
|
}
|
|
|
|
func (p *Paragraph) Render(ctx Context) {
|
|
p.RenderBackground(ctx)
|
|
|
|
pad := p.ActualTextPadding(ctx)
|
|
width := p.Bounds().Dx() - pad.Left - pad.Right
|
|
lines := p.lines.GetContext(ctx, p.updateLines, p.hashTextArranged).([]string)
|
|
|
|
fontColor := p.TextColor(ctx)
|
|
fontName := p.FontName(ctx)
|
|
fontHeight := ctx.Fonts().Font(fontName).Height()
|
|
bounds := pad.InsetRect(p.bounds)
|
|
|
|
left := bounds.Min.X
|
|
switch p.TextAlignment {
|
|
case AlignRight:
|
|
left = bounds.Max.X
|
|
case AlignCenter:
|
|
left += .5 * width
|
|
}
|
|
offset := bounds.Min.Y
|
|
for _, line := range lines {
|
|
ctx.Fonts().TextAlign(fontName, geom.PtF32(left, offset), fontColor, line, p.TextAlignment)
|
|
offset += fontHeight
|
|
}
|
|
}
|