2021-09-07 17:36:50 +03:00
package rui
import (
"fmt"
"strings"
)
2024-09-12 14:05:11 +03:00
// Constants for [RadiusProperty] specific properties
2021-09-07 17:36:50 +03:00
const (
2024-09-18 13:50:06 +03:00
// Radius is the constant for "radius" property tag.
//
// Used by `View`, `BackgroundElement`, `ClipShape`.
//
// Usage in `View`:
// Specifies the corners rounding radius of an element's outer border edge.
//
// Supported types: `RadiusProperty`, `SizeUnit`, `SizeFunc`, `BoxRadius`, `string`, `float`, `int`.
//
// Internal type is either `RadiusProperty` or `SizeUnit`, other types converted to them during assignment.
// See `RadiusProperty`, `SizeUnit`, `SizeFunc` and `BoxRadius` description for more details.
//
// Conversion rules:
// `RadiusProperty` - stored as is, no conversion performed.
// `SizeUnit` - stored as is and set all corners to have the same value.
// `BoxRadius` - a new `RadiusProperty` will be created and all corresponding elliptical radius values will be set.
// `string` - if one value will be provided then it will be set as a radius for all corners. If two values will be provided divided by (`/`) then x and y radius will be set for all corners. Examples: "1em", "1em/0.5em", "2/4". Values which doesn't have size prefix will use size in pixels by default.
// `float` - values of this type will set radius for all corners in pixels.
// `int` - values of this type will set radius for all corners in pixels.
//
// Usage in `BackgroundElement`:
// Same as "radial-gradient-radius".
//
// Usage in `ClipShape`:
// Specifies the radius of the corners or the radius of the cropping area.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
Radius PropertyName = "radius"
2024-09-18 13:50:06 +03:00
// RadiusX is the constant for "radius-x" property tag.
//
// Used by `View`, `ClipShape`.
//
// Usage in `View`:
// Specifies the x-axis corners elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
//
// Usage in `ClipShape`:
// Specifies the x-axis corners elliptic rounding radius of the elliptic clip shape.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusX PropertyName = "radius-x"
2024-09-18 13:50:06 +03:00
// RadiusY is the constant for "radius-y" property tag.
//
// Used by `View`, `ClipShape`.
//
// Usage in `View`:
// Specifies the y-axis corners elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
//
// Usage in `ClipShape`:
// Specifies the y-axis corners elliptic rounding radius of of the elliptic clip shape.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusY PropertyName = "radius-y"
2024-09-18 13:50:06 +03:00
// RadiusTopLeft is the constant for "radius-top-left" property tag.
//
// Used by `View`.
// Specifies the top-left corner rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusTopLeft PropertyName = "radius-top-left"
2024-09-18 13:50:06 +03:00
// RadiusTopLeftX is the constant for "radius-top-left-x" property tag.
//
// Used by `View`.
// Specifies the x-axis top-left corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusTopLeftX PropertyName = "radius-top-left-x"
2024-09-18 13:50:06 +03:00
// RadiusTopLeftY is the constant for "radius-top-left-y" property tag.
//
// Used by `View`.
// Specifies the y-axis top-left corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusTopLeftY PropertyName = "radius-top-left-y"
2024-09-18 13:50:06 +03:00
// RadiusTopRight is the constant for "radius-top-right" property tag.
//
// Used by `View`.
// Specifies the top-right corner rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusTopRight PropertyName = "radius-top-right"
2024-09-18 13:50:06 +03:00
// RadiusTopRightX is the constant for "radius-top-right-x" property tag.
//
// Used by `View`.
// Specifies the x-axis top-right corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusTopRightX PropertyName = "radius-top-right-x"
2024-09-18 13:50:06 +03:00
// RadiusTopRightY is the constant for "radius-top-right-y" property tag.
//
// Used by `View`.
// Specifies the y-axis top-right corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusTopRightY PropertyName = "radius-top-right-y"
2024-09-18 13:50:06 +03:00
// RadiusBottomLeft is the constant for "radius-bottom-left" property tag.
//
// Used by `View`.
// Specifies the bottom-left corner rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusBottomLeft PropertyName = "radius-bottom-left"
2024-09-18 13:50:06 +03:00
// RadiusBottomLeftX is the constant for "radius-bottom-left-x" property tag.
//
// Used by `View`.
// Specifies the x-axis bottom-left corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusBottomLeftX PropertyName = "radius-bottom-left-x"
2024-09-18 13:50:06 +03:00
// RadiusBottomLeftY is the constant for "radius-bottom-left-y" property tag.
//
// Used by `View`.
// Specifies the y-axis bottom-left corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusBottomLeftY PropertyName = "radius-bottom-left-y"
2024-09-18 13:50:06 +03:00
// RadiusBottomRight is the constant for "radius-bottom-right" property tag.
//
// Used by `View`.
// Specifies the bottom-right corner rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusBottomRight PropertyName = "radius-bottom-right"
2024-09-18 13:50:06 +03:00
// RadiusBottomRightX is the constant for "radius-bottom-right-x" property tag.
//
// Used by `View`.
// Specifies the x-axis bottom-right corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusBottomRightX PropertyName = "radius-bottom-right-x"
2024-09-18 13:50:06 +03:00
// RadiusBottomRightY is the constant for "radius-bottom-right-y" property tag.
//
// Used by `View`.
// Specifies the y-axis bottom-right corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
RadiusBottomRightY PropertyName = "radius-bottom-right-y"
2024-09-18 13:50:06 +03:00
// X is the constant for "x" property tag.
//
// Used by `ClipShape`, `RadiusProperty`.
//
// Usage in `ClipShape`:
// Specifies x-axis position of the clip shape.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
//
// Usage in `RadiusProperty`:
// Determines the x-axis top-right corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
X PropertyName = "x"
2024-09-18 13:50:06 +03:00
// Y is the constant for "y" property tag.
//
// Used by `ClipShape`, `RadiusProperty`.
//
// Usage in `ClipShape`:
// Specifies y-axis position of the clip shape.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
//
// Usage in `RadiusProperty`:
// Determines the y-axis top-right corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
Y PropertyName = "y"
2024-09-18 13:50:06 +03:00
// TopLeft is the constant for "top-left" property tag.
//
// Used by `RadiusProperty`.
// Determines the top-left corner rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
TopLeft PropertyName = "top-left"
2024-09-18 13:50:06 +03:00
// TopLeftX is the constant for "top-left-x" property tag.
//
// Used by `RadiusProperty`.
// Determines the x-axis top-left corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
TopLeftX PropertyName = "top-left-x"
2024-09-18 13:50:06 +03:00
// TopLeftY is the constant for "top-left-y" property tag.
//
// Used by `RadiusProperty`.
// Determines the y-axis top-left corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
TopLeftY PropertyName = "top-left-y"
2024-09-18 13:50:06 +03:00
// TopRight is the constant for "top-right" property tag.
//
// Used by `RadiusProperty`.
// Determines the top-right corner rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
TopRight PropertyName = "top-right"
2024-09-18 13:50:06 +03:00
// TopRightX is the constant for "top-right-x" property tag.
//
// Used by `RadiusProperty`.
// Determines the x-axis top-right corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
TopRightX PropertyName = "top-right-x"
2024-09-18 13:50:06 +03:00
// TopRightY is the constant for "top-right-y" property tag.
//
// Used by `RadiusProperty`.
// Determines the y-axis top-right corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
TopRightY PropertyName = "top-right-y"
2024-09-18 13:50:06 +03:00
// BottomLeft is the constant for "bottom-left" property tag.
//
// Used by `RadiusProperty`.
// Determines the bottom-left corner rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
BottomLeft PropertyName = "bottom-left"
2024-09-18 13:50:06 +03:00
// BottomLeftX is the constant for "bottom-left-x" property tag.
//
// Used by `RadiusProperty`.
// Determines the x-axis bottom-left corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
BottomLeftX PropertyName = "bottom-left-x"
2024-09-18 13:50:06 +03:00
// BottomLeftY is the constant for "bottom-left-y" property tag.
//
// Used by `RadiusProperty`.
// Determines the y-axis bottom-left corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
BottomLeftY PropertyName = "bottom-left-y"
2024-09-18 13:50:06 +03:00
// BottomRight is the constant for "bottom-right" property tag.
//
// Used by `RadiusProperty`.
// Determines the bottom-right corner rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
BottomRight PropertyName = "bottom-right"
2024-09-18 13:50:06 +03:00
// BottomRightX is the constant for "bottom-right-x" property tag.
//
// Used by `RadiusProperty`.
// Determines the x-axis bottom-right corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
BottomRightX PropertyName = "bottom-right-x"
2024-09-18 13:50:06 +03:00
// BottomRightY is the constant for "bottom-right-y" property tag.
//
// Used by `RadiusProperty`.
// Determines the y-axis bottom-right corner elliptic rounding radius of an element's outer border edge.
//
// Supported types: `SizeUnit`, `SizeFunc`, `string`, `float`, `int`.
//
// Internal type is `SizeUnit`, other types converted to it during assignment.
// See `SizeUnit` description for more details.
2024-11-13 12:56:39 +03:00
BottomRightY PropertyName = "bottom-right-y"
2021-09-07 17:36:50 +03:00
)
2024-09-12 14:05:11 +03:00
// RadiusProperty is a description of the [View] (shape) elliptical corner radius.
2021-09-07 17:36:50 +03:00
type RadiusProperty interface {
Properties
2022-05-22 12:54:02 +03:00
stringWriter
2021-09-07 17:36:50 +03:00
fmt . Stringer
2024-09-12 14:05:11 +03:00
// BoxRadius returns x and y radius of the corners of the element
2021-09-07 17:36:50 +03:00
BoxRadius ( session Session ) BoxRadius
}
type radiusPropertyData struct {
2024-11-13 12:56:39 +03:00
dataProperty
2021-09-07 17:36:50 +03:00
}
// NewRadiusProperty creates the new RadiusProperty
func NewRadiusProperty ( params Params ) RadiusProperty {
result := new ( radiusPropertyData )
2024-11-13 12:56:39 +03:00
result . dataProperty . init ( )
result . normalize = radiusPropertyNormalize
result . get = radiusPropertyGet
result . remove = radiusPropertyRemove
result . set = radiusPropertySet
result . supportedProperties = [ ] PropertyName {
X , Y , TopLeft , TopRight , BottomLeft , BottomRight , TopLeftX , TopLeftY ,
TopRightX , TopRightY , BottomLeftX , BottomLeftY , BottomRightX , BottomRightY ,
}
2021-09-07 17:36:50 +03:00
if params != nil {
2024-11-13 12:56:39 +03:00
for _ , tag := range result . supportedProperties {
2021-09-07 17:36:50 +03:00
if value , ok := params [ tag ] ; ok {
2024-11-13 12:56:39 +03:00
radiusPropertySet ( result , tag , value )
2021-09-07 17:36:50 +03:00
}
}
}
return result
}
2024-11-13 12:56:39 +03:00
func radiusPropertyNormalize ( tag PropertyName ) PropertyName {
name := strings . TrimPrefix ( strings . ToLower ( string ( tag ) ) , "radius-" )
return PropertyName ( name )
2021-09-07 17:36:50 +03:00
}
2022-05-22 12:54:02 +03:00
func ( radius * radiusPropertyData ) writeString ( buffer * strings . Builder , indent string ) {
buffer . WriteString ( "_{ " )
comma := false
2024-11-13 12:56:39 +03:00
for _ , tag := range radius . supportedProperties {
2021-09-07 17:36:50 +03:00
if value , ok := radius . properties [ tag ] ; ok {
2022-05-22 12:54:02 +03:00
if comma {
buffer . WriteString ( ", " )
}
2024-11-13 12:56:39 +03:00
buffer . WriteString ( string ( tag ) )
2022-05-22 12:54:02 +03:00
buffer . WriteString ( " = " )
writePropertyValue ( buffer , tag , value , indent )
comma = true
2021-09-07 17:36:50 +03:00
}
}
2022-05-22 12:54:02 +03:00
buffer . WriteString ( " }" )
2021-09-07 17:36:50 +03:00
}
func ( radius * radiusPropertyData ) String ( ) string {
2022-05-22 12:54:02 +03:00
return runStringWriter ( radius )
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
func radiusPropertyRemove ( properties Properties , tag PropertyName ) [ ] PropertyName {
result := [ ] PropertyName { }
removeTag := func ( tag PropertyName ) {
if properties . getRaw ( tag ) != nil {
properties . setRaw ( tag , nil )
result = append ( result , tag )
}
}
switch tag {
case X , Y :
if properties . getRaw ( tag ) == nil {
for _ , prefix := range [ ] PropertyName { TopLeft , TopRight , BottomLeft , BottomRight } {
removeTag ( prefix + "-" + tag )
}
} else {
removeTag ( tag )
}
case TopLeftX , TopLeftY , TopRightX , TopRightY , BottomLeftX , BottomLeftY , BottomRightX , BottomRightY :
removeTag ( tag )
case TopLeft , TopRight , BottomLeft , BottomRight :
for _ , tag := range [ ] PropertyName { tag , tag + "-x" , tag + "-y" } {
removeTag ( tag )
}
default :
ErrorLogF ( ` "%s" property is not compatible with the RadiusProperty ` , tag )
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
return result
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
func deleteRadiusUnusedTags ( radius Properties , result [ ] PropertyName ) {
for _ , tag := range [ ] PropertyName { X , Y } {
if radius . getRaw ( tag ) != nil {
2021-09-07 17:36:50 +03:00
unused := true
2024-11-13 12:56:39 +03:00
for _ , t := range [ ] PropertyName { TopLeft , TopRight , BottomLeft , BottomRight } {
if radius . getRaw ( t + "-" + tag ) == nil && radius . getRaw ( t ) == nil {
unused = false
break
2021-09-07 17:36:50 +03:00
}
}
if unused {
2024-11-13 12:56:39 +03:00
radius . setRaw ( tag , nil )
result = append ( result , tag )
2021-09-07 17:36:50 +03:00
}
}
}
2022-07-26 18:36:00 +03:00
equalValue := func ( value1 , value2 any ) bool {
2021-09-07 17:36:50 +03:00
switch value1 := value1 . ( type ) {
case string :
switch value2 := value2 . ( type ) {
case string :
return value1 == value2
}
case SizeUnit :
switch value2 := value2 . ( type ) {
case SizeUnit :
return value1 . Equal ( value2 )
}
}
return false
}
2024-11-13 12:56:39 +03:00
for _ , tag := range [ ] PropertyName { TopLeft , TopRight , BottomLeft , BottomRight } {
2021-09-07 17:36:50 +03:00
tagX := tag + "-x"
tagY := tag + "-y"
2024-11-13 12:56:39 +03:00
valueX := radius . getRaw ( tagX )
valueY := radius . getRaw ( tagY )
if value := radius . getRaw ( tag ) ; value != nil {
if valueX != nil && valueY != nil {
radius . setRaw ( tag , nil )
result = append ( result , tag )
} else if valueX != nil && valueY == nil {
2021-09-07 17:36:50 +03:00
if equalValue ( value , valueX ) {
2024-11-13 12:56:39 +03:00
radius . setRaw ( tagX , nil )
result = append ( result , tagX )
2021-09-07 17:36:50 +03:00
} else {
2024-11-13 12:56:39 +03:00
radius . setRaw ( tagY , value )
result = append ( result , tagY )
radius . setRaw ( tag , nil )
result = append ( result , tag )
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
} else if valueX == nil && valueY != nil {
2021-09-07 17:36:50 +03:00
if equalValue ( value , valueY ) {
2024-11-13 12:56:39 +03:00
radius . setRaw ( tagY , nil )
result = append ( result , tagY )
2021-09-07 17:36:50 +03:00
} else {
2024-11-13 12:56:39 +03:00
radius . setRaw ( tagX , value )
result = append ( result , tagX )
radius . setRaw ( tag , nil )
result = append ( result , tag )
2021-09-07 17:36:50 +03:00
}
}
2024-11-13 12:56:39 +03:00
} else if valueX != nil && valueY != nil && equalValue ( valueX , valueY ) {
radius . setRaw ( tag , valueX )
result = append ( result , tag )
radius . setRaw ( tagX , nil )
result = append ( result , tagX )
radius . setRaw ( tagY , nil )
result = append ( result , tagY )
2021-09-07 17:36:50 +03:00
}
}
}
2024-11-13 12:56:39 +03:00
func radiusPropertySet ( radius Properties , tag PropertyName , value any ) [ ] PropertyName {
var result [ ] PropertyName = nil
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
deleteTags := func ( tags [ ] PropertyName ) {
for _ , tag := range tags {
if radius . getRaw ( tag ) != nil {
radius . setRaw ( tag , nil )
result = append ( result , tag )
}
2021-09-07 17:36:50 +03:00
}
}
switch tag {
case X :
2024-11-13 12:56:39 +03:00
if result = setSizeProperty ( radius , tag , value ) ; result != nil {
deleteTags ( [ ] PropertyName { TopLeftX , TopRightX , BottomLeftX , BottomRightX } )
for _ , t := range [ ] PropertyName { TopLeft , TopRight , BottomLeft , BottomRight } {
if val := radius . getRaw ( t ) ; val != nil {
t2 := t + "-y"
if radius . getRaw ( t2 ) != nil {
radius . setRaw ( t2 , val )
result = append ( result , t2 )
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
radius . setRaw ( t , nil )
result = append ( result , t )
2021-09-07 17:36:50 +03:00
}
}
}
case Y :
2024-11-13 12:56:39 +03:00
if result = setSizeProperty ( radius , tag , value ) ; result != nil {
deleteTags ( [ ] PropertyName { TopLeftY , TopRightY , BottomLeftY , BottomRightY } )
for _ , t := range [ ] PropertyName { TopLeft , TopRight , BottomLeft , BottomRight } {
if val := radius . getRaw ( t ) ; val != nil {
t2 := t + "-x"
if radius . getRaw ( t2 ) != nil {
radius . setRaw ( t2 , val )
result = append ( result , t2 )
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
radius . setRaw ( t , nil )
result = append ( result , t )
2021-09-07 17:36:50 +03:00
}
}
}
case TopLeftX , TopLeftY , TopRightX , TopRightY , BottomLeftX , BottomLeftY , BottomRightX , BottomRightY :
2024-11-13 12:56:39 +03:00
if result = setSizeProperty ( radius , tag , value ) ; result != nil {
deleteRadiusUnusedTags ( radius , result )
2021-09-07 17:36:50 +03:00
}
case TopLeft , TopRight , BottomLeft , BottomRight :
switch value := value . ( type ) {
case SizeUnit :
2024-11-13 12:56:39 +03:00
radius . setRaw ( tag , value )
result = [ ] PropertyName { tag }
deleteTags ( [ ] PropertyName { tag + "-x" , tag + "-y" } )
deleteRadiusUnusedTags ( radius , result )
2021-09-07 17:36:50 +03:00
case string :
if strings . Contains ( value , "/" ) {
if values := strings . Split ( value , "/" ) ; len ( values ) == 2 {
2024-11-13 12:56:39 +03:00
if result = radiusPropertySet ( radius , tag + "-x" , value [ 0 ] ) ; result != nil {
if resultY := radiusPropertySet ( radius , tag + "-y" , value [ 1 ] ) ; resultY != nil {
result = append ( result , resultY ... )
}
}
2021-09-07 17:36:50 +03:00
} else {
notCompatibleType ( tag , value )
}
} else {
2024-11-13 12:56:39 +03:00
if result = setSizeProperty ( radius , tag , value ) ; result != nil {
deleteTags ( [ ] PropertyName { tag + "-x" , tag + "-y" } )
deleteRadiusUnusedTags ( radius , result )
2021-09-07 17:36:50 +03:00
}
}
}
default :
ErrorLogF ( ` "%s" property is not compatible with the RadiusProperty ` , tag )
}
2024-11-13 12:56:39 +03:00
return result
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
func radiusPropertyGet ( properties Properties , tag PropertyName ) any {
if value := properties . getRaw ( tag ) ; value != nil {
2021-09-07 17:36:50 +03:00
return value
}
switch tag {
case TopLeftX , TopLeftY , TopRightX , TopRightY , BottomLeftX , BottomLeftY , BottomRightX , BottomRightY :
tagLen := len ( tag )
2024-11-13 12:56:39 +03:00
if value := properties . getRaw ( tag [ : tagLen - 2 ] ) ; value != nil {
2021-09-07 17:36:50 +03:00
return value
}
2024-11-13 12:56:39 +03:00
if value := properties . getRaw ( tag [ tagLen - 1 : ] ) ; value != nil {
2021-09-07 17:36:50 +03:00
return value
}
}
2022-05-06 18:19:13 +03:00
switch tag {
case TopLeftX , TopRightX , BottomLeftX , BottomRightX :
2024-11-13 12:56:39 +03:00
if value := properties . getRaw ( X ) ; value != nil {
2022-05-06 18:19:13 +03:00
return value
}
case TopLeftY , TopRightY , BottomLeftY , BottomRightY :
2024-11-13 12:56:39 +03:00
if value := properties . getRaw ( Y ) ; value != nil {
2022-05-06 18:19:13 +03:00
return value
}
}
2021-09-07 17:36:50 +03:00
return nil
}
func ( radius * radiusPropertyData ) BoxRadius ( session Session ) BoxRadius {
x , _ := sizeProperty ( radius , X , session )
y , _ := sizeProperty ( radius , Y , session )
2024-11-13 12:56:39 +03:00
getRadius := func ( tag PropertyName ) ( SizeUnit , SizeUnit ) {
2021-09-07 17:36:50 +03:00
rx := x
ry := y
if r , ok := sizeProperty ( radius , tag , session ) ; ok {
rx = r
ry = r
}
if r , ok := sizeProperty ( radius , tag + "-x" , session ) ; ok {
rx = r
}
if r , ok := sizeProperty ( radius , tag + "-y" , session ) ; ok {
ry = r
}
return rx , ry
}
var result BoxRadius
result . TopLeftX , result . TopLeftY = getRadius ( TopLeft )
result . TopRightX , result . TopRightY = getRadius ( TopRight )
result . BottomLeftX , result . BottomLeftY = getRadius ( BottomLeft )
result . BottomRightX , result . BottomRightY = getRadius ( BottomRight )
return result
}
// BoxRadius defines radii of rounds the corners of an element's outer border edge
type BoxRadius struct {
TopLeftX , TopLeftY , TopRightX , TopRightY , BottomLeftX , BottomLeftY , BottomRightX , BottomRightY SizeUnit
}
// AllAnglesIsEqual returns 'true' if all angles is equal, 'false' otherwise
func ( radius BoxRadius ) AllAnglesIsEqual ( ) bool {
return radius . TopLeftX . Equal ( radius . TopRightX ) &&
radius . TopLeftY . Equal ( radius . TopRightY ) &&
radius . TopLeftX . Equal ( radius . BottomLeftX ) &&
radius . TopLeftY . Equal ( radius . BottomLeftY ) &&
radius . TopLeftX . Equal ( radius . BottomRightX ) &&
radius . TopLeftY . Equal ( radius . BottomRightY )
}
// String returns a string representation of a BoxRadius struct
func ( radius BoxRadius ) String ( ) string {
if radius . AllAnglesIsEqual ( ) {
if radius . TopLeftX . Equal ( radius . TopLeftY ) {
return radius . TopLeftX . String ( )
} else {
return fmt . Sprintf ( "_{ x = %s, y = %s }" , radius . TopLeftX . String ( ) , radius . TopLeftY . String ( ) )
}
}
buffer := allocStringBuilder ( )
defer freeStringBuilder ( buffer )
buffer . WriteString ( "_{ " )
if radius . TopLeftX . Equal ( radius . TopLeftY ) {
buffer . WriteString ( "top-left = " )
buffer . WriteString ( radius . TopLeftX . String ( ) )
} else {
buffer . WriteString ( "top-left-x = " )
buffer . WriteString ( radius . TopLeftX . String ( ) )
buffer . WriteString ( "top-left-y = " )
buffer . WriteString ( radius . TopLeftY . String ( ) )
}
if radius . TopRightX . Equal ( radius . TopRightY ) {
buffer . WriteString ( ", top-right = " )
buffer . WriteString ( radius . TopRightX . String ( ) )
} else {
buffer . WriteString ( ", top-right-x = " )
buffer . WriteString ( radius . TopRightX . String ( ) )
buffer . WriteString ( ", top-right-y = " )
buffer . WriteString ( radius . TopRightY . String ( ) )
}
if radius . BottomLeftX . Equal ( radius . BottomLeftY ) {
buffer . WriteString ( ", bottom-left = " )
buffer . WriteString ( radius . BottomLeftX . String ( ) )
} else {
buffer . WriteString ( ", bottom-left-x = " )
buffer . WriteString ( radius . BottomLeftX . String ( ) )
buffer . WriteString ( ", bottom-left-y = " )
buffer . WriteString ( radius . BottomLeftY . String ( ) )
}
if radius . BottomRightX . Equal ( radius . BottomRightY ) {
buffer . WriteString ( ", bottom-right = " )
buffer . WriteString ( radius . BottomRightX . String ( ) )
} else {
buffer . WriteString ( ", bottom-right-x = " )
buffer . WriteString ( radius . BottomRightX . String ( ) )
buffer . WriteString ( ", bottom-right-y = " )
buffer . WriteString ( radius . BottomRightY . String ( ) )
}
buffer . WriteString ( " }" )
return buffer . String ( )
}
2022-09-05 14:00:07 +03:00
func ( radius BoxRadius ) cssValue ( builder cssBuilder , session Session ) {
2021-09-07 17:36:50 +03:00
if ( radius . TopLeftX . Type == Auto || radius . TopLeftX . Value == 0 ) &&
( radius . TopLeftY . Type == Auto || radius . TopLeftY . Value == 0 ) &&
( radius . TopRightX . Type == Auto || radius . TopRightX . Value == 0 ) &&
( radius . TopRightY . Type == Auto || radius . TopRightY . Value == 0 ) &&
( radius . BottomRightX . Type == Auto || radius . BottomRightX . Value == 0 ) &&
( radius . BottomRightY . Type == Auto || radius . BottomRightY . Value == 0 ) &&
( radius . BottomLeftX . Type == Auto || radius . BottomLeftX . Value == 0 ) &&
( radius . BottomLeftY . Type == Auto || radius . BottomLeftY . Value == 0 ) {
return
}
buffer := allocStringBuilder ( )
defer freeStringBuilder ( buffer )
2022-09-05 14:00:07 +03:00
buffer . WriteString ( radius . TopLeftX . cssString ( "0" , session ) )
2021-09-07 17:36:50 +03:00
if radius . AllAnglesIsEqual ( ) {
if ! radius . TopLeftX . Equal ( radius . TopLeftY ) {
buffer . WriteString ( " / " )
2022-09-05 14:00:07 +03:00
buffer . WriteString ( radius . TopLeftY . cssString ( "0" , session ) )
2021-09-07 17:36:50 +03:00
}
} else {
buffer . WriteRune ( ' ' )
2022-09-05 14:00:07 +03:00
buffer . WriteString ( radius . TopRightX . cssString ( "0" , session ) )
2021-09-07 17:36:50 +03:00
buffer . WriteRune ( ' ' )
2022-09-05 14:00:07 +03:00
buffer . WriteString ( radius . BottomRightX . cssString ( "0" , session ) )
2021-09-07 17:36:50 +03:00
buffer . WriteRune ( ' ' )
2022-09-05 14:00:07 +03:00
buffer . WriteString ( radius . BottomLeftX . cssString ( "0" , session ) )
2021-09-07 17:36:50 +03:00
if ! radius . TopLeftX . Equal ( radius . TopLeftY ) ||
! radius . TopRightX . Equal ( radius . TopRightY ) ||
! radius . BottomLeftX . Equal ( radius . BottomLeftY ) ||
! radius . BottomRightX . Equal ( radius . BottomRightY ) {
buffer . WriteString ( " / " )
2022-09-05 14:00:07 +03:00
buffer . WriteString ( radius . TopLeftY . cssString ( "0" , session ) )
2021-09-07 17:36:50 +03:00
buffer . WriteRune ( ' ' )
2022-09-05 14:00:07 +03:00
buffer . WriteString ( radius . TopRightY . cssString ( "0" , session ) )
2021-09-07 17:36:50 +03:00
buffer . WriteRune ( ' ' )
2022-09-05 14:00:07 +03:00
buffer . WriteString ( radius . BottomRightY . cssString ( "0" , session ) )
2021-09-07 17:36:50 +03:00
buffer . WriteRune ( ' ' )
2022-09-05 14:00:07 +03:00
buffer . WriteString ( radius . BottomLeftY . cssString ( "0" , session ) )
2021-09-07 17:36:50 +03:00
}
}
builder . add ( "border-radius" , buffer . String ( ) )
}
2022-09-05 14:00:07 +03:00
func ( radius BoxRadius ) cssString ( session Session ) string {
2021-09-07 17:36:50 +03:00
var builder cssValueBuilder
2022-09-05 14:00:07 +03:00
radius . cssValue ( & builder , session )
2021-09-07 17:36:50 +03:00
return builder . finish ( )
}
func getRadiusProperty ( style Properties ) RadiusProperty {
if value := style . Get ( Radius ) ; value != nil {
switch value := value . ( type ) {
case RadiusProperty :
return value
case BoxRadius :
result := NewRadiusProperty ( nil )
if value . AllAnglesIsEqual ( ) {
result . Set ( X , value . TopLeftX )
result . Set ( Y , value . TopLeftY )
} else {
if value . TopLeftX . Equal ( value . TopLeftY ) {
result . Set ( TopLeft , value . TopLeftX )
} else {
result . Set ( TopLeftX , value . TopLeftX )
result . Set ( TopLeftY , value . TopLeftY )
}
if value . TopRightX . Equal ( value . TopRightY ) {
result . Set ( TopRight , value . TopRightX )
} else {
result . Set ( TopRightX , value . TopRightX )
result . Set ( TopRightY , value . TopRightY )
}
if value . BottomLeftX . Equal ( value . BottomLeftY ) {
result . Set ( BottomLeft , value . BottomLeftX )
} else {
result . Set ( BottomLeftX , value . BottomLeftX )
result . Set ( BottomLeftY , value . BottomLeftY )
}
if value . BottomRightX . Equal ( value . BottomRightY ) {
result . Set ( BottomRight , value . BottomRightX )
} else {
result . Set ( BottomRightX , value . BottomRightX )
result . Set ( BottomRightY , value . BottomRightY )
}
}
return result
case SizeUnit :
return NewRadiusProperty ( Params {
X : value ,
Y : value ,
} )
case string :
return NewRadiusProperty ( Params {
X : value ,
Y : value ,
} )
}
}
return NewRadiusProperty ( nil )
}
2024-11-13 12:56:39 +03:00
func setRadiusProperty ( properties Properties , value any ) [ ] PropertyName {
2021-09-07 17:36:50 +03:00
if value == nil {
2024-11-13 12:56:39 +03:00
return propertiesRemove ( properties , Radius )
2021-09-07 17:36:50 +03:00
}
switch value := value . ( type ) {
case RadiusProperty :
2024-11-13 12:56:39 +03:00
properties . setRaw ( Radius , value )
2021-09-07 17:36:50 +03:00
case SizeUnit :
2024-11-13 12:56:39 +03:00
properties . setRaw ( Radius , value )
2021-09-07 17:36:50 +03:00
case BoxRadius :
radius := NewRadiusProperty ( nil )
if value . AllAnglesIsEqual ( ) {
radius . Set ( X , value . TopLeftX )
radius . Set ( Y , value . TopLeftY )
} else {
if value . TopLeftX . Equal ( value . TopLeftY ) {
radius . Set ( TopLeft , value . TopLeftX )
} else {
radius . Set ( TopLeftX , value . TopLeftX )
radius . Set ( TopLeftY , value . TopLeftY )
}
if value . TopRightX . Equal ( value . TopRightY ) {
radius . Set ( TopRight , value . TopRightX )
} else {
radius . Set ( TopRightX , value . TopRightX )
radius . Set ( TopRightY , value . TopRightY )
}
if value . BottomLeftX . Equal ( value . BottomLeftY ) {
radius . Set ( BottomLeft , value . BottomLeftX )
} else {
radius . Set ( BottomLeftX , value . BottomLeftX )
radius . Set ( BottomLeftY , value . BottomLeftY )
}
if value . BottomRightX . Equal ( value . BottomRightY ) {
radius . Set ( BottomRight , value . BottomRightX )
} else {
radius . Set ( BottomRightX , value . BottomRightX )
radius . Set ( BottomRightY , value . BottomRightY )
}
}
2024-11-13 12:56:39 +03:00
properties . setRaw ( Radius , radius )
2021-09-07 17:36:50 +03:00
case string :
if strings . Contains ( value , "/" ) {
values := strings . Split ( value , "/" )
if len ( values ) == 2 {
2024-11-13 12:56:39 +03:00
if setRadiusPropertyElement ( properties , RadiusX , values [ 0 ] ) {
result := [ ] PropertyName { Radius , RadiusX }
if setRadiusPropertyElement ( properties , RadiusY , values [ 1 ] ) {
result = append ( result , RadiusY )
}
return result
}
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
notCompatibleType ( Radius , value )
return nil
2021-09-07 17:36:50 +03:00
} else {
2024-11-13 12:56:39 +03:00
return setSizeProperty ( properties , Radius , value )
2021-09-07 17:36:50 +03:00
}
case DataObject :
radius := NewRadiusProperty ( nil )
2024-11-13 12:56:39 +03:00
for _ , tag := range [ ] PropertyName { X , Y , TopLeft , TopRight , BottomLeft , BottomRight , TopLeftX , TopLeftY ,
2021-09-07 17:36:50 +03:00
TopRightX , TopRightY , BottomLeftX , BottomLeftY , BottomRightX , BottomRightY } {
2024-11-13 12:56:39 +03:00
if value , ok := value . PropertyValue ( string ( tag ) ) ; ok {
2021-09-07 17:36:50 +03:00
radius . Set ( tag , value )
}
}
2024-11-13 12:56:39 +03:00
properties . setRaw ( Radius , radius )
2021-09-07 17:36:50 +03:00
2022-08-16 11:40:42 +03:00
case float32 :
2024-11-13 12:56:39 +03:00
properties . setRaw ( Radius , Px ( float64 ( value ) ) )
2022-08-16 11:40:42 +03:00
case float64 :
2024-11-13 12:56:39 +03:00
properties . setRaw ( Radius , Px ( value ) )
2022-08-16 11:40:42 +03:00
2021-09-07 17:36:50 +03:00
default :
2022-08-16 11:40:42 +03:00
if n , ok := isInt ( value ) ; ok {
2024-11-13 12:56:39 +03:00
properties . setRaw ( Radius , Px ( float64 ( n ) ) )
} else {
notCompatibleType ( Radius , value )
return nil
2022-08-16 11:40:42 +03:00
}
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
return [ ] PropertyName { Radius }
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
func removeRadiusPropertyElement ( properties Properties , tag PropertyName ) bool {
if value := properties . getRaw ( Radius ) ; value != nil {
2021-09-07 17:36:50 +03:00
radius := getRadiusProperty ( properties )
radius . Remove ( tag )
2024-11-13 12:56:39 +03:00
if radius . empty ( ) {
properties . setRaw ( Radius , nil )
2021-09-07 17:36:50 +03:00
} else {
2024-11-13 12:56:39 +03:00
properties . setRaw ( Radius , radius )
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
return true
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
return false
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
func setRadiusPropertyElement ( properties Properties , tag PropertyName , value any ) bool {
2021-09-07 17:36:50 +03:00
if value == nil {
2024-11-13 12:56:39 +03:00
removeRadiusPropertyElement ( properties , tag )
2021-09-07 17:36:50 +03:00
return true
}
radius := getRadiusProperty ( properties )
if radius . Set ( tag , value ) {
2024-11-13 12:56:39 +03:00
properties . setRaw ( Radius , radius )
2021-09-07 17:36:50 +03:00
return true
}
return false
}
2024-11-13 12:56:39 +03:00
func getRadiusElement ( style Properties , tag PropertyName ) any {
2021-09-07 17:36:50 +03:00
value := style . Get ( Radius )
if value != nil {
switch value := value . ( type ) {
case string :
return value
case SizeUnit :
return value
case RadiusProperty :
return value . Get ( tag )
case BoxRadius :
switch tag {
case RadiusX :
if value . TopLeftX . Equal ( value . TopRightX ) &&
value . TopLeftX . Equal ( value . BottomLeftX ) &&
value . TopLeftX . Equal ( value . BottomRightX ) {
return value . TopLeftX
}
case RadiusY :
if value . TopLeftY . Equal ( value . TopRightY ) &&
value . TopLeftY . Equal ( value . BottomLeftY ) &&
value . TopLeftY . Equal ( value . BottomRightY ) {
return value . TopLeftY
}
case RadiusTopLeft :
if value . TopLeftX . Equal ( value . TopLeftY ) {
return value . TopLeftY
}
case RadiusTopRight :
if value . TopRightX . Equal ( value . TopRightY ) {
return value . TopRightY
}
case RadiusBottomLeft :
if value . BottomLeftX . Equal ( value . BottomLeftY ) {
return value . BottomLeftY
}
case RadiusBottomRight :
if value . BottomRightX . Equal ( value . BottomRightY ) {
return value . BottomRightY
}
case RadiusTopLeftX :
return value . TopLeftX
case RadiusTopLeftY :
return value . TopLeftY
case RadiusTopRightX :
return value . TopRightX
case RadiusTopRightY :
return value . TopRightY
case RadiusBottomLeftX :
return value . BottomLeftX
case RadiusBottomLeftY :
return value . BottomLeftY
case RadiusBottomRightX :
return value . BottomRightX
case RadiusBottomRightY :
return value . BottomRightY
}
}
}
return nil
}
func getRadius ( properties Properties , session Session ) BoxRadius {
if value := properties . Get ( Radius ) ; value != nil {
switch value := value . ( type ) {
case BoxRadius :
return value
case RadiusProperty :
return value . BoxRadius ( session )
case SizeUnit :
return BoxRadius { TopLeftX : value , TopLeftY : value , TopRightX : value , TopRightY : value ,
BottomLeftX : value , BottomLeftY : value , BottomRightX : value , BottomRightY : value }
case string :
if text , ok := session . resolveConstants ( value ) ; ok {
if size , ok := StringToSizeUnit ( text ) ; ok {
return BoxRadius { TopLeftX : size , TopLeftY : size , TopRightX : size , TopRightY : size ,
BottomLeftX : size , BottomLeftY : size , BottomRightX : size , BottomRightY : size }
}
}
}
}
return BoxRadius { }
}