2021-09-07 17:36:50 +03:00
package rui
import (
"fmt"
"strings"
)
2024-09-12 14:05:11 +03:00
// Constants for [ViewFilter] specific properties and events
2021-09-07 17:36:50 +03:00
const (
2024-09-18 13:50:06 +03:00
// Blur is the constant for "blur" property tag.
//
// Used by `ViewFilter`.
2024-11-13 12:56:39 +03:00
// Applies a Gaussian blur. The value of radius defines the value of the standard deviation to the Gaussian function, or
// how many pixels on the screen blend into each other, so a larger value will create more blur. The lacuna value for
2024-09-18 13:50:06 +03:00
// interpolation is 0. The parameter is specified as a length in pixels.
//
// Supported types: `float`, `int`, `string`.
//
// Internal type is `float`, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
Blur PropertyName = "blur"
2021-09-07 17:36:50 +03:00
2024-09-18 13:50:06 +03:00
// Brightness is the constant for "brightness" property tag.
//
// Used by `ViewFilter`.
2024-11-13 12:56:39 +03:00
// Applies a linear multiplier to input image, making it appear more or less bright. A value of 0% will create an image
// that is completely black. A value of 100% leaves the input unchanged. Other values are linear multipliers on the
2024-09-18 13:50:06 +03:00
// effect. Values of an amount over 100% are allowed, providing brighter results.
//
// Supported types: `float`, `int`, `string`.
//
// Internal type is `float`, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
Brightness PropertyName = "brightness"
2021-09-07 17:36:50 +03:00
2024-09-18 13:50:06 +03:00
// Contrast is the constant for "contrast" property tag.
//
// Used by `ViewFilter`.
2024-11-13 12:56:39 +03:00
// Adjusts the contrast of the input. A value of 0% will create an image that is completely black. A value of 100% leaves
2024-09-18 13:50:06 +03:00
// the input unchanged. Values of amount over 100% are allowed, providing results with less contrast.
//
// Supported types: `float`, `int`, `string`.
//
// Internal type is `float`, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
Contrast PropertyName = "contrast"
2021-09-07 17:36:50 +03:00
2024-09-18 13:50:06 +03:00
// DropShadow is the constant for "drop-shadow" property tag.
//
// Used by `ViewFilter`.
2024-11-13 12:56:39 +03:00
// Applies a drop shadow effect to the input image. A drop shadow is effectively a blurred, offset version of the input
// image's alpha mask drawn in a particular color, composited below the image. Shadow parameters are set using the
2024-09-18 13:50:06 +03:00
// `ViewShadow` interface.
//
// Supported types: `[]ViewShadow`, `ViewShadow`, `string`.
//
// Internal type is `[]ViewShadow`, other types converted to it during assignment.
// See `ViewShadow` description for more details.
//
// Conversion rules:
// `[]ViewShadow` - stored as is, no conversion performed.
// `ViewShadow` - converted to `[]ViewShadow`.
// `string` - string representation of `ViewShadow`. Example: "_{blur = 1em, color = black, spread-radius = 0.5em}".
2024-11-13 12:56:39 +03:00
DropShadow PropertyName = "drop-shadow"
2021-09-07 17:36:50 +03:00
2024-09-18 13:50:06 +03:00
// Grayscale is the constant for "grayscale" property tag.
//
// Used by `ViewFilter`.
2024-11-13 12:56:39 +03:00
// Converts the input image to grayscale. The value of ‘ amount’ defines the proportion of the conversion. A value of 100%
// is completely grayscale. A value of 0% leaves the input unchanged. Values between 0% and 100% are linear multipliers on
2024-09-18 13:50:06 +03:00
// the effect.
//
// Supported types: `float`, `int`, `string`.
//
// Internal type is `float`, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
Grayscale PropertyName = "grayscale"
2021-09-07 17:36:50 +03:00
2024-09-18 13:50:06 +03:00
// HueRotate is the constant for "hue-rotate" property tag.
//
// Used by `ViewFilter`.
2024-11-13 12:56:39 +03:00
// Applies a hue rotation on the input image. The value of ‘ angle’ defines the number of degrees around the color circle
// the input samples will be adjusted. A value of 0deg leaves the input unchanged. If the ‘ angle’ parameter is missing, a
2024-09-18 13:50:06 +03:00
// value of 0deg is used. Though there is no maximum value, the effect of values above 360deg wraps around.
//
// Supported types: `AngleUnit`, `string`, `float`, `int`.
//
// Internal type is `AngleUnit`, other types will be converted to it during assignment.
// See `AngleUnit` description for more details.
//
// Conversion rules:
// `AngleUnit` - stored as is, no conversion performed.
// `string` - must contain string representation of `AngleUnit`. If numeric value will be provided without any suffix then `AngleUnit` with value and `Radian` value type will be created.
// `float` - a new `AngleUnit` value will be created with `Radian` as a type.
// `int` - a new `AngleUnit` value will be created with `Radian` as a type.
2024-11-13 12:56:39 +03:00
HueRotate PropertyName = "hue-rotate"
2021-09-07 17:36:50 +03:00
2024-09-18 13:50:06 +03:00
// Invert is the constant for "invert" property tag.
//
// Used by `ViewFilter`.
2024-11-13 12:56:39 +03:00
// Inverts the samples in the input image. The value of ‘ amount’ defines the proportion of the conversion. A value of 100%
// is completely inverted. A value of 0% leaves the input unchanged. Values between 0% and 100% are linear multipliers on
2024-09-18 13:50:06 +03:00
// the effect.
//
// Supported types: `float64`, `int`, `string`.
//
// Internal type is `float`, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
Invert PropertyName = "invert"
2021-09-07 17:36:50 +03:00
2024-09-18 13:50:06 +03:00
// Saturate is the constant for "saturate" property tag.
//
// Used by `ViewFilter`.
2024-11-13 12:56:39 +03:00
// Saturates the input image. The value of ‘ amount’ defines the proportion of the conversion. A value of 0% is completely
// un-saturated. A value of 100% leaves the input unchanged. Other values are linear multipliers on the effect. Values of
2024-09-18 13:50:06 +03:00
// amount over 100% are allowed, providing super-saturated results.
//
// Supported types: `float`, `int`, `string`.
//
// Internal type is `float`, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
Saturate PropertyName = "saturate"
2021-09-07 17:36:50 +03:00
2024-09-18 13:50:06 +03:00
// Sepia is the constant for "sepia" property tag.
//
// Used by `ViewFilter`.
2024-11-13 12:56:39 +03:00
// Converts the input image to sepia. The value of ‘ amount’ defines the proportion of the conversion. A value of 100% is
// completely sepia. A value of 0% leaves the input unchanged. Values between 0% and 100% are linear multipliers on the
2024-09-18 13:50:06 +03:00
// effect.
//
// Supported types: `float`, `int`, `string`.
//
// Internal type is `float`, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
Sepia PropertyName = "sepia"
2021-09-07 17:36:50 +03:00
)
// ViewFilter defines an applied to a View a graphical effects like blur or color shift.
// Allowable properties are Blur, Brightness, Contrast, DropShadow, Grayscale, HueRotate, Invert, Opacity, Saturate, and Sepia
type ViewFilter interface {
Properties
fmt . Stringer
2022-05-22 12:54:02 +03:00
stringWriter
2021-09-07 17:36:50 +03:00
cssStyle ( session Session ) string
}
type viewFilter struct {
2024-11-13 12:56:39 +03:00
dataProperty
2021-09-07 17:36:50 +03:00
}
// NewViewFilter creates the new ViewFilter
func NewViewFilter ( params Params ) ViewFilter {
2024-11-13 12:56:39 +03:00
if len ( params ) > 0 {
2022-05-05 17:18:08 +03:00
filter := new ( viewFilter )
filter . init ( )
for tag , value := range params {
2024-11-13 12:56:39 +03:00
if ! filter . Set ( tag , value ) {
return nil
}
2022-05-05 17:18:08 +03:00
}
2024-11-13 12:56:39 +03:00
return filter
2021-09-07 17:36:50 +03:00
}
return nil
}
func newViewFilter ( obj DataObject ) ViewFilter {
filter := new ( viewFilter )
filter . init ( )
for i := 0 ; i < obj . PropertyCount ( ) ; i ++ {
if node := obj . Property ( i ) ; node != nil {
tag := node . Tag ( )
switch node . Type ( ) {
case TextNode :
2024-11-13 12:56:39 +03:00
filter . Set ( PropertyName ( tag ) , node . Text ( ) )
2021-09-07 17:36:50 +03:00
case ObjectNode :
2024-11-13 12:56:39 +03:00
if tag == string ( HueRotate ) {
2021-09-07 17:36:50 +03:00
// TODO
} else {
ErrorLog ( ` Invalid value of " ` + tag + ` " ` )
}
default :
ErrorLog ( ` Invalid value of " ` + tag + ` " ` )
}
}
}
if len ( filter . properties ) > 0 {
return filter
}
ErrorLog ( "Empty view filter" )
return nil
}
2024-11-13 12:56:39 +03:00
func ( filter * viewFilter ) init ( ) {
filter . dataProperty . init ( )
filter . set = viewFilterSet
filter . supportedProperties = [ ] PropertyName { Blur , Brightness , Contrast , Saturate , Grayscale , Invert , Opacity , Sepia , HueRotate , DropShadow }
}
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
func viewFilterSet ( properties Properties , tag PropertyName , value any ) [ ] PropertyName {
switch tag {
2021-09-07 17:36:50 +03:00
case Blur , Brightness , Contrast , Saturate :
2024-11-13 12:56:39 +03:00
return setFloatProperty ( properties , tag , value , 0 , 10000 )
2021-09-07 17:36:50 +03:00
case Grayscale , Invert , Opacity , Sepia :
2024-11-13 12:56:39 +03:00
return setFloatProperty ( properties , tag , value , 0 , 100 )
2021-09-07 17:36:50 +03:00
case HueRotate :
2024-11-13 12:56:39 +03:00
return setAngleProperty ( properties , tag , value )
2021-09-07 17:36:50 +03:00
case DropShadow :
2024-11-13 12:56:39 +03:00
if setShadowProperty ( properties , tag , value ) {
return [ ] PropertyName { tag }
}
2021-09-07 17:36:50 +03:00
}
ErrorLogF ( ` "%s" property is not supported by the view filter ` , tag )
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
func ( filter * viewFilter ) String ( ) string {
2022-05-22 12:54:02 +03:00
return runStringWriter ( filter )
2021-09-07 17:36:50 +03:00
}
2022-05-22 12:54:02 +03:00
func ( filter * viewFilter ) writeString ( buffer * strings . Builder , indent string ) {
buffer . WriteString ( "filter { " )
comma := false
tags := filter . AllTags ( )
for _ , tag := range tags {
if value , ok := filter . properties [ tag ] ; ok {
if comma {
buffer . WriteString ( ", " )
}
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 ( filter * viewFilter ) cssStyle ( session Session ) string {
buffer := allocStringBuilder ( )
defer freeStringBuilder ( buffer )
2022-08-18 18:18:36 +03:00
if value , ok := floatTextProperty ( filter , Blur , session , 0 ) ; ok {
2024-11-13 12:56:39 +03:00
buffer . WriteString ( string ( Blur ) )
2021-09-07 17:36:50 +03:00
buffer . WriteRune ( '(' )
2022-08-18 18:18:36 +03:00
buffer . WriteString ( value )
buffer . WriteString ( "px)" )
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
for _ , tag := range [ ] PropertyName { Brightness , Contrast , Saturate , Grayscale , Invert , Opacity , Sepia } {
2022-08-18 18:18:36 +03:00
if value , ok := floatTextProperty ( filter , tag , session , 0 ) ; ok {
2021-09-07 17:36:50 +03:00
if buffer . Len ( ) > 0 {
buffer . WriteRune ( ' ' )
}
2024-11-13 12:56:39 +03:00
buffer . WriteString ( string ( tag ) )
2022-08-18 18:18:36 +03:00
buffer . WriteRune ( '(' )
buffer . WriteString ( value )
buffer . WriteString ( "%)" )
2021-09-07 17:36:50 +03:00
}
}
if value , ok := angleProperty ( filter , HueRotate , session ) ; ok {
if buffer . Len ( ) > 0 {
buffer . WriteRune ( ' ' )
}
2024-11-13 12:56:39 +03:00
buffer . WriteString ( string ( HueRotate ) )
2021-09-07 17:36:50 +03:00
buffer . WriteRune ( '(' )
buffer . WriteString ( value . cssString ( ) )
buffer . WriteRune ( ')' )
}
var lead string
if buffer . Len ( ) > 0 {
lead = " drop-shadow("
} else {
lead = "drop-shadow("
}
for _ , shadow := range getShadows ( filter , DropShadow ) {
if shadow . cssTextStyle ( buffer , session , lead ) {
buffer . WriteRune ( ')' )
lead = " drop-shadow("
}
}
return buffer . String ( )
}
2024-11-13 12:56:39 +03:00
func setFilterProperty ( properties Properties , tag PropertyName , value any ) [ ] PropertyName {
2021-09-07 17:36:50 +03:00
switch value := value . ( type ) {
case ViewFilter :
2024-11-13 12:56:39 +03:00
properties . setRaw ( tag , value )
return [ ] PropertyName { tag }
2021-09-07 17:36:50 +03:00
case string :
if obj := NewDataObject ( value ) ; obj == nil {
if filter := newViewFilter ( obj ) ; filter != nil {
2024-11-13 12:56:39 +03:00
properties . setRaw ( tag , filter )
return [ ] PropertyName { tag }
2021-09-07 17:36:50 +03:00
}
}
2024-11-13 12:56:39 +03:00
2021-09-07 17:36:50 +03:00
case DataObject :
if filter := newViewFilter ( value ) ; filter != nil {
2024-11-13 12:56:39 +03:00
properties . setRaw ( tag , filter )
return [ ] PropertyName { tag }
2021-09-07 17:36:50 +03:00
}
case DataValue :
if value . IsObject ( ) {
if filter := newViewFilter ( value . Object ( ) ) ; filter != nil {
2024-11-13 12:56:39 +03:00
properties . setRaw ( tag , filter )
return [ ] PropertyName { tag }
2021-09-07 17:36:50 +03:00
}
}
}
Added some properties and functions
* Added "resize", "grid-auto-flow", "caret-color", and "backdrop-filter" properties
* Added BlurView, BlurViewByID, GetResize, GetGridAutoFlow, GetCaretColor, GetBackdropFilter functions
* The "warp" property for ListView and ListLayout renamed to "list-warp"
* The "warp" property for EditView renamed to "edit-warp"
* Added CertFile and KeyFile optional fields to the AppParams struct.If they are set, then an https connection is created, otherwise http.
2022-06-07 13:07:10 +03:00
notCompatibleType ( tag , value )
2024-11-13 12:56:39 +03:00
return nil
2021-09-07 17:36:50 +03:00
}
// GetFilter returns a View graphical effects like blur or color shift.
2022-08-31 22:17:46 +03:00
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
func GetFilter ( view View , subviewID ... string ) ViewFilter {
2024-11-24 16:43:31 +03:00
if view = getSubview ( view , subviewID ) ; view != nil {
2021-09-07 17:36:50 +03:00
if value := view . getRaw ( Filter ) ; value != nil {
if filter , ok := value . ( ViewFilter ) ; ok {
return filter
}
}
2022-08-31 22:17:46 +03:00
if value := valueFromStyle ( view , Filter ) ; value != nil {
if filter , ok := value . ( ViewFilter ) ; ok {
return filter
}
}
2021-09-07 17:36:50 +03:00
}
return nil
}
Added some properties and functions
* Added "resize", "grid-auto-flow", "caret-color", and "backdrop-filter" properties
* Added BlurView, BlurViewByID, GetResize, GetGridAutoFlow, GetCaretColor, GetBackdropFilter functions
* The "warp" property for ListView and ListLayout renamed to "list-warp"
* The "warp" property for EditView renamed to "edit-warp"
* Added CertFile and KeyFile optional fields to the AppParams struct.If they are set, then an https connection is created, otherwise http.
2022-06-07 13:07:10 +03:00
// GetBackdropFilter returns the area behind a View graphical effects like blur or color shift.
2022-08-31 22:17:46 +03:00
// If the second argument (subviewID) is not specified or it is "" then a top position of the first argument (view) is returned
func GetBackdropFilter ( view View , subviewID ... string ) ViewFilter {
2024-11-24 16:43:31 +03:00
if view = getSubview ( view , subviewID ) ; view != nil {
Added some properties and functions
* Added "resize", "grid-auto-flow", "caret-color", and "backdrop-filter" properties
* Added BlurView, BlurViewByID, GetResize, GetGridAutoFlow, GetCaretColor, GetBackdropFilter functions
* The "warp" property for ListView and ListLayout renamed to "list-warp"
* The "warp" property for EditView renamed to "edit-warp"
* Added CertFile and KeyFile optional fields to the AppParams struct.If they are set, then an https connection is created, otherwise http.
2022-06-07 13:07:10 +03:00
if value := view . getRaw ( BackdropFilter ) ; value != nil {
if filter , ok := value . ( ViewFilter ) ; ok {
return filter
}
}
2022-08-31 22:17:46 +03:00
if value := valueFromStyle ( view , BackdropFilter ) ; value != nil {
if filter , ok := value . ( ViewFilter ) ; ok {
return filter
}
}
Added some properties and functions
* Added "resize", "grid-auto-flow", "caret-color", and "backdrop-filter" properties
* Added BlurView, BlurViewByID, GetResize, GetGridAutoFlow, GetCaretColor, GetBackdropFilter functions
* The "warp" property for ListView and ListLayout renamed to "list-warp"
* The "warp" property for EditView renamed to "edit-warp"
* Added CertFile and KeyFile optional fields to the AppParams struct.If they are set, then an https connection is created, otherwise http.
2022-06-07 13:07:10 +03:00
}
return nil
}