123 lines
2.8 KiB
Go
123 lines
2.8 KiB
Go
package cache
|
|
|
|
import (
|
|
"os"
|
|
"time"
|
|
|
|
"fyne.io/fyne/v2"
|
|
)
|
|
|
|
var (
|
|
ValidDuration = 1 * time.Minute
|
|
cleanTaskInterval = ValidDuration / 2
|
|
|
|
lastClean time.Time
|
|
skippedCleanWithCanvasRefresh = false
|
|
|
|
// testing purpose only
|
|
timeNow = time.Now
|
|
)
|
|
|
|
func init() {
|
|
if t, err := time.ParseDuration(os.Getenv("FYNE_CACHE")); err == nil {
|
|
ValidDuration = t
|
|
cleanTaskInterval = ValidDuration / 2
|
|
}
|
|
}
|
|
|
|
// Clean run cache clean task, it should be called on paint events.
|
|
func Clean(canvasRefreshed bool) {
|
|
now := timeNow()
|
|
// do not run clean task too fast
|
|
if now.Sub(lastClean) < 10*time.Second {
|
|
if canvasRefreshed {
|
|
skippedCleanWithCanvasRefresh = true
|
|
}
|
|
return
|
|
}
|
|
if skippedCleanWithCanvasRefresh {
|
|
skippedCleanWithCanvasRefresh = false
|
|
canvasRefreshed = true
|
|
}
|
|
if !canvasRefreshed && now.Sub(lastClean) < cleanTaskInterval {
|
|
return
|
|
}
|
|
destroyExpiredSvgs(now)
|
|
destroyExpiredFontMetrics(now)
|
|
if canvasRefreshed {
|
|
// Destroy renderers on canvas refresh to avoid flickering screen.
|
|
destroyExpiredRenderers(now)
|
|
// canvases cache should be invalidated only on canvas refresh, otherwise there wouldn't
|
|
// be a way to recover them later
|
|
destroyExpiredCanvases(now)
|
|
}
|
|
lastClean = timeNow()
|
|
}
|
|
|
|
// CleanCanvas performs a complete remove of all the objects that belong to the specified
|
|
// canvas. Usually used to free all objects from a closing windows.
|
|
func CleanCanvas(canvas fyne.Canvas) {
|
|
canvases.Range(func(obj fyne.CanvasObject, cinfo *canvasInfo) bool {
|
|
if cinfo.canvas != canvas {
|
|
return true
|
|
}
|
|
|
|
canvases.Delete(obj)
|
|
|
|
wid, ok := obj.(fyne.Widget)
|
|
if !ok {
|
|
return true
|
|
}
|
|
rinfo, ok := renderers.LoadAndDelete(wid)
|
|
if !ok {
|
|
return true
|
|
}
|
|
rinfo.renderer.Destroy()
|
|
overrides.Delete(wid)
|
|
return true
|
|
})
|
|
}
|
|
|
|
// ResetThemeCaches clears all the svg and text size cache maps
|
|
func ResetThemeCaches() {
|
|
svgs.Clear()
|
|
fontSizeCache.Clear()
|
|
}
|
|
|
|
// destroyExpiredCanvases deletes objects from the canvases cache.
|
|
func destroyExpiredCanvases(now time.Time) {
|
|
canvases.Range(func(obj fyne.CanvasObject, cinfo *canvasInfo) bool {
|
|
if cinfo.isExpired(now) {
|
|
canvases.Delete(obj)
|
|
}
|
|
return true
|
|
})
|
|
}
|
|
|
|
// destroyExpiredRenderers deletes the renderer from the cache and calls
|
|
// renderer.Destroy()
|
|
func destroyExpiredRenderers(now time.Time) {
|
|
renderers.Range(func(wid fyne.Widget, rinfo *rendererInfo) bool {
|
|
if rinfo.isExpired(now) {
|
|
rinfo.renderer.Destroy()
|
|
overrides.Delete(wid)
|
|
renderers.Delete(wid)
|
|
}
|
|
return true
|
|
})
|
|
}
|
|
|
|
type expiringCache struct {
|
|
expires time.Time
|
|
}
|
|
|
|
// isExpired check if the cache data is expired.
|
|
func (c *expiringCache) isExpired(now time.Time) bool {
|
|
return c.expires.Before(now)
|
|
}
|
|
|
|
// setAlive updates expiration time.
|
|
func (c *expiringCache) setAlive() {
|
|
c.expires = timeNow().Add(ValidDuration)
|
|
}
|