Added Resources abstraction.
This commit is contained in:
parent
a0660a9650
commit
b28b3e1838
76
addons/fs/afero.go
Normal file
76
addons/fs/afero.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package fs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
"opslag.de/schobers/zntg"
|
||||||
|
"opslag.de/schobers/zntg/ui"
|
||||||
|
)
|
||||||
|
|
||||||
|
type aferoResources struct {
|
||||||
|
dir string
|
||||||
|
fs afero.Fs
|
||||||
|
copy *zntg.Dir
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ ui.Resources = &aferoResources{}
|
||||||
|
|
||||||
|
// NewAferoResources provides resources from a afero file system. The prefix is used as a prefix of the temporary directory.
|
||||||
|
func NewAferoResources(fs afero.Fs, prefix string) (ui.Resources, error) {
|
||||||
|
return NewAferoFallbackResources("", fs, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAferoFallbackResources provides resources from the directory first and uses afero file system as a fallback if the resource in the directory doesn't exist. The prefix is used as a prefix of the temporary directory.
|
||||||
|
func NewAferoFallbackResources(dir string, fs afero.Fs, prefix string) (ui.Resources, error) {
|
||||||
|
copy, err := zntg.NewTempDir(prefix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &aferoResources{dir, fs, copy}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *aferoResources) fetchAferoResource(name string) (string, error) {
|
||||||
|
path := r.copy.FilePath(name)
|
||||||
|
if !zntg.FileExists(path) {
|
||||||
|
src, err := r.fs.Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
err = r.copy.Write(name, src)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *aferoResources) openAferoResource(name string) (io.ReadCloser, error) { return r.fs.Open(name) }
|
||||||
|
|
||||||
|
func (r *aferoResources) Destroy() error { return r.copy.Destroy() }
|
||||||
|
|
||||||
|
func (r *aferoResources) FetchResource(name string) (string, error) {
|
||||||
|
if r.dir == "" {
|
||||||
|
return r.fetchAferoResource(name)
|
||||||
|
}
|
||||||
|
path := filepath.Join(r.dir, name)
|
||||||
|
if zntg.FileExists(path) {
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
return r.fetchAferoResource(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *aferoResources) OpenResource(name string) (io.ReadCloser, error) {
|
||||||
|
if r.dir == "" {
|
||||||
|
return r.openAferoResource(name)
|
||||||
|
}
|
||||||
|
path := filepath.Join(r.dir, name)
|
||||||
|
if zntg.FileExists(path) {
|
||||||
|
return os.Open(path)
|
||||||
|
}
|
||||||
|
return r.openAferoResource(name)
|
||||||
|
}
|
@ -47,7 +47,7 @@ func NewRenderer(w, h int, opts allg5.NewDisplayOptions) (*Renderer, error) {
|
|||||||
})
|
})
|
||||||
clean = nil
|
clean = nil
|
||||||
|
|
||||||
return &Renderer{disp, eq, nil, map[string]*font{}, user, ui.KeyState{}, ui.KeyModifierNone, ui.MouseCursorDefault}, nil
|
return &Renderer{disp, eq, nil, map[string]*font{}, user, &ui.OSResources{}, ui.KeyState{}, ui.KeyModifierNone, ui.MouseCursorDefault}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderer implements ui.Renderer using Allegro 5.
|
// Renderer implements ui.Renderer using Allegro 5.
|
||||||
@ -57,6 +57,7 @@ type Renderer struct {
|
|||||||
unh func(allg5.Event)
|
unh func(allg5.Event)
|
||||||
ft map[string]*font
|
ft map[string]*font
|
||||||
user *allg5.UserEventSource
|
user *allg5.UserEventSource
|
||||||
|
res ui.Resources
|
||||||
|
|
||||||
keys ui.KeyState
|
keys ui.KeyState
|
||||||
modifiers ui.KeyModifier
|
modifiers ui.KeyModifier
|
||||||
@ -153,6 +154,7 @@ func (r *Renderer) Destroy() error {
|
|||||||
}
|
}
|
||||||
r.ft = nil
|
r.ft = nil
|
||||||
r.disp.Destroy()
|
r.disp.Destroy()
|
||||||
|
r.res.Destroy()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,10 +184,14 @@ func (r *Renderer) CreateTexture(source ui.ImageSource) (ui.Texture, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) CreateTextureGo(im image.Image, source bool) (ui.Texture, error) {
|
func (r *Renderer) CreateTextureGo(im image.Image, source bool) (ui.Texture, error) {
|
||||||
return r.createTexture(ui.ImageGoSource{im}, true)
|
return r.createTexture(ui.ImageSourceGo{im}, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) CreateTexturePath(path string, source bool) (ui.Texture, error) {
|
func (r *Renderer) CreateTexturePath(path string, source bool) (ui.Texture, error) {
|
||||||
|
path, err := r.res.FetchResource(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
bmp, err := allg5.LoadBitmap(path)
|
bmp, err := allg5.LoadBitmap(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -250,7 +256,11 @@ func (r *Renderer) Rectangle(rect geom.RectangleF32, c color.Color, thickness fl
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) RegisterFont(name, path string, size int) error {
|
func (r *Renderer) RegisterFont(name, path string, size int) error {
|
||||||
var f, err = allg5.LoadTTFFont(path, size)
|
path, err := r.res.FetchResource(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
font, err := allg5.LoadTTFFont(path, size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -258,7 +268,7 @@ func (r *Renderer) RegisterFont(name, path string, size int) error {
|
|||||||
if prev != nil {
|
if prev != nil {
|
||||||
prev.Destroy()
|
prev.Destroy()
|
||||||
}
|
}
|
||||||
r.ft[name] = newFont(f)
|
r.ft[name] = newFont(font)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,6 +291,8 @@ func (r *Renderer) RenderToDisplay() {
|
|||||||
r.disp.SetAsTarget()
|
r.disp.SetAsTarget()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) Resources() ui.Resources { return r.res }
|
||||||
|
|
||||||
func (r *Renderer) Size() geom.PointF32 {
|
func (r *Renderer) Size() geom.PointF32 {
|
||||||
return geom.PtF32(float32(r.disp.Width()), float32(r.disp.Height()))
|
return geom.PtF32(float32(r.disp.Width()), float32(r.disp.Height()))
|
||||||
}
|
}
|
||||||
@ -294,6 +306,13 @@ func (r *Renderer) SetMouseCursor(c ui.MouseCursor) {
|
|||||||
r.cursor = c
|
r.cursor = c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Renderer) SetResourceProvider(factory func() ui.Resources) {
|
||||||
|
if r.res != nil {
|
||||||
|
r.res.Destroy()
|
||||||
|
}
|
||||||
|
r.res = factory()
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Renderer) SetUnhandledEventHandler(handler func(allg5.Event)) {
|
func (r *Renderer) SetUnhandledEventHandler(handler func(allg5.Event)) {
|
||||||
r.unh = handler
|
r.unh = handler
|
||||||
}
|
}
|
||||||
|
49
io.go
49
io.go
@ -7,6 +7,7 @@ import (
|
|||||||
_ "image/jpeg" // decoding of JPEG
|
_ "image/jpeg" // decoding of JPEG
|
||||||
"image/png"
|
"image/png"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
@ -47,6 +48,29 @@ func DecodeJSON(path string, value interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dir is a convenience struct for representing a path to a directory.
|
||||||
|
type Dir struct {
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilePath returns the path of a file with the specified name in the directory.
|
||||||
|
func (d *Dir) FilePath(name string) string {
|
||||||
|
return filepath.Join(d.Path, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes the content of the reader into a file with the specified name.
|
||||||
|
func (d *Dir) Write(name string, r io.Reader) error {
|
||||||
|
path := d.FilePath(name)
|
||||||
|
dir := filepath.Dir(path)
|
||||||
|
os.MkdirAll(dir, 0777)
|
||||||
|
return EncodeFile(path, r, CopyReader)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy removes the directory.
|
||||||
|
func (d *Dir) Destroy() error {
|
||||||
|
return os.RemoveAll(d.Path)
|
||||||
|
}
|
||||||
|
|
||||||
// EncoderFn describes a generic encoder.
|
// EncoderFn describes a generic encoder.
|
||||||
type EncoderFn func(io.Writer, interface{}) error
|
type EncoderFn func(io.Writer, interface{}) error
|
||||||
|
|
||||||
@ -70,6 +94,14 @@ func EncodePNG(path string, im image.Image) error {
|
|||||||
return EncodeFile(path, im, PNGEncoder)
|
return EncodeFile(path, im, PNGEncoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileExists returns if file exists on specified path.
|
||||||
|
func FileExists(path string) bool {
|
||||||
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
var _ DecoderFn = ImageDecoder
|
var _ DecoderFn = ImageDecoder
|
||||||
|
|
||||||
// ImageDecoder is a generic image decoder.
|
// ImageDecoder is a generic image decoder.
|
||||||
@ -91,6 +123,15 @@ var _ EncoderFn = PNGEncoder
|
|||||||
// PNGEncoder is a generic PNG encoder.
|
// PNGEncoder is a generic PNG encoder.
|
||||||
func PNGEncoder(w io.Writer, value interface{}) error { return png.Encode(w, value.(image.Image)) }
|
func PNGEncoder(w io.Writer, value interface{}) error { return png.Encode(w, value.(image.Image)) }
|
||||||
|
|
||||||
|
// NewTempDir creates a temporary directory.
|
||||||
|
func NewTempDir(prefix string) (*Dir, error) {
|
||||||
|
path, err := ioutil.TempDir("", prefix)
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Dir{path}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// UserDir gives back the user configuration directory with given name.
|
// UserDir gives back the user configuration directory with given name.
|
||||||
func UserDir(name string) (string, error) {
|
func UserDir(name string) (string, error) {
|
||||||
config, err := os.UserConfigDir()
|
config, err := os.UserConfigDir()
|
||||||
@ -113,3 +154,11 @@ func UserFile(app, name string) (string, error) {
|
|||||||
}
|
}
|
||||||
return filepath.Join(dir, name), nil
|
return filepath.Join(dir, name), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ EncoderFn = CopyReader
|
||||||
|
|
||||||
|
// CopyReader copies the provided value to the output.
|
||||||
|
func CopyReader(w io.Writer, value interface{}) error {
|
||||||
|
_, err := io.Copy(w, value.(io.Reader))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@ type Renderer struct {
|
|||||||
renderer *sdl.Renderer
|
renderer *sdl.Renderer
|
||||||
refresh uint32
|
refresh uint32
|
||||||
fonts map[string]*Font
|
fonts map[string]*Font
|
||||||
|
resources ui.Resources
|
||||||
|
|
||||||
mouse geom.PointF32
|
mouse geom.PointF32
|
||||||
cursor ui.MouseCursor
|
cursor ui.MouseCursor
|
||||||
@ -88,6 +89,7 @@ func NewRenderer(title string, width, height int32, opts NewRendererOptions) (*R
|
|||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
refresh: refresh,
|
refresh: refresh,
|
||||||
fonts: map[string]*Font{},
|
fonts: map[string]*Font{},
|
||||||
|
resources: &ui.OSResources{},
|
||||||
cursors: map[sdl.SystemCursor]*sdl.Cursor{},
|
cursors: map[sdl.SystemCursor]*sdl.Cursor{},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -210,6 +212,7 @@ func (r *Renderer) Destroy() error {
|
|||||||
r.window.Destroy()
|
r.window.Destroy()
|
||||||
ttf.Quit()
|
ttf.Quit()
|
||||||
sdl.Quit()
|
sdl.Quit()
|
||||||
|
r.resources.Destroy()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,11 +256,11 @@ func (r *Renderer) CreateTexture(source ui.ImageSource) (ui.Texture, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) CreateTextureGo(m image.Image, source bool) (ui.Texture, error) {
|
func (r *Renderer) CreateTextureGo(m image.Image, source bool) (ui.Texture, error) {
|
||||||
return r.createTexture(ui.ImageGoSource{Image: m}, source)
|
return r.createTexture(ui.ImageSourceGo{Image: m}, source)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) CreateTexturePath(path string, source bool) (ui.Texture, error) {
|
func (r *Renderer) CreateTexturePath(path string, source bool) (ui.Texture, error) {
|
||||||
return r.createTexture(ui.ImageFileSource(path), source)
|
return r.createTexture(ui.ImageSourceResource{Resources: r.resources, Name: path}, source)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) CreateTextureTarget(w, h float32) (ui.Texture, error) {
|
func (r *Renderer) CreateTextureTarget(w, h float32) (ui.Texture, error) {
|
||||||
@ -331,6 +334,10 @@ func (r *Renderer) Rectangle(rect geom.RectangleF32, c color.Color, thickness fl
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) RegisterFont(name, path string, size int) error {
|
func (r *Renderer) RegisterFont(name, path string, size int) error {
|
||||||
|
path, err := r.resources.FetchResource(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
font, err := ttf.OpenFont(path, size)
|
font, err := ttf.OpenFont(path, size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -420,6 +427,17 @@ func (r *Renderer) TextAlign(p geom.PointF32, font string, color color.Color, te
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resources
|
||||||
|
|
||||||
|
func (r *Renderer) Resources() ui.Resources { return r.resources }
|
||||||
|
|
||||||
|
func (r *Renderer) SetResourceProvider(factory func() ui.Resources) {
|
||||||
|
if r.resources != nil {
|
||||||
|
r.resources.Destroy()
|
||||||
|
}
|
||||||
|
r.resources = factory()
|
||||||
|
}
|
||||||
|
|
||||||
// Texture
|
// Texture
|
||||||
|
|
||||||
func (r *Renderer) Image() image.Image { return nil }
|
func (r *Renderer) Image() image.Image { return nil }
|
||||||
|
@ -3,10 +3,10 @@ package ui
|
|||||||
type Context interface {
|
type Context interface {
|
||||||
Animate()
|
Animate()
|
||||||
HasQuit() bool
|
HasQuit() bool
|
||||||
Textures() *Textures
|
|
||||||
Quit()
|
Quit()
|
||||||
Renderer() Renderer
|
Renderer() Renderer
|
||||||
Style() *Style
|
Style() *Style
|
||||||
|
Textures() *Textures
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Context = &context{}
|
var _ Context = &context{}
|
||||||
@ -32,7 +32,9 @@ func (c *context) HasQuit() bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Textures() *Textures { return c.textures }
|
func (c *context) Renderer() Renderer { return c.r }
|
||||||
|
|
||||||
|
func (c *context) Style() *Style { return c.style }
|
||||||
|
|
||||||
func (c *context) Quit() {
|
func (c *context) Quit() {
|
||||||
if !c.HasQuit() {
|
if !c.HasQuit() {
|
||||||
@ -40,9 +42,7 @@ func (c *context) Quit() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Renderer() Renderer { return c.r }
|
func (c *context) Textures() *Textures { return c.textures }
|
||||||
|
|
||||||
func (c *context) Style() *Style { return c.style }
|
|
||||||
|
|
||||||
// Handle implement EventTarget
|
// Handle implement EventTarget
|
||||||
|
|
||||||
|
56
ui/copyresources.go
Normal file
56
ui/copyresources.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"opslag.de/schobers/zntg"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Resources = &CopyResources{}
|
||||||
|
|
||||||
|
// CopyResources copies and opens resources to a temporary directory.
|
||||||
|
type CopyResources struct {
|
||||||
|
Source Resources
|
||||||
|
|
||||||
|
copy *zntg.Dir
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCopyResource creates a proxy that copied resources first to disk.
|
||||||
|
func NewCopyResource(prefix string, source Resources) (*CopyResources, error) {
|
||||||
|
copy, err := zntg.NewTempDir(prefix)
|
||||||
|
if nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &CopyResources{source, copy}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchResource copies the file from the source to disk and returns the path to it.
|
||||||
|
func (r *CopyResources) FetchResource(name string) (string, error) {
|
||||||
|
path := r.copy.FilePath(name)
|
||||||
|
if !zntg.FileExists(path) {
|
||||||
|
src, err := r.Source.OpenResource(name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
err = r.copy.Write(name, src)
|
||||||
|
if nil != err {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenResource opens the (copied) resource on disk.
|
||||||
|
func (r *CopyResources) OpenResource(name string) (io.ReadCloser, error) {
|
||||||
|
path := r.copy.FilePath(name)
|
||||||
|
src, err := os.Open(path)
|
||||||
|
return src, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy destroy the copy of the resources.
|
||||||
|
func (r *CopyResources) Destroy() error {
|
||||||
|
return r.copy.Destroy()
|
||||||
|
}
|
@ -2,36 +2,46 @@ package ui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
"os"
|
|
||||||
|
"opslag.de/schobers/zntg"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ImageSource interface {
|
type ImageSource interface {
|
||||||
CreateImage() (image.Image, error)
|
CreateImage() (image.Image, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImageFileSource string
|
type ImageSourceFile string
|
||||||
|
|
||||||
var _ ImageSource = ImageFileSource("")
|
var _ ImageSource = ImageSourceFile("")
|
||||||
|
|
||||||
func (s ImageFileSource) CreateImage() (image.Image, error) {
|
func (s ImageSourceFile) CreateImage() (image.Image, error) {
|
||||||
f, err := os.Open(string(s))
|
return zntg.DecodeImage(string(s))
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
m, _, err := image.Decode(f)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImageGoSource struct {
|
type ImageSourceGo struct {
|
||||||
image.Image
|
image.Image
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ ImageSource = ImageGoSource{}
|
var _ ImageSource = ImageSourceGo{}
|
||||||
|
|
||||||
func (s ImageGoSource) CreateImage() (image.Image, error) {
|
func (s ImageSourceGo) CreateImage() (image.Image, error) {
|
||||||
return s.Image, nil
|
return s.Image, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ImageSourceResource struct {
|
||||||
|
Resources Resources
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s ImageSourceResource) CreateImage() (image.Image, error) {
|
||||||
|
src, err := s.Resources.OpenResource(s.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
value, err := zntg.ImageDecoder(src)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return value.(image.Image), nil
|
||||||
|
}
|
||||||
|
34
ui/osresources.go
Normal file
34
ui/osresources.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Resources = &OSResources{}
|
||||||
|
|
||||||
|
// DefaultResources returns the default Resources implementation (OSResources).
|
||||||
|
func DefaultResources() Resources {
|
||||||
|
return &OSResources{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSResources is Resources implementation that uses the default file system directly.
|
||||||
|
type OSResources struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchResource checks if file is available and returns the specified path.
|
||||||
|
func (r *OSResources) FetchResource(name string) (string, error) {
|
||||||
|
_, err := os.Stat(name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenResource opens the specified file on disk.
|
||||||
|
func (r *OSResources) OpenResource(name string) (io.ReadCloser, error) {
|
||||||
|
return os.Open(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy does nothing.
|
||||||
|
func (r *OSResources) Destroy() error { return nil }
|
@ -35,4 +35,8 @@ type Renderer interface {
|
|||||||
Target() Texture
|
Target() Texture
|
||||||
Text(p geom.PointF32, font string, color color.Color, text string)
|
Text(p geom.PointF32, font string, color color.Color, text string)
|
||||||
TextAlign(p geom.PointF32, font string, color color.Color, text string, align HorizontalAlignment)
|
TextAlign(p geom.PointF32, font string, color color.Color, text string, align HorizontalAlignment)
|
||||||
|
|
||||||
|
// Resources
|
||||||
|
Resources() Resources
|
||||||
|
SetResourceProvider(factory func() Resources)
|
||||||
}
|
}
|
||||||
|
13
ui/resources.go
Normal file
13
ui/resources.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
// Resources is an abstraction on resources.
|
||||||
|
type Resources interface {
|
||||||
|
// FetchResource should fetch the resource with the specified name and return a path (on disk) where the resource can be accessed.
|
||||||
|
FetchResource(name string) (string, error)
|
||||||
|
// OpenResource should open the resource with the specified name. The user is responsible for closing the resource.
|
||||||
|
OpenResource(name string) (io.ReadCloser, error)
|
||||||
|
// Destroy can be used for cleaning up at the end of the applications lifetime.
|
||||||
|
Destroy() error
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user