mirror of https://github.com/anoshenko/rui.git
909 lines
25 KiB
Go
909 lines
25 KiB
Go
package rui
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// Constants related to view's border description
|
|
const (
|
|
// NoneLine constant specifies that there is no border
|
|
NoneLine = 0
|
|
|
|
// SolidLine constant specifies the border/line as a solid line
|
|
SolidLine = 1
|
|
|
|
// DashedLine constant specifies the border/line as a dashed line
|
|
DashedLine = 2
|
|
|
|
// DottedLine constant specifies the border/line as a dotted line
|
|
DottedLine = 3
|
|
|
|
// DoubleLine constant specifies the border/line as a double solid line
|
|
DoubleLine = 4
|
|
|
|
// DoubleLine constant specifies the border/line as a double solid line
|
|
WavyLine = 5
|
|
|
|
// LeftStyle is the constant for "left-style" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Left border line style.
|
|
//
|
|
// Supported types: `int`, `string`.
|
|
//
|
|
// Values:
|
|
// `0`(`NoneLine`) or "none" - The border will not be drawn.
|
|
// `1`(`SolidLine`) or "solid" - Solid line as a border.
|
|
// `2`(`DashedLine`) or "dashed" - Dashed line as a border.
|
|
// `3`(`DottedLine`) or "dotted" - Dotted line as a border.
|
|
// `4`(`DoubleLine`) or "double" - Double line as a border.
|
|
LeftStyle PropertyName = "left-style"
|
|
|
|
// RightStyle is the constant for "right-style" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Right border line style.
|
|
//
|
|
// Supported types: `int`, `string`.
|
|
//
|
|
// Values:
|
|
// `0`(`NoneLine`) or "none" - The border will not be drawn.
|
|
// `1`(`SolidLine`) or "solid" - Solid line as a border.
|
|
// `2`(`DashedLine`) or "dashed" - Dashed line as a border.
|
|
// `3`(`DottedLine`) or "dotted" - Dotted line as a border.
|
|
// `4`(`DoubleLine`) or "double" - Double line as a border.
|
|
RightStyle PropertyName = "right-style"
|
|
|
|
// TopStyle is the constant for "top-style" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Top border line style.
|
|
//
|
|
// Supported types: `int`, `string`.
|
|
//
|
|
// Values:
|
|
// `0`(`NoneLine`) or "none" - The border will not be drawn.
|
|
// `1`(`SolidLine`) or "solid" - Solid line as a border.
|
|
// `2`(`DashedLine`) or "dashed" - Dashed line as a border.
|
|
// `3`(`DottedLine`) or "dotted" - Dotted line as a border.
|
|
// `4`(`DoubleLine`) or "double" - Double line as a border.
|
|
TopStyle PropertyName = "top-style"
|
|
|
|
// BottomStyle is the constant for "bottom-style" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Bottom border line style.
|
|
//
|
|
// Supported types: `int`, `string`.
|
|
//
|
|
// Values:
|
|
// `0`(`NoneLine`) or "none" - The border will not be drawn.
|
|
// `1`(`SolidLine`) or "solid" - Solid line as a border.
|
|
// `2`(`DashedLine`) or "dashed" - Dashed line as a border.
|
|
// `3`(`DottedLine`) or "dotted" - Dotted line as a border.
|
|
// `4`(`DoubleLine`) or "double" - Double line as a border.
|
|
BottomStyle PropertyName = "bottom-style"
|
|
|
|
// LeftWidth is the constant for "left-width" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Left border line width.
|
|
//
|
|
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
|
|
//
|
|
// Internal type is `SizeUnit`, other types converted to it during assignment.
|
|
// See `SizeUnit` description for more details.
|
|
LeftWidth PropertyName = "left-width"
|
|
|
|
// RightWidth is the constant for "right-width" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Right border line width.
|
|
//
|
|
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
|
|
//
|
|
// Internal type is `SizeUnit`, other types converted to it during assignment.
|
|
// See `SizeUnit` description for more details.
|
|
RightWidth PropertyName = "right-width"
|
|
|
|
// TopWidth is the constant for "top-width" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Top border line width.
|
|
//
|
|
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
|
|
//
|
|
// Internal type is `SizeUnit`, other types converted to it during assignment.
|
|
// See `SizeUnit` description for more details.
|
|
TopWidth PropertyName = "top-width"
|
|
|
|
// BottomWidth is the constant for "bottom-width" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Bottom border line width.
|
|
//
|
|
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
|
|
//
|
|
// Internal type is `SizeUnit`, other types converted to it during assignment.
|
|
// See `SizeUnit` description for more details.
|
|
BottomWidth PropertyName = "bottom-width"
|
|
|
|
// LeftColor is the constant for "left-color" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Left border line color.
|
|
//
|
|
// Supported types: `Color`, `string`.
|
|
//
|
|
// Internal type is `Color`, other types converted to it during assignment.
|
|
// See `Color` description for more details.
|
|
LeftColor PropertyName = "left-color"
|
|
|
|
// RightColor is the constant for "right-color" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Right border line color.
|
|
//
|
|
// Supported types: `Color`, `string`.
|
|
//
|
|
// Internal type is `Color`, other types converted to it during assignment.
|
|
// See `Color` description for more details.
|
|
RightColor PropertyName = "right-color"
|
|
|
|
// TopColor is the constant for "top-color" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Top border line color.
|
|
//
|
|
// Supported types: `Color`, `string`.
|
|
//
|
|
// Internal type is `Color`, other types converted to it during assignment.
|
|
// See `Color` description for more details.
|
|
TopColor PropertyName = "top-color"
|
|
|
|
// BottomColor is the constant for "bottom-color" property tag.
|
|
//
|
|
// Used by `BorderProperty`.
|
|
// Bottom border line color.
|
|
//
|
|
// Supported types: `Color`, `string`.
|
|
//
|
|
// Internal type is `Color`, other types converted to it during assignment.
|
|
// See `Color` description for more details.
|
|
BottomColor PropertyName = "bottom-color"
|
|
)
|
|
|
|
// BorderProperty is the interface of a view border data
|
|
type BorderProperty interface {
|
|
Properties
|
|
fmt.Stringer
|
|
stringWriter
|
|
|
|
// ViewBorders returns top, right, bottom and left borders information all together
|
|
ViewBorders(session Session) ViewBorders
|
|
|
|
deleteTag(tag PropertyName) bool
|
|
cssStyle(builder cssBuilder, session Session)
|
|
cssWidth(builder cssBuilder, session Session)
|
|
cssColor(builder cssBuilder, session Session)
|
|
cssStyleValue(session Session) string
|
|
cssWidthValue(session Session) string
|
|
cssColorValue(session Session) string
|
|
}
|
|
|
|
type borderProperty struct {
|
|
dataProperty
|
|
}
|
|
|
|
func newBorderProperty(value any) BorderProperty {
|
|
border := new(borderProperty)
|
|
border.init()
|
|
|
|
if value != nil {
|
|
switch value := value.(type) {
|
|
case BorderProperty:
|
|
return value
|
|
|
|
case DataNode:
|
|
if value.Type() == ObjectNode {
|
|
_ = border.setBorderObject(value.Object())
|
|
} else {
|
|
return nil
|
|
}
|
|
|
|
case DataObject:
|
|
_ = border.setBorderObject(value)
|
|
|
|
case ViewBorder:
|
|
border.properties[Style] = value.Style
|
|
border.properties[Width] = value.Width
|
|
border.properties[ColorTag] = value.Color
|
|
|
|
case ViewBorders:
|
|
if value.Left.Style == value.Right.Style &&
|
|
value.Left.Style == value.Top.Style &&
|
|
value.Left.Style == value.Bottom.Style {
|
|
border.properties[Style] = value.Left.Style
|
|
} else {
|
|
border.properties[LeftStyle] = value.Left.Style
|
|
border.properties[RightStyle] = value.Right.Style
|
|
border.properties[TopStyle] = value.Top.Style
|
|
border.properties[BottomStyle] = value.Bottom.Style
|
|
}
|
|
if value.Left.Width.Equal(value.Right.Width) &&
|
|
value.Left.Width.Equal(value.Top.Width) &&
|
|
value.Left.Width.Equal(value.Bottom.Width) {
|
|
border.properties[Width] = value.Left.Width
|
|
} else {
|
|
border.properties[LeftWidth] = value.Left.Width
|
|
border.properties[RightWidth] = value.Right.Width
|
|
border.properties[TopWidth] = value.Top.Width
|
|
border.properties[BottomWidth] = value.Bottom.Width
|
|
}
|
|
if value.Left.Color == value.Right.Color &&
|
|
value.Left.Color == value.Top.Color &&
|
|
value.Left.Color == value.Bottom.Color {
|
|
border.properties[ColorTag] = value.Left.Color
|
|
} else {
|
|
border.properties[LeftColor] = value.Left.Color
|
|
border.properties[RightColor] = value.Right.Color
|
|
border.properties[TopColor] = value.Top.Color
|
|
border.properties[BottomColor] = value.Bottom.Color
|
|
}
|
|
|
|
default:
|
|
invalidPropertyValue(Border, value)
|
|
return nil
|
|
}
|
|
}
|
|
return border
|
|
}
|
|
|
|
// NewBorder creates the new BorderProperty.
|
|
// The following properties can be used:
|
|
//
|
|
// "style" (Style). Determines the line style (int). Valid values: 0 (NoneLine), 1 (SolidLine), 2 (DashedLine), 3 (DottedLine), or 4 (DoubleLine);
|
|
//
|
|
// "color" (ColorTag). Determines the line color (Color);
|
|
//
|
|
// "width" (Width). Determines the line thickness (SizeUnit).
|
|
func NewBorder(params Params) BorderProperty {
|
|
border := new(borderProperty)
|
|
border.init()
|
|
|
|
if params != nil {
|
|
for _, tag := range []PropertyName{Style, Width, ColorTag, Left, Right, Top, Bottom,
|
|
LeftStyle, RightStyle, TopStyle, BottomStyle,
|
|
LeftWidth, RightWidth, TopWidth, BottomWidth,
|
|
LeftColor, RightColor, TopColor, BottomColor} {
|
|
if value, ok := params[tag]; ok && value != nil {
|
|
border.Set(tag, value)
|
|
}
|
|
}
|
|
}
|
|
return border
|
|
}
|
|
|
|
func (border *borderProperty) init() {
|
|
border.dataProperty.init()
|
|
border.normalize = normalizeBorderTag
|
|
border.get = borderGet
|
|
border.set = borderSet
|
|
border.remove = borderRemove
|
|
border.supportedProperties = []PropertyName{
|
|
Left,
|
|
Right,
|
|
Top,
|
|
Bottom,
|
|
Style,
|
|
LeftStyle,
|
|
RightStyle,
|
|
TopStyle,
|
|
BottomStyle,
|
|
Width,
|
|
LeftWidth,
|
|
RightWidth,
|
|
TopWidth,
|
|
BottomWidth,
|
|
ColorTag,
|
|
LeftColor,
|
|
RightColor,
|
|
TopColor,
|
|
BottomColor,
|
|
}
|
|
}
|
|
|
|
func normalizeBorderTag(tag PropertyName) PropertyName {
|
|
tag = defaultNormalize(tag)
|
|
switch tag {
|
|
case BorderLeft, CellBorderLeft:
|
|
return Left
|
|
|
|
case BorderRight, CellBorderRight:
|
|
return Right
|
|
|
|
case BorderTop, CellBorderTop:
|
|
return Top
|
|
|
|
case BorderBottom, CellBorderBottom:
|
|
return Bottom
|
|
|
|
case BorderStyle, CellBorderStyle:
|
|
return Style
|
|
|
|
case BorderLeftStyle, CellBorderLeftStyle, "style-left":
|
|
return LeftStyle
|
|
|
|
case BorderRightStyle, CellBorderRightStyle, "style-right":
|
|
return RightStyle
|
|
|
|
case BorderTopStyle, CellBorderTopStyle, "style-top":
|
|
return TopStyle
|
|
|
|
case BorderBottomStyle, CellBorderBottomStyle, "style-bottom":
|
|
return BottomStyle
|
|
|
|
case BorderWidth, CellBorderWidth:
|
|
return Width
|
|
|
|
case BorderLeftWidth, CellBorderLeftWidth, "width-left":
|
|
return LeftWidth
|
|
|
|
case BorderRightWidth, CellBorderRightWidth, "width-right":
|
|
return RightWidth
|
|
|
|
case BorderTopWidth, CellBorderTopWidth, "width-top":
|
|
return TopWidth
|
|
|
|
case BorderBottomWidth, CellBorderBottomWidth, "width-bottom":
|
|
return BottomWidth
|
|
|
|
case BorderColor, CellBorderColor:
|
|
return ColorTag
|
|
|
|
case BorderLeftColor, CellBorderLeftColor, "color-left":
|
|
return LeftColor
|
|
|
|
case BorderRightColor, CellBorderRightColor, "color-right":
|
|
return RightColor
|
|
|
|
case BorderTopColor, CellBorderTopColor, "color-top":
|
|
return TopColor
|
|
|
|
case BorderBottomColor, CellBorderBottomColor, "color-bottom":
|
|
return BottomColor
|
|
}
|
|
|
|
return tag
|
|
}
|
|
|
|
func (border *borderProperty) writeString(buffer *strings.Builder, indent string) {
|
|
buffer.WriteString("_{ ")
|
|
comma := false
|
|
|
|
write := func(tag PropertyName, value any) {
|
|
if comma {
|
|
buffer.WriteString(", ")
|
|
}
|
|
buffer.WriteString(string(tag))
|
|
buffer.WriteString(" = ")
|
|
writePropertyValue(buffer, BorderStyle, value, indent)
|
|
comma = true
|
|
}
|
|
|
|
for _, tag := range []PropertyName{Style, Width, ColorTag} {
|
|
if value, ok := border.properties[tag]; ok {
|
|
write(tag, value)
|
|
}
|
|
}
|
|
|
|
for _, side := range []PropertyName{Top, Right, Bottom, Left} {
|
|
style, okStyle := border.properties[side+"-"+Style]
|
|
width, okWidth := border.properties[side+"-"+Width]
|
|
color, okColor := border.properties[side+"-"+ColorTag]
|
|
if okStyle || okWidth || okColor {
|
|
if comma {
|
|
buffer.WriteString(", ")
|
|
comma = false
|
|
}
|
|
|
|
buffer.WriteString(string(side))
|
|
buffer.WriteString(" = _{ ")
|
|
if okStyle {
|
|
write(Style, style)
|
|
}
|
|
if okWidth {
|
|
write(Width, width)
|
|
}
|
|
if okColor {
|
|
write(ColorTag, color)
|
|
}
|
|
buffer.WriteString(" }")
|
|
comma = true
|
|
}
|
|
}
|
|
|
|
buffer.WriteString(" }")
|
|
}
|
|
|
|
func (border *borderProperty) String() string {
|
|
return runStringWriter(border)
|
|
}
|
|
|
|
func (border *borderProperty) setBorderObject(obj DataObject) bool {
|
|
result := true
|
|
for i := 0; i < obj.PropertyCount(); i++ {
|
|
if node := obj.Property(i); node != nil {
|
|
tag := PropertyName(node.Tag())
|
|
switch node.Type() {
|
|
case TextNode:
|
|
if borderSet(border, tag, node.Text()) == nil {
|
|
result = false
|
|
}
|
|
|
|
case ObjectNode:
|
|
if borderSet(border, tag, node.Object()) == nil {
|
|
result = false
|
|
}
|
|
|
|
default:
|
|
result = false
|
|
}
|
|
} else {
|
|
result = false
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func borderRemove(properties Properties, tag PropertyName) []PropertyName {
|
|
result := []PropertyName{}
|
|
removeTag := func(t PropertyName) {
|
|
if properties.getRaw(t) != nil {
|
|
properties.setRaw(t, nil)
|
|
result = append(result, t)
|
|
}
|
|
}
|
|
|
|
switch tag {
|
|
case Style:
|
|
for _, t := range []PropertyName{tag, TopStyle, RightStyle, BottomStyle, LeftStyle} {
|
|
removeTag(t)
|
|
}
|
|
|
|
case Width:
|
|
for _, t := range []PropertyName{tag, TopWidth, RightWidth, BottomWidth, LeftWidth} {
|
|
removeTag(t)
|
|
}
|
|
|
|
case ColorTag:
|
|
for _, t := range []PropertyName{tag, TopColor, RightColor, BottomColor, LeftColor} {
|
|
removeTag(t)
|
|
}
|
|
|
|
case Left, Right, Top, Bottom:
|
|
removeTag(tag + "-style")
|
|
removeTag(tag + "-width")
|
|
removeTag(tag + "-color")
|
|
|
|
case LeftStyle, RightStyle, TopStyle, BottomStyle:
|
|
removeTag(tag)
|
|
if style := properties.getRaw(Style); style != nil {
|
|
for _, t := range []PropertyName{TopStyle, RightStyle, BottomStyle, LeftStyle} {
|
|
if t != tag {
|
|
if properties.getRaw(t) == nil {
|
|
properties.setRaw(t, style)
|
|
result = append(result, t)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
case LeftWidth, RightWidth, TopWidth, BottomWidth:
|
|
removeTag(tag)
|
|
if width := properties.getRaw(Width); width != nil {
|
|
for _, t := range []PropertyName{TopWidth, RightWidth, BottomWidth, LeftWidth} {
|
|
if t != tag {
|
|
if properties.getRaw(t) == nil {
|
|
properties.setRaw(t, width)
|
|
result = append(result, t)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
case LeftColor, RightColor, TopColor, BottomColor:
|
|
removeTag(tag)
|
|
if color := properties.getRaw(ColorTag); color != nil {
|
|
for _, t := range []PropertyName{TopColor, RightColor, BottomColor, LeftColor} {
|
|
if t != tag {
|
|
if properties.getRaw(t) == nil {
|
|
properties.setRaw(t, color)
|
|
result = append(result, t)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
default:
|
|
ErrorLogF(`"%s" property is not compatible with the BorderProperty`, tag)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func borderSet(properties Properties, tag PropertyName, value any) []PropertyName {
|
|
|
|
setSingleBorderObject := func(prefix PropertyName, obj DataObject) []PropertyName {
|
|
result := []PropertyName{}
|
|
if text, ok := obj.PropertyValue(string(Style)); ok {
|
|
props := setEnumProperty(properties, prefix+"-style", text, enumProperties[BorderStyle].values)
|
|
if props == nil {
|
|
return nil
|
|
}
|
|
result = append(result, props...)
|
|
}
|
|
if text, ok := obj.PropertyValue(string(ColorTag)); ok {
|
|
props := setColorProperty(properties, prefix+"-color", text)
|
|
if props == nil && len(result) == 0 {
|
|
return nil
|
|
}
|
|
result = append(result, props...)
|
|
}
|
|
if text, ok := obj.PropertyValue("width"); ok {
|
|
props := setSizeProperty(properties, prefix+"-width", text)
|
|
if props == nil && len(result) == 0 {
|
|
return nil
|
|
}
|
|
result = append(result, props...)
|
|
}
|
|
if len(result) > 0 {
|
|
result = append(result, prefix)
|
|
}
|
|
return result
|
|
}
|
|
|
|
switch tag {
|
|
case Style:
|
|
if result := setEnumProperty(properties, Style, value, enumProperties[BorderStyle].values); result != nil {
|
|
for _, side := range []PropertyName{TopStyle, RightStyle, BottomStyle, LeftStyle} {
|
|
if value := properties.getRaw(side); value != nil {
|
|
properties.setRaw(side, nil)
|
|
result = append(result, side)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
case Width:
|
|
if result := setSizeProperty(properties, Width, value); result != nil {
|
|
for _, side := range []PropertyName{TopWidth, RightWidth, BottomWidth, LeftWidth} {
|
|
if value := properties.getRaw(side); value != nil {
|
|
properties.setRaw(side, nil)
|
|
result = append(result, side)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
case ColorTag:
|
|
if result := setColorProperty(properties, ColorTag, value); result != nil {
|
|
for _, side := range []PropertyName{TopColor, RightColor, BottomColor, LeftColor} {
|
|
if value := properties.getRaw(side); value != nil {
|
|
properties.setRaw(side, nil)
|
|
result = append(result, side)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
case LeftStyle, RightStyle, TopStyle, BottomStyle:
|
|
return setEnumProperty(properties, tag, value, enumProperties[BorderStyle].values)
|
|
|
|
case LeftWidth, RightWidth, TopWidth, BottomWidth:
|
|
return setSizeProperty(properties, tag, value)
|
|
|
|
case LeftColor, RightColor, TopColor, BottomColor:
|
|
return setColorProperty(properties, tag, value)
|
|
|
|
case Left, Right, Top, Bottom:
|
|
switch value := value.(type) {
|
|
case string:
|
|
if obj := ParseDataText(value); obj != nil {
|
|
return setSingleBorderObject(tag, obj)
|
|
}
|
|
|
|
case DataObject:
|
|
return setSingleBorderObject(tag, value)
|
|
|
|
case BorderProperty:
|
|
result := []PropertyName{}
|
|
styleTag := tag + "-" + Style
|
|
if style := value.Get(styleTag); value != nil {
|
|
properties.setRaw(styleTag, style)
|
|
result = append(result, styleTag)
|
|
}
|
|
colorTag := tag + "-" + ColorTag
|
|
if color := value.Get(colorTag); value != nil {
|
|
properties.setRaw(colorTag, color)
|
|
result = append(result, colorTag)
|
|
}
|
|
widthTag := tag + "-" + Width
|
|
if width := value.Get(widthTag); value != nil {
|
|
properties.setRaw(widthTag, width)
|
|
result = append(result, widthTag)
|
|
}
|
|
return result
|
|
|
|
case ViewBorder:
|
|
properties.setRaw(tag+"-"+Style, value.Style)
|
|
properties.setRaw(tag+"-"+Width, value.Width)
|
|
properties.setRaw(tag+"-"+ColorTag, value.Color)
|
|
return []PropertyName{tag + "-" + Style, tag + "-" + Width, tag + "-" + ColorTag}
|
|
}
|
|
fallthrough
|
|
|
|
default:
|
|
ErrorLogF(`"%s" property is not compatible with the BorderProperty`, tag)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func borderGet(properties Properties, tag PropertyName) any {
|
|
if result := properties.getRaw(tag); result != nil {
|
|
return result
|
|
}
|
|
|
|
switch tag {
|
|
case Left, Right, Top, Bottom:
|
|
result := newBorderProperty(nil)
|
|
if style := properties.getRaw(tag + "-" + Style); style != nil {
|
|
result.Set(Style, style)
|
|
} else if style := properties.getRaw(Style); style != nil {
|
|
result.Set(Style, style)
|
|
}
|
|
if width := properties.getRaw(tag + "-" + Width); width != nil {
|
|
result.Set(Width, width)
|
|
} else if width := properties.getRaw(Width); width != nil {
|
|
result.Set(Width, width)
|
|
}
|
|
if color := properties.getRaw(tag + "-" + ColorTag); color != nil {
|
|
result.Set(ColorTag, color)
|
|
} else if color := properties.getRaw(ColorTag); color != nil {
|
|
result.Set(ColorTag, color)
|
|
}
|
|
return result
|
|
|
|
case LeftStyle, RightStyle, TopStyle, BottomStyle:
|
|
if style := properties.getRaw(tag); style != nil {
|
|
return style
|
|
}
|
|
return properties.getRaw(Style)
|
|
|
|
case LeftWidth, RightWidth, TopWidth, BottomWidth:
|
|
if width := properties.getRaw(tag); width != nil {
|
|
return width
|
|
}
|
|
return properties.getRaw(Width)
|
|
|
|
case LeftColor, RightColor, TopColor, BottomColor:
|
|
if color := properties.getRaw(tag); color != nil {
|
|
return color
|
|
}
|
|
return properties.getRaw(ColorTag)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (border *borderProperty) deleteTag(tag PropertyName) bool {
|
|
|
|
result := false
|
|
removeTags := func(tags []PropertyName) {
|
|
for _, tag := range tags {
|
|
if border.getRaw(tag) != nil {
|
|
border.setRaw(tag, nil)
|
|
result = true
|
|
}
|
|
}
|
|
}
|
|
|
|
switch tag {
|
|
case Style:
|
|
removeTags([]PropertyName{Style, LeftStyle, RightStyle, TopStyle, BottomStyle})
|
|
|
|
case Width:
|
|
removeTags([]PropertyName{Width, LeftWidth, RightWidth, TopWidth, BottomWidth})
|
|
|
|
case ColorTag:
|
|
removeTags([]PropertyName{ColorTag, LeftColor, RightColor, TopColor, BottomColor})
|
|
|
|
case Left, Right, Top, Bottom:
|
|
if border.Get(Style) != nil {
|
|
border.properties[tag+"-"+Style] = 0
|
|
result = true
|
|
removeTags([]PropertyName{tag + "-" + ColorTag, tag + "-" + Width})
|
|
} else {
|
|
removeTags([]PropertyName{tag + "-" + Style, tag + "-" + ColorTag, tag + "-" + Width})
|
|
}
|
|
|
|
case LeftStyle, RightStyle, TopStyle, BottomStyle:
|
|
if border.getRaw(tag) != nil {
|
|
if border.Get(Style) != nil {
|
|
border.properties[tag] = 0
|
|
result = true
|
|
} else {
|
|
removeTags([]PropertyName{tag})
|
|
}
|
|
}
|
|
|
|
case LeftWidth, RightWidth, TopWidth, BottomWidth:
|
|
if border.getRaw(tag) != nil {
|
|
if border.Get(Width) != nil {
|
|
border.properties[tag] = AutoSize()
|
|
result = true
|
|
} else {
|
|
removeTags([]PropertyName{tag})
|
|
}
|
|
}
|
|
|
|
case LeftColor, RightColor, TopColor, BottomColor:
|
|
if border.getRaw(tag) != nil {
|
|
if border.Get(ColorTag) != nil {
|
|
border.properties[tag] = 0
|
|
result = true
|
|
} else {
|
|
removeTags([]PropertyName{tag})
|
|
}
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func (border *borderProperty) ViewBorders(session Session) ViewBorders {
|
|
|
|
defStyle, _ := valueToEnum(border.getRaw(Style), BorderStyle, session, NoneLine)
|
|
defWidth, _ := sizeProperty(border, Width, session)
|
|
defColor, _ := colorProperty(border, ColorTag, session)
|
|
|
|
getBorder := func(prefix PropertyName) ViewBorder {
|
|
var result ViewBorder
|
|
var ok bool
|
|
if result.Style, ok = valueToEnum(border.getRaw(prefix+Style), BorderStyle, session, NoneLine); !ok {
|
|
result.Style = defStyle
|
|
}
|
|
if result.Width, ok = sizeProperty(border, prefix+Width, session); !ok {
|
|
result.Width = defWidth
|
|
}
|
|
if result.Color, ok = colorProperty(border, prefix+ColorTag, session); !ok {
|
|
result.Color = defColor
|
|
}
|
|
return result
|
|
}
|
|
|
|
return ViewBorders{
|
|
Top: getBorder("top-"),
|
|
Left: getBorder("left-"),
|
|
Right: getBorder("right-"),
|
|
Bottom: getBorder("bottom-"),
|
|
}
|
|
}
|
|
|
|
func (border *borderProperty) cssStyle(builder cssBuilder, session Session) {
|
|
borders := border.ViewBorders(session)
|
|
values := enumProperties[BorderStyle].cssValues
|
|
if borders.Top.Style == borders.Right.Style &&
|
|
borders.Top.Style == borders.Left.Style &&
|
|
borders.Top.Style == borders.Bottom.Style {
|
|
builder.add(string(BorderStyle), values[borders.Top.Style])
|
|
} else {
|
|
builder.addValues(string(BorderStyle), " ", values[borders.Top.Style],
|
|
values[borders.Right.Style], values[borders.Bottom.Style], values[borders.Left.Style])
|
|
}
|
|
}
|
|
|
|
func (border *borderProperty) cssWidth(builder cssBuilder, session Session) {
|
|
borders := border.ViewBorders(session)
|
|
if borders.Top.Width == borders.Right.Width &&
|
|
borders.Top.Width == borders.Left.Width &&
|
|
borders.Top.Width == borders.Bottom.Width {
|
|
if borders.Top.Width.Type != Auto {
|
|
builder.add("border-width", borders.Top.Width.cssString("0", session))
|
|
}
|
|
} else {
|
|
builder.addValues("border-width", " ",
|
|
borders.Top.Width.cssString("0", session),
|
|
borders.Right.Width.cssString("0", session),
|
|
borders.Bottom.Width.cssString("0", session),
|
|
borders.Left.Width.cssString("0", session))
|
|
}
|
|
}
|
|
|
|
func (border *borderProperty) cssColor(builder cssBuilder, session Session) {
|
|
borders := border.ViewBorders(session)
|
|
if borders.Top.Color == borders.Right.Color &&
|
|
borders.Top.Color == borders.Left.Color &&
|
|
borders.Top.Color == borders.Bottom.Color {
|
|
if borders.Top.Color != 0 {
|
|
builder.add("border-color", borders.Top.Color.cssString())
|
|
}
|
|
} else {
|
|
builder.addValues("border-color", " ", borders.Top.Color.cssString(),
|
|
borders.Right.Color.cssString(), borders.Bottom.Color.cssString(), borders.Left.Color.cssString())
|
|
}
|
|
}
|
|
|
|
func (border *borderProperty) cssStyleValue(session Session) string {
|
|
var builder cssValueBuilder
|
|
border.cssStyle(&builder, session)
|
|
return builder.finish()
|
|
}
|
|
|
|
func (border *borderProperty) cssWidthValue(session Session) string {
|
|
var builder cssValueBuilder
|
|
border.cssWidth(&builder, session)
|
|
return builder.finish()
|
|
}
|
|
|
|
func (border *borderProperty) cssColorValue(session Session) string {
|
|
var builder cssValueBuilder
|
|
border.cssColor(&builder, session)
|
|
return builder.finish()
|
|
}
|
|
|
|
// ViewBorder describes parameters of a view border
|
|
type ViewBorder struct {
|
|
// Style of the border line
|
|
Style int
|
|
|
|
// Color of the border line
|
|
Color Color
|
|
|
|
// Width of the border line
|
|
Width SizeUnit
|
|
}
|
|
|
|
// ViewBorders describes the top, right, bottom, and left border of a view
|
|
type ViewBorders struct {
|
|
Top, Right, Bottom, Left ViewBorder
|
|
}
|
|
|
|
// AllTheSame returns true if all borders are the same
|
|
func (border *ViewBorders) AllTheSame() bool {
|
|
return border.Top.Style == border.Right.Style &&
|
|
border.Top.Style == border.Left.Style &&
|
|
border.Top.Style == border.Bottom.Style &&
|
|
border.Top.Color == border.Right.Color &&
|
|
border.Top.Color == border.Left.Color &&
|
|
border.Top.Color == border.Bottom.Color &&
|
|
border.Top.Width.Equal(border.Right.Width) &&
|
|
border.Top.Width.Equal(border.Left.Width) &&
|
|
border.Top.Width.Equal(border.Bottom.Width)
|
|
}
|
|
|
|
func getBorderProperty(properties Properties, tag PropertyName) BorderProperty {
|
|
if value := properties.getRaw(tag); value != nil {
|
|
if border, ok := value.(BorderProperty); ok {
|
|
return border
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func setBorderPropertyElement(properties Properties, mainTag, tag PropertyName, value any) []PropertyName {
|
|
border := getBorderProperty(properties, mainTag)
|
|
if border == nil {
|
|
border = NewBorder(nil)
|
|
if border.Set(tag, value) {
|
|
properties.setRaw(mainTag, border)
|
|
return []PropertyName{mainTag, tag}
|
|
}
|
|
} else if border.Set(tag, value) {
|
|
return []PropertyName{mainTag, tag}
|
|
}
|
|
return nil
|
|
}
|