package rui import ( "errors" "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 const ( // Auto is the SizeUnit type: default value. Auto SizeUnitType = 0 // SizeInPixel is the SizeUnit type: the Value field specifies the size in pixels. SizeInPixel SizeUnitType = 1 // SizeInEM is the SizeUnit type: the Value field specifies the size in em. SizeInEM SizeUnitType = 2 // SizeInEX is the SizeUnit type: the Value field specifies the size in em. SizeInEX SizeUnitType = 3 // SizeInPercent is the SizeUnit type: the Value field specifies the size in percents of the parent size. SizeInPercent SizeUnitType = 4 // SizeInPt is the SizeUnit type: the Value field specifies the size in pt (1/72 inch). SizeInPt SizeUnitType = 5 // SizeInPc is the SizeUnit type: the Value field specifies the size in pc (1pc = 12pt). SizeInPc SizeUnitType = 6 // SizeInInch is the SizeUnit type: the Value field specifies the size in inches. SizeInInch SizeUnitType = 7 // SizeInMM is the SizeUnit type: the Value field specifies the size in millimeters. SizeInMM SizeUnitType = 8 // SizeInCM is the SizeUnit type: the Value field specifies the size in centimeters. SizeInCM SizeUnitType = 9 // SizeInFraction is the SizeUnit type: the Value field specifies the size in fraction. // Used only for "cell-width" and "cell-height" property. SizeInFraction SizeUnitType = 10 // 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 ) // SizeUnit describe a size (Value field) and size unit (Type field). type SizeUnit struct { Type SizeUnitType Value float64 Function SizeFunc } // AutoSize creates SizeUnit with Auto type func AutoSize() SizeUnit { return SizeUnit{Auto, 0, nil} } // Px creates SizeUnit with SizeInPixel type func Px(value float64) SizeUnit { return SizeUnit{SizeInPixel, value, nil} } // Em creates SizeUnit with SizeInEM type func Em(value float64) SizeUnit { return SizeUnit{SizeInEM, value, nil} } // Ex creates SizeUnit with SizeInEX type func Ex(value float64) SizeUnit { return SizeUnit{SizeInEX, value, nil} } // Percent creates SizeUnit with SizeInDIP type func Percent(value float64) SizeUnit { return SizeUnit{SizeInPercent, value, nil} } // Pt creates SizeUnit with SizeInPt type func Pt(value float64) SizeUnit { return SizeUnit{SizeInPt, value, nil} } // Pc creates SizeUnit with SizeInPc type func Pc(value float64) SizeUnit { return SizeUnit{SizeInPc, value, nil} } // Mm creates SizeUnit with SizeInMM type func Mm(value float64) SizeUnit { return SizeUnit{SizeInMM, value, nil} } // Cm creates SizeUnit with SizeInCM type func Cm(value float64) SizeUnit { return SizeUnit{SizeInCM, value, nil} } // Inch creates SizeUnit with SizeInInch type func Inch(value float64) SizeUnit { return SizeUnit{SizeInInch, value, nil} } // Fr creates SizeUnit with SizeInFraction type func Fr(value float64) SizeUnit { return SizeUnit{SizeInFraction, value, nil} } // 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) { size, err := stringToSizeUnit(value) if err != nil { ErrorLog(err.Error()) return size, false } return size, true } func stringToSizeUnit(value string) (SizeUnit, error) { value = strings.Trim(value, " \t\n\r") switch value { case "auto", "none", "": return SizeUnit{Type: Auto, Value: 0}, nil case "0": return SizeUnit{Type: SizeInPixel, Value: 0}, nil } 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 { return SizeUnit{Type: Auto, Value: 0}, err } return SizeUnit{Type: unitType, Value: val}, nil } } if val, err := strconv.ParseFloat(value, 64); err == nil { return SizeUnit{Type: SizeInPixel, Value: val}, nil } return SizeUnit{Type: Auto, Value: 0}, errors.New(`Invalid SizeUnit value: "` + value + `"`) } // String - convert SizeUnit to string func (size SizeUnit) String() string { switch size.Type { case Auto: return "auto" case SizeFunction: if size.Function == nil { return "auto" } return size.Function.String() } 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 func (size SizeUnit) cssString(textForAuto string, session Session) string { switch size.Type { case Auto: return textForAuto case SizeInEM: return fmt.Sprintf("%grem", size.Value) case SizeFunction: if size.Function == nil { return textForAuto } return size.Function.cssString(session) } if size.Value == 0 { return "0" } return size.String() }