Made cache more generic.

This commit is contained in:
Sander Schobers 2020-05-12 20:58:42 +02:00
parent 280b4842e8
commit 5ecfd10754
3 changed files with 67 additions and 34 deletions

38
ui/cache.go Normal file
View File

@ -0,0 +1,38 @@
package ui
type CacheHashFn func(interface{}) string
type CacheHashContextFn func(Context) string
func (c CacheHashContextFn) Fn() CacheHashFn {
return func(state interface{}) string { return c(state.(Context)) }
}
type CacheUpdateFn func(interface{}) interface{}
type CacheUpdateContextFn func(Context) interface{}
func (c CacheUpdateContextFn) Fn() CacheUpdateFn {
return func(state interface{}) interface{} { return c(state.(Context)) }
}
type Cache struct {
value interface{}
hash string
updateFn CacheUpdateFn
hashFn CacheHashFn
}
func NewCache(update CacheUpdateFn, hash CacheHashFn) *Cache {
return &Cache{updateFn: update, hashFn: hash}
}
func NewCacheContext(update CacheUpdateContextFn, hash CacheHashContextFn) *Cache {
return NewCache(update.Fn(), hash.Fn())
}
func (c *Cache) Get(state interface{}) interface{} {
if c.hashFn(state) != c.hash {
c.value = c.updateFn(state)
}
return c.value
}

View File

@ -1,21 +0,0 @@
package ui
import (
"github.com/minio/highwayhash"
"opslag.de/schobers/geom"
)
type desiredSizeCache struct {
sum [32]byte
size geom.PointF32
}
func (c *desiredSizeCache) Update(ctx Context, data string, calcFn func(Context) geom.PointF32) geom.PointF32 {
var key = [32]byte{}
sum := highwayhash.Sum([]byte(data), key[:])
if c.sum != sum {
c.size = calcFn(ctx)
c.sum = sum
}
return c.size
}

View File

@ -9,7 +9,8 @@ type Label struct {
Text string Text string
size desiredSizeCache init bool
size *Cache
} }
func BuildLabel(text string, fn func(*Label)) *Label { func BuildLabel(text string, fn func(*Label)) *Label {
@ -20,23 +21,38 @@ func BuildLabel(text string, fn func(*Label)) *Label {
return l return l
} }
func (l *Label) DesiredSize(ctx Context) geom.PointF32 { func (l *Label) initialize() {
var fontName = l.FontName(ctx) if l.init {
return l.size.Update(ctx, fontName+l.Text, func(ctx Context) geom.PointF32 { return
var font = ctx.Renderer().Font(fontName) }
var width = font.WidthOf(l.Text) l.size = NewCacheContext(l.desiredSize, l.hashContent)
var height = font.Height() l.init = true
var pad = ctx.Style().Dimensions.TextPadding }
func (l *Label) hashContent(ctx Context) string {
return l.FontName(ctx) + l.Text
}
func (l *Label) desiredSize(ctx Context) interface{} {
fontName := l.FontName(ctx)
font := ctx.Renderer().Font(fontName)
width := font.WidthOf(l.Text)
height := font.Height()
pad := ctx.Style().Dimensions.TextPadding
return geom.PtF32(width+pad*2, height+pad*2) return geom.PtF32(width+pad*2, height+pad*2)
}) }
func (l *Label) DesiredSize(ctx Context) geom.PointF32 {
l.initialize()
return l.size.Get(ctx).(geom.PointF32)
} }
func (l *Label) Render(ctx Context) { func (l *Label) Render(ctx Context) {
l.RenderBackground(ctx) l.RenderBackground(ctx)
var c = l.FontColor(ctx) c := l.FontColor(ctx)
var f = l.FontName(ctx) f := l.FontName(ctx)
var pad = ctx.Style().Dimensions.TextPadding pad := ctx.Style().Dimensions.TextPadding
var bounds = l.bounds.Inset(pad) bounds := l.bounds.Inset(pad)
switch l.TextAlignment { switch l.TextAlignment {
case AlignLeft: case AlignLeft:
ctx.Renderer().TextAlign(bounds.Min, f, c, l.Text, l.TextAlignment) ctx.Renderer().TextAlign(bounds.Min, f, c, l.Text, l.TextAlignment)