Added Properties iterator to DataObject

This commit is contained in:
Alexei Anoshenko 2025-07-03 12:49:41 +03:00
parent 90b1d44597
commit 86f3f4c731
12 changed files with 145 additions and 154 deletions

View File

@ -245,14 +245,12 @@ func parseAnimation(obj DataObject) AnimationProperty {
animation := new(animationData) animation := new(animationData)
animation.init() animation.init()
for i := range obj.PropertyCount() { for node := range obj.Properties() {
if node := obj.Property(i); node != nil { tag := PropertyName(node.Tag())
tag := PropertyName(node.Tag()) if node.Type() == TextNode {
if node.Type() == TextNode { animation.Set(tag, node.Text())
animation.Set(tag, node.Text()) } else {
} else { animation.Set(tag, node)
animation.Set(tag, node)
}
} }
} }
return animation return animation
@ -493,8 +491,8 @@ func animationSet(properties Properties, tag PropertyName, value any) []Property
case DataNode: case DataNode:
parseObject := func(obj DataObject) (AnimatedProperty, bool) { parseObject := func(obj DataObject) (AnimatedProperty, bool) {
result := AnimatedProperty{} result := AnimatedProperty{}
for i := range obj.PropertyCount() { for node := range obj.Properties() {
if node := obj.Property(i); node.Type() == TextNode { if node.Type() == TextNode {
propTag := strings.ToLower(node.Tag()) propTag := strings.ToLower(node.Tag())
switch propTag { switch propTag {
case "from", "0", "0%": case "from", "0", "0%":

View File

@ -66,9 +66,8 @@ func createBackground(obj DataObject) BackgroundElement {
return nil return nil
} }
count := obj.PropertyCount() for node := range obj.Properties() {
for i := range count { if node.Type() == TextNode {
if node := obj.Property(i); node.Type() == TextNode {
if value := node.Text(); value != "" { if value := node.Text(); value != "" {
result.Set(PropertyName(node.Tag()), value) result.Set(PropertyName(node.Tag()), value)
} }

View File

@ -436,24 +436,20 @@ func (border *borderProperty) String() string {
func (border *borderProperty) setBorderObject(obj DataObject) bool { func (border *borderProperty) setBorderObject(obj DataObject) bool {
result := true result := true
for i := range obj.PropertyCount() { for node := range obj.Properties() {
if node := obj.Property(i); node != nil { tag := PropertyName(node.Tag())
tag := PropertyName(node.Tag()) switch node.Type() {
switch node.Type() { case TextNode:
case TextNode: if borderSet(border, tag, node.Text()) == nil {
if borderSet(border, tag, node.Text()) == nil {
result = false
}
case ObjectNode:
if borderSet(border, tag, node.Object()) == nil {
result = false
}
default:
result = false result = false
} }
} else {
case ObjectNode:
if borderSet(border, tag, node.Object()) == nil {
result = false
}
default:
result = false result = false
} }
} }

26
data.go
View File

@ -3,6 +3,7 @@ package rui
import ( import (
"errors" "errors"
"fmt" "fmt"
"iter"
"slices" "slices"
"strings" "strings"
"unicode" "unicode"
@ -27,6 +28,9 @@ type DataObject interface {
// Tag returns data object tag // Tag returns data object tag
Tag() string Tag() string
// Properties() returns an iterator to access the properties
Properties() iter.Seq[DataNode]
// PropertyCount returns properties count // PropertyCount returns properties count
PropertyCount() int PropertyCount() int
@ -142,6 +146,16 @@ func (object *dataObject) Tag() string {
return object.tag return object.tag
} }
func (object *dataObject) Properties() iter.Seq[DataNode] {
return func(yield func(DataNode) bool) {
for _, node := range object.property {
if !yield(node) {
return
}
}
}
}
func (object *dataObject) PropertyCount() int { func (object *dataObject) PropertyCount() int {
if object.property != nil { if object.property != nil {
return len(object.property) return len(object.property)
@ -231,10 +245,14 @@ func (object *dataObject) SetPropertyValue(tag, value string) {
// SetPropertyObject - set a property with tag by object // SetPropertyObject - set a property with tag by object
func (object *dataObject) SetPropertyObject(tag string, obj DataObject) { func (object *dataObject) SetPropertyObject(tag string, obj DataObject) {
node := new(dataNode) if obj != nil {
node.tag = tag node := new(dataNode)
node.value = obj node.tag = tag
object.setNode(node) node.value = obj
object.setNode(node)
} else {
object.RemovePropertyByTag(tag)
}
} }
func (object *dataObject) ToParams() Params { func (object *dataObject) ToParams() Params {

View File

@ -159,23 +159,21 @@ func NewFilterProperty(params Params) FilterProperty {
func newFilterProperty(obj DataObject) FilterProperty { func newFilterProperty(obj DataObject) FilterProperty {
filter := new(filterData) filter := new(filterData)
filter.init() filter.init()
for i := range obj.PropertyCount() { for node := range obj.Properties() {
if node := obj.Property(i); node != nil { tag := node.Tag()
tag := node.Tag() switch node.Type() {
switch node.Type() { case TextNode:
case TextNode: filter.Set(PropertyName(tag), node.Text())
filter.Set(PropertyName(tag), node.Text())
case ObjectNode: case ObjectNode:
if tag == string(HueRotate) { if tag == string(HueRotate) {
// TODO // TODO
} else { } else {
ErrorLog(`Invalid value of "` + tag + `"`)
}
default:
ErrorLog(`Invalid value of "` + tag + `"`) ErrorLog(`Invalid value of "` + tag + `"`)
} }
default:
ErrorLog(`Invalid value of "` + tag + `"`)
} }
} }

View File

@ -118,19 +118,16 @@ func (properties *propertyList) writeToBuffer(buffer *strings.Builder,
} }
func parseProperties(properties Properties, object DataObject) { func parseProperties(properties Properties, object DataObject) {
count := object.PropertyCount() for node := range object.Properties() {
for i := range count { switch node.Type() {
if node := object.Property(i); node != nil { case TextNode:
switch node.Type() { properties.Set(PropertyName(node.Tag()), node.Text())
case TextNode:
properties.Set(PropertyName(node.Tag()), node.Text())
case ObjectNode: case ObjectNode:
properties.Set(PropertyName(node.Tag()), node.Object()) properties.Set(PropertyName(node.Tag()), node.Object())
case ArrayNode: case ArrayNode:
properties.Set(PropertyName(node.Tag()), node.ArrayElements()) properties.Set(PropertyName(node.Tag()), node.ArrayElements())
}
} }
} }
} }

View File

@ -735,8 +735,8 @@ func (session *sessionData) handleSessionInfo(params DataObject) {
if node := params.PropertyByTag("storage"); node != nil && node.Type() == ObjectNode { if node := params.PropertyByTag("storage"); node != nil && node.Type() == ObjectNode {
if obj := node.Object(); obj != nil { if obj := node.Object(); obj != nil {
for i := range obj.PropertyCount() { for element := range obj.Properties() {
if element := obj.Property(i); element.Type() == TextNode { if element.Type() == TextNode {
session.clientStorage[element.Tag()] = element.Text() session.clientStorage[element.Tag()] = element.Text()
} }
} }

View File

@ -62,8 +62,8 @@ func loadStringResources(text string) {
table = map[string]string{} table = map[string]string{}
} }
for i := range obj.PropertyCount() { for prop := range obj.Properties() {
if prop := obj.Property(i); prop != nil && prop.Type() == TextNode { if prop.Type() == TextNode {
table[prop.Tag()] = prop.Text() table[prop.Tag()] = prop.Text()
} }
} }
@ -73,8 +73,8 @@ func loadStringResources(text string) {
tag := data.Tag() tag := data.Tag()
if tag == "strings" { if tag == "strings" {
for i := range data.PropertyCount() { for prop := range data.Properties() {
if prop := data.Property(i); prop != nil && prop.Type() == ObjectNode { if prop.Type() == ObjectNode {
parseStrings(prop.Object(), prop.Tag()) parseStrings(prop.Object(), prop.Tag())
} }
} }

View File

@ -731,8 +731,8 @@ func (table *tableViewData) setFunc(tag PropertyName, value any) []PropertyName
case DataObject: case DataObject:
params := Params{} params := Params{}
for k := range value.PropertyCount() { for prop := range value.Properties() {
if prop := value.Property(k); prop != nil && prop.Type() == TextNode { if prop.Type() == TextNode {
params[PropertyName(prop.Tag())] = prop.Text() params[PropertyName(prop.Tag())] = prop.Text()
} }
} }

150
theme.go
View File

@ -694,127 +694,115 @@ func (theme *theme) addText(themeText string) bool {
return false return false
} }
count := data.PropertyCount()
objToStyle := func(obj DataObject) ViewStyle { objToStyle := func(obj DataObject) ViewStyle {
params := Params{} params := Params{}
for i := range obj.PropertyCount() { for node := range obj.Properties() {
if node := obj.Property(i); node != nil { switch node.Type() {
switch node.Type() { case ArrayNode:
case ArrayNode: params[PropertyName(node.Tag())] = node.ArrayElements()
params[PropertyName(node.Tag())] = node.ArrayElements()
case ObjectNode: case ObjectNode:
params[PropertyName(node.Tag())] = node.Object() params[PropertyName(node.Tag())] = node.Object()
default: default:
params[PropertyName(node.Tag())] = node.Text() params[PropertyName(node.Tag())] = node.Text()
}
} }
} }
return NewViewStyle(params) return NewViewStyle(params)
} }
for i := range count { for d := range data.Properties() {
if d := data.Property(i); d != nil { switch tag := d.Tag(); tag {
switch tag := d.Tag(); tag { case "constants":
case "constants": if d.Type() == ObjectNode {
if d.Type() == ObjectNode { if obj := d.Object(); obj != nil {
if obj := d.Object(); obj != nil { for prop := range obj.Properties() {
objCount := obj.PropertyCount() if prop.Type() == TextNode {
for k := range objCount { theme.constants[prop.Tag()] = prop.Text()
if prop := obj.Property(k); prop != nil && prop.Type() == TextNode {
theme.constants[prop.Tag()] = prop.Text()
}
} }
} }
} }
}
case "constants:touch": case "constants:touch":
if d.Type() == ObjectNode { if d.Type() == ObjectNode {
if obj := d.Object(); obj != nil { if obj := d.Object(); obj != nil {
objCount := obj.PropertyCount() for prop := range obj.Properties() {
for k := range objCount { if prop.Type() == TextNode {
if prop := obj.Property(k); prop != nil && prop.Type() == TextNode { theme.touchConstants[prop.Tag()] = prop.Text()
theme.touchConstants[prop.Tag()] = prop.Text()
}
} }
} }
} }
}
case "colors": case "colors":
if d.Type() == ObjectNode { if d.Type() == ObjectNode {
if obj := d.Object(); obj != nil { if obj := d.Object(); obj != nil {
objCount := obj.PropertyCount() for prop := range obj.Properties() {
for k := range objCount { if prop.Type() == TextNode {
if prop := obj.Property(k); prop != nil && prop.Type() == TextNode { theme.colors[prop.Tag()] = prop.Text()
theme.colors[prop.Tag()] = prop.Text()
}
} }
} }
} }
}
case "colors:dark": case "colors:dark":
if d.Type() == ObjectNode { if d.Type() == ObjectNode {
if obj := d.Object(); obj != nil { if obj := d.Object(); obj != nil {
objCount := obj.PropertyCount() for prop := range obj.Properties() {
for k := range objCount { if prop.Type() == TextNode {
if prop := obj.Property(k); prop != nil && prop.Type() == TextNode { theme.darkColors[prop.Tag()] = prop.Text()
theme.darkColors[prop.Tag()] = prop.Text()
}
} }
} }
} }
}
case "images": case "images":
if d.Type() == ObjectNode { if d.Type() == ObjectNode {
if obj := d.Object(); obj != nil { if obj := d.Object(); obj != nil {
objCount := obj.PropertyCount() for prop := range obj.Properties() {
for k := range objCount { if prop.Type() == TextNode {
if prop := obj.Property(k); prop != nil && prop.Type() == TextNode { theme.images[prop.Tag()] = prop.Text()
theme.images[prop.Tag()] = prop.Text()
}
} }
} }
} }
}
case "images:dark": case "images:dark":
if d.Type() == ObjectNode { if d.Type() == ObjectNode {
if obj := d.Object(); obj != nil { if obj := d.Object(); obj != nil {
objCount := obj.PropertyCount() for prop := range obj.Properties() {
for k := range objCount { if prop.Type() == TextNode {
if prop := obj.Property(k); prop != nil && prop.Type() == TextNode { theme.darkImages[prop.Tag()] = prop.Text()
theme.darkImages[prop.Tag()] = prop.Text()
}
} }
} }
} }
}
case "styles": case "styles":
if d.Type() == ArrayNode { if d.Type() == ArrayNode {
arraySize := d.ArraySize()
for k := range arraySize {
if element := d.ArrayElement(k); element != nil && element.IsObject() {
if obj := element.Object(); obj != nil {
theme.styles[obj.Tag()] = objToStyle(obj)
}
}
}
}
default:
if d.Type() == ArrayNode && strings.HasPrefix(tag, "styles:") {
if rule, ok := parseMediaRule(tag); ok {
arraySize := d.ArraySize() arraySize := d.ArraySize()
for k := range arraySize { for k := range arraySize {
if element := d.ArrayElement(k); element != nil && element.IsObject() { if element := d.ArrayElement(k); element != nil && element.IsObject() {
if obj := element.Object(); obj != nil { if obj := element.Object(); obj != nil {
theme.styles[obj.Tag()] = objToStyle(obj) rule.styles[obj.Tag()] = objToStyle(obj)
} }
} }
} }
} theme.mediaStyles = append(theme.mediaStyles, rule)
default:
if d.Type() == ArrayNode && strings.HasPrefix(tag, "styles:") {
if rule, ok := parseMediaRule(tag); ok {
arraySize := d.ArraySize()
for k := range arraySize {
if element := d.ArrayElement(k); element != nil && element.IsObject() {
if obj := element.Object(); obj != nil {
rule.styles[obj.Tag()] = objToStyle(obj)
}
}
}
theme.mediaStyles = append(theme.mediaStyles, rule)
}
} }
} }
} }

View File

@ -352,8 +352,8 @@ func valueToTransformProperty(value any) TransformProperty {
parseObject := func(obj DataObject) TransformProperty { parseObject := func(obj DataObject) TransformProperty {
transform := NewTransformProperty(nil) transform := NewTransformProperty(nil)
ok := true ok := true
for i := range obj.PropertyCount() { for prop := range obj.Properties() {
if prop := obj.Property(i); prop.Type() == TextNode { if prop.Type() == TextNode {
if !transform.Set(PropertyName(prop.Tag()), prop.Text()) { if !transform.Set(PropertyName(prop.Tag()), prop.Text()) {
ok = false ok = false
} }

View File

@ -371,8 +371,7 @@ func (view *viewData) setFunc(tag PropertyName, value any) []PropertyName {
case changeListeners: case changeListeners:
switch value := value.(type) { switch value := value.(type) {
case DataObject: case DataObject:
for i := range value.PropertyCount() { for node := range value.Properties() {
node := value.Property(i)
if node.Type() == TextNode { if node.Type() == TextNode {
if text := node.Text(); text != "" { if text := node.Text(); text != "" {
view.changeListener[PropertyName(node.Tag())] = newOneArgListenerBinding[View, PropertyName](text) view.changeListener[PropertyName(node.Tag())] = newOneArgListenerBinding[View, PropertyName](text)
@ -496,9 +495,7 @@ func (view *viewData) setFunc(tag PropertyName, value any) []PropertyName {
case DataObject: case DataObject:
data := map[string]string{} data := map[string]string{}
count := value.PropertyCount() for node := range value.Properties() {
for i := range count {
node := value.Property(i)
if node.Type() == TextNode { if node.Type() == TextNode {
data[node.Tag()] = node.Text() data[node.Tag()] = node.Text()
} else { } else {