Added "image constants"

This commit is contained in:
Alexei Anoshenko 2022-04-23 18:13:35 +03:00
parent 50cbb10bf6
commit 371079e27b
8 changed files with 155 additions and 13 deletions

View File

@ -239,7 +239,7 @@ func (image *backgroundImage) Get(tag string) interface{} {
}
func (image *backgroundImage) cssStyle(session Session) string {
if src, ok := stringProperty(image, Source, session); ok && src != "" {
if src, ok := imageProperty(image, Source, session); ok && src != "" {
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)

View File

@ -128,5 +128,10 @@ func (manager *imageManager) imageLoadError(obj DataObject, session Session) {
// 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)
}

View File

@ -109,8 +109,12 @@ func (imageView *imageViewData) set(tag string, value interface{}) bool {
if text, ok := value.(string); ok {
imageView.properties[Source] = text
if imageView.created {
updateProperty(imageView.htmlID(), "src", text, imageView.session)
if srcset := imageView.srcSet(text); srcset != "" {
src := text
if src != "" && src[0] == '@' {
src, _ = imageProperty(imageView, Source, imageView.session)
}
updateProperty(imageView.htmlID(), "src", src, imageView.session)
if srcset := imageView.srcSet(src); srcset != "" {
updateProperty(imageView.htmlID(), "srcset", srcset, imageView.session)
} else {
removeProperty(imageView.htmlID(), "srcset", imageView.session)
@ -179,15 +183,25 @@ func (imageView *imageViewData) closeHTMLTag() bool {
func (imageView *imageViewData) htmlProperties(self View, buffer *strings.Builder) {
imageView.viewData.htmlProperties(self, buffer)
imageResource := GetImageViewSource(imageView, "")
if imageResource != "" {
buffer.WriteString(` src="`)
buffer.WriteString(imageResource)
buffer.WriteString(`"`)
if srcset := imageView.srcSet(imageResource); srcset != "" {
buffer.WriteString(` srcset="`)
buffer.WriteString(srcset)
if imageResource, ok := imageProperty(imageView, Source, imageView.Session()); ok && imageResource != "" {
if imageResource[0] == '@' {
if image, ok := imageView.Session().ImageConstant(imageResource[1:]); ok {
imageResource = image
} else {
imageResource = ""
}
}
if imageResource != "" {
buffer.WriteString(` src="`)
buffer.WriteString(imageResource)
buffer.WriteString(`"`)
if srcset := imageView.srcSet(imageResource); srcset != "" {
buffer.WriteString(` srcset="`)
buffer.WriteString(srcset)
buffer.WriteString(`"`)
}
}
}
@ -236,9 +250,16 @@ func (imageView *imageViewData) cssStyle(self View, builder cssBuilder) {
// GetImageViewSource returns the image URL of an ImageView subview.
// If the second argument (subviewID) is "" then a left position of the first argument (view) is returned
func GetImageViewSource(view View, subviewID string) string {
if image, ok := stringProperty(view, Source, view.Session()); ok {
return image
if subviewID != "" {
view = ViewByID(view, subviewID)
}
if view != nil {
if image, ok := imageProperty(view, Source, view.Session()); ok {
return image
}
}
return ""
}

View File

@ -14,6 +14,23 @@ func stringProperty(properties Properties, tag string, session Session) (string,
return "", false
}
func imageProperty(properties Properties, tag string, session Session) (string, bool) {
if value := properties.getRaw(tag); value != nil {
if text, ok := value.(string); ok {
if text != "" && text[0] == '@' {
if image, ok := session.ImageConstant(text[1:]); ok {
return image, true
} else {
return "", false
}
}
return text, true
}
}
return "", false
}
func valueToSizeUnit(value interface{}, session Session) (SizeUnit, bool) {
if value != nil {
switch value := value.(type) {

View File

@ -7,6 +7,7 @@ import (
"net/http"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
)
@ -422,5 +423,6 @@ func AllImageResources() []string {
for image := range resources.images {
result = append(result, image)
}
sort.Strings(result)
return result
}

View File

@ -35,6 +35,10 @@ type Session interface {
Color(tag string) (Color, bool)
// ColorTags returns the list of all available color constants
ColorTags() []string
// ImageConstant returns the image constant with "tag" name or "" if it is not exists
ImageConstant(tag string) (string, bool)
// ImageConstantTags returns the list of all available image constants
ImageConstantTags() []string
// SetCustomTheme set the custom theme
SetCustomTheme(name string) bool
// UserAgent returns the "user-agent" text of the client browser

View File

@ -186,6 +186,45 @@ func (session *sessionData) Color(tag string) (Color, bool) {
}
}
func (session *sessionData) ImageConstant(tag string) (string, bool) {
tags := []string{tag}
result := ""
theme := session.getCurrentTheme()
for {
ok := false
if session.darkTheme {
if theme.darkImages != nil {
result, ok = theme.darkImages[tag]
}
}
if !ok {
if theme.images != nil {
result, ok = theme.images[tag]
}
}
if !ok {
ErrorLogF(`"%v" image not found`, tag)
return "", false
}
if result == "" || result[0] != '@' {
return result, true
}
tag = result[1:]
for _, t := range tags {
if t == tag {
ErrorLogF(`"%v" image is cyclic`, tag)
return "", false
}
}
tags = append(tags, tag)
}
}
func (session *sessionData) SetCustomTheme(name string) bool {
if name == "" {
if session.customTheme == nil {
@ -374,3 +413,21 @@ func (session *sessionData) ColorTags() []string {
sort.Strings(keys)
return keys
}
func (session *sessionData) ImageConstantTags() []string {
theme := session.getCurrentTheme()
keys := make([]string, 0, len(theme.colors))
for k := range theme.images {
keys = append(keys, k)
}
for tag := range theme.darkImages {
if _, ok := theme.images[tag]; !ok {
keys = append(keys, tag)
}
}
sort.Strings(keys)
return keys
}

View File

@ -111,6 +111,8 @@ type theme struct {
touchConstants map[string]string
colors map[string]string
darkColors map[string]string
images map[string]string
darkImages map[string]string
styles map[string]Params
mediaStyles []mediaStyle
}
@ -129,6 +131,8 @@ func (theme *theme) init() {
theme.touchConstants = map[string]string{}
theme.colors = map[string]string{}
theme.darkColors = map[string]string{}
theme.images = map[string]string{}
theme.darkImages = map[string]string{}
theme.styles = map[string]Params{}
theme.mediaStyles = []mediaStyle{}
}
@ -154,6 +158,14 @@ func (theme *theme) concat(anotherTheme *theme) {
theme.darkColors[tag] = color
}
for tag, image := range anotherTheme.images {
theme.images[tag] = image
}
for tag, image := range anotherTheme.darkImages {
theme.darkImages[tag] = image
}
for tag, style := range anotherTheme.styles {
theme.styles[tag] = style
}
@ -308,6 +320,30 @@ func (theme *theme) parseThemeData(data DataObject) {
}
}
case "images":
if d.Type() == ObjectNode {
if obj := d.Object(); obj != nil {
objCount := obj.PropertyCount()
for k := 0; k < objCount; k++ {
if prop := obj.Property(k); prop != nil && prop.Type() == TextNode {
theme.images[prop.Tag()] = prop.Text()
}
}
}
}
case "images:dark":
if d.Type() == ObjectNode {
if obj := d.Object(); obj != nil {
objCount := obj.PropertyCount()
for k := 0; k < objCount; k++ {
if prop := obj.Property(k); prop != nil && prop.Type() == TextNode {
theme.darkImages[prop.Tag()] = prop.Text()
}
}
}
}
case "styles":
if d.Type() == ArrayNode {
arraySize := d.ArraySize()