Optimisation

This commit is contained in:
Alexei Anoshenko 2026-05-22 15:54:35 -04:00
parent 167fbd2fd8
commit ca68b80b38
13 changed files with 439 additions and 401 deletions

View File

@ -4,6 +4,7 @@
* Added GoogleFonts field to AppParams * Added GoogleFonts field to AppParams
* Added functions: GetWhiteSpace, GetWordBreak, ScrollIntoViewIfNeeded * Added functions: GetWhiteSpace, GetWordBreak, ScrollIntoViewIfNeeded
* Added PopupShowAnimation and SetPopupShowAnimation methods to Session interface * Added PopupShowAnimation and SetPopupShowAnimation methods to Session interface
* Added ToBoundsProperty method to Bounds struct
# v0.20.0 # v0.20.0

View File

@ -423,11 +423,9 @@ func animationSet(properties Properties, tag PropertyName, value any) []Property
if text, ok := value.(string); ok { if text, ok := value.(string); ok {
text = strings.Trim(text, " \t\n\r") text = strings.Trim(text, " \t\n\r")
if text == "" { if text == "" {
properties.setRaw(tag, nil) return removeProperty(properties, tag)
} else {
properties.setRaw(tag, text)
} }
return []PropertyName{tag} return setPropertyValue(properties, tag, text)
} }
notCompatibleType(tag, value) notCompatibleType(tag, value)
return nil return nil
@ -571,8 +569,7 @@ func animationSet(properties Properties, tag PropertyName, value any) []Property
case TimingFunction: case TimingFunction:
if text, ok := value.(string); ok { if text, ok := value.(string); ok {
properties.setRaw(tag, text) return setPropertyValue(properties, tag, text)
return []PropertyName{tag}
} }
case IterationCount: case IterationCount:

View File

@ -178,14 +178,11 @@ func setBackgroundProperty(properties Properties, tag PropertyName, value any) [
return nil return nil
} }
if len(background) > 0 { if len(background) == 0 {
properties.setRaw(tag, background) return removeProperty(properties, tag)
} else if properties.getRaw(tag) != nil {
properties.setRaw(tag, nil)
} else {
return []PropertyName{}
} }
properties.setRaw(tag, background)
return []PropertyName{tag} return []PropertyName{tag}
} }

View File

@ -167,8 +167,7 @@ func backgroundConicGradientSet(properties Properties, tag PropertyName, value a
return []PropertyName{tag} return []PropertyName{tag}
} }
} else if ok, _ := isConstantName(value); ok { } else if ok, _ := isConstantName(value); ok {
properties.setRaw(Gradient, value) return setPropertyValue(properties, Gradient, value)
return []PropertyName{tag}
} }
ErrorLogF(`Invalid conic gradient: "%s"`, value) ErrorLogF(`Invalid conic gradient: "%s"`, value)

View File

@ -104,8 +104,7 @@ func backgroundGradientSet(properties Properties, tag PropertyName, value any) [
switch value := value.(type) { switch value := value.(type) {
case string: case string:
if ok, _ := isConstantName(value); ok { if ok, _ := isConstantName(value); ok {
properties.setRaw(Gradient, value) return setPropertyValue(properties, tag, value)
return []PropertyName{tag}
} }
if strings.ContainsAny(value, " ,") { if strings.ContainsAny(value, " ,") {
@ -319,16 +318,14 @@ func backgroundLinearGradientSet(properties Properties, tag PropertyName, value
if tag == Direction { if tag == Direction {
switch value := value.(type) { switch value := value.(type) {
case AngleUnit: case AngleUnit:
properties.setRaw(Direction, value) return setPropertyValue(properties, tag, value)
return []PropertyName{tag}
case string: case string:
if setSimpleProperty(properties, tag, value) { if result := setSimpleProperty(properties, tag, value); result != nil {
return []PropertyName{tag} return result
} }
if angle, ok := StringToAngleUnit(value); ok { if angle, ok := StringToAngleUnit(value); ok {
properties.setRaw(Direction, angle) return setPropertyValue(properties, tag, angle)
return []PropertyName{tag}
} }
case LinearGradientDirectionType: case LinearGradientDirectionType:

View File

@ -141,25 +141,23 @@ func backgroundRadialGradientSet(properties Properties, tag PropertyName, value
case []SizeUnit: case []SizeUnit:
switch len(value) { switch len(value) {
case 0: case 0:
properties.setRaw(RadialGradientRadius, nil) return removeProperty(properties, tag)
case 1: case 1:
if value[0].Type == Auto { if value[0].Type == Auto {
properties.setRaw(RadialGradientRadius, nil) return removeProperty(properties, tag)
} else {
properties.setRaw(RadialGradientRadius, value[0])
} }
return setPropertyValue(properties, tag, value[0])
default: default:
properties.setRaw(RadialGradientRadius, value) properties.setRaw(RadialGradientRadius, value)
return []PropertyName{tag}
} }
return []PropertyName{tag}
case []any: case []any:
switch len(value) { switch len(value) {
case 0: case 0:
properties.setRaw(RadialGradientRadius, nil) return removeProperty(properties, tag)
return []PropertyName{tag}
case 1: case 1:
return backgroundRadialGradientSet(properties, RadialGradientRadius, value[0]) return backgroundRadialGradientSet(properties, RadialGradientRadius, value[0])
@ -170,26 +168,24 @@ func backgroundRadialGradientSet(properties Properties, tag PropertyName, value
} }
case string: case string:
if setSimpleProperty(properties, RadialGradientRadius, value) { if result := setSimpleProperty(properties, tag, value); result != nil {
return []PropertyName{tag} return result
} }
if size, err := stringToSizeUnit(value); err == nil { if size, err := stringToSizeUnit(value); err == nil {
if size.Type == Auto { if size.Type == Auto {
properties.setRaw(RadialGradientRadius, nil) return removeProperty(properties, tag)
} else { } else {
properties.setRaw(RadialGradientRadius, size) return setPropertyValue(properties, tag, size)
} }
return []PropertyName{tag}
} }
return setEnumProperty(properties, RadialGradientRadius, value, enumProperties[RadialGradientRadius].values) return setEnumProperty(properties, RadialGradientRadius, value, enumProperties[RadialGradientRadius].values)
case SizeUnit: case SizeUnit:
if value.Type == Auto { if value.Type == Auto {
properties.setRaw(RadialGradientRadius, nil) return removeProperty(properties, tag)
} else { } else {
properties.setRaw(RadialGradientRadius, value) return setPropertyValue(properties, tag, value)
} }
return []PropertyName{tag}
case RadialGradientRadiusType: case RadialGradientRadiusType:
return setEnumProperty(properties, RadialGradientRadius, int(value), enumProperties[RadialGradientRadius].values) return setEnumProperty(properties, RadialGradientRadius, int(value), enumProperties[RadialGradientRadius].values)

162
bounds.go
View File

@ -107,6 +107,26 @@ func DefaultBounds() Bounds {
} }
} }
// ToBoundsProperty() convert Bounds to BoundsProperty.
// The fields with Auto value will not be set in the result BoundsProperty.
func (bounds *Bounds) ToBoundsProperty() BoundsProperty {
result := NewBoundsProperty(nil)
if bounds.Top.Type != Auto {
result.setRaw(Top, bounds.Top)
}
if bounds.Right.Type != Auto {
result.setRaw(Right, bounds.Right)
}
if bounds.Bottom.Type != Auto {
result.setRaw(Bottom, bounds.Bottom)
}
if bounds.Left.Type != Auto {
result.setRaw(Left, bounds.Left)
}
return result
}
// SetAll set the Top, Right, Bottom and Left field to the equal value // SetAll set the Top, Right, Bottom and Left field to the equal value
func (bounds *Bounds) SetAll(value SizeUnit) { func (bounds *Bounds) SetAll(value SizeUnit) {
bounds.Top = value bounds.Top = value
@ -179,80 +199,90 @@ func (bounds *Bounds) cssString(session Session) string {
} }
func setBoundsProperty(properties Properties, tag PropertyName, value any) []PropertyName { func setBoundsProperty(properties Properties, tag PropertyName, value any) []PropertyName {
if !setSimpleProperty(properties, tag, value) { if result := setSimpleProperty(properties, tag, value); result != nil {
switch value := value.(type) { return result
case string: }
if strings.ContainsRune(value, ',') {
values := split4Values(value)
count := len(values)
switch count {
case 1:
value = values[0]
case 4: switch value := value.(type) {
bounds := NewBoundsProperty(nil) case string:
for i, tag := range []PropertyName{Top, Right, Bottom, Left} { if strings.ContainsRune(value, ',') {
if !bounds.Set(tag, values[i]) { values := split4Values(value)
return nil switch count := len(values); count {
} case 1:
return setSizeProperty(properties, tag, value[0])
case 5:
text := strings.Trim(values[4], " \t\n\r")
if text != "" {
notCompatibleType(tag, value)
return nil
}
fallthrough
case 4:
bounds := NewBoundsProperty(nil)
for i, tag := range []PropertyName{Top, Right, Bottom, Left} {
if !bounds.Set(tag, values[i]) {
return nil
} }
properties.setRaw(tag, bounds) }
return []PropertyName{tag}
default: if bounds.IsEmpty() {
return removeProperty(properties, tag)
}
properties.setRaw(tag, bounds)
return []PropertyName{tag}
default:
notCompatibleType(tag, value)
return nil
}
}
return setSizeProperty(properties, tag, value)
case SizeUnit:
return setPropertyValue(properties, tag, value)
case float32:
return setPropertyValue(properties, tag, Px(float64(value)))
case float64:
return setPropertyValue(properties, tag, Px(value))
case Bounds:
bounds := value.ToBoundsProperty()
if bounds.IsEmpty() {
return removeProperty(properties, tag)
}
properties.setRaw(tag, bounds)
case BoundsProperty:
if value.IsEmpty() {
return removeProperty(properties, tag)
}
properties.setRaw(tag, value)
case DataObject:
bounds := NewBoundsProperty(nil)
for _, tag := range []PropertyName{Top, Right, Bottom, Left} {
if text, ok := value.PropertyValue(string(tag)); ok {
if !bounds.Set(tag, text) {
notCompatibleType(tag, value) notCompatibleType(tag, value)
return nil return nil
} }
} }
return setSizeProperty(properties, tag, value) }
if bounds.IsEmpty() {
return removeProperty(properties, tag)
}
properties.setRaw(tag, bounds)
case SizeUnit: default:
properties.setRaw(tag, value) if n, ok := isInt(value); ok {
return setPropertyValue(properties, tag, Px(float64(n)))
case float32: } else {
properties.setRaw(tag, Px(float64(value))) notCompatibleType(tag, value)
return nil
case float64:
properties.setRaw(tag, Px(value))
case Bounds:
bounds := NewBoundsProperty(nil)
if value.Top.Type != Auto {
bounds.setRaw(Top, value.Top)
}
if value.Right.Type != Auto {
bounds.setRaw(Right, value.Right)
}
if value.Bottom.Type != Auto {
bounds.setRaw(Bottom, value.Bottom)
}
if value.Left.Type != Auto {
bounds.setRaw(Left, value.Left)
}
properties.setRaw(tag, bounds)
case BoundsProperty:
properties.setRaw(tag, value)
case DataObject:
bounds := NewBoundsProperty(nil)
for _, tag := range []PropertyName{Top, Right, Bottom, Left} {
if text, ok := value.PropertyValue(string(tag)); ok {
if !bounds.Set(tag, text) {
notCompatibleType(tag, value)
return nil
}
}
}
properties.setRaw(tag, bounds)
default:
if n, ok := isInt(value); ok {
properties.setRaw(tag, Px(float64(n)))
} else {
notCompatibleType(tag, value)
return nil
}
} }
} }

View File

@ -635,8 +635,7 @@ func setClipShapePropertyProperty(properties Properties, tag PropertyName, value
case string: case string:
if ok, _ := isConstantName(value); ok { if ok, _ := isConstantName(value); ok {
properties.setRaw(tag, value) return setPropertyValue(properties, tag, value)
return []PropertyName{tag}
} }
if obj := NewDataObject(value); obj == nil { if obj := NewDataObject(value); obj == nil {

View File

@ -214,18 +214,15 @@ func (picker *datePickerData) setFunc(tag PropertyName, value any) []PropertyNam
setDateValue := func(tag PropertyName) []PropertyName { setDateValue := func(tag PropertyName) []PropertyName {
switch value := value.(type) { switch value := value.(type) {
case time.Time: case time.Time:
picker.setRaw(tag, value) return setPropertyValue(picker, tag, value)
return []PropertyName{tag}
case string: case string:
if ok, _ := isConstantName(value); ok { if ok, _ := isConstantName(value); ok {
picker.setRaw(tag, value) return setPropertyValue(picker, tag, value)
return []PropertyName{tag}
} }
if date, ok := stringToDate(value); ok { if date, ok := stringToDate(value); ok {
picker.setRaw(tag, date) return setPropertyValue(picker, tag, date)
return []PropertyName{tag}
} }
} }

View File

@ -285,43 +285,39 @@ func stringToDropEffect(text string) (int, bool) {
} }
func (view *viewData) setDropEffect(value any) []PropertyName { func (view *viewData) setDropEffect(value any) []PropertyName {
if !setSimpleProperty(view, DropEffect, value) { if result := setSimpleProperty(view, DropEffect, value); result != nil {
if text, ok := value.(string); ok { return result
}
if n, ok := stringToDropEffect(text); ok { var newValue int
if n == DropEffectUndefined { if text, ok := value.(string); ok {
view.setRaw(DropEffect, nil)
} else {
view.setRaw(DropEffect, n)
}
} else {
invalidPropertyValue(DropEffect, value)
return nil
}
} else if i, ok := isInt(value); ok { if newValue, ok = stringToDropEffect(text); !ok {
invalidPropertyValue(DropEffect, value)
switch i {
case DropEffectUndefined:
view.setRaw(DropEffect, nil)
case DropEffectCopy, DropEffectMove, DropEffectLink:
view.setRaw(DropEffect, i)
default:
invalidPropertyValue(DropEffect, value)
return nil
}
} else {
notCompatibleType(DropEffect, value)
return nil return nil
} }
} else if i, ok := isInt(value); ok {
newValue = i
} else {
notCompatibleType(DropEffect, value)
return nil
} }
return []PropertyName{DropEffect} switch newValue {
case DropEffectUndefined:
return removeProperty(view, DropEffect)
case DropEffectCopy, DropEffectMove, DropEffectLink:
return setPropertyValue(view, DropEffect, newValue)
default:
invalidPropertyValue(DropEffect, value)
return nil
}
} }
func stringToDropEffectAllowed(text string) (int, bool) { func stringToDropEffectAllowed(text string) (int, bool) {
@ -348,39 +344,35 @@ func stringToDropEffectAllowed(text string) (int, bool) {
} }
func (view *viewData) setDropEffectAllowed(value any) []PropertyName { func (view *viewData) setDropEffectAllowed(value any) []PropertyName {
if !setSimpleProperty(view, DropEffectAllowed, value) {
if text, ok := value.(string); ok {
if n, ok := stringToDropEffectAllowed(text); ok { if result := setSimpleProperty(view, DropEffectAllowed, value); result != nil {
if n == DropEffectUndefined { return result
view.setRaw(DropEffectAllowed, nil) }
} else {
view.setRaw(DropEffectAllowed, n)
}
} else {
invalidPropertyValue(DropEffectAllowed, value)
return nil
}
} else { var newValue int
n, ok := isInt(value) if text, ok := value.(string); ok {
if !ok { if newValue, ok = stringToDropEffectAllowed(text); !ok {
notCompatibleType(DropEffectAllowed, value) invalidPropertyValue(DropEffectAllowed, value)
return nil return nil
} }
} else {
if n == DropEffectUndefined { var ok bool
view.setRaw(DropEffectAllowed, nil) if newValue, ok = isInt(value); !ok {
} else if n > DropEffectUndefined && n <= DropEffectAll { notCompatibleType(DropEffectAllowed, value)
view.setRaw(DropEffectAllowed, n) return nil
} else {
notCompatibleType(DropEffectAllowed, value)
return nil
}
} }
} }
return []PropertyName{DropEffectAllowed} if newValue == DropEffectUndefined {
return removeProperty(view, DropEffectAllowed)
}
if newValue < DropEffectUndefined || newValue > DropEffectAll {
notCompatibleType(DropEffectAllowed, value)
return nil
}
return setPropertyValue(view, DropEffectAllowed, newValue)
} }
func handleDragAndDropEvents(view View, tag PropertyName, data DataObject) { func handleDragAndDropEvents(view View, tag PropertyName, data DataObject) {

View File

@ -166,6 +166,9 @@ func (edit *editViewData) setFunc(tag PropertyName, value any) []PropertyName {
old := "" old := ""
if val := edit.getRaw(Text); val != nil { if val := edit.getRaw(Text); val != nil {
if txt, ok := val.(string); ok { if txt, ok := val.(string); ok {
if txt == text {
return []PropertyName{}
}
old = txt old = txt
} }
} }

View File

@ -561,280 +561,309 @@ func isInt(value any) (int, bool) {
return n, true return n, true
} }
func setSimpleProperty(properties Properties, tag PropertyName, value any) bool { func setPropertyValue[T comparable](properties Properties, tag PropertyName, value T) []PropertyName {
if value == nil { if oldValue := properties.getRaw(tag); oldValue != nil {
properties.setRaw(tag, nil) if oldTypedValue, ok := oldValue.(T); ok && oldTypedValue == value {
return true return []PropertyName{}
} else if text, ok := value.(string); ok {
text = strings.Trim(text, " \t\n\r")
if text == "" {
properties.setRaw(tag, nil)
return true
}
if ok, _ := isConstantName(text); ok {
properties.setRaw(tag, text)
return true
} }
} }
return false
}
func setStringPropertyValue(properties Properties, tag PropertyName, text any) []PropertyName { properties.setRaw(tag, value)
if text != "" {
properties.setRaw(tag, text)
} else if properties.getRaw(tag) != nil {
properties.setRaw(tag, nil)
} else {
return []PropertyName{}
}
return []PropertyName{tag} return []PropertyName{tag}
} }
func setArrayPropertyValue[T any](properties Properties, tag PropertyName, value []T) []PropertyName { func removeProperty(properties Properties, tag PropertyName) []PropertyName {
if len(value) > 0 { if properties.getRaw(tag) != nil {
properties.setRaw(tag, value)
} else if properties.getRaw(tag) != nil {
properties.setRaw(tag, nil) properties.setRaw(tag, nil)
} else { return []PropertyName{tag}
return []PropertyName{}
} }
return []PropertyName{}
}
func setSimpleProperty(properties Properties, tag PropertyName, value any) []PropertyName {
if value == nil {
return removeProperty(properties, tag)
}
if text, ok := value.(string); ok {
text = strings.Trim(text, " \t\n\r")
if text == "" {
return removeProperty(properties, tag)
}
if oldValue := properties.getRaw(tag); oldValue != nil {
if oldText, ok := oldValue.(string); ok && oldText == text {
return []PropertyName{}
}
}
if ok, _ := isConstantName(text); ok {
properties.setRaw(tag, text)
return []PropertyName{tag}
}
}
return nil
}
func setStringPropertyValue(properties Properties, tag PropertyName, text string) []PropertyName {
if text == "" {
return removeProperty(properties, tag)
}
return setPropertyValue(properties, tag, text)
}
func setArrayPropertyValue[T any](properties Properties, tag PropertyName, value []T) []PropertyName {
if len(value) == 0 {
return removeProperty(properties, tag)
}
/*
oldValue := properties.getRaw(tag)
if oldValue != nil {
if oldArray, ok := oldValue.([]T); ok && slices.Equal(oldArray, value) {
return []PropertyName{}
}
}
*/
properties.setRaw(tag, value)
return []PropertyName{tag} return []PropertyName{tag}
} }
func setSizeProperty(properties Properties, tag PropertyName, value any) []PropertyName { func setSizeProperty(properties Properties, tag PropertyName, value any) []PropertyName {
if !setSimpleProperty(properties, tag, value) { if result := setSimpleProperty(properties, tag, value); result != nil {
var size SizeUnit return result
switch value := value.(type) { }
case string:
var ok bool
if fn := parseSizeFunc(value); fn != nil {
size.Type = SizeFunction
size.Function = fn
} else if size, ok = StringToSizeUnit(value); !ok {
invalidPropertyValue(tag, value)
return nil
}
case SizeUnit:
size = value
case SizeFunc: var size SizeUnit
switch value := value.(type) {
case string:
var ok bool
if fn := parseSizeFunc(value); fn != nil {
size.Type = SizeFunction size.Type = SizeFunction
size.Function = value size.Function = fn
} else if size, ok = StringToSizeUnit(value); !ok {
case float32: invalidPropertyValue(tag, value)
size.Type = SizeInPixel return nil
size.Value = float64(value)
case float64:
size.Type = SizeInPixel
size.Value = value
default:
if n, ok := isInt(value); ok {
size.Type = SizeInPixel
size.Value = float64(n)
} else {
notCompatibleType(tag, value)
return nil
}
} }
case SizeUnit:
size = value
if size.Type == Auto { case SizeFunc:
properties.setRaw(tag, nil) size.Type = SizeFunction
size.Function = value
case float32:
size.Type = SizeInPixel
size.Value = float64(value)
case float64:
size.Type = SizeInPixel
size.Value = value
default:
if n, ok := isInt(value); ok {
size.Type = SizeInPixel
size.Value = float64(n)
} else { } else {
properties.setRaw(tag, size) notCompatibleType(tag, value)
return nil
} }
} }
return []PropertyName{tag} if size.Type == Auto {
return removeProperty(properties, tag)
}
return setPropertyValue(properties, tag, size)
} }
func setAngleProperty(properties Properties, tag PropertyName, value any) []PropertyName { func setAngleProperty(properties Properties, tag PropertyName, value any) []PropertyName {
if !setSimpleProperty(properties, tag, value) { if result := setSimpleProperty(properties, tag, value); result != nil {
var angle AngleUnit return result
switch value := value.(type) {
case string:
var ok bool
if angle, ok = StringToAngleUnit(value); !ok {
invalidPropertyValue(tag, value)
return nil
}
case AngleUnit:
angle = value
case float32:
angle = Rad(float64(value))
case float64:
angle = Rad(value)
default:
if n, ok := isInt(value); ok {
angle = Rad(float64(n))
} else {
notCompatibleType(tag, value)
return nil
}
}
properties.setRaw(tag, angle)
} }
return []PropertyName{tag} var angle AngleUnit
switch value := value.(type) {
case string:
var ok bool
if angle, ok = StringToAngleUnit(value); !ok {
invalidPropertyValue(tag, value)
return nil
}
case AngleUnit:
angle = value
case float32:
angle = Rad(float64(value))
case float64:
angle = Rad(value)
default:
if n, ok := isInt(value); ok {
angle = Rad(float64(n))
} else {
notCompatibleType(tag, value)
return nil
}
}
return setPropertyValue(properties, tag, angle)
} }
func setColorProperty(properties Properties, tag PropertyName, value any) []PropertyName { func setColorProperty(properties Properties, tag PropertyName, value any) []PropertyName {
if !setSimpleProperty(properties, tag, value) { if result := setSimpleProperty(properties, tag, value); result != nil {
var result Color return result
switch value := value.(type) {
case string:
var err error
if result, err = stringToColor(value); err != nil {
invalidPropertyValue(tag, value)
return nil
}
case Color:
result = value
default:
if color, ok := isInt(value); ok {
result = Color(color)
} else {
notCompatibleType(tag, value)
return nil
}
}
properties.setRaw(tag, result)
} }
return []PropertyName{tag} var result Color
switch value := value.(type) {
case string:
var err error
if result, err = stringToColor(value); err != nil {
invalidPropertyValue(tag, value)
return nil
}
case Color:
result = value
default:
if color, ok := isInt(value); ok {
result = Color(color)
} else {
notCompatibleType(tag, value)
return nil
}
}
return setPropertyValue(properties, tag, result)
} }
func setEnumProperty(properties Properties, tag PropertyName, value any, values []string) []PropertyName { func setEnumProperty(properties Properties, tag PropertyName, value any, values []string) []PropertyName {
if !setSimpleProperty(properties, tag, value) { if result := setSimpleProperty(properties, tag, value); result != nil {
var n int return result
if text, ok := value.(string); ok {
if n, ok = enumStringToInt(text, values, false); !ok {
invalidPropertyValue(tag, value)
return nil
}
} else if i, ok := isInt(value); ok {
if i < 0 || i >= len(values) {
invalidPropertyValue(tag, value)
return nil
}
n = i
} else {
notCompatibleType(tag, value)
return nil
}
properties.setRaw(tag, n)
} }
return []PropertyName{tag} var n int
if text, ok := value.(string); ok {
if n, ok = enumStringToInt(text, values, false); !ok {
invalidPropertyValue(tag, value)
return nil
}
} else if i, ok := isInt(value); ok {
if i < 0 || i >= len(values) {
invalidPropertyValue(tag, value)
return nil
}
n = i
} else {
notCompatibleType(tag, value)
return nil
}
return setPropertyValue(properties, tag, n)
} }
func setBoolProperty(properties Properties, tag PropertyName, value any) []PropertyName { func setBoolProperty(properties Properties, tag PropertyName, value any) []PropertyName {
if !setSimpleProperty(properties, tag, value) { if result := setSimpleProperty(properties, tag, value); result != nil {
if text, ok := value.(string); ok { return result
switch strings.ToLower(strings.Trim(text, " \t")) {
case "true", "yes", "on", "1":
properties.setRaw(tag, true)
case "false", "no", "off", "0":
properties.setRaw(tag, false)
default:
invalidPropertyValue(tag, value)
return nil
}
} else if n, ok := isInt(value); ok {
switch n {
case 1:
properties.setRaw(tag, true)
case 0:
properties.setRaw(tag, false)
default:
invalidPropertyValue(tag, value)
return nil
}
} else if b, ok := value.(bool); ok {
properties.setRaw(tag, b)
} else {
notCompatibleType(tag, value)
return nil
}
} }
return []PropertyName{tag} var flag bool
if text, ok := value.(string); ok {
switch strings.ToLower(strings.Trim(text, " \t")) {
case "true", "yes", "on", "1":
flag = true
case "false", "no", "off", "0":
flag = false
default:
invalidPropertyValue(tag, value)
return nil
}
} else if n, ok := isInt(value); ok {
switch n {
case 1:
flag = true
case 0:
flag = false
default:
invalidPropertyValue(tag, value)
return nil
}
} else if b, ok := value.(bool); ok {
flag = b
} else {
notCompatibleType(tag, value)
return nil
}
return setPropertyValue(properties, tag, flag)
} }
func setIntProperty(properties Properties, tag PropertyName, value any) []PropertyName { func setIntProperty(properties Properties, tag PropertyName, value any) []PropertyName {
if !setSimpleProperty(properties, tag, value) { if result := setSimpleProperty(properties, tag, value); result != nil {
if text, ok := value.(string); ok { return result
n, err := strconv.Atoi(strings.Trim(text, " \t")) }
if err != nil {
invalidPropertyValue(tag, value) var result int
ErrorLog(err.Error()) if text, ok := value.(string); ok {
return nil n, err := strconv.Atoi(strings.Trim(text, " \t"))
} if err != nil {
properties.setRaw(tag, n) invalidPropertyValue(tag, value)
} else if n, ok := isInt(value); ok { ErrorLog(err.Error())
properties.setRaw(tag, n) return nil
}
result = n
} else if n, ok := isInt(value); ok {
result = n
} else {
notCompatibleType(tag, value)
return nil
}
return setPropertyValue(properties, tag, result)
}
func setFloatProperty(properties Properties, tag PropertyName, value any, min, max float64) []PropertyName {
if result := setSimpleProperty(properties, tag, value); result != nil {
return result
}
var result float64
switch value := value.(type) {
case string:
f, err := strconv.ParseFloat(strings.Trim(value, " \t"), 64)
if err != nil {
invalidPropertyValue(tag, value)
ErrorLog(err.Error())
return nil
}
result = f
case float32:
result = float64(value)
case float64:
result = value
default:
if n, ok := isInt(value); ok {
result = float64(n)
} else { } else {
notCompatibleType(tag, value) notCompatibleType(tag, value)
return nil return nil
} }
} }
return []PropertyName{tag} if result < min || result > max {
} ErrorLogF(`"%T" out of range of "%s" property`, value, tag)
return nil
func setFloatProperty(properties Properties, tag PropertyName, value any, min, max float64) []PropertyName {
if !setSimpleProperty(properties, tag, value) {
f := float64(0)
switch value := value.(type) {
case string:
var err error
if f, err = strconv.ParseFloat(strings.Trim(value, " \t"), 64); err != nil {
invalidPropertyValue(tag, value)
ErrorLog(err.Error())
return nil
}
if f < min || f > max {
ErrorLogF(`"%T" out of range of "%s" property`, value, tag)
return nil
}
properties.setRaw(tag, value)
return nil
case float32:
f = float64(value)
case float64:
f = value
default:
if n, ok := isInt(value); ok {
f = float64(n)
} else {
notCompatibleType(tag, value)
return nil
}
}
if f >= min && f <= max {
properties.setRaw(tag, f)
} else {
ErrorLogF(`"%T" out of range of "%s" property`, value, tag)
return nil
}
} }
return []PropertyName{tag} return setPropertyValue(properties, tag, result)
} }
func propertiesSet(properties Properties, tag PropertyName, value any) []PropertyName { func propertiesSet(properties Properties, tag PropertyName, value any) []PropertyName {

View File

@ -47,29 +47,30 @@ func (r *Range) setValue(value string) bool {
} }
func setRangeProperty(properties Properties, tag PropertyName, value any) []PropertyName { func setRangeProperty(properties Properties, tag PropertyName, value any) []PropertyName {
if result := setSimpleProperty(properties, tag, value); result != nil {
return result
}
var r Range
switch value := value.(type) { switch value := value.(type) {
case string: case string:
if setSimpleProperty(properties, tag, value) {
return []PropertyName{tag}
}
var r Range
if !r.setValue(value) { if !r.setValue(value) {
invalidPropertyValue(tag, value) invalidPropertyValue(tag, value)
return nil return nil
} }
properties.setRaw(tag, r)
case Range: case Range:
properties.setRaw(tag, value) r = value
default: default:
if n, ok := isInt(value); ok { if n, ok := isInt(value); ok {
properties.setRaw(tag, Range{First: n, Last: n}) r.First = n
r.Last = n
} else { } else {
notCompatibleType(tag, value) notCompatibleType(tag, value)
return nil return nil
} }
} }
return []PropertyName{tag}
return setPropertyValue(properties, tag, r)
} }