diff --git a/application.go b/application.go index a97ccd3..1228970 100644 --- a/application.go +++ b/application.go @@ -11,6 +11,7 @@ type Application struct { backend Backend config Config callbackManager CallbackManager + imageManager ImageManager } // Run initializes the application, starts it, and then returns a channel that @@ -114,3 +115,21 @@ func (application *Application) Config () (config *Config) { config = &application.config return } + +// AddImage adds a new image buffer and returns a pointer to it. +func (application *Application) NewImage () (im *ColorImage) { + cellWidth, cellHeight := application.backend.CellMetrics() + im = &ColorImage { + cellWidth: cellWidth, + cellHeight: cellHeight, + } + application.imageManager.Add(im) + return +} + +// Remove removes the specified image buffer, if the application has it. If the +// image was found and removed, removed will be true. +func (application *Application) RemoveImage (im *ColorImage) (removed bool) { + removed = application.imageManager.Remove(im) + return +} diff --git a/backend.go b/backend.go index d29e526..5c009f4 100644 --- a/backend.go +++ b/backend.go @@ -8,11 +8,13 @@ type Backend interface { SetTitle (title string) (err error) SetIcon (icons []image.Image) (err error) Draw () + CellMetrics () (width, height int) } type BackendFactory func ( - application *Application, + application *Application, callbackManager *CallbackManager, + imageManager *ImageManager, ) ( backend Backend, err error, @@ -27,7 +29,10 @@ func RegisterBackend (factory BackendFactory) { func instantiateBackend (application *Application) (backend Backend, err error) { // find a suitable backend for _, factory := range factories { - backend, err = factory(application, &application.callbackManager) + backend, err = factory ( + application, + &application.callbackManager, + &application.imageManager) if err == nil && backend != nil { return } } diff --git a/backends/x/factory.go b/backends/x/factory.go index bf0728b..8fc9267 100644 --- a/backends/x/factory.go +++ b/backends/x/factory.go @@ -19,8 +19,9 @@ import "github.com/flopp/go-findfont" // factory instantiates an X backend. func factory ( - application *stone.Application, + application *stone.Application, callbackManager *stone.CallbackManager, + imageManager *stone.ImageManager, ) ( output stone.Backend, err error, @@ -29,6 +30,7 @@ func factory ( application: application, config: application.Config(), callbackManager: callbackManager, + imageManager: imageManager, } // load font diff --git a/backends/x/x.go b/backends/x/x.go index 74a7818..0eac148 100644 --- a/backends/x/x.go +++ b/backends/x/x.go @@ -17,6 +17,7 @@ type Backend struct { application *stone.Application config *stone.Config callbackManager *stone.CallbackManager + imageManager *stone.ImageManager connection *xgbutil.XUtil window *xwindow.Window canvas *xgraphics.Image @@ -88,6 +89,12 @@ func (backend *Backend) SetIcon (icons []image.Image) (err error) { return } +func (backend *Backend) CellMetrics () (width, height int) { + width = backend.metrics.cellWidth + height = backend.metrics.cellHeight + return +} + // calculateWindowSize calculates window bounds based on the internal buffer // size. func (backend *Backend) calculateWindowSize () (x, y int) { diff --git a/image.go b/image.go index 15a4aa8..5602dd9 100644 --- a/image.go +++ b/image.go @@ -1,8 +1,65 @@ package stone +import "sync" import "image" import "image/color" +type ImageManager struct { + lock sync.RWMutex + images []*ColorImage +} + +func (manager *ImageManager) For (callback func (im *ColorImage)) { + manager.lock.RLock() + defer manager.lock.RUnlock() + + for _, im := range manager.images { + callback(im) + } +} + +func (manager *ImageManager) Add (im *ColorImage) { + manager.lock.Lock() + defer manager.lock.Unlock() + + manager.images = append(manager.images, im) +} + +func (manager *ImageManager) Size () (size int) { + manager.lock.RLock() + defer manager.lock.RUnlock() + + size = len(manager.images) + return +} + +func (manager *ImageManager) At (index int) (im *ColorImage) { + manager.lock.RLock() + defer manager.lock.RUnlock() + + if index < 0 || index > len(manager.images) { return } + im = manager.images[index] + return +} + +func (manager *ImageManager) Remove (im *ColorImage) (removed bool) { + manager.lock.Lock() + defer manager.lock.Unlock() + + index := 0 + for manager.images[index] != im && index < len(manager.images) { + index ++ + } + + if index >= len(manager.images) { return } + + manager.images = append ( + manager.images[:index], + manager.images[index + 1:]...) + removed = true + return +} + type ColorImage struct { x, y int width, height int