mirror of https://github.com/anoshenko/rui.git
Refactoring
This commit is contained in:
parent
bed6c1bf41
commit
f81ffe6bed
192
background.go
192
background.go
|
@ -2,62 +2,9 @@ package rui
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Constants related to view's background description
|
||||
const (
|
||||
// NoRepeat is value of the Repeat property of an background image:
|
||||
// The image is not repeated (and hence the background image painting area
|
||||
// will not necessarily be entirely covered). The position of the non-repeated
|
||||
// background image is defined by the background-position CSS property.
|
||||
NoRepeat = 0
|
||||
|
||||
// RepeatXY is value of the Repeat property of an background image:
|
||||
// The image is repeated as much as needed to cover the whole background
|
||||
// image painting area. The last image will be clipped if it doesn't fit.
|
||||
RepeatXY = 1
|
||||
|
||||
// RepeatX is value of the Repeat property of an background image:
|
||||
// The image is repeated horizontally as much as needed to cover
|
||||
// the whole width background image painting area. The image is not repeated vertically.
|
||||
// The last image will be clipped if it doesn't fit.
|
||||
RepeatX = 2
|
||||
|
||||
// RepeatY is value of the Repeat property of an background image:
|
||||
// The image is repeated vertically as much as needed to cover
|
||||
// the whole height background image painting area. The image is not repeated horizontally.
|
||||
// The last image will be clipped if it doesn't fit.
|
||||
RepeatY = 3
|
||||
|
||||
// RepeatRound is value of the Repeat property of an background image:
|
||||
// As the allowed space increases in size, the repeated images will stretch (leaving no gaps)
|
||||
// until there is room (space left >= half of the image width) for another one to be added.
|
||||
// When the next image is added, all of the current ones compress to allow room.
|
||||
RepeatRound = 4
|
||||
|
||||
// RepeatSpace is value of the Repeat property of an background image:
|
||||
// The image is repeated as much as possible without clipping. The first and last images
|
||||
// are pinned to either side of the element, and whitespace is distributed evenly between the images.
|
||||
RepeatSpace = 5
|
||||
|
||||
// ScrollAttachment is value of the Attachment property of an background image:
|
||||
// The background is fixed relative to the element itself and does not scroll with its contents.
|
||||
// (It is effectively attached to the element's border.)
|
||||
ScrollAttachment = 0
|
||||
|
||||
// FixedAttachment is value of the Attachment property of an background image:
|
||||
// The background is fixed relative to the viewport. Even if an element has
|
||||
// a scrolling mechanism, the background doesn't move with the element.
|
||||
FixedAttachment = 1
|
||||
|
||||
// LocalAttachment is value of the Attachment property of an background image:
|
||||
// The background is fixed relative to the element's contents. If the element has a scrolling mechanism,
|
||||
// the background scrolls with the element's contents, and the background painting area
|
||||
// and background positioning area are relative to the scrollable area of the element
|
||||
// rather than to the border framing them.
|
||||
LocalAttachment = 2
|
||||
|
||||
// BorderBox is the value of the following properties:
|
||||
//
|
||||
// * BackgroundClip - The background extends to the outside edge of the border (but underneath the border in z-ordering).
|
||||
|
@ -111,10 +58,6 @@ type backgroundElement struct {
|
|||
dataProperty
|
||||
}
|
||||
|
||||
type backgroundImage struct {
|
||||
backgroundElement
|
||||
}
|
||||
|
||||
// NewBackgroundImage creates the new background image
|
||||
func createBackground(obj DataObject) BackgroundElement {
|
||||
var result BackgroundElement = nil
|
||||
|
@ -148,141 +91,6 @@ func createBackground(obj DataObject) BackgroundElement {
|
|||
return result
|
||||
}
|
||||
|
||||
// NewBackgroundImage creates the new background image
|
||||
func NewBackgroundImage(params Params) BackgroundElement {
|
||||
result := new(backgroundImage)
|
||||
result.init()
|
||||
for tag, value := range params {
|
||||
result.Set(tag, value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (image *backgroundImage) init() {
|
||||
image.backgroundElement.init()
|
||||
image.normalize = normalizeBackgroundImageTag
|
||||
image.supportedProperties = []PropertyName{
|
||||
Attachment, Width, Height, Repeat, ImageHorizontalAlign, ImageVerticalAlign, backgroundFit, Source,
|
||||
}
|
||||
}
|
||||
|
||||
func (image *backgroundImage) Tag() string {
|
||||
return "image"
|
||||
}
|
||||
|
||||
func (image *backgroundImage) Clone() BackgroundElement {
|
||||
result := NewBackgroundImage(nil)
|
||||
for tag, value := range image.properties {
|
||||
result.setRaw(tag, value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func normalizeBackgroundImageTag(tag PropertyName) PropertyName {
|
||||
tag = defaultNormalize(tag)
|
||||
switch tag {
|
||||
case "source":
|
||||
tag = Source
|
||||
|
||||
case Fit:
|
||||
tag = backgroundFit
|
||||
|
||||
case HorizontalAlign:
|
||||
tag = ImageHorizontalAlign
|
||||
|
||||
case VerticalAlign:
|
||||
tag = ImageVerticalAlign
|
||||
}
|
||||
|
||||
return tag
|
||||
}
|
||||
|
||||
func (image *backgroundImage) cssStyle(session Session) string {
|
||||
if src, ok := imageProperty(image, Source, session); ok && src != "" {
|
||||
buffer := allocStringBuilder()
|
||||
defer freeStringBuilder(buffer)
|
||||
|
||||
buffer.WriteString(`url(`)
|
||||
buffer.WriteString(src)
|
||||
buffer.WriteRune(')')
|
||||
|
||||
attachment, _ := enumProperty(image, Attachment, session, NoRepeat)
|
||||
values := enumProperties[Attachment].values
|
||||
if attachment > 0 && attachment < len(values) {
|
||||
buffer.WriteRune(' ')
|
||||
buffer.WriteString(values[attachment])
|
||||
}
|
||||
|
||||
align, _ := enumProperty(image, ImageHorizontalAlign, session, LeftAlign)
|
||||
values = enumProperties[ImageHorizontalAlign].values
|
||||
if align >= 0 && align < len(values) {
|
||||
buffer.WriteRune(' ')
|
||||
buffer.WriteString(values[align])
|
||||
} else {
|
||||
buffer.WriteString(` left`)
|
||||
}
|
||||
|
||||
align, _ = enumProperty(image, ImageVerticalAlign, session, TopAlign)
|
||||
values = enumProperties[ImageVerticalAlign].values
|
||||
if align >= 0 && align < len(values) {
|
||||
buffer.WriteRune(' ')
|
||||
buffer.WriteString(values[align])
|
||||
} else {
|
||||
buffer.WriteString(` top`)
|
||||
}
|
||||
|
||||
fit, _ := enumProperty(image, backgroundFit, session, NoneFit)
|
||||
values = enumProperties[backgroundFit].values
|
||||
if fit > 0 && fit < len(values) {
|
||||
|
||||
buffer.WriteString(` / `)
|
||||
buffer.WriteString(values[fit])
|
||||
|
||||
} else {
|
||||
|
||||
width, _ := sizeProperty(image, Width, session)
|
||||
height, _ := sizeProperty(image, Height, session)
|
||||
|
||||
if width.Type != Auto || height.Type != Auto {
|
||||
buffer.WriteString(` / `)
|
||||
buffer.WriteString(width.cssString("auto", session))
|
||||
buffer.WriteRune(' ')
|
||||
buffer.WriteString(height.cssString("auto", session))
|
||||
}
|
||||
}
|
||||
|
||||
repeat, _ := enumProperty(image, Repeat, session, NoRepeat)
|
||||
values = enumProperties[Repeat].values
|
||||
if repeat >= 0 && repeat < len(values) {
|
||||
buffer.WriteRune(' ')
|
||||
buffer.WriteString(values[repeat])
|
||||
} else {
|
||||
buffer.WriteString(` no-repeat`)
|
||||
}
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (image *backgroundImage) writeString(buffer *strings.Builder, indent string) {
|
||||
image.writeToBuffer(buffer, indent, image.Tag(), []PropertyName{
|
||||
Source,
|
||||
Width,
|
||||
Height,
|
||||
ImageHorizontalAlign,
|
||||
ImageVerticalAlign,
|
||||
backgroundFit,
|
||||
Repeat,
|
||||
Attachment,
|
||||
})
|
||||
}
|
||||
|
||||
func (image *backgroundImage) String() string {
|
||||
return runStringWriter(image)
|
||||
}
|
||||
|
||||
func parseBackgroundValue(value any) []BackgroundElement {
|
||||
|
||||
switch value := value.(type) {
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
package rui
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Constants related to view's background description
|
||||
const (
|
||||
// NoRepeat is value of the Repeat property of an background image:
|
||||
// The image is not repeated (and hence the background image painting area
|
||||
// will not necessarily be entirely covered). The position of the non-repeated
|
||||
// background image is defined by the background-position CSS property.
|
||||
NoRepeat = 0
|
||||
|
||||
// RepeatXY is value of the Repeat property of an background image:
|
||||
// The image is repeated as much as needed to cover the whole background
|
||||
// image painting area. The last image will be clipped if it doesn't fit.
|
||||
RepeatXY = 1
|
||||
|
||||
// RepeatX is value of the Repeat property of an background image:
|
||||
// The image is repeated horizontally as much as needed to cover
|
||||
// the whole width background image painting area. The image is not repeated vertically.
|
||||
// The last image will be clipped if it doesn't fit.
|
||||
RepeatX = 2
|
||||
|
||||
// RepeatY is value of the Repeat property of an background image:
|
||||
// The image is repeated vertically as much as needed to cover
|
||||
// the whole height background image painting area. The image is not repeated horizontally.
|
||||
// The last image will be clipped if it doesn't fit.
|
||||
RepeatY = 3
|
||||
|
||||
// RepeatRound is value of the Repeat property of an background image:
|
||||
// As the allowed space increases in size, the repeated images will stretch (leaving no gaps)
|
||||
// until there is room (space left >= half of the image width) for another one to be added.
|
||||
// When the next image is added, all of the current ones compress to allow room.
|
||||
RepeatRound = 4
|
||||
|
||||
// RepeatSpace is value of the Repeat property of an background image:
|
||||
// The image is repeated as much as possible without clipping. The first and last images
|
||||
// are pinned to either side of the element, and whitespace is distributed evenly between the images.
|
||||
RepeatSpace = 5
|
||||
|
||||
// ScrollAttachment is value of the Attachment property of an background image:
|
||||
// The background is fixed relative to the element itself and does not scroll with its contents.
|
||||
// (It is effectively attached to the element's border.)
|
||||
ScrollAttachment = 0
|
||||
|
||||
// FixedAttachment is value of the Attachment property of an background image:
|
||||
// The background is fixed relative to the viewport. Even if an element has
|
||||
// a scrolling mechanism, the background doesn't move with the element.
|
||||
FixedAttachment = 1
|
||||
|
||||
// LocalAttachment is value of the Attachment property of an background image:
|
||||
// The background is fixed relative to the element's contents. If the element has a scrolling mechanism,
|
||||
// the background scrolls with the element's contents, and the background painting area
|
||||
// and background positioning area are relative to the scrollable area of the element
|
||||
// rather than to the border framing them.
|
||||
LocalAttachment = 2
|
||||
)
|
||||
|
||||
type backgroundImage struct {
|
||||
backgroundElement
|
||||
}
|
||||
|
||||
// NewBackgroundImage creates the new background image
|
||||
func NewBackgroundImage(params Params) BackgroundElement {
|
||||
result := new(backgroundImage)
|
||||
result.init()
|
||||
for tag, value := range params {
|
||||
result.Set(tag, value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (image *backgroundImage) init() {
|
||||
image.backgroundElement.init()
|
||||
image.normalize = normalizeBackgroundImageTag
|
||||
image.supportedProperties = []PropertyName{
|
||||
Attachment, Width, Height, Repeat, ImageHorizontalAlign, ImageVerticalAlign, backgroundFit, Source,
|
||||
}
|
||||
}
|
||||
|
||||
func (image *backgroundImage) Tag() string {
|
||||
return "image"
|
||||
}
|
||||
|
||||
func (image *backgroundImage) Clone() BackgroundElement {
|
||||
result := NewBackgroundImage(nil)
|
||||
for tag, value := range image.properties {
|
||||
result.setRaw(tag, value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func normalizeBackgroundImageTag(tag PropertyName) PropertyName {
|
||||
tag = defaultNormalize(tag)
|
||||
switch tag {
|
||||
case "source":
|
||||
tag = Source
|
||||
|
||||
case Fit:
|
||||
tag = backgroundFit
|
||||
|
||||
case HorizontalAlign:
|
||||
tag = ImageHorizontalAlign
|
||||
|
||||
case VerticalAlign:
|
||||
tag = ImageVerticalAlign
|
||||
}
|
||||
|
||||
return tag
|
||||
}
|
||||
|
||||
func (image *backgroundImage) cssStyle(session Session) string {
|
||||
if src, ok := imageProperty(image, Source, session); ok && src != "" {
|
||||
buffer := allocStringBuilder()
|
||||
defer freeStringBuilder(buffer)
|
||||
|
||||
buffer.WriteString(`url(`)
|
||||
buffer.WriteString(src)
|
||||
buffer.WriteRune(')')
|
||||
|
||||
attachment, _ := enumProperty(image, Attachment, session, NoRepeat)
|
||||
values := enumProperties[Attachment].values
|
||||
if attachment > 0 && attachment < len(values) {
|
||||
buffer.WriteRune(' ')
|
||||
buffer.WriteString(values[attachment])
|
||||
}
|
||||
|
||||
align, _ := enumProperty(image, ImageHorizontalAlign, session, LeftAlign)
|
||||
values = enumProperties[ImageHorizontalAlign].values
|
||||
if align >= 0 && align < len(values) {
|
||||
buffer.WriteRune(' ')
|
||||
buffer.WriteString(values[align])
|
||||
} else {
|
||||
buffer.WriteString(` left`)
|
||||
}
|
||||
|
||||
align, _ = enumProperty(image, ImageVerticalAlign, session, TopAlign)
|
||||
values = enumProperties[ImageVerticalAlign].values
|
||||
if align >= 0 && align < len(values) {
|
||||
buffer.WriteRune(' ')
|
||||
buffer.WriteString(values[align])
|
||||
} else {
|
||||
buffer.WriteString(` top`)
|
||||
}
|
||||
|
||||
fit, _ := enumProperty(image, backgroundFit, session, NoneFit)
|
||||
values = enumProperties[backgroundFit].values
|
||||
if fit > 0 && fit < len(values) {
|
||||
|
||||
buffer.WriteString(` / `)
|
||||
buffer.WriteString(values[fit])
|
||||
|
||||
} else {
|
||||
|
||||
width, _ := sizeProperty(image, Width, session)
|
||||
height, _ := sizeProperty(image, Height, session)
|
||||
|
||||
if width.Type != Auto || height.Type != Auto {
|
||||
buffer.WriteString(` / `)
|
||||
buffer.WriteString(width.cssString("auto", session))
|
||||
buffer.WriteRune(' ')
|
||||
buffer.WriteString(height.cssString("auto", session))
|
||||
}
|
||||
}
|
||||
|
||||
repeat, _ := enumProperty(image, Repeat, session, NoRepeat)
|
||||
values = enumProperties[Repeat].values
|
||||
if repeat >= 0 && repeat < len(values) {
|
||||
buffer.WriteRune(' ')
|
||||
buffer.WriteString(values[repeat])
|
||||
} else {
|
||||
buffer.WriteString(` no-repeat`)
|
||||
}
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (image *backgroundImage) writeString(buffer *strings.Builder, indent string) {
|
||||
image.writeToBuffer(buffer, indent, image.Tag(), []PropertyName{
|
||||
Source,
|
||||
Width,
|
||||
Height,
|
||||
ImageHorizontalAlign,
|
||||
ImageVerticalAlign,
|
||||
backgroundFit,
|
||||
Repeat,
|
||||
Attachment,
|
||||
})
|
||||
}
|
||||
|
||||
func (image *backgroundImage) String() string {
|
||||
return runStringWriter(image)
|
||||
}
|
|
@ -4,47 +4,29 @@ import "strings"
|
|||
|
||||
// Constants related to view's background gradient description
|
||||
const (
|
||||
|
||||
// ToTopGradient is value of the Direction property of a linear gradient. The value is equivalent to the 0deg angle
|
||||
ToTopGradient = 0
|
||||
|
||||
// ToRightTopGradient is value of the Direction property of a linear gradient.
|
||||
ToRightTopGradient = 1
|
||||
|
||||
// ToRightGradient is value of the Direction property of a linear gradient. The value is equivalent to the 90deg angle
|
||||
ToRightGradient = 2
|
||||
|
||||
// ToRightBottomGradient is value of the Direction property of a linear gradient.
|
||||
ToRightBottomGradient = 3
|
||||
|
||||
// ToBottomGradient is value of the Direction property of a linear gradient. The value is equivalent to the 180deg angle
|
||||
ToBottomGradient = 4
|
||||
|
||||
// ToLeftBottomGradient is value of the Direction property of a linear gradient.
|
||||
ToLeftBottomGradient = 5
|
||||
|
||||
// ToLeftGradient is value of the Direction property of a linear gradient. The value is equivalent to the 270deg angle
|
||||
ToLeftGradient = 6
|
||||
|
||||
// ToLeftTopGradient is value of the Direction property of a linear gradient.
|
||||
ToLeftTopGradient = 7
|
||||
|
||||
// EllipseGradient is value of the Shape property of a radial gradient background:
|
||||
// the shape is an axis-aligned ellipse
|
||||
EllipseGradient = 0
|
||||
// CircleGradient is value of the Shape property of a radial gradient background:
|
||||
// the gradient's shape is a circle with constant radius
|
||||
CircleGradient = 1
|
||||
|
||||
// ClosestSideGradient is value of the Radius property of a radial gradient background:
|
||||
// The gradient's ending shape meets the side of the box closest to its center (for circles)
|
||||
// or meets both the vertical and horizontal sides closest to the center (for ellipses).
|
||||
ClosestSideGradient = 0
|
||||
// ClosestCornerGradient is value of the Radius property of a radial gradient background:
|
||||
// The gradient's ending shape is sized so that it exactly meets the closest corner
|
||||
// of the box from its center.
|
||||
ClosestCornerGradient = 1
|
||||
// FarthestSideGradient is value of the Radius property of a radial gradient background:
|
||||
// Similar to closest-side, except the ending shape is sized to meet the side of the box
|
||||
// farthest from its center (or vertical and horizontal sides).
|
||||
FarthestSideGradient = 2
|
||||
// FarthestCornerGradient is value of the Radius property of a radial gradient background:
|
||||
// The default value, the gradient's ending shape is sized so that it exactly meets
|
||||
// the farthest corner of the box from its center.
|
||||
FarthestCornerGradient = 3
|
||||
)
|
||||
|
||||
// BackgroundGradientPoint define point on gradient straight line
|
||||
|
@ -65,10 +47,6 @@ type backgroundLinearGradient struct {
|
|||
backgroundGradient
|
||||
}
|
||||
|
||||
type backgroundRadialGradient struct {
|
||||
backgroundGradient
|
||||
}
|
||||
|
||||
// NewBackgroundLinearGradient creates the new background linear gradient
|
||||
func NewBackgroundLinearGradient(params Params) BackgroundElement {
|
||||
result := new(backgroundLinearGradient)
|
||||
|
@ -79,16 +57,6 @@ func NewBackgroundLinearGradient(params Params) BackgroundElement {
|
|||
return result
|
||||
}
|
||||
|
||||
// NewBackgroundRadialGradient creates the new background radial gradient
|
||||
func NewBackgroundRadialGradient(params Params) BackgroundElement {
|
||||
result := new(backgroundRadialGradient)
|
||||
result.init()
|
||||
for tag, value := range params {
|
||||
result.Set(tag, value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func parseGradientText(value string) []BackgroundGradientPoint {
|
||||
elements := strings.Split(value, ",")
|
||||
count := len(elements)
|
||||
|
@ -422,261 +390,3 @@ func (gradient *backgroundLinearGradient) writeString(buffer *strings.Builder, i
|
|||
func (gradient *backgroundLinearGradient) String() string {
|
||||
return runStringWriter(gradient)
|
||||
}
|
||||
|
||||
func (gradient *backgroundRadialGradient) init() {
|
||||
gradient.backgroundElement.init()
|
||||
gradient.normalize = normalizeRadialGradientTag
|
||||
gradient.set = backgroundRadialGradientSet
|
||||
gradient.supportedProperties = []PropertyName{
|
||||
RadialGradientRadius, RadialGradientShape, CenterX, CenterY, Gradient, Repeating,
|
||||
}
|
||||
}
|
||||
|
||||
func (gradient *backgroundRadialGradient) Tag() string {
|
||||
return "radial-gradient"
|
||||
}
|
||||
|
||||
func (image *backgroundRadialGradient) Clone() BackgroundElement {
|
||||
result := NewBackgroundRadialGradient(nil)
|
||||
for tag, value := range image.properties {
|
||||
result.setRaw(tag, value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func normalizeRadialGradientTag(tag PropertyName) PropertyName {
|
||||
tag = defaultNormalize(tag)
|
||||
switch tag {
|
||||
case Radius:
|
||||
tag = RadialGradientRadius
|
||||
|
||||
case Shape:
|
||||
tag = RadialGradientShape
|
||||
|
||||
case "x-center":
|
||||
tag = CenterX
|
||||
|
||||
case "y-center":
|
||||
tag = CenterY
|
||||
}
|
||||
|
||||
return tag
|
||||
}
|
||||
|
||||
func backgroundRadialGradientSet(properties Properties, tag PropertyName, value any) []PropertyName {
|
||||
switch tag {
|
||||
case RadialGradientRadius:
|
||||
switch value := value.(type) {
|
||||
case []SizeUnit:
|
||||
switch len(value) {
|
||||
case 0:
|
||||
properties.setRaw(RadialGradientRadius, nil)
|
||||
|
||||
case 1:
|
||||
if value[0].Type == Auto {
|
||||
properties.setRaw(RadialGradientRadius, nil)
|
||||
} else {
|
||||
properties.setRaw(RadialGradientRadius, value[0])
|
||||
}
|
||||
|
||||
default:
|
||||
properties.setRaw(RadialGradientRadius, value)
|
||||
}
|
||||
return []PropertyName{tag}
|
||||
|
||||
case []any:
|
||||
switch len(value) {
|
||||
case 0:
|
||||
properties.setRaw(RadialGradientRadius, nil)
|
||||
return []PropertyName{tag}
|
||||
|
||||
case 1:
|
||||
return backgroundRadialGradientSet(properties, RadialGradientRadius, value[0])
|
||||
|
||||
default:
|
||||
properties.setRaw(RadialGradientRadius, value)
|
||||
return []PropertyName{tag}
|
||||
}
|
||||
|
||||
case string:
|
||||
if setSimpleProperty(properties, RadialGradientRadius, value) {
|
||||
return []PropertyName{tag}
|
||||
}
|
||||
if size, err := stringToSizeUnit(value); err == nil {
|
||||
if size.Type == Auto {
|
||||
properties.setRaw(RadialGradientRadius, nil)
|
||||
} else {
|
||||
properties.setRaw(RadialGradientRadius, size)
|
||||
}
|
||||
return []PropertyName{tag}
|
||||
}
|
||||
return setEnumProperty(properties, RadialGradientRadius, value, enumProperties[RadialGradientRadius].values)
|
||||
|
||||
case SizeUnit:
|
||||
if value.Type == Auto {
|
||||
properties.setRaw(RadialGradientRadius, nil)
|
||||
} else {
|
||||
properties.setRaw(RadialGradientRadius, value)
|
||||
}
|
||||
return []PropertyName{tag}
|
||||
|
||||
case int:
|
||||
return setEnumProperty(properties, RadialGradientRadius, value, enumProperties[RadialGradientRadius].values)
|
||||
}
|
||||
|
||||
ErrorLogF(`Invalid value of "%s" property: %v`, tag, value)
|
||||
return nil
|
||||
|
||||
case RadialGradientShape, CenterX, CenterY:
|
||||
return propertiesSet(properties, tag, value)
|
||||
}
|
||||
|
||||
return backgroundGradientSet(properties, tag, value)
|
||||
}
|
||||
|
||||
func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
|
||||
buffer := allocStringBuilder()
|
||||
defer freeStringBuilder(buffer)
|
||||
|
||||
if repeating, _ := boolProperty(gradient, Repeating, session); repeating {
|
||||
buffer.WriteString(`repeating-radial-gradient(`)
|
||||
} else {
|
||||
buffer.WriteString(`radial-gradient(`)
|
||||
}
|
||||
|
||||
var shapeText string
|
||||
if shape, ok := enumProperty(gradient, RadialGradientShape, session, EllipseGradient); ok && shape == CircleGradient {
|
||||
shapeText = `circle `
|
||||
} else {
|
||||
shapeText = `ellipse `
|
||||
}
|
||||
|
||||
if value, ok := gradient.properties[RadialGradientRadius]; ok {
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
if text, ok := session.resolveConstants(value); ok {
|
||||
values := enumProperties[RadialGradientRadius]
|
||||
if n, ok := enumStringToInt(text, values.values, false); ok {
|
||||
buffer.WriteString(shapeText)
|
||||
shapeText = ""
|
||||
buffer.WriteString(values.cssValues[n])
|
||||
buffer.WriteString(" ")
|
||||
} else {
|
||||
if r, ok := StringToSizeUnit(text); ok && r.Type != Auto {
|
||||
buffer.WriteString("ellipse ")
|
||||
shapeText = ""
|
||||
buffer.WriteString(r.cssString("", session))
|
||||
buffer.WriteString(" ")
|
||||
buffer.WriteString(r.cssString("", session))
|
||||
buffer.WriteString(" ")
|
||||
} else {
|
||||
ErrorLog(`Invalid radial gradient radius: ` + text)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ErrorLog(`Invalid radial gradient radius: ` + value)
|
||||
}
|
||||
|
||||
case int:
|
||||
values := enumProperties[RadialGradientRadius].cssValues
|
||||
if value >= 0 && value < len(values) {
|
||||
buffer.WriteString(shapeText)
|
||||
shapeText = ""
|
||||
buffer.WriteString(values[value])
|
||||
buffer.WriteString(" ")
|
||||
} else {
|
||||
ErrorLogF(`Invalid radial gradient radius: %d`, value)
|
||||
}
|
||||
|
||||
case SizeUnit:
|
||||
if value.Type != Auto {
|
||||
buffer.WriteString("ellipse ")
|
||||
shapeText = ""
|
||||
buffer.WriteString(value.cssString("", session))
|
||||
buffer.WriteString(" ")
|
||||
buffer.WriteString(value.cssString("", session))
|
||||
buffer.WriteString(" ")
|
||||
}
|
||||
|
||||
case []SizeUnit:
|
||||
count := len(value)
|
||||
if count > 2 {
|
||||
count = 2
|
||||
}
|
||||
buffer.WriteString("ellipse ")
|
||||
shapeText = ""
|
||||
for i := 0; i < count; i++ {
|
||||
buffer.WriteString(value[i].cssString("50%", session))
|
||||
buffer.WriteString(" ")
|
||||
}
|
||||
|
||||
case []any:
|
||||
count := len(value)
|
||||
if count > 2 {
|
||||
count = 2
|
||||
}
|
||||
buffer.WriteString("ellipse ")
|
||||
shapeText = ""
|
||||
for i := 0; i < count; i++ {
|
||||
if value[i] != nil {
|
||||
switch value := value[i].(type) {
|
||||
case SizeUnit:
|
||||
buffer.WriteString(value.cssString("50%", session))
|
||||
buffer.WriteString(" ")
|
||||
|
||||
case string:
|
||||
if text, ok := session.resolveConstants(value); ok {
|
||||
if size, err := stringToSizeUnit(text); err == nil {
|
||||
buffer.WriteString(size.cssString("50%", session))
|
||||
buffer.WriteString(" ")
|
||||
} else {
|
||||
buffer.WriteString("50% ")
|
||||
}
|
||||
} else {
|
||||
buffer.WriteString("50% ")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buffer.WriteString("50% ")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x, _ := sizeProperty(gradient, CenterX, session)
|
||||
y, _ := sizeProperty(gradient, CenterX, session)
|
||||
if x.Type != Auto || y.Type != Auto {
|
||||
if shapeText != "" {
|
||||
buffer.WriteString(shapeText)
|
||||
}
|
||||
buffer.WriteString("at ")
|
||||
buffer.WriteString(x.cssString("50%", session))
|
||||
buffer.WriteString(" ")
|
||||
buffer.WriteString(y.cssString("50%", session))
|
||||
} else if shapeText != "" {
|
||||
buffer.WriteString(shapeText)
|
||||
}
|
||||
|
||||
buffer.WriteString(", ")
|
||||
if !gradient.writeGradient(session, buffer) {
|
||||
return ""
|
||||
}
|
||||
|
||||
buffer.WriteString(") ")
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
func (gradient *backgroundRadialGradient) writeString(buffer *strings.Builder, indent string) {
|
||||
gradient.writeToBuffer(buffer, indent, gradient.Tag(), []PropertyName{
|
||||
Gradient,
|
||||
CenterX,
|
||||
CenterY,
|
||||
Repeating,
|
||||
RadialGradientShape,
|
||||
RadialGradientRadius,
|
||||
})
|
||||
}
|
||||
|
||||
func (gradient *backgroundRadialGradient) String() string {
|
||||
return runStringWriter(gradient)
|
||||
}
|
|
@ -0,0 +1,307 @@
|
|||
package rui
|
||||
|
||||
import "strings"
|
||||
|
||||
// Constants related to view's background gradient description
|
||||
const (
|
||||
// EllipseGradient is value of the Shape property of a radial gradient background:
|
||||
// the shape is an axis-aligned ellipse
|
||||
EllipseGradient = 0
|
||||
|
||||
// CircleGradient is value of the Shape property of a radial gradient background:
|
||||
// the gradient's shape is a circle with constant radius
|
||||
CircleGradient = 1
|
||||
|
||||
// ClosestSideGradient is value of the Radius property of a radial gradient background:
|
||||
// The gradient's ending shape meets the side of the box closest to its center (for circles)
|
||||
// or meets both the vertical and horizontal sides closest to the center (for ellipses).
|
||||
ClosestSideGradient = 0
|
||||
|
||||
// ClosestCornerGradient is value of the Radius property of a radial gradient background:
|
||||
// The gradient's ending shape is sized so that it exactly meets the closest corner
|
||||
// of the box from its center.
|
||||
ClosestCornerGradient = 1
|
||||
|
||||
// FarthestSideGradient is value of the Radius property of a radial gradient background:
|
||||
// Similar to closest-side, except the ending shape is sized to meet the side of the box
|
||||
// farthest from its center (or vertical and horizontal sides).
|
||||
FarthestSideGradient = 2
|
||||
|
||||
// FarthestCornerGradient is value of the Radius property of a radial gradient background:
|
||||
// The default value, the gradient's ending shape is sized so that it exactly meets
|
||||
// the farthest corner of the box from its center.
|
||||
FarthestCornerGradient = 3
|
||||
)
|
||||
|
||||
type backgroundRadialGradient struct {
|
||||
backgroundGradient
|
||||
}
|
||||
|
||||
// NewBackgroundRadialGradient creates the new background radial gradient
|
||||
func NewBackgroundRadialGradient(params Params) BackgroundElement {
|
||||
result := new(backgroundRadialGradient)
|
||||
result.init()
|
||||
for tag, value := range params {
|
||||
result.Set(tag, value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (gradient *backgroundRadialGradient) init() {
|
||||
gradient.backgroundElement.init()
|
||||
gradient.normalize = normalizeRadialGradientTag
|
||||
gradient.set = backgroundRadialGradientSet
|
||||
gradient.supportedProperties = []PropertyName{
|
||||
RadialGradientRadius, RadialGradientShape, CenterX, CenterY, Gradient, Repeating,
|
||||
}
|
||||
}
|
||||
|
||||
func (gradient *backgroundRadialGradient) Tag() string {
|
||||
return "radial-gradient"
|
||||
}
|
||||
|
||||
func (image *backgroundRadialGradient) Clone() BackgroundElement {
|
||||
result := NewBackgroundRadialGradient(nil)
|
||||
for tag, value := range image.properties {
|
||||
result.setRaw(tag, value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func normalizeRadialGradientTag(tag PropertyName) PropertyName {
|
||||
tag = defaultNormalize(tag)
|
||||
switch tag {
|
||||
case Radius:
|
||||
tag = RadialGradientRadius
|
||||
|
||||
case Shape:
|
||||
tag = RadialGradientShape
|
||||
|
||||
case "x-center":
|
||||
tag = CenterX
|
||||
|
||||
case "y-center":
|
||||
tag = CenterY
|
||||
}
|
||||
|
||||
return tag
|
||||
}
|
||||
|
||||
func backgroundRadialGradientSet(properties Properties, tag PropertyName, value any) []PropertyName {
|
||||
switch tag {
|
||||
case RadialGradientRadius:
|
||||
switch value := value.(type) {
|
||||
case []SizeUnit:
|
||||
switch len(value) {
|
||||
case 0:
|
||||
properties.setRaw(RadialGradientRadius, nil)
|
||||
|
||||
case 1:
|
||||
if value[0].Type == Auto {
|
||||
properties.setRaw(RadialGradientRadius, nil)
|
||||
} else {
|
||||
properties.setRaw(RadialGradientRadius, value[0])
|
||||
}
|
||||
|
||||
default:
|
||||
properties.setRaw(RadialGradientRadius, value)
|
||||
}
|
||||
return []PropertyName{tag}
|
||||
|
||||
case []any:
|
||||
switch len(value) {
|
||||
case 0:
|
||||
properties.setRaw(RadialGradientRadius, nil)
|
||||
return []PropertyName{tag}
|
||||
|
||||
case 1:
|
||||
return backgroundRadialGradientSet(properties, RadialGradientRadius, value[0])
|
||||
|
||||
default:
|
||||
properties.setRaw(RadialGradientRadius, value)
|
||||
return []PropertyName{tag}
|
||||
}
|
||||
|
||||
case string:
|
||||
if setSimpleProperty(properties, RadialGradientRadius, value) {
|
||||
return []PropertyName{tag}
|
||||
}
|
||||
if size, err := stringToSizeUnit(value); err == nil {
|
||||
if size.Type == Auto {
|
||||
properties.setRaw(RadialGradientRadius, nil)
|
||||
} else {
|
||||
properties.setRaw(RadialGradientRadius, size)
|
||||
}
|
||||
return []PropertyName{tag}
|
||||
}
|
||||
return setEnumProperty(properties, RadialGradientRadius, value, enumProperties[RadialGradientRadius].values)
|
||||
|
||||
case SizeUnit:
|
||||
if value.Type == Auto {
|
||||
properties.setRaw(RadialGradientRadius, nil)
|
||||
} else {
|
||||
properties.setRaw(RadialGradientRadius, value)
|
||||
}
|
||||
return []PropertyName{tag}
|
||||
|
||||
case int:
|
||||
return setEnumProperty(properties, RadialGradientRadius, value, enumProperties[RadialGradientRadius].values)
|
||||
}
|
||||
|
||||
ErrorLogF(`Invalid value of "%s" property: %v`, tag, value)
|
||||
return nil
|
||||
|
||||
case RadialGradientShape, CenterX, CenterY:
|
||||
return propertiesSet(properties, tag, value)
|
||||
}
|
||||
|
||||
return backgroundGradientSet(properties, tag, value)
|
||||
}
|
||||
|
||||
func (gradient *backgroundRadialGradient) cssStyle(session Session) string {
|
||||
buffer := allocStringBuilder()
|
||||
defer freeStringBuilder(buffer)
|
||||
|
||||
if repeating, _ := boolProperty(gradient, Repeating, session); repeating {
|
||||
buffer.WriteString(`repeating-radial-gradient(`)
|
||||
} else {
|
||||
buffer.WriteString(`radial-gradient(`)
|
||||
}
|
||||
|
||||
var shapeText string
|
||||
if shape, ok := enumProperty(gradient, RadialGradientShape, session, EllipseGradient); ok && shape == CircleGradient {
|
||||
shapeText = `circle `
|
||||
} else {
|
||||
shapeText = `ellipse `
|
||||
}
|
||||
|
||||
if value, ok := gradient.properties[RadialGradientRadius]; ok {
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
if text, ok := session.resolveConstants(value); ok {
|
||||
values := enumProperties[RadialGradientRadius]
|
||||
if n, ok := enumStringToInt(text, values.values, false); ok {
|
||||
buffer.WriteString(shapeText)
|
||||
shapeText = ""
|
||||
buffer.WriteString(values.cssValues[n])
|
||||
buffer.WriteString(" ")
|
||||
} else {
|
||||
if r, ok := StringToSizeUnit(text); ok && r.Type != Auto {
|
||||
buffer.WriteString("ellipse ")
|
||||
shapeText = ""
|
||||
buffer.WriteString(r.cssString("", session))
|
||||
buffer.WriteString(" ")
|
||||
buffer.WriteString(r.cssString("", session))
|
||||
buffer.WriteString(" ")
|
||||
} else {
|
||||
ErrorLog(`Invalid radial gradient radius: ` + text)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ErrorLog(`Invalid radial gradient radius: ` + value)
|
||||
}
|
||||
|
||||
case int:
|
||||
values := enumProperties[RadialGradientRadius].cssValues
|
||||
if value >= 0 && value < len(values) {
|
||||
buffer.WriteString(shapeText)
|
||||
shapeText = ""
|
||||
buffer.WriteString(values[value])
|
||||
buffer.WriteString(" ")
|
||||
} else {
|
||||
ErrorLogF(`Invalid radial gradient radius: %d`, value)
|
||||
}
|
||||
|
||||
case SizeUnit:
|
||||
if value.Type != Auto {
|
||||
buffer.WriteString("ellipse ")
|
||||
shapeText = ""
|
||||
buffer.WriteString(value.cssString("", session))
|
||||
buffer.WriteString(" ")
|
||||
buffer.WriteString(value.cssString("", session))
|
||||
buffer.WriteString(" ")
|
||||
}
|
||||
|
||||
case []SizeUnit:
|
||||
count := len(value)
|
||||
if count > 2 {
|
||||
count = 2
|
||||
}
|
||||
buffer.WriteString("ellipse ")
|
||||
shapeText = ""
|
||||
for i := 0; i < count; i++ {
|
||||
buffer.WriteString(value[i].cssString("50%", session))
|
||||
buffer.WriteString(" ")
|
||||
}
|
||||
|
||||
case []any:
|
||||
count := len(value)
|
||||
if count > 2 {
|
||||
count = 2
|
||||
}
|
||||
buffer.WriteString("ellipse ")
|
||||
shapeText = ""
|
||||
for i := 0; i < count; i++ {
|
||||
if value[i] != nil {
|
||||
switch value := value[i].(type) {
|
||||
case SizeUnit:
|
||||
buffer.WriteString(value.cssString("50%", session))
|
||||
buffer.WriteString(" ")
|
||||
|
||||
case string:
|
||||
if text, ok := session.resolveConstants(value); ok {
|
||||
if size, err := stringToSizeUnit(text); err == nil {
|
||||
buffer.WriteString(size.cssString("50%", session))
|
||||
buffer.WriteString(" ")
|
||||
} else {
|
||||
buffer.WriteString("50% ")
|
||||
}
|
||||
} else {
|
||||
buffer.WriteString("50% ")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buffer.WriteString("50% ")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x, _ := sizeProperty(gradient, CenterX, session)
|
||||
y, _ := sizeProperty(gradient, CenterX, session)
|
||||
if x.Type != Auto || y.Type != Auto {
|
||||
if shapeText != "" {
|
||||
buffer.WriteString(shapeText)
|
||||
}
|
||||
buffer.WriteString("at ")
|
||||
buffer.WriteString(x.cssString("50%", session))
|
||||
buffer.WriteString(" ")
|
||||
buffer.WriteString(y.cssString("50%", session))
|
||||
} else if shapeText != "" {
|
||||
buffer.WriteString(shapeText)
|
||||
}
|
||||
|
||||
buffer.WriteString(", ")
|
||||
if !gradient.writeGradient(session, buffer) {
|
||||
return ""
|
||||
}
|
||||
|
||||
buffer.WriteString(") ")
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
func (gradient *backgroundRadialGradient) writeString(buffer *strings.Builder, indent string) {
|
||||
gradient.writeToBuffer(buffer, indent, gradient.Tag(), []PropertyName{
|
||||
Gradient,
|
||||
CenterX,
|
||||
CenterY,
|
||||
Repeating,
|
||||
RadialGradientShape,
|
||||
RadialGradientRadius,
|
||||
})
|
||||
}
|
||||
|
||||
func (gradient *backgroundRadialGradient) String() string {
|
||||
return runStringWriter(gradient)
|
||||
}
|
Loading…
Reference in New Issue