package rui import ( "strconv" ) const ( // ImageLoading is the image loading status: in the process of loading ImageLoading = 0 // ImageReady is the image loading status: the image is loaded successfully ImageReady = 1 // ImageLoadingError is the image loading status: an error occurred while loading ImageLoadingError = 2 ) // Image defines the image that is used for drawing operations on the Canvas. type Image interface { // URL returns the url of the image URL() string // LoadingStatus returns the status of the image loading: ImageLoading (0), ImageReady (1), ImageLoadingError (2) LoadingStatus() int // LoadingError: if LoadingStatus() == ImageLoadingError then returns the error text, "" otherwise LoadingError() string setLoadingError(err string) // Width returns the width of the image in pixels. While LoadingStatus() != ImageReady returns 0 Width() float64 // Height returns the height of the image in pixels. While LoadingStatus() != ImageReady returns 0 Height() float64 } type imageData struct { url string loadingStatus int loadingError string width, height float64 listener func(Image) } type imageManager struct { images map[string]*imageData } func (image *imageData) URL() string { return image.url } func (image *imageData) LoadingStatus() int { return image.loadingStatus } func (image *imageData) LoadingError() string { return image.loadingError } func (image *imageData) setLoadingError(err string) { image.loadingError = err } func (image *imageData) Width() float64 { return image.width } func (image *imageData) Height() float64 { return image.height } func (manager *imageManager) loadImage(url string, onLoaded func(Image), session Session) Image { if manager.images == nil { manager.images = make(map[string]*imageData) } if image, ok := manager.images[url]; ok && image.loadingStatus == ImageReady { return image } image := new(imageData) image.url = url image.listener = onLoaded image.loadingStatus = ImageLoading manager.images[url] = image session.callFunc("loadImage", url) return image } func (manager *imageManager) imageLoaded(obj DataObject, session Session) { if manager.images == nil { manager.images = make(map[string]*imageData) return } if url, ok := obj.PropertyValue("url"); ok { if image, ok := manager.images[url]; ok { image.loadingStatus = ImageReady if width, ok := obj.PropertyValue("width"); ok { if w, err := strconv.ParseFloat(width, 64); err == nil { image.width = w } } if height, ok := obj.PropertyValue("height"); ok { if h, err := strconv.ParseFloat(height, 64); err == nil { image.height = h } } if image.listener != nil { image.listener(image) } } } } func (manager *imageManager) imageLoadError(obj DataObject, session Session) { if manager.images == nil { manager.images = make(map[string]*imageData) return } if url, ok := obj.PropertyValue("url"); ok { if image, ok := manager.images[url]; ok { delete(manager.images, url) text, _ := obj.PropertyValue("message") image.setLoadingError(text) if image.listener != nil { image.listener(image) } } } } // LoadImage starts the async image loading by url func LoadImage(url string, onLoaded func(Image), session Session) Image { if url != "" && url[0] == '@' { if image, ok := session.ImageConstant(url[1:]); ok { url = image } } return session.imageManager().loadImage(url, onLoaded, session) }