2021-09-07 17:36:50 +03:00
|
|
|
package rui
|
|
|
|
|
|
|
|
import (
|
2022-05-01 13:27:04 +03:00
|
|
|
"errors"
|
2021-09-07 17:36:50 +03:00
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// SizeUnitType : type of enumerated constants for define a type of SizeUnit value.
|
|
|
|
//
|
|
|
|
// Can take the following values: Auto, SizeInPixel, SizeInPercent,
|
|
|
|
// SizeInDIP, SizeInPt, SizeInInch, SizeInMM, SizeInFraction
|
|
|
|
type SizeUnitType uint8
|
|
|
|
|
2024-09-12 14:05:11 +03:00
|
|
|
// Constants which represent values of a [SizeUnitType]
|
2021-09-07 17:36:50 +03:00
|
|
|
const (
|
2022-09-05 14:00:07 +03:00
|
|
|
// Auto is the SizeUnit type: default value.
|
2021-09-07 17:36:50 +03:00
|
|
|
Auto SizeUnitType = 0
|
2022-09-05 14:00:07 +03:00
|
|
|
// SizeInPixel is the SizeUnit type: the Value field specifies the size in pixels.
|
2021-09-07 17:36:50 +03:00
|
|
|
SizeInPixel SizeUnitType = 1
|
2022-09-05 14:00:07 +03:00
|
|
|
// SizeInEM is the SizeUnit type: the Value field specifies the size in em.
|
2021-09-07 17:36:50 +03:00
|
|
|
SizeInEM SizeUnitType = 2
|
2022-09-05 14:00:07 +03:00
|
|
|
// SizeInEX is the SizeUnit type: the Value field specifies the size in em.
|
2021-09-07 17:36:50 +03:00
|
|
|
SizeInEX SizeUnitType = 3
|
2022-09-05 14:00:07 +03:00
|
|
|
// SizeInPercent is the SizeUnit type: the Value field specifies the size in percents of the parent size.
|
2021-09-07 17:36:50 +03:00
|
|
|
SizeInPercent SizeUnitType = 4
|
2022-09-05 14:00:07 +03:00
|
|
|
// SizeInPt is the SizeUnit type: the Value field specifies the size in pt (1/72 inch).
|
2021-09-07 17:36:50 +03:00
|
|
|
SizeInPt SizeUnitType = 5
|
2022-09-05 14:00:07 +03:00
|
|
|
// SizeInPc is the SizeUnit type: the Value field specifies the size in pc (1pc = 12pt).
|
2021-09-07 17:36:50 +03:00
|
|
|
SizeInPc SizeUnitType = 6
|
2022-09-05 14:00:07 +03:00
|
|
|
// SizeInInch is the SizeUnit type: the Value field specifies the size in inches.
|
2021-09-07 17:36:50 +03:00
|
|
|
SizeInInch SizeUnitType = 7
|
2022-09-05 14:00:07 +03:00
|
|
|
// SizeInMM is the SizeUnit type: the Value field specifies the size in millimeters.
|
2021-09-07 17:36:50 +03:00
|
|
|
SizeInMM SizeUnitType = 8
|
2022-09-05 14:00:07 +03:00
|
|
|
// SizeInCM is the SizeUnit type: the Value field specifies the size in centimeters.
|
2021-09-07 17:36:50 +03:00
|
|
|
SizeInCM SizeUnitType = 9
|
2022-09-05 14:00:07 +03:00
|
|
|
// SizeInFraction is the SizeUnit type: the Value field specifies the size in fraction.
|
|
|
|
// Used only for "cell-width" and "cell-height" property.
|
2021-09-07 17:36:50 +03:00
|
|
|
SizeInFraction SizeUnitType = 10
|
2022-09-05 14:00:07 +03:00
|
|
|
// SizeFunction is the SizeUnit type: the Function field specifies the size function.
|
|
|
|
// "min", "max", "clamp", "sum", "sub", "mul", and "div" functions are available.
|
|
|
|
SizeFunction = 11
|
2021-09-07 17:36:50 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// SizeUnit describe a size (Value field) and size unit (Type field).
|
|
|
|
type SizeUnit struct {
|
2024-09-12 14:05:11 +03:00
|
|
|
// Type or dimension of the value
|
|
|
|
Type SizeUnitType
|
|
|
|
|
|
|
|
// Value of the size in Type units
|
|
|
|
Value float64
|
|
|
|
|
|
|
|
// Function representation of a size unit.
|
|
|
|
// When setting this value type should be set to SizeFunction
|
2022-09-05 14:00:07 +03:00
|
|
|
Function SizeFunc
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// AutoSize creates SizeUnit with Auto type
|
|
|
|
func AutoSize() SizeUnit {
|
2022-09-05 14:00:07 +03:00
|
|
|
return SizeUnit{Auto, 0, nil}
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Px creates SizeUnit with SizeInPixel type
|
|
|
|
func Px(value float64) SizeUnit {
|
2022-09-05 14:00:07 +03:00
|
|
|
return SizeUnit{SizeInPixel, value, nil}
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Em creates SizeUnit with SizeInEM type
|
|
|
|
func Em(value float64) SizeUnit {
|
2022-09-05 14:00:07 +03:00
|
|
|
return SizeUnit{SizeInEM, value, nil}
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Ex creates SizeUnit with SizeInEX type
|
|
|
|
func Ex(value float64) SizeUnit {
|
2022-09-05 14:00:07 +03:00
|
|
|
return SizeUnit{SizeInEX, value, nil}
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Percent creates SizeUnit with SizeInDIP type
|
|
|
|
func Percent(value float64) SizeUnit {
|
2022-09-05 14:00:07 +03:00
|
|
|
return SizeUnit{SizeInPercent, value, nil}
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Pt creates SizeUnit with SizeInPt type
|
|
|
|
func Pt(value float64) SizeUnit {
|
2022-09-05 14:00:07 +03:00
|
|
|
return SizeUnit{SizeInPt, value, nil}
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Pc creates SizeUnit with SizeInPc type
|
|
|
|
func Pc(value float64) SizeUnit {
|
2022-09-05 14:00:07 +03:00
|
|
|
return SizeUnit{SizeInPc, value, nil}
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Mm creates SizeUnit with SizeInMM type
|
|
|
|
func Mm(value float64) SizeUnit {
|
2022-09-05 14:00:07 +03:00
|
|
|
return SizeUnit{SizeInMM, value, nil}
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Cm creates SizeUnit with SizeInCM type
|
|
|
|
func Cm(value float64) SizeUnit {
|
2022-09-05 14:00:07 +03:00
|
|
|
return SizeUnit{SizeInCM, value, nil}
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Inch creates SizeUnit with SizeInInch type
|
|
|
|
func Inch(value float64) SizeUnit {
|
2022-09-05 14:00:07 +03:00
|
|
|
return SizeUnit{SizeInInch, value, nil}
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fr creates SizeUnit with SizeInFraction type
|
|
|
|
func Fr(value float64) SizeUnit {
|
2022-09-05 14:00:07 +03:00
|
|
|
return SizeUnit{SizeInFraction, value, nil}
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Equal compare two SizeUnit. Return true if SizeUnit are equal
|
|
|
|
func (size SizeUnit) Equal(size2 SizeUnit) bool {
|
|
|
|
return size.Type == size2.Type && (size.Type == Auto || size.Value == size2.Value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func sizeUnitSuffixes() map[SizeUnitType]string {
|
|
|
|
return map[SizeUnitType]string{
|
|
|
|
SizeInPixel: "px",
|
|
|
|
SizeInPercent: "%",
|
|
|
|
SizeInEM: "em",
|
|
|
|
SizeInEX: "ex",
|
|
|
|
SizeInPt: "pt",
|
|
|
|
SizeInPc: "pc",
|
|
|
|
SizeInInch: "in",
|
|
|
|
SizeInMM: "mm",
|
|
|
|
SizeInCM: "cm",
|
|
|
|
SizeInFraction: "fr",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// StringToSizeUnit converts the string argument to SizeUnit
|
|
|
|
func StringToSizeUnit(value string) (SizeUnit, bool) {
|
2022-05-01 13:27:04 +03:00
|
|
|
size, err := stringToSizeUnit(value)
|
|
|
|
if err != nil {
|
|
|
|
ErrorLog(err.Error())
|
|
|
|
return size, false
|
|
|
|
}
|
|
|
|
return size, true
|
|
|
|
}
|
2021-09-07 17:36:50 +03:00
|
|
|
|
2022-05-01 13:27:04 +03:00
|
|
|
func stringToSizeUnit(value string) (SizeUnit, error) {
|
2021-09-07 17:36:50 +03:00
|
|
|
value = strings.Trim(value, " \t\n\r")
|
|
|
|
|
|
|
|
switch value {
|
|
|
|
case "auto", "none", "":
|
2022-05-01 13:27:04 +03:00
|
|
|
return SizeUnit{Type: Auto, Value: 0}, nil
|
2021-09-07 17:36:50 +03:00
|
|
|
|
|
|
|
case "0":
|
2022-05-01 13:27:04 +03:00
|
|
|
return SizeUnit{Type: SizeInPixel, Value: 0}, nil
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
suffixes := sizeUnitSuffixes()
|
|
|
|
for unitType, suffix := range suffixes {
|
|
|
|
if strings.HasSuffix(value, suffix) {
|
|
|
|
var err error
|
|
|
|
var val float64
|
|
|
|
if val, err = strconv.ParseFloat(value[:len(value)-len(suffix)], 64); err != nil {
|
2022-05-01 13:27:04 +03:00
|
|
|
return SizeUnit{Type: Auto, Value: 0}, err
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
2022-05-01 13:27:04 +03:00
|
|
|
return SizeUnit{Type: unitType, Value: val}, nil
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-05 14:00:07 +03:00
|
|
|
if val, err := strconv.ParseFloat(value, 64); err == nil {
|
2022-08-08 17:00:49 +03:00
|
|
|
return SizeUnit{Type: SizeInPixel, Value: val}, nil
|
|
|
|
}
|
|
|
|
|
2022-05-01 13:27:04 +03:00
|
|
|
return SizeUnit{Type: Auto, Value: 0}, errors.New(`Invalid SizeUnit value: "` + value + `"`)
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// String - convert SizeUnit to string
|
|
|
|
func (size SizeUnit) String() string {
|
2022-09-05 14:00:07 +03:00
|
|
|
switch size.Type {
|
|
|
|
case Auto:
|
2021-09-07 17:36:50 +03:00
|
|
|
return "auto"
|
2022-09-05 14:00:07 +03:00
|
|
|
|
|
|
|
case SizeFunction:
|
|
|
|
if size.Function == nil {
|
|
|
|
return "auto"
|
|
|
|
}
|
|
|
|
return size.Function.String()
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
if suffix, ok := sizeUnitSuffixes()[size.Type]; ok {
|
|
|
|
return fmt.Sprintf("%g%s", size.Value, suffix)
|
|
|
|
}
|
|
|
|
return strconv.FormatFloat(size.Value, 'g', -1, 64)
|
|
|
|
}
|
|
|
|
|
|
|
|
// cssString - convert SizeUnit to string
|
2022-09-05 14:00:07 +03:00
|
|
|
func (size SizeUnit) cssString(textForAuto string, session Session) string {
|
2021-09-07 17:36:50 +03:00
|
|
|
switch size.Type {
|
|
|
|
case Auto:
|
|
|
|
return textForAuto
|
|
|
|
|
|
|
|
case SizeInEM:
|
|
|
|
return fmt.Sprintf("%grem", size.Value)
|
2022-09-05 14:00:07 +03:00
|
|
|
|
|
|
|
case SizeFunction:
|
|
|
|
if size.Function == nil {
|
|
|
|
return textForAuto
|
|
|
|
}
|
|
|
|
return size.Function.cssString(session)
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if size.Value == 0 {
|
|
|
|
return "0"
|
|
|
|
}
|
|
|
|
|
|
|
|
return size.String()
|
|
|
|
}
|