diff --git a/border.go b/border.go index 18f325d..e270c07 100644 --- a/border.go +++ b/border.go @@ -73,6 +73,13 @@ func newBorderProperty(value interface{}) BorderProperty { case BorderProperty: return value + case DataNode: + if value.Type() == ObjectNode { + _ = border.setBorderObject(value.Object()) + } else { + return nil + } + case DataObject: _ = border.setBorderObject(value) diff --git a/bounds.go b/bounds.go index 102046a..6f6626c 100644 --- a/bounds.go +++ b/bounds.go @@ -261,7 +261,20 @@ func (properties *propertyList) setBounds(tag string, value interface{}) bool { properties.properties[tag] = value case Bounds: - properties.properties[tag] = value + bounds := NewBoundsProperty(nil) + if value.Top.Type != Auto { + bounds.Set(Top, value.Top) + } + if value.Right.Type != Auto { + bounds.Set(Right, value.Right) + } + if value.Bottom.Type != Auto { + bounds.Set(Bottom, value.Bottom) + } + if value.Left.Type != Auto { + bounds.Set(Left, value.Left) + } + properties.properties[tag] = bounds case BoundsProperty: properties.properties[tag] = value diff --git a/colorPicker.go b/colorPicker.go index 52febfa..1e87f13 100644 --- a/colorPicker.go +++ b/colorPicker.go @@ -235,7 +235,7 @@ func GetColorPickerValue(view View, subviewID string) Color { return result } for _, tag := range []string{Value, ColorTag} { - if value, ok := valueFromStyle(view, tag); ok { + if value := valueFromStyle(view, tag); value != nil { if result, ok := valueToColor(value, view.Session()); ok { return result } diff --git a/columnLayout.go b/columnLayout.go index 3d1b405..8ef7d35 100644 --- a/columnLayout.go +++ b/columnLayout.go @@ -186,7 +186,7 @@ func GetColumnSeparator(view View, subviewID string) ViewBorder { if view != nil { value := view.Get(ColumnSeparator) if value == nil { - value, _ = valueFromStyle(view, ColumnSeparator) + value = valueFromStyle(view, ColumnSeparator) } if value != nil { diff --git a/datePicker.go b/datePicker.go index a2f6f67..1fb8ad6 100644 --- a/datePicker.go +++ b/datePicker.go @@ -361,7 +361,7 @@ func getDateProperty(view View, mainTag, shortTag string) (time.Time, bool) { return result, true } - if value, ok := valueFromStyle(view, shortTag); ok { + if value := valueFromStyle(view, shortTag); value != nil { if result, ok := valueToTime(value); ok { return result, true } diff --git a/editView.go b/editView.go index b1f29b8..7ad9439 100644 --- a/editView.go +++ b/editView.go @@ -568,9 +568,11 @@ func GetHint(view View, subviewID string) string { if text, ok := stringProperty(view, Hint, view.Session()); ok { return text } - if text, ok := valueFromStyle(view, Hint); ok { - if text, ok = view.Session().resolveConstants(text); ok { - return text + if value := valueFromStyle(view, Hint); value != nil { + if text, ok := value.(string); ok { + if text, ok = view.Session().resolveConstants(text); ok { + return text + } } } } @@ -659,9 +661,11 @@ func GetEditViewPattern(view View, subviewID string) string { if pattern, ok := stringProperty(view, EditViewPattern, view.Session()); ok { return pattern } - if pattern, ok := valueFromStyle(view, EditViewPattern); ok { - if pattern, ok = view.Session().resolveConstants(pattern); ok { - return pattern + if value := valueFromStyle(view, EditViewPattern); value != nil { + if pattern, ok := value.(string); ok { + if pattern, ok = view.Session().resolveConstants(pattern); ok { + return pattern + } } } } diff --git a/filePicker.go b/filePicker.go index ad49141..7437be7 100644 --- a/filePicker.go +++ b/filePicker.go @@ -260,8 +260,11 @@ func (picker *filePickerData) htmlTag() string { func (picker *filePickerData) acceptCSS() string { accept, ok := stringProperty(picker, Accept, picker.Session()) if !ok { - accept, ok = valueFromStyle(picker, Accept) + if value := valueFromStyle(picker, Accept); value != nil { + accept, ok = value.(string) + } } + if ok { buffer := allocStringBuilder() defer freeStringBuilder(buffer) @@ -414,7 +417,9 @@ func GetFilePickerAccept(view View, subviewID string) []string { if view != nil { accept, ok := stringProperty(view, Accept, view.Session()) if !ok { - accept, ok = valueFromStyle(view, Accept) + if value := valueFromStyle(view, Accept); value != nil { + accept, ok = value.(string) + } } if ok { result := strings.Split(accept, ",") diff --git a/listLayout.go b/listLayout.go index d4b27b0..cd39579 100644 --- a/listLayout.go +++ b/listLayout.go @@ -139,7 +139,7 @@ func GetListOrientation(view View, subviewID string) int { return orientation } - if value, ok := valueFromStyle(view, Orientation); ok { + if value := valueFromStyle(view, Orientation); value != nil { if orientation, ok := valueToOrientation(value, view.Session()); ok { return orientation } diff --git a/session.go b/session.go index 56fca9e..b79e0d3 100644 --- a/session.go +++ b/session.go @@ -80,8 +80,7 @@ type Session interface { viewByHTMLID(id string) View nextViewID() string - styleProperty(styleTag, property string) (string, bool) - stylePropertyNode(styleTag, propertyTag string) DataNode + styleProperty(styleTag, property string) interface{} setBrige(events chan DataObject, brige WebBrige) writeInitScript(writer *strings.Builder) @@ -214,26 +213,11 @@ func (session *sessionData) close() { } } -func (session *sessionData) styleProperty(styleTag, propertyTag string) (string, bool) { - style := session.getCurrentTheme().style(styleTag) - if value, ok := style[propertyTag]; ok { - if text, ok := value.(string); ok { - return session.resolveConstants(text) - } +func (session *sessionData) styleProperty(styleTag, propertyTag string) interface{} { + if style := session.getCurrentTheme().style(styleTag); style != nil { + return style.getRaw(propertyTag) } - //errorLogF(`property "%v" not found`, propertyTag) - return "", false -} - -func (session *sessionData) stylePropertyNode(styleTag, propertyTag string) DataNode { - style := session.getCurrentTheme().style(styleTag) - if value, ok := style[propertyTag]; ok { - if node, ok := value.(DataNode); ok { - return node - } - } - return nil } diff --git a/tableView.go b/tableView.go index 8ec793e..e8aaaad 100644 --- a/tableView.go +++ b/tableView.go @@ -1267,72 +1267,68 @@ func (table *tableViewData) htmlSubviews(self View, buffer *strings.Builder) { } func (table *tableViewData) cellPaddingFromStyle(style string) BoundsProperty { - session := table.Session() - var result BoundsProperty = nil + if value := table.Session().styleProperty(style, CellPadding); value != nil { + switch value := value.(type) { + case SizeUnit: + return NewBoundsProperty(Params{ + Top: value, + Right: value, + Bottom: value, + Left: value, + }) - if node := session.stylePropertyNode(style, CellPadding); node != nil && node.Type() == ObjectNode { - for _, tag := range []string{Left, Right, Top, Bottom} { - if node := node.Object().PropertyWithTag(tag); node != nil && node.Type() == TextNode { - if result == nil { - result = NewBoundsProperty(nil) + case BoundsProperty: + return value + + case string: + if value, ok := table.Session().resolveConstants(value); ok { + if strings.Contains(value, ",") { + values := split4Values(value) + switch len(values) { + case 1: + value = values[0] + + case 4: + result := NewBoundsProperty(nil) + n := 0 + for i, tag := range []string{Top, Right, Bottom, Left} { + if size, ok := StringToSizeUnit(values[i]); ok && size.Type != Auto { + result.Set(tag, size) + n++ + } + } + if n > 0 { + return result + } + return nil + + default: + return nil + } + } + + if size, ok := StringToSizeUnit(value); ok && size.Type != Auto { + return NewBoundsProperty(Params{ + Top: size, + Right: size, + Bottom: size, + Left: size, + }) } - result.Set(tag, node.Text()) } } } - for _, tag := range []string{CellPaddingLeft, CellPaddingRight, CellPaddingTop, CellPaddingBottom} { - if value, ok := session.styleProperty(style, CellPadding); ok { - if result == nil { - result = NewBoundsProperty(nil) - } - result.Set(tag, value) - } - } - - return result + return nil } func (table *tableViewData) cellBorderFromStyle(style string) BorderProperty { - - border := new(borderProperty) - border.properties = map[string]interface{}{} - - session := table.Session() - if node := session.stylePropertyNode(style, CellBorder); node != nil && node.Type() == ObjectNode { - border.setBorderObject(node.Object()) - } - - for _, tag := range []string{ - CellBorderLeft, - CellBorderRight, - CellBorderTop, - CellBorderBottom, - CellBorderStyle, - CellBorderLeftStyle, - CellBorderRightStyle, - CellBorderTopStyle, - CellBorderBottomStyle, - CellBorderWidth, - CellBorderLeftWidth, - CellBorderRightWidth, - CellBorderTopWidth, - CellBorderBottomWidth, - CellBorderColor, - CellBorderLeftColor, - CellBorderRightColor, - CellBorderTopColor, - CellBorderBottomColor, - } { - if value, ok := session.styleProperty(style, tag); ok { - border.Set(tag, value) + if value := table.Session().styleProperty(style, CellBorder); value != nil { + if border, ok := value.(BorderProperty); ok { + return border } } - - if len(border.properties) == 0 { - return nil - } - return border + return nil } func (table *tableViewData) getCellBorder() BorderProperty { diff --git a/theme.go b/theme.go index a051731..a85f60c 100644 --- a/theme.go +++ b/theme.go @@ -1,6 +1,7 @@ package rui import ( + "fmt" "sort" "strconv" "strings" @@ -16,7 +17,7 @@ type MediaStyle struct { Orientation int MaxWidth int MaxHeight int - Styles map[string]Params + Styles map[string]ViewStyle } type theme struct { @@ -27,11 +28,12 @@ type theme struct { darkColors map[string]string images map[string]string darkImages map[string]string - styles map[string]Params + styles map[string]ViewStyle mediaStyles []MediaStyle } type Theme interface { + fmt.Stringer Name() string Constant(tag string) (string, string) SetConstant(tag string, value, touchUIValue string) @@ -50,7 +52,7 @@ type Theme interface { constant(tag string, touchUI bool) string color(tag string, darkUI bool) string image(tag string, darkUI bool) string - style(tag string) Params + style(tag string) ViewStyle cssText(session Session) string data() *theme } @@ -87,7 +89,7 @@ func parseMediaRule(text string) (MediaStyle, bool) { Orientation: DefaultMedia, MaxWidth: 0, MaxHeight: 0, - Styles: map[string]Params{}, + Styles: map[string]ViewStyle{}, } elements := strings.Split(text, ":") @@ -170,7 +172,7 @@ func (theme *theme) init() { theme.darkColors = map[string]string{} theme.images = map[string]string{} theme.darkImages = map[string]string{} - theme.styles = map[string]Params{} + theme.styles = map[string]ViewStyle{} theme.mediaStyles = []MediaStyle{} } @@ -352,12 +354,12 @@ func (theme *theme) cssText(session Session) string { var builder cssStyleBuilder builder.init() - for tag, obj := range theme.styles { - var style viewStyle + for tag, style := range theme.styles { + /*var style viewStyle style.init() for tag, value := range obj { style.Set(tag, value) - } + }*/ builder.startStyle(tag) style.cssViewStyle(&builder, session) builder.endStyle() @@ -365,12 +367,12 @@ func (theme *theme) cssText(session Session) string { for _, media := range theme.mediaStyles { builder.startMedia(media.cssText()) - for tag, obj := range media.Styles { - var style viewStyle + for tag, style := range media.Styles { + /*var style viewStyle style.init() for tag, value := range obj { style.Set(tag, value) - } + }*/ builder.startStyle(tag) style.cssViewStyle(&builder, session) builder.endStyle() @@ -404,7 +406,7 @@ func (theme *theme) addData(data DataObject) { func (theme *theme) parseThemeData(data DataObject) { count := data.PropertyCount() - objToParams := func(obj DataObject) Params { + objToStyle := func(obj DataObject) ViewStyle { params := Params{} for i := 0; i < obj.PropertyCount(); i++ { if node := obj.Property(i); node != nil { @@ -420,7 +422,7 @@ func (theme *theme) parseThemeData(data DataObject) { } } } - return params + return NewViewStyle(params) } for i := 0; i < count; i++ { @@ -504,7 +506,7 @@ func (theme *theme) parseThemeData(data DataObject) { for k := 0; k < arraySize; k++ { if element := d.ArrayElement(k); element != nil && element.IsObject() { if obj := element.Object(); obj != nil { - theme.styles[obj.Tag()] = objToParams(obj) + theme.styles[obj.Tag()] = objToStyle(obj) } } } @@ -517,7 +519,7 @@ func (theme *theme) parseThemeData(data DataObject) { for k := 0; k < arraySize; k++ { if element := d.ArrayElement(k); element != nil && element.IsObject() { if obj := element.Object(); obj != nil { - rule.Styles[obj.Tag()] = objToParams(obj) + rule.Styles[obj.Tag()] = objToStyle(obj) } } } @@ -586,10 +588,74 @@ func (theme *theme) image(tag string, darkUI bool) string { return result } -func (theme *theme) style(tag string) Params { +func (theme *theme) style(tag string) ViewStyle { if style, ok := theme.styles[tag]; ok { return style } - return Params{} + return nil +} + +func (theme *theme) String() string { + buffer := allocStringBuilder() + 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) + } + buffer.WriteRune('"') + buffer.WriteString(text) + buffer.WriteRune('"') + } else { + buffer.WriteString(text) + } + } + + writeConstants := func(tag string, constants map[string]string) { + count := len(constants) + if count == 0 { + return + } + + buffer.WriteString("\t") + buffer.WriteString(tag) + buffer.WriteString(" = _{\n") + + tags := make([]string, 0, count) + for name := range constants { + tags = append(tags, name) + } + sort.Strings(tags) + for _, name := range tags { + if value, ok := constants[name]; ok && value != "" { + buffer.WriteString("\t\t") + writeString(name) + buffer.WriteString(" = ") + writeString(value) + buffer.WriteString(",\n") + } + } + + buffer.WriteString("\t},\n") + } + + buffer.WriteString("theme {\n") + writeConstants("colors", theme.colors) + writeConstants("colors:dark", theme.darkColors) + writeConstants("images", theme.images) + writeConstants("images:dark", theme.darkImages) + writeConstants("constants", theme.constants) + writeConstants("constants:touch", theme.touchConstants) + + buffer.WriteString("}\n") + return buffer.String() } diff --git a/timePicker.go b/timePicker.go index 5e412d7..f6c4231 100644 --- a/timePicker.go +++ b/timePicker.go @@ -361,7 +361,7 @@ func getTimeProperty(view View, mainTag, shortTag string) (time.Time, bool) { return result, true } - if value, ok := valueFromStyle(view, shortTag); ok { + if value := valueFromStyle(view, shortTag); value != nil { if result, ok := valueToTime(value); ok { return result, true } diff --git a/viewUtils.go b/viewUtils.go index 62de339..d0db90d 100644 --- a/viewUtils.go +++ b/viewUtils.go @@ -410,8 +410,10 @@ func GetFontName(view View, subviewID string) string { if font, ok := stringProperty(view, FontName, view.Session()); ok { return font } - if font, ok := valueFromStyle(view, FontName); ok { - return font + if value := valueFromStyle(view, FontName); value != nil { + if font, ok := value.(string); ok { + return font + } } if parent := view.Parent(); parent != nil { return GetFontName(parent, "") @@ -784,7 +786,7 @@ func GetRow(view View, subviewID string) Range { if result, ok := rangeProperty(view, Row, session); ok { return result } - if value, ok := valueFromStyle(view, Row); ok { + if value := valueFromStyle(view, Row); value != nil { if result, ok := valueToRange(value, session); ok { return result } @@ -804,7 +806,7 @@ func GetColumn(view View, subviewID string) Range { if result, ok := rangeProperty(view, Column, session); ok { return result } - if value, ok := valueFromStyle(view, Column); ok { + if value := valueFromStyle(view, Column); value != nil { if result, ok := valueToRange(value, session); ok { return result } @@ -954,20 +956,20 @@ func GetNotTranslate(view View, subviewID string) bool { return false } -func valueFromStyle(view View, tag string) (string, bool) { +func valueFromStyle(view View, tag string) interface{} { session := view.Session() - getValue := func(styleTag string) (string, bool) { + getValue := func(styleTag string) interface{} { if style, ok := stringProperty(view, styleTag, session); ok { if style, ok := session.resolveConstants(style); ok { return session.styleProperty(style, tag) } } - return "", false + return nil } if IsDisabled(view, "") { - if value, ok := getValue(StyleDisabled); ok { - return value, true + if value := getValue(StyleDisabled); value != nil { + return value } } return getValue(Style) @@ -977,7 +979,7 @@ func sizeStyledProperty(view View, tag string) (SizeUnit, bool) { if value, ok := sizeProperty(view, tag, view.Session()); ok { return value, true } - if value, ok := valueFromStyle(view, tag); ok { + if value := valueFromStyle(view, tag); value != nil { return valueToSizeUnit(value, view.Session()) } return AutoSize(), false @@ -987,7 +989,7 @@ func enumStyledProperty(view View, tag string, defaultValue int) (int, bool) { if value, ok := enumProperty(view, tag, view.Session(), defaultValue); ok { return value, true } - if value, ok := valueFromStyle(view, tag); ok { + if value := valueFromStyle(view, tag); value != nil { return valueToEnum(value, tag, view.Session(), defaultValue) } return defaultValue, false @@ -997,7 +999,7 @@ func boolStyledProperty(view View, tag string) (bool, bool) { if value, ok := boolProperty(view, tag, view.Session()); ok { return value, true } - if value, ok := valueFromStyle(view, tag); ok { + if value := valueFromStyle(view, tag); value != nil { return valueToBool(value, view.Session()) } return false, false @@ -1007,7 +1009,7 @@ func intStyledProperty(view View, tag string, defaultValue int) (int, bool) { if value, ok := intProperty(view, tag, view.Session(), defaultValue); ok { return value, true } - if value, ok := valueFromStyle(view, tag); ok { + if value := valueFromStyle(view, tag); value != nil { return valueToInt(value, view.Session(), defaultValue) } return defaultValue, false @@ -1017,7 +1019,7 @@ func floatStyledProperty(view View, tag string, defaultValue float64) (float64, if value, ok := floatProperty(view, tag, view.Session(), defaultValue); ok { return value, true } - if value, ok := valueFromStyle(view, tag); ok { + if value := valueFromStyle(view, tag); value != nil { return valueToFloat(value, view.Session(), defaultValue) } @@ -1028,7 +1030,7 @@ func colorStyledProperty(view View, tag string) (Color, bool) { if value, ok := colorProperty(view, tag, view.Session()); ok { return value, true } - if value, ok := valueFromStyle(view, tag); ok { + if value := valueFromStyle(view, tag); value != nil { return valueToColor(value, view.Session()) } return Color(0), false