Added fmt.Stringer implementation to Popup

This commit is contained in:
Alexei Anoshenko 2025-07-03 10:42:04 +03:00
parent 0e4068bcfb
commit 83ec4f0a20
16 changed files with 411 additions and 514 deletions

View File

@ -599,11 +599,14 @@ func (animation *animationData) String() string {
for _, tag := range animation.AllTags() {
if tag != PropertyTag {
if value, ok := animation.properties[tag]; ok && value != nil {
buffer.WriteString("\n\t")
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, "\t")
buffer.WriteRune(',')
text := propertyValueToString(tag, value, "\t")
if text != "" {
buffer.WriteString("\n\t")
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
buffer.WriteString(text)
buffer.WriteRune(',')
}
}
}
}
@ -613,18 +616,21 @@ func (animation *animationData) String() string {
buffer.WriteString("{\n")
buffer.WriteString(indent)
buffer.WriteString("from = ")
writePropertyValue(buffer, "from", prop.From, indent)
buffer.WriteString(propertyValueToString("from", prop.From, indent))
buffer.WriteString(",\n")
buffer.WriteString(indent)
buffer.WriteString("to = ")
writePropertyValue(buffer, "to", prop.To, indent)
buffer.WriteString(propertyValueToString("to", prop.To, indent))
for key, value := range prop.KeyFrames {
buffer.WriteString(",\n")
buffer.WriteString(indent)
tag := strconv.Itoa(key) + "%"
buffer.WriteString(tag)
buffer.WriteString(" = ")
writePropertyValue(buffer, PropertyName(tag), value, indent)
text := propertyValueToString(PropertyName(tag), value, indent)
if text != "" {
buffer.WriteString(",\n")
buffer.WriteString(indent)
buffer.WriteString(tag)
buffer.WriteString(" = ")
buffer.WriteString(text)
}
}
buffer.WriteString("\n")
buffer.WriteString(indent[1:])
@ -725,12 +731,15 @@ func (animation *animationData) writeTransitionString(tag PropertyName, buffer *
writeFloatProperty := func(name PropertyName) bool {
if value := animation.getRaw(name); value != nil {
buffer.WriteString(lead)
buffer.WriteString(string(name))
buffer.WriteString(" = ")
writePropertyValue(buffer, name, value, "")
lead = ", "
return true
text := propertyValueToString(name, value, "")
if text != "" {
buffer.WriteString(lead)
buffer.WriteString(string(name))
buffer.WriteString(" = ")
buffer.WriteString(text)
lead = ", "
return true
}
}
return false
}
@ -770,11 +779,14 @@ func (animation *animationData) writeAnimationString(tag PropertyName, buffer *s
for _, tag := range animation.AllTags() {
if tag != PropertyTag {
if value := animation.Get(tag); value != nil {
buffer.WriteString("\n" + indent2)
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent2)
buffer.WriteRune(',')
text := propertyValueToString(tag, value, indent2)
if text != "" {
buffer.WriteString("\n" + indent2)
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
buffer.WriteString(text)
buffer.WriteRune(',')
}
}
}
}
@ -785,18 +797,21 @@ func (animation *animationData) writeAnimationString(tag PropertyName, buffer *s
indent2 := indent + "\t"
buffer.WriteString(indent2)
buffer.WriteString("from = ")
writePropertyValue(buffer, "from", prop.From, indent2)
buffer.WriteString(propertyValueToString("from", prop.From, indent2))
buffer.WriteString(",\n")
buffer.WriteString(indent2)
buffer.WriteString("to = ")
writePropertyValue(buffer, "to", prop.To, indent2)
buffer.WriteString(propertyValueToString("to", prop.To, indent2))
for key, value := range prop.KeyFrames {
buffer.WriteString(",\n")
buffer.WriteString(indent2)
tag := strconv.Itoa(key) + "%"
buffer.WriteString(tag)
buffer.WriteString(" = ")
writePropertyValue(buffer, PropertyName(tag), value, indent2)
text := propertyValueToString(PropertyName(tag), value, indent2)
if text != "" {
buffer.WriteString(",\n")
buffer.WriteString(indent2)
tag := strconv.Itoa(key) + "%"
buffer.WriteString(tag)
buffer.WriteString(" = ")
buffer.WriteString(text)
}
}
buffer.WriteString(",\n")
buffer.WriteString(indent)

View File

@ -383,13 +383,16 @@ func (border *borderProperty) writeString(buffer *strings.Builder, indent string
comma := false
write := func(tag PropertyName, value any) {
if comma {
buffer.WriteString(", ")
text := propertyValueToString(tag, value, indent)
if text != "" {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
buffer.WriteString(text)
comma = true
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, BorderStyle, value, indent)
comma = true
}
for _, tag := range []PropertyName{Style, Width, ColorTag} {

View File

@ -84,23 +84,6 @@ func (bounds *boundsPropertyData) String() string {
return runStringWriter(bounds)
}
func (bounds *boundsPropertyData) writeString(buffer *strings.Builder, indent string) {
buffer.WriteString("_{ ")
comma := false
for _, tag := range []PropertyName{Top, Right, Bottom, Left} {
if value, ok := bounds.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
}
}
buffer.WriteString(" }")
}
func (bounds *boundsPropertyData) Bounds(session Session) Bounds {
top, _ := sizeProperty(bounds, Top, session)
right, _ := sizeProperty(bounds, Right, session)

View File

@ -815,40 +815,6 @@ func (canvas *canvasData) FillAndStrokeEllipse(x, y, radiusX, radiusY, rotation
}
}
/*
func (canvas *canvasData) writePointArgs(x, y float64) {
canvas.script.WriteString(strconv.FormatFloat(x, 'g', -1, 64))
canvas.script.WriteRune(',')
canvas.script.WriteString(strconv.FormatFloat(y, 'g', -1, 64))
}
func (canvas *canvasData) writeStringArgs(text string, script *strings.Builder) {
//rText := []rune(text)
for _, ch := range text {
switch ch {
case '\t':
script.WriteString(`\t`)
case '\n':
script.WriteString(`\n`)
case '\r':
script.WriteString(`\r`)
case '\\':
script.WriteString(`\\`)
case '"':
script.WriteString(`\"`)
case '\'':
script.WriteString(`\'`)
default:
if ch < ' ' {
script.WriteString(fmt.Sprintf("\\x%02X", int(ch)))
} else {
script.WriteRune(ch)
}
}
}
}
*/
func (canvas *canvasData) FillText(x, y float64, text string) {
canvas.session.callCanvasFunc("fillText", text, x, y)
}

View File

@ -230,13 +230,16 @@ func (clip *insetClipData) writeString(buffer *strings.Builder, indent string) {
comma := false
for _, tag := range []PropertyName{Top, Right, Bottom, Left, Radius} {
if value, ok := clip.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
text := propertyValueToString(tag, value, indent)
if text != "" {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
buffer.WriteString(text)
comma = true
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
}
}
@ -303,13 +306,16 @@ func (clip *circleClipData) writeString(buffer *strings.Builder, indent string)
comma := false
for _, tag := range []PropertyName{Radius, X, Y} {
if value, ok := clip.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
text := propertyValueToString(tag, value, indent)
if text != "" {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
buffer.WriteString(text)
comma = true
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
}
}
@ -380,13 +386,16 @@ func (clip *ellipseClipData) writeString(buffer *strings.Builder, indent string)
comma := false
for _, tag := range []PropertyName{RadiusX, RadiusY, X, Y} {
if value, ok := clip.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
text := propertyValueToString(tag, value, indent)
if text != "" {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
buffer.WriteString(text)
comma = true
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
}
}
@ -511,11 +520,16 @@ func (clip *polygonClipData) writeString(buffer *strings.Builder, indent string)
if points := clip.points(); points != nil {
buffer.WriteString(string(Points))
buffer.WriteString(` = "`)
for i, value := range points {
if i > 0 {
buffer.WriteString(", ")
comma := false
for _, value := range points {
text := propertyValueToString("", value, indent)
if text != "" {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(text)
comma = true
}
writePropertyValue(buffer, "", value, indent)
}
buffer.WriteString(`" `)

View File

@ -2,7 +2,6 @@ package rui
import (
"fmt"
"strings"
)
// ColumnSeparatorProperty is the interface of a view separator data
@ -114,24 +113,6 @@ func normalizeColumnSeparatorTag(tag PropertyName) PropertyName {
return tag
}
func (separator *columnSeparatorProperty) writeString(buffer *strings.Builder, indent string) {
buffer.WriteString("_{ ")
comma := false
for _, tag := range []PropertyName{Style, Width, ColorTag} {
if value, ok := separator.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, BorderStyle, value, indent)
comma = true
}
}
buffer.WriteString(" }")
}
func (separator *columnSeparatorProperty) String() string {
return runStringWriter(separator)
}

View File

@ -218,21 +218,7 @@ func (filter *filterData) String() string {
}
func (filter *filterData) writeString(buffer *strings.Builder, indent string) {
buffer.WriteString("filter { ")
comma := false
tags := filter.AllTags()
for _, tag := range tags {
if value, ok := filter.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
}
}
buffer.WriteString(" }")
filter.writeToBuffer(buffer, indent, "filter", filter.AllTags())
}
func (filter *filterData) cssStyle(session Session) string {

View File

@ -40,24 +40,6 @@ func (outline *outlinePropertyData) init() {
outline.supportedProperties = []PropertyName{Style, Width, ColorTag}
}
func (outline *outlinePropertyData) writeString(buffer *strings.Builder, indent string) {
buffer.WriteString("_{ ")
comma := false
for _, tag := range []PropertyName{Style, Width, ColorTag} {
if value, ok := outline.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, BorderStyle, value, indent)
comma = true
}
}
buffer.WriteString(" }")
}
func (outline *outlinePropertyData) String() string {
return runStringWriter(outline)
}

View File

@ -279,6 +279,7 @@ type popupButton struct {
// Popup represents a Popup view
type Popup interface {
Properties
fmt.Stringer
// View returns a content view of the popup
View() View
@ -600,6 +601,7 @@ func (popup *popupData) Set(tag PropertyName, value any) bool {
switch value := value.(type) {
case View:
popup.contentView = value
popup.setRaw(Content, popup.contentView)
case DataObject:
view := CreateViewFromObject(popup.session, value, nil)
@ -607,6 +609,7 @@ func (popup *popupData) Set(tag PropertyName, value any) bool {
return false
}
popup.contentView = view
popup.setRaw(Content, popup.contentView)
case string:
if len(value) > 0 && value[0] == '@' {
@ -617,6 +620,7 @@ func (popup *popupData) Set(tag PropertyName, value any) bool {
}
}
popup.contentView = NewTextView(popup.session, Params{Text: value})
popup.setRaw(Content, value)
default:
notCompatibleType(Buttons, value)
@ -626,12 +630,14 @@ func (popup *popupData) Set(tag PropertyName, value any) bool {
if binding := popup.getRaw(Binding); binding != nil {
popup.contentView.Set(Binding, binding)
}
popup.setRaw(Content, popup.contentView)
popup.propertyChanged(Content)
return true
case Binding:
popup.contentView.Set(Binding, value)
if popup.contentView != nil {
popup.contentView.Set(Binding, value)
}
popup.setRaw(Binding, value)
popup.propertyChanged(Binding)
return true
@ -777,18 +783,19 @@ func (popup *popupData) animationProperty() AnimationProperty {
})
}
func (popup *popupData) AllTags() []PropertyName {
tags := make([]PropertyName, 0, len(popup.properties)+1)
for tag := range popup.properties {
tags = append(tags, tag)
/*
func (popup *popupData) AllTags() []PropertyName {
tags := make([]PropertyName, 0, len(popup.properties)+1)
for tag := range popup.properties {
tags = append(tags, tag)
}
if popup.contentView != nil {
tags = append(tags, Content)
}
slices.Sort(tags)
return tags
}
if popup.contentView != nil {
tags = append(tags, Content)
}
slices.Sort(tags)
return tags
}
*/
func (popup *popupData) View() View {
return popup.contentView
}
@ -797,6 +804,13 @@ func (popup *popupData) Session() Session {
return popup.session
}
func (popup *popupData) String() string {
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
writeViewStyle("Popup", popup, buffer, "", nil)
return buffer.String()
}
func (popup *popupData) setButtons(value any) bool {
popupButtonFromObject := func(obj DataObject) popupButton {
var button popupButton
@ -1570,3 +1584,13 @@ func valueToPopupEventListeners(value any) ([]popupListener, bool) {
return nil, false
}
func getPopupListenerBinding(listeners []popupListener) string {
for _, listener := range listeners {
raw := listener.rawListener()
if text, ok := raw.(string); ok && text != "" {
return text
}
}
return ""
}

View File

@ -102,11 +102,14 @@ func (properties *propertyList) writeToBuffer(buffer *strings.Builder,
for _, tag := range tags {
if value, ok := properties.properties[tag]; ok {
buffer.WriteString(indent2)
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent2)
buffer.WriteString(",\n")
text := propertyValueToString(tag, value, indent2)
if text != "" {
buffer.WriteString(indent2)
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
buffer.WriteString(text)
buffer.WriteString(",\n")
}
}
}
@ -158,3 +161,28 @@ func (data *dataProperty) Get(tag PropertyName) any {
func (data *dataProperty) Remove(tag PropertyName) {
data.remove(data, data.normalize(tag))
}
func (data *dataProperty) writeToBuffer(buffer *strings.Builder, indent string, objectName string, tags []PropertyName) {
buffer.WriteString(objectName)
buffer.WriteString("{ ")
comma := false
for _, tag := range tags {
if value, ok := data.properties[tag]; ok {
text := propertyValueToString(tag, value, indent)
if text != "" {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
buffer.WriteString(text)
comma = true
}
}
}
buffer.WriteString(" }")
}
func (data *dataProperty) writeString(buffer *strings.Builder, indent string) {
data.writeToBuffer(buffer, indent, "_", data.AllTags())
}

View File

@ -475,24 +475,6 @@ func (radius *radiusPropertyData) init() {
}
}
func (radius *radiusPropertyData) writeString(buffer *strings.Builder, indent string) {
buffer.WriteString("_{ ")
comma := false
for _, tag := range radius.supportedProperties {
if value, ok := radius.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
}
}
buffer.WriteString(" }")
}
func (radius *radiusPropertyData) String() string {
return runStringWriter(radius)
}

View File

@ -59,7 +59,7 @@ func (writer *ruiWriterData) writeString(str string) {
{old: "\"", new: `\"`},
}
for _, s := range replace {
str = strings.Replace(str, s.old, s.new, -1)
str = strings.ReplaceAll(str, s.old, s.new)
}
writer.buffer.WriteRune('"')
writer.buffer.WriteString(str)

View File

@ -281,23 +281,6 @@ func (shadow *shadowPropertyData) String() string {
return runStringWriter(shadow)
}
func (shadow *shadowPropertyData) writeString(buffer *strings.Builder, indent string) {
buffer.WriteString("_{ ")
comma := false
for _, tag := range shadow.AllTags() {
if value, ok := shadow.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
}
}
buffer.WriteString(" }")
}
func setShadowProperty(properties Properties, tag PropertyName, value any) bool {
if value == nil {

View File

@ -902,19 +902,9 @@ func (theme *theme) String() string {
defer freeStringBuilder(buffer)
writeString := func(text string) {
if strings.ContainsAny(text, " \t\n\r\\\"'`,;{}[]()") {
replace := []struct{ old, new string }{
{old: "\\", new: `\\`},
{old: "\t", new: `\t`},
{old: "\r", new: `\r`},
{old: "\n", new: `\n`},
{old: "\"", new: `\"`},
}
for _, s := range replace {
text = strings.Replace(text, s.old, s.new, -1)
}
if isQuotesNeeded(text) {
buffer.WriteRune('"')
buffer.WriteString(text)
buffer.WriteString(replaceEscapeSymbols(text))
buffer.WriteRune('"')
} else {
buffer.WriteString(text)

View File

@ -328,23 +328,6 @@ func (transform *transformPropertyData) String() string {
return buffer.String()
}
func (transform *transformPropertyData) writeString(buffer *strings.Builder, indent string) {
buffer.WriteString("_{ ")
comma := false
for _, tag := range transform.supportedProperties {
if value, ok := transform.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
}
}
buffer.WriteString(" }")
}
func transformSet(properties Properties, tag PropertyName, value any) []PropertyName {
switch tag {

View File

@ -551,235 +551,134 @@ func viewStyleGet(style Properties, tag PropertyName) any {
return style.getRaw(tag)
}
func supportedPropertyValue(value any) bool {
switch value := value.(type) {
case string, bool, float32, float64, int, stringWriter, fmt.Stringer:
return true
case []string:
return len(value) > 0
case []ShadowProperty:
return len(value) > 0
case []View:
return len(value) > 0
case []any:
return len(value) > 0
case []BackgroundElement:
return len(value) > 0
case []BackgroundGradientPoint:
return len(value) > 0
case []BackgroundGradientAngle:
return len(value) > 0
case map[PropertyName]AnimationProperty:
return len(value) > 0
case []AnimationProperty:
return len(value) > 0
case []noArgListener[View]:
return getNoArgBinding(value) != ""
case []noArgListener[ImageView]:
return getNoArgBinding(value) != ""
case []noArgListener[MediaPlayer]:
return getNoArgBinding(value) != ""
case []oneArgListener[View, KeyEvent]:
return getOneArgBinding(value) != ""
case []oneArgListener[View, MouseEvent]:
return getOneArgBinding(value) != ""
case []oneArgListener[View, TouchEvent]:
return getOneArgBinding(value) != ""
case []oneArgListener[View, PointerEvent]:
return getOneArgBinding(value) != ""
case []oneArgListener[View, PropertyName]:
return getOneArgBinding(value) != ""
case []oneArgListener[View, string]:
return getOneArgBinding(value) != ""
case []oneArgListener[View, Frame]:
return getOneArgBinding(value) != ""
case []oneArgListener[View, DragAndDropEvent]:
return getOneArgBinding(value) != ""
case []oneArgListener[Checkbox, bool]:
return getOneArgBinding(value) != ""
case []oneArgListener[FilePicker, []FileInfo]:
return getOneArgBinding(value) != ""
case []oneArgListener[ListView, int]:
return getOneArgBinding(value) != ""
case []oneArgListener[ListView, []int]:
return getOneArgBinding(value) != ""
case []oneArgListener[MediaPlayer, float64]:
return getOneArgBinding(value) != ""
case []oneArgListener[TableView, int]:
return getOneArgBinding(value) != ""
case []oneArgListener[TabsLayout, int]:
return getOneArgBinding(value) != ""
case []twoArgListener[ColorPicker, Color]:
return getTwoArgBinding(value) != ""
case []twoArgListener[DatePicker, time.Time]:
return getTwoArgBinding(value) != ""
case []twoArgListener[TimePicker, time.Time]:
return getTwoArgBinding(value) != ""
case []twoArgListener[DropDownList, int]:
return getTwoArgBinding(value) != ""
case []twoArgListener[EditView, string]:
return getTwoArgBinding(value) != ""
case []twoArgListener[NumberPicker, float64]:
return getTwoArgBinding(value) != ""
case []twoArgListener[TableView, int]:
return getTwoArgBinding(value) != ""
case []twoArgListener[TabsLayout, int]:
return getTwoArgBinding(value) != ""
case []mediaPlayerErrorListener:
return getMediaPlayerErrorListenerBinding(value) != ""
case map[PropertyName]oneArgListener[View, PropertyName]:
for _, listener := range value {
if text, ok := listener.rawListener().(string); ok && text != "" {
func isQuotesNeeded(text string) bool {
if len(text) == 1 {
simple := (text[0] >= '0' && text[0] <= '9') || (text[0] >= 'A' && text[0] <= 'Z') || (text[0] >= 'a' && text[0] <= 'z')
return !simple
} else {
for _, ch := range text {
if (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') ||
ch == '+' || ch == '-' || ch == '@' || ch == '/' || ch == '_' || ch == '.' ||
ch == ':' || ch == '#' || ch == '%' || ch == 'π' || ch == '°' {
} else {
return true
}
}
return false
default:
return false
}
return false
}
func writePropertyValue(buffer *strings.Builder, tag PropertyName, value any, indent string) {
func replaceEscapeSymbols(text string) string {
replace := []struct{ old, new string }{
{old: "\\", new: `\\`},
{old: "\t", new: `\t`},
{old: "\r", new: `\r`},
{old: "\n", new: `\n`},
{old: "\"", new: `\"`},
}
for _, s := range replace {
text = strings.ReplaceAll(text, s.old, s.new)
}
return text
}
writeString := func(text string) {
simple := (tag != Text && tag != Title && tag != Summary)
if simple {
if len(text) == 1 {
simple = (text[0] >= '0' && text[0] <= '9') || (text[0] >= 'A' && text[0] <= 'Z') || (text[0] >= 'a' && text[0] <= 'z')
} else {
for _, ch := range text {
if (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') ||
ch == '+' || ch == '-' || ch == '@' || ch == '/' || ch == '_' || ch == '.' ||
ch == ':' || ch == '#' || ch == '%' || ch == 'π' || ch == '°' {
} else {
simple = false
break
}
}
}
}
func propertyValueToString(tag PropertyName, value any, indent string) string {
if !simple {
replace := []struct{ old, new string }{
{old: "\\", new: `\\`},
{old: "\t", new: `\t`},
{old: "\r", new: `\r`},
{old: "\n", new: `\n`},
{old: "\"", new: `\"`},
}
for _, s := range replace {
text = strings.Replace(text, s.old, s.new, -1)
}
writeString := func(buffer *strings.Builder, text string) string {
if isQuotesNeeded(text) {
buffer.WriteRune('"')
buffer.WriteString(text)
buffer.WriteString(replaceEscapeSymbols(text))
buffer.WriteRune('"')
} else {
buffer.WriteString(text)
}
return text
}
switch value := value.(type) {
case string:
writeString(value)
if tag == Text || tag == Title || tag == Summary || isQuotesNeeded(value) {
return `"` + replaceEscapeSymbols(value) + `"`
}
return value
case []string:
if len(value) == 0 {
buffer.WriteString("[]")
} else {
size := 0
for _, text := range value {
size += len(text) + 2
}
if size < 80 {
lead := "["
for _, text := range value {
buffer.WriteString(lead)
writeString(text)
lead = ", "
}
} else {
buffer.WriteString("[\n")
for _, text := range value {
buffer.WriteString(indent)
buffer.WriteRune('\t')
writeString(text)
buffer.WriteString(",\n")
}
buffer.WriteString(indent)
}
buffer.WriteRune(']')
return "[]"
}
size := 0
for _, text := range value {
size += len(text) + 2
}
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
if size < 80 {
lead := "["
for _, text := range value {
buffer.WriteString(lead)
writeString(buffer, text)
lead = ", "
}
} else {
buffer.WriteString("[\n")
for _, text := range value {
buffer.WriteString(indent)
buffer.WriteRune('\t')
writeString(buffer, text)
buffer.WriteString(",\n")
}
buffer.WriteString(indent)
}
buffer.WriteRune(']')
return buffer.String()
case bool:
if value {
buffer.WriteString("true")
} else {
buffer.WriteString("false")
return "true"
}
return "false"
case float32:
fmt.Fprintf(buffer, "%g", float64(value))
return fmt.Sprintf("%g", float64(value))
case float64:
fmt.Fprintf(buffer, "%g", value)
return fmt.Sprintf("%g", value)
case int:
if prop, ok := enumProperties[tag]; ok && value >= 0 && value < len(prop.values) {
buffer.WriteString(prop.values[value])
} else {
buffer.WriteString(strconv.Itoa(value))
return prop.values[value]
}
return strconv.Itoa(value)
case stringWriter:
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
value.writeString(buffer, indent+"\t")
return buffer.String()
case View:
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
writeViewStyle(value.Tag(), value, buffer, indent, value.excludeTags())
return buffer.String()
case fmt.Stringer:
writeString(value.String())
return value.String()
case []ShadowProperty:
switch len(value) {
case 0:
// do nothing
size := len(value)
if size == 0 {
return ""
}
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
switch len(value) {
case 1:
value[0].writeString(buffer, indent)
@ -795,58 +694,73 @@ func writePropertyValue(buffer *strings.Builder, tag PropertyName, value any, in
buffer.WriteString(indent)
buffer.WriteRune(']')
}
return buffer.String()
case []View:
switch len(value) {
case 0:
buffer.WriteString("[]")
size := len(value)
if size == 0 {
return "[]"
}
case 1:
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
if size == 1 {
writeViewStyle(value[0].Tag(), value[0], buffer, indent, value[0].excludeTags())
default:
} else {
buffer.WriteString("[\n")
indent2 := indent + "\t"
for _, v := range value {
for _, view := range value {
buffer.WriteString(indent2)
writeViewStyle(v.Tag(), v, buffer, indent2, v.excludeTags())
writeViewStyle(view.Tag(), view, buffer, indent2, view.excludeTags())
buffer.WriteString(",\n")
}
buffer.WriteString(indent)
buffer.WriteRune(']')
}
return buffer.String()
case []any:
switch count := len(value); count {
case 0:
buffer.WriteString("[]")
size := len(value)
if size == 0 {
return "[]"
}
case 1:
writePropertyValue(buffer, tag, value[0], indent)
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
default:
if size == 1 {
return propertyValueToString(tag, value[0], indent)
} else {
buffer.WriteString("[ ")
comma := false
for _, v := range value {
if comma {
buffer.WriteString(", ")
text := propertyValueToString(tag, v, indent)
if text != "" {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(text)
comma = true
}
writePropertyValue(buffer, tag, v, indent)
comma = true
}
buffer.WriteString(" ]")
}
return buffer.String()
case []BackgroundElement:
switch len(value) {
case 0:
buffer.WriteString("[]\n")
size := len(value)
if size == 0 {
return "[]"
}
case 1:
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
if size == 1 {
value[0].writeString(buffer, indent)
default:
} else {
buffer.WriteString("[\n")
indent2 := indent + "\t"
for _, element := range value {
@ -858,8 +772,12 @@ func writePropertyValue(buffer *strings.Builder, tag PropertyName, value any, in
buffer.WriteString(indent)
buffer.WriteRune(']')
}
return buffer.String()
case []BackgroundGradientPoint:
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
buffer.WriteRune('"')
for i, point := range value {
if i > 0 {
@ -868,8 +786,12 @@ func writePropertyValue(buffer *strings.Builder, tag PropertyName, value any, in
buffer.WriteString(point.String())
}
buffer.WriteRune('"')
return buffer.String()
case []BackgroundGradientAngle:
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
buffer.WriteRune('"')
for i, point := range value {
if i > 0 {
@ -878,19 +800,23 @@ func writePropertyValue(buffer *strings.Builder, tag PropertyName, value any, in
buffer.WriteString(point.String())
}
buffer.WriteRune('"')
return buffer.String()
case map[PropertyName]AnimationProperty:
switch count := len(value); count {
case 0:
buffer.WriteString("[]")
size := len(value)
if size == 0 {
return "[]"
}
case 1:
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
if size == 1 {
for tag, animation := range value {
animation.writeTransitionString(tag, buffer)
break
}
default:
} else {
tags := make([]PropertyName, 0, len(value))
for tag := range value {
tags = append(tags, tag)
@ -908,121 +834,171 @@ func writePropertyValue(buffer *strings.Builder, tag PropertyName, value any, in
buffer.WriteString(indent)
buffer.WriteRune(']')
}
return buffer.String()
case []AnimationProperty:
switch count := len(value); count {
case 0:
buffer.WriteString("[]")
default:
buffer.WriteString("[\n")
indent2 := indent + "\t"
for _, anim := range value {
if anim != nil {
anim.writeAnimationString(Animation, buffer, indent2)
}
}
buffer.WriteString(indent)
buffer.WriteRune(']')
size := len(value)
if size == 0 {
return "[]"
}
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
buffer.WriteString("[\n")
indent2 := indent + "\t"
for _, anim := range value {
if anim != nil {
anim.writeAnimationString(Animation, buffer, indent2)
}
}
buffer.WriteString(indent)
buffer.WriteRune(']')
return buffer.String()
case []noArgListener[View]:
buffer.WriteString(getNoArgBinding(value))
return getNoArgBinding(value)
case []noArgListener[ImageView]:
buffer.WriteString(getNoArgBinding(value))
return getNoArgBinding(value)
case []noArgListener[MediaPlayer]:
buffer.WriteString(getNoArgBinding(value))
return getNoArgBinding(value)
case []oneArgListener[View, KeyEvent]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[View, MouseEvent]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[View, TouchEvent]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[View, PointerEvent]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[View, PropertyName]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[View, string]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[View, Frame]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[View, DragAndDropEvent]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[Checkbox, bool]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[FilePicker, []FileInfo]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[ListView, int]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[ListView, []int]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[MediaPlayer, float64]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[TableView, int]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []oneArgListener[TabsLayout, int]:
buffer.WriteString(getOneArgBinding(value))
return getOneArgBinding(value)
case []twoArgListener[ColorPicker, Color]:
buffer.WriteString(getTwoArgBinding(value))
return getTwoArgBinding(value)
case []twoArgListener[DatePicker, time.Time]:
buffer.WriteString(getTwoArgBinding(value))
return getTwoArgBinding(value)
case []twoArgListener[TimePicker, time.Time]:
buffer.WriteString(getTwoArgBinding(value))
return getTwoArgBinding(value)
case []twoArgListener[DropDownList, int]:
buffer.WriteString(getTwoArgBinding(value))
return getTwoArgBinding(value)
case []twoArgListener[EditView, string]:
buffer.WriteString(getTwoArgBinding(value))
return getTwoArgBinding(value)
case []twoArgListener[NumberPicker, float64]:
buffer.WriteString(getTwoArgBinding(value))
return getTwoArgBinding(value)
case []twoArgListener[TableView, int]:
buffer.WriteString(getTwoArgBinding(value))
return getTwoArgBinding(value)
case []twoArgListener[TabsLayout, int]:
buffer.WriteString(getTwoArgBinding(value))
return getTwoArgBinding(value)
case []mediaPlayerErrorListener:
buffer.WriteString(getMediaPlayerErrorListenerBinding(value))
return getMediaPlayerErrorListenerBinding(value)
case []popupListener:
return getPopupListenerBinding(value)
case map[PropertyName]oneArgListener[View, PropertyName]:
buffer.WriteString("_{")
if len(value) == 0 {
return ""
}
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
indent2 := indent + "\t"
buffer.WriteString("_{\n")
for key, listener := range value {
if text, ok := listener.rawListener().(string); ok && text != "" {
buffer.WriteRune('\n')
buffer.WriteString(indent)
buffer.WriteRune('\t')
writeString(string(key))
buffer.WriteString(indent2)
writeString(buffer, string(key))
buffer.WriteString(" = ")
writeString(text)
buffer.WriteRune(',')
writeString(buffer, text)
buffer.WriteString(",\n")
}
buffer.WriteRune('\n')
buffer.WriteString(indent)
buffer.WriteRune('}')
}
return buffer.String()
case []popupButton:
if len(value) == 0 {
return ""
}
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
lead := indent + "\t_{ title = "
buffer.WriteString("[\n")
for _, button := range value {
buffer.WriteString(lead)
writeString(buffer, button.title)
switch button.buttonType {
case CancelButton:
buffer.WriteString(`, type = cancel`)
case DefaultButton:
buffer.WriteString(`, type = default`)
}
if button.onClick != nil {
if text, ok := button.onClick.rawListener().(string); ok {
buffer.WriteString(`, click = `)
writeString(buffer, text)
}
}
buffer.WriteString(" },\n")
}
buffer.WriteString(indent)
buffer.WriteRune(']')
return buffer.String()
default:
return ""
}
}
@ -1033,11 +1009,12 @@ func writeViewStyle(name string, view Properties, buffer *strings.Builder, inden
writeProperty := func(tag PropertyName, value any) {
if !slices.Contains(excludeTags, tag) {
if supportedPropertyValue(value) {
text := propertyValueToString(tag, value, indent)
if text != "" {
buffer.WriteString(indent)
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
buffer.WriteString(text)
buffer.WriteString(",\n")
}
}